diff --git a/README.md b/README.md index 42fc0a63c0ffb..c2ded10f05a36 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ -# The Rust Programming Language + +The Rust Programming Language + This is the main source code repository for [Rust]. It contains the compiler, -standard library, and documentation. +standard library, and documentation. [Rust]: https://www.rust-lang.org @@ -17,9 +19,9 @@ Read ["Installation"] from [The Book]. _Note: If you wish to contribute to the compiler, you should read [this chapter][rustcguidebuild] of the rustc-dev-guide instead of this section._ -The Rust build system has a Python script called `x.py` to bootstrap building -the compiler. More information about it may be found by running `./x.py --help` -or reading the [rustc dev guide][rustcguidebuild]. +The Rust build system uses a Python script called `x.py` to build the compiler, +which manages the bootstrapping process. More information about it can be found +by running `./x.py --help` or reading the [rustc dev guide][rustcguidebuild]. [rustcguidebuild]: https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html @@ -54,9 +56,8 @@ or reading the [rustc dev guide][rustcguidebuild]. $ cp config.toml.example config.toml ``` - It is recommended that if you plan to use the Rust build system to create - an installation (using `./x.py install`) that you set the `prefix` value - in the `[install]` section to a directory that you have write permissions. + If you plan to use `x.py install` to create an installation, it is recommended + that you set the `prefix` value in the `[install]` section to a directory. Create install directory if you are not installing in default directory @@ -143,8 +144,8 @@ shell with: ``` Currently, building Rust only works with some known versions of Visual Studio. If -you have a more recent version installed the build system doesn't understand -then you may need to force rustbuild to use an older version. This can be done +you have a more recent version installed and the build system doesn't understand, +you may need to force rustbuild to use an older version. This can be done by manually calling the appropriate vcvars file before running the bootstrap. ```batch diff --git a/src/doc/unstable-book/src/language-features/track-caller.md b/src/doc/unstable-book/src/language-features/track-caller.md deleted file mode 100644 index afc11a2b9492c..0000000000000 --- a/src/doc/unstable-book/src/language-features/track-caller.md +++ /dev/null @@ -1,5 +0,0 @@ -# `track_caller` - -The tracking issue for this feature is: [#47809](https://github.com/rust-lang/rust/issues/47809). - ------------------------- diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index f1b560b9b9685..3320ebdf821d0 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -384,7 +384,10 @@ impl Box { /// /// unsafe { /// let ptr = alloc(Layout::new::()) as *mut i32; - /// *ptr = 5; + /// // In general .write is required to avoid attempting to destruct + /// // the (uninitialized) previous contents of `ptr`, though for this + /// // simple example `*ptr = 5` would have worked as well. + /// ptr.write(5); /// let x = Box::from_raw(ptr); /// } /// ``` diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 64d9692244dde..13ef94dee2326 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -2518,3 +2518,11 @@ impl DoubleEndedIterator for Drain<'_> { #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Drain<'_> {} + +#[stable(feature = "from_char_for_string", since = "1.46.0")] +impl From for String { + #[inline] + fn from(c: char) -> Self { + c.to_string() + } +} diff --git a/src/liballoc/tests/string.rs b/src/liballoc/tests/string.rs index 9ea020d2d19f4..d38655af78cb7 100644 --- a/src/liballoc/tests/string.rs +++ b/src/liballoc/tests/string.rs @@ -714,3 +714,10 @@ fn test_try_reserve_exact() { } } } + +#[test] +fn test_from_char() { + assert_eq!(String::from('a'), 'a'.to_string()); + let s: String = 'x'.into(); + assert_eq!(s, 'x'.to_string()); +} diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 5d09018759191..57ffed19c0085 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -952,6 +952,7 @@ extern "rust-intrinsic" { /// Any use other than with `if` statements will probably not have an effect. /// /// This intrinsic does not have a stable counterpart. + #[rustc_const_unstable(feature = "const_likely", issue = "none")] pub fn likely(b: bool) -> bool; /// Hints to the compiler that branch condition is likely to be false. @@ -960,6 +961,7 @@ extern "rust-intrinsic" { /// Any use other than with `if` statements will probably not have an effect. /// /// This intrinsic does not have a stable counterpart. + #[rustc_const_unstable(feature = "const_likely", issue = "none")] pub fn unlikely(b: bool) -> bool; /// Executes a breakpoint trap, for inspection by a debugger. diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index aeb52bffbf24c..63ddd97eed3df 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -92,6 +92,7 @@ #![feature(const_slice_from_raw_parts)] #![feature(const_slice_ptr_len)] #![feature(const_type_name)] +#![feature(const_likely)] #![feature(custom_inner_attributes)] #![feature(decl_macro)] #![feature(doc_cfg)] @@ -118,7 +119,7 @@ #![feature(staged_api)] #![feature(std_internals)] #![feature(stmt_expr_attributes)] -#![feature(track_caller)] +#![cfg_attr(bootstrap, feature(track_caller))] #![feature(transparent_unions)] #![feature(unboxed_closures)] #![feature(unsized_locals)] diff --git a/src/libcore/macros/mod.rs b/src/libcore/macros/mod.rs index 3cfdde60135b7..13c0e8daf740f 100644 --- a/src/libcore/macros/mod.rs +++ b/src/libcore/macros/mod.rs @@ -1,6 +1,6 @@ #[doc(include = "panic.md")] #[macro_export] -#[allow_internal_unstable(core_panic, track_caller)] +#[allow_internal_unstable(core_panic, const_caller_location)] #[stable(feature = "core", since = "1.6.0")] macro_rules! panic { () => ( diff --git a/src/libcore/panic.rs b/src/libcore/panic.rs index c7009b76e8148..543aa969330ae 100644 --- a/src/libcore/panic.rs +++ b/src/libcore/panic.rs @@ -190,7 +190,6 @@ impl<'a> Location<'a> { /// # Examples /// /// ``` - /// #![feature(track_caller)] /// use core::panic::Location; /// /// /// Returns the [`Location`] at which it is called. @@ -206,7 +205,7 @@ impl<'a> Location<'a> { /// /// let fixed_location = get_just_one_location(); /// assert_eq!(fixed_location.file(), file!()); - /// assert_eq!(fixed_location.line(), 15); + /// assert_eq!(fixed_location.line(), 14); /// assert_eq!(fixed_location.column(), 5); /// /// // running the same untracked function in a different location gives us the same result @@ -217,7 +216,7 @@ impl<'a> Location<'a> { /// /// let this_location = get_caller_location(); /// assert_eq!(this_location.file(), file!()); - /// assert_eq!(this_location.line(), 29); + /// assert_eq!(this_location.line(), 28); /// assert_eq!(this_location.column(), 21); /// /// // running the tracked function in a different location produces a different value @@ -226,13 +225,8 @@ impl<'a> Location<'a> { /// assert_ne!(this_location.line(), another_location.line()); /// assert_ne!(this_location.column(), another_location.column()); /// ``` - // FIXME: When stabilizing this method, please also update the documentation - // of `intrinsics::caller_location`. - #[unstable( - feature = "track_caller", - reason = "uses #[track_caller] which is not yet stable", - issue = "47809" - )] + #[stable(feature = "track_caller", since = "1.46.0")] + #[rustc_const_unstable(feature = "const_caller_location", issue = "47809")] #[track_caller] pub const fn caller() -> &'static Location<'static> { crate::intrinsics::caller_location() diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs index 86faa1f086ce2..501cd3748282b 100644 --- a/src/librustc_ast_pretty/pprust.rs +++ b/src/librustc_ast_pretty/pprust.rs @@ -9,7 +9,7 @@ use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_ast::attr; use rustc_ast::ptr::P; use rustc_ast::token::{self, BinOpToken, DelimToken, Nonterminal, Token, TokenKind}; -use rustc_ast::tokenstream::{self, TokenStream, TokenTree}; +use rustc_ast::tokenstream::{TokenStream, TokenTree}; use rustc_ast::util::parser::{self, AssocOp, Fixity}; use rustc_ast::util::{classify, comments}; use rustc_span::edition::Edition; @@ -293,7 +293,7 @@ pub fn nonterminal_to_string(nt: &Nonterminal) -> String { token::NtIdent(e, is_raw) => IdentPrinter::for_ast_ident(e, is_raw).to_string(), token::NtLifetime(e) => e.to_string(), token::NtLiteral(ref e) => expr_to_string(e), - token::NtTT(ref tree) => tt_to_string(tree.clone()), + token::NtTT(ref tree) => tt_to_string(tree), token::NtVis(ref e) => vis_to_string(e), } } @@ -314,11 +314,11 @@ pub fn expr_to_string(e: &ast::Expr) -> String { to_string(|s| s.print_expr(e)) } -pub fn tt_to_string(tt: tokenstream::TokenTree) -> String { +pub fn tt_to_string(tt: &TokenTree) -> String { to_string(|s| s.print_tt(tt, false)) } -pub fn tts_to_string(tokens: TokenStream) -> String { +pub fn tts_to_string(tokens: &TokenStream) -> String { to_string(|s| s.print_tts(tokens, false)) } @@ -585,7 +585,7 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere false, None, delim.to_token(), - tokens.clone(), + tokens, true, span, ), @@ -594,7 +594,7 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere if let MacArgs::Eq(_, tokens) = &item.args { self.space(); self.word_space("="); - self.print_tts(tokens.clone(), true); + self.print_tts(tokens, true); } } } @@ -635,9 +635,9 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere /// appropriate macro, transcribe back into the grammar we just parsed from, /// and then pretty-print the resulting AST nodes (so, e.g., we print /// expression arguments as expressions). It can be done! I think. - fn print_tt(&mut self, tt: tokenstream::TokenTree, convert_dollar_crate: bool) { + fn print_tt(&mut self, tt: &TokenTree, convert_dollar_crate: bool) { match tt { - TokenTree::Token(ref token) => { + TokenTree::Token(token) => { self.word(token_to_string_ext(&token, convert_dollar_crate)); if let token::DocComment(..) = token.kind { self.hardbreak() @@ -648,7 +648,7 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere None, false, None, - delim, + *delim, tts, convert_dollar_crate, dspan.entire(), @@ -657,14 +657,14 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere } } - fn print_tts(&mut self, tts: tokenstream::TokenStream, convert_dollar_crate: bool) { - let mut iter = tts.into_trees().peekable(); + fn print_tts(&mut self, tts: &TokenStream, convert_dollar_crate: bool) { + let mut iter = tts.trees().peekable(); while let Some(tt) = iter.next() { - let show_space = - if let Some(next) = iter.peek() { tt_prepend_space(next, &tt) } else { false }; - self.print_tt(tt, convert_dollar_crate); - if show_space { - self.space(); + self.print_tt(&tt, convert_dollar_crate); + if let Some(next) = iter.peek() { + if tt_prepend_space(next, &tt) { + self.space(); + } } } } @@ -675,7 +675,7 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere has_bang: bool, ident: Option, delim: DelimToken, - tts: TokenStream, + tts: &TokenStream, convert_dollar_crate: bool, span: Span, ) { @@ -1253,7 +1253,7 @@ impl<'a> State<'a> { has_bang, Some(item.ident), macro_def.body.delim(), - macro_def.body.inner_tokens(), + ¯o_def.body.inner_tokens(), true, item.span, ); @@ -1577,7 +1577,7 @@ impl<'a> State<'a> { true, None, m.args.delim(), - m.args.inner_tokens(), + &m.args.inner_tokens(), true, m.span(), ); diff --git a/src/librustc_builtin_macros/log_syntax.rs b/src/librustc_builtin_macros/log_syntax.rs index ae3a889428ae4..ede34a7612589 100644 --- a/src/librustc_builtin_macros/log_syntax.rs +++ b/src/librustc_builtin_macros/log_syntax.rs @@ -7,7 +7,7 @@ pub fn expand_log_syntax<'cx>( sp: rustc_span::Span, tts: TokenStream, ) -> Box { - println!("{}", pprust::tts_to_string(tts)); + println!("{}", pprust::tts_to_string(&tts)); // any so that `log_syntax` can be invoked as an expression and item. base::DummyResult::any_valid(sp) diff --git a/src/librustc_builtin_macros/source_util.rs b/src/librustc_builtin_macros/source_util.rs index 1b164eae5a345..e46cf67e64d66 100644 --- a/src/librustc_builtin_macros/source_util.rs +++ b/src/librustc_builtin_macros/source_util.rs @@ -71,7 +71,7 @@ pub fn expand_stringify( tts: TokenStream, ) -> Box { let sp = cx.with_def_site_ctxt(sp); - let s = pprust::tts_to_string(tts); + let s = pprust::tts_to_string(&tts); base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&s))) } diff --git a/src/librustc_error_codes/error_codes/E0736.md b/src/librustc_error_codes/error_codes/E0736.md index 8a60dc320599b..0f3d41ba66dc4 100644 --- a/src/librustc_error_codes/error_codes/E0736.md +++ b/src/librustc_error_codes/error_codes/E0736.md @@ -3,8 +3,6 @@ Erroneous code example: ```compile_fail,E0736 -#![feature(track_caller)] - #[naked] #[track_caller] fn foo() {} diff --git a/src/librustc_error_codes/error_codes/E0737.md b/src/librustc_error_codes/error_codes/E0737.md index c6553e97b7e91..ab5e60692b4da 100644 --- a/src/librustc_error_codes/error_codes/E0737.md +++ b/src/librustc_error_codes/error_codes/E0737.md @@ -5,8 +5,6 @@ restrictions. Erroneous code example: ```compile_fail,E0737 -#![feature(track_caller)] - #[track_caller] extern "C" fn foo() {} ``` diff --git a/src/librustc_error_codes/error_codes/E0739.md b/src/librustc_error_codes/error_codes/E0739.md index 707751066edbc..8d9039bef93f6 100644 --- a/src/librustc_error_codes/error_codes/E0739.md +++ b/src/librustc_error_codes/error_codes/E0739.md @@ -3,7 +3,6 @@ Erroneous code example: ```compile_fail,E0739 -#![feature(track_caller)] #[track_caller] struct Bar { a: u8, diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 0c1418d3cad27..362913ceadf18 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -5,7 +5,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(crate_visibility_modifier)] #![feature(nll)] -#![feature(track_caller)] +#![cfg_attr(bootstrap, feature(track_caller))] pub use emitter::ColorConfig; diff --git a/src/librustc_expand/mbe/macro_rules.rs b/src/librustc_expand/mbe/macro_rules.rs index 8cdb5b09c9e8b..28a3970918ee6 100644 --- a/src/librustc_expand/mbe/macro_rules.rs +++ b/src/librustc_expand/mbe/macro_rules.rs @@ -224,7 +224,7 @@ fn generic_extension<'cx>( let sess = cx.parse_sess; if cx.trace_macros() { - let msg = format!("expanding `{}! {{ {} }}`", name, pprust::tts_to_string(arg.clone())); + let msg = format!("expanding `{}! {{ {} }}`", name, pprust::tts_to_string(&arg)); trace_macros_note(&mut cx.expansions, sp, msg); } @@ -300,7 +300,7 @@ fn generic_extension<'cx>( } if cx.trace_macros() { - let msg = format!("to `{}`", pprust::tts_to_string(tts.clone())); + let msg = format!("to `{}`", pprust::tts_to_string(&tts)); trace_macros_note(&mut cx.expansions, sp, msg); } diff --git a/src/librustc_expand/proc_macro_server.rs b/src/librustc_expand/proc_macro_server.rs index c88b5a37f718a..e5e530227e43a 100644 --- a/src/librustc_expand/proc_macro_server.rs +++ b/src/librustc_expand/proc_macro_server.rs @@ -413,7 +413,7 @@ impl server::TokenStream for Rustc<'_> { ) } fn to_string(&mut self, stream: &Self::TokenStream) -> String { - pprust::tts_to_string(stream.clone()) + pprust::tts_to_string(stream) } fn from_token_tree( &mut self, diff --git a/src/librustc_feature/accepted.rs b/src/librustc_feature/accepted.rs index b164b21913d6e..d93c17b05b498 100644 --- a/src/librustc_feature/accepted.rs +++ b/src/librustc_feature/accepted.rs @@ -265,6 +265,9 @@ declare_features! ( (accepted, const_if_match, "1.45.0", Some(49146), None), /// Allows the use of `loop` and `while` in constants. (accepted, const_loop, "1.45.0", Some(52000), None), + /// Allows `#[track_caller]` to be used which provides + /// accurate caller location reporting during panic (RFC 2091). + (accepted, track_caller, "1.46.0", Some(47809), None), // ------------------------------------------------------------------------- // feature-group-end: accepted features diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs index 8660d6a8d6410..b9a55377949f2 100644 --- a/src/librustc_feature/active.rs +++ b/src/librustc_feature/active.rs @@ -494,10 +494,6 @@ declare_features! ( /// Allows the use of raw-dylibs (RFC 2627). (active, raw_dylib, "1.40.0", Some(58713), None), - /// Allows `#[track_caller]` to be used which provides - /// accurate caller location reporting during panic (RFC 2091). - (active, track_caller, "1.40.0", Some(47809), None), - /// Allows making `dyn Trait` well-formed even if `Trait` is not object safe. /// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden. diff --git a/src/librustc_feature/builtin_attrs.rs b/src/librustc_feature/builtin_attrs.rs index 524a357971029..c9a34f033758b 100644 --- a/src/librustc_feature/builtin_attrs.rs +++ b/src/librustc_feature/builtin_attrs.rs @@ -260,6 +260,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ungated!(cold, Whitelisted, template!(Word)), ungated!(no_builtins, Whitelisted, template!(Word)), ungated!(target_feature, Whitelisted, template!(List: r#"enable = "name""#)), + ungated!(track_caller, Whitelisted, template!(Word)), gated!( no_sanitize, Whitelisted, template!(List: "address, memory, thread"), @@ -333,7 +334,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ gated!(ffi_returns_twice, Whitelisted, template!(Word), experimental!(ffi_returns_twice)), gated!(ffi_pure, Whitelisted, template!(Word), experimental!(ffi_pure)), gated!(ffi_const, Whitelisted, template!(Word), experimental!(ffi_const)), - gated!(track_caller, Whitelisted, template!(Word), experimental!(track_caller)), gated!( register_attr, CrateLevel, template!(List: "attr1, attr2, ..."), experimental!(register_attr), diff --git a/src/librustc_infer/infer/at.rs b/src/librustc_infer/infer/at.rs index d44b8f554143c..a7749d33b7c13 100644 --- a/src/librustc_infer/infer/at.rs +++ b/src/librustc_infer/infer/at.rs @@ -82,7 +82,7 @@ impl<'a, 'tcx> At<'a, 'tcx> { where T: ToTrace<'tcx>, { - self.trace_exp(a_is_expected, a, b).sub(&a, &b) + self.trace_exp(a_is_expected, a, b).sub(a, b) } /// Makes `actual <: expected`. For example, if type-checking a @@ -109,7 +109,7 @@ impl<'a, 'tcx> At<'a, 'tcx> { where T: ToTrace<'tcx>, { - self.trace_exp(a_is_expected, a, b).eq(&a, &b) + self.trace_exp(a_is_expected, a, b).eq(a, b) } /// Makes `expected <: actual`. @@ -117,7 +117,7 @@ impl<'a, 'tcx> At<'a, 'tcx> { where T: ToTrace<'tcx>, { - self.trace(expected, actual).eq(&expected, &actual) + self.trace(expected, actual).eq(expected, actual) } pub fn relate(self, expected: T, variance: ty::Variance, actual: T) -> InferResult<'tcx, ()> @@ -147,7 +147,7 @@ impl<'a, 'tcx> At<'a, 'tcx> { where T: ToTrace<'tcx>, { - self.trace(expected, actual).lub(&expected, &actual) + self.trace(expected, actual).lub(expected, actual) } /// Computes the greatest-lower-bound, or mutual subtype, of two @@ -157,7 +157,7 @@ impl<'a, 'tcx> At<'a, 'tcx> { where T: ToTrace<'tcx>, { - self.trace(expected, actual).glb(&expected, &actual) + self.trace(expected, actual).glb(expected, actual) } /// Sets the "trace" values that will be used for @@ -186,7 +186,7 @@ impl<'a, 'tcx> At<'a, 'tcx> { impl<'a, 'tcx> Trace<'a, 'tcx> { /// Makes `a <: b` where `a` may or may not be expected (if /// `a_is_expected` is true, then `a` is expected). - pub fn sub(self, a: &T, b: &T) -> InferResult<'tcx, ()> + pub fn sub(self, a: T, b: T) -> InferResult<'tcx, ()> where T: Relate<'tcx>, { @@ -203,7 +203,7 @@ impl<'a, 'tcx> Trace<'a, 'tcx> { /// Makes `a == b`; the expectation is set by the call to /// `trace()`. - pub fn eq(self, a: &T, b: &T) -> InferResult<'tcx, ()> + pub fn eq(self, a: T, b: T) -> InferResult<'tcx, ()> where T: Relate<'tcx>, { @@ -218,7 +218,7 @@ impl<'a, 'tcx> Trace<'a, 'tcx> { }) } - pub fn lub(self, a: &T, b: &T) -> InferResult<'tcx, T> + pub fn lub(self, a: T, b: T) -> InferResult<'tcx, T> where T: Relate<'tcx>, { @@ -233,7 +233,7 @@ impl<'a, 'tcx> Trace<'a, 'tcx> { }) } - pub fn glb(self, a: &T, b: &T) -> InferResult<'tcx, T> + pub fn glb(self, a: T, b: T) -> InferResult<'tcx, T> where T: Relate<'tcx>, { diff --git a/src/librustc_infer/infer/canonical/query_response.rs b/src/librustc_infer/infer/canonical/query_response.rs index 8af526e3ad31b..5cba581b9dffb 100644 --- a/src/librustc_infer/infer/canonical/query_response.rs +++ b/src/librustc_infer/infer/canonical/query_response.rs @@ -271,7 +271,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { }, ty::Variance::Invariant, ) - .relate(&v1, &v2)?; + .relate(v1, v2)?; } (GenericArgKind::Const(v1), GenericArgKind::Const(v2)) => { @@ -285,7 +285,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { }, ty::Variance::Invariant, ) - .relate(&v1, &v2)?; + .relate(v1, v2)?; } _ => { @@ -302,7 +302,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { // Screen out `'a: 'a` cases -- we skip the binder here but // only compare the inner values to one another, so they are still at // consistent binding levels. - let &ty::OutlivesPredicate(k1, r2) = r_c.skip_binder(); + let ty::OutlivesPredicate(k1, r2) = r_c.skip_binder(); if k1 != r2.into() { Some(r_c) } else { None } }), ); @@ -526,7 +526,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { ) -> impl Iterator> + 'a + Captures<'tcx> { unsubstituted_region_constraints.iter().map(move |constraint| { let constraint = substitute_value(self.tcx, result_subst, constraint); - let &ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below + let ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below Obligation::new( cause.clone(), diff --git a/src/librustc_infer/infer/combine.rs b/src/librustc_infer/infer/combine.rs index 4ef4ed47cb11a..c8d4e9f0e14b9 100644 --- a/src/librustc_infer/infer/combine.rs +++ b/src/librustc_infer/infer/combine.rs @@ -318,10 +318,10 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { // to associate causes/spans with each of the relations in // the stack to get this right. match dir { - EqTo => self.equate(a_is_expected).relate(&a_ty, &b_ty), - SubtypeOf => self.sub(a_is_expected).relate(&a_ty, &b_ty), + EqTo => self.equate(a_is_expected).relate(a_ty, b_ty), + SubtypeOf => self.sub(a_is_expected).relate(a_ty, b_ty), SupertypeOf => { - self.sub(a_is_expected).relate_with_variance(ty::Contravariant, &a_ty, &b_ty) + self.sub(a_is_expected).relate_with_variance(ty::Contravariant, a_ty, b_ty) } }?; @@ -379,7 +379,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { param_env: self.param_env, }; - let ty = match generalize.relate(&ty, &ty) { + let ty = match generalize.relate(ty, ty) { Ok(ty) => ty, Err(e) => { debug!("generalize: failure {:?}", e); @@ -490,8 +490,8 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { fn binders( &mut self, - a: &ty::Binder, - b: &ty::Binder, + a: ty::Binder, + b: ty::Binder, ) -> RelateResult<'tcx, ty::Binder> where T: Relate<'tcx>, @@ -519,8 +519,8 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { fn relate_with_variance>( &mut self, variance: ty::Variance, - a: &T, - b: &T, + a: T, + b: T, ) -> RelateResult<'tcx, T> { let old_ambient_variance = self.ambient_variance; self.ambient_variance = self.ambient_variance.xform(variance); @@ -552,7 +552,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { match probe { TypeVariableValue::Known { value: u } => { debug!("generalize: known value {:?}", u); - self.relate(&u, &u) + self.relate(u, u) } TypeVariableValue::Unknown { universe } => { match self.ambient_variance { @@ -655,7 +655,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { let variable_table = &mut inner.const_unification_table(); let var_value = variable_table.probe_value(vid); match var_value.val { - ConstVariableValue::Known { value: u } => self.relate(&u, &u), + ConstVariableValue::Known { value: u } => self.relate(u, u), ConstVariableValue::Unknown { universe } => { if self.for_universe.can_name(universe) { Ok(c) diff --git a/src/librustc_infer/infer/equate.rs b/src/librustc_infer/infer/equate.rs index e3cafb82719dd..7de752d1de0db 100644 --- a/src/librustc_infer/infer/equate.rs +++ b/src/librustc_infer/infer/equate.rs @@ -59,8 +59,8 @@ impl TypeRelation<'tcx> for Equate<'combine, 'infcx, 'tcx> { fn relate_with_variance>( &mut self, _: ty::Variance, - a: &T, - b: &T, + a: T, + b: T, ) -> RelateResult<'tcx, T> { self.relate(a, b) } @@ -124,8 +124,8 @@ impl TypeRelation<'tcx> for Equate<'combine, 'infcx, 'tcx> { fn binders( &mut self, - a: &ty::Binder, - b: &ty::Binder, + a: ty::Binder, + b: ty::Binder, ) -> RelateResult<'tcx, ty::Binder> where T: Relate<'tcx>, @@ -136,7 +136,7 @@ impl TypeRelation<'tcx> for Equate<'combine, 'infcx, 'tcx> { } else { // Fast path for the common case. self.relate(a.skip_binder(), b.skip_binder())?; - Ok(a.clone()) + Ok(a) } } } diff --git a/src/librustc_infer/infer/glb.rs b/src/librustc_infer/infer/glb.rs index ec219a95b9441..8a0ab52f38306 100644 --- a/src/librustc_infer/infer/glb.rs +++ b/src/librustc_infer/infer/glb.rs @@ -43,8 +43,8 @@ impl TypeRelation<'tcx> for Glb<'combine, 'infcx, 'tcx> { fn relate_with_variance>( &mut self, variance: ty::Variance, - a: &T, - b: &T, + a: T, + b: T, ) -> RelateResult<'tcx, T> { match variance { ty::Invariant => self.fields.equate(self.a_is_expected).relate(a, b), @@ -85,8 +85,8 @@ impl TypeRelation<'tcx> for Glb<'combine, 'infcx, 'tcx> { fn binders( &mut self, - a: &ty::Binder, - b: &ty::Binder, + a: ty::Binder, + b: ty::Binder, ) -> RelateResult<'tcx, ty::Binder> where T: Relate<'tcx>, @@ -112,8 +112,8 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Glb<'combine, 'infcx, fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> { let mut sub = self.fields.sub(self.a_is_expected); - sub.relate(&v, &a)?; - sub.relate(&v, &b)?; + sub.relate(v, a)?; + sub.relate(v, b)?; Ok(()) } } diff --git a/src/librustc_infer/infer/higher_ranked/mod.rs b/src/librustc_infer/infer/higher_ranked/mod.rs index b6251e34008a3..ea19dff7db125 100644 --- a/src/librustc_infer/infer/higher_ranked/mod.rs +++ b/src/librustc_infer/infer/higher_ranked/mod.rs @@ -11,8 +11,8 @@ use rustc_middle::ty::{self, Binder, TypeFoldable}; impl<'a, 'tcx> CombineFields<'a, 'tcx> { pub fn higher_ranked_sub( &mut self, - a: &Binder, - b: &Binder, + a: Binder, + b: Binder, a_is_expected: bool, ) -> RelateResult<'tcx, Binder> where @@ -33,20 +33,20 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> { self.infcx.commit_if_ok(|_| { // First, we instantiate each bound region in the supertype with a // fresh placeholder region. - let (b_prime, _) = self.infcx.replace_bound_vars_with_placeholders(b); + let (b_prime, _) = self.infcx.replace_bound_vars_with_placeholders(&b); // Next, we instantiate each bound region in the subtype // with a fresh region variable. These region variables -- // but no other pre-existing region variables -- can name // the placeholders. let (a_prime, _) = - self.infcx.replace_bound_vars_with_fresh_vars(span, HigherRankedType, a); + self.infcx.replace_bound_vars_with_fresh_vars(span, HigherRankedType, &a); debug!("a_prime={:?}", a_prime); debug!("b_prime={:?}", b_prime); // Compare types now that bound regions have been replaced. - let result = self.sub(a_is_expected).relate(&a_prime, &b_prime)?; + let result = self.sub(a_is_expected).relate(a_prime, b_prime)?; debug!("higher_ranked_sub: OK result={:?}", result); diff --git a/src/librustc_infer/infer/lub.rs b/src/librustc_infer/infer/lub.rs index a0453db2cb499..3e2ea3d0f8fbf 100644 --- a/src/librustc_infer/infer/lub.rs +++ b/src/librustc_infer/infer/lub.rs @@ -43,8 +43,8 @@ impl TypeRelation<'tcx> for Lub<'combine, 'infcx, 'tcx> { fn relate_with_variance>( &mut self, variance: ty::Variance, - a: &T, - b: &T, + a: T, + b: T, ) -> RelateResult<'tcx, T> { match variance { ty::Invariant => self.fields.equate(self.a_is_expected).relate(a, b), @@ -85,8 +85,8 @@ impl TypeRelation<'tcx> for Lub<'combine, 'infcx, 'tcx> { fn binders( &mut self, - a: &ty::Binder, - b: &ty::Binder, + a: ty::Binder, + b: ty::Binder, ) -> RelateResult<'tcx, ty::Binder> where T: Relate<'tcx>, @@ -97,7 +97,7 @@ impl TypeRelation<'tcx> for Lub<'combine, 'infcx, 'tcx> { // very challenging, switch to invariance. This is obviously // overly conservative but works ok in practice. self.relate_with_variance(ty::Variance::Invariant, a, b)?; - Ok(a.clone()) + Ok(a) } } @@ -118,8 +118,8 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Lub<'combine, 'infcx, fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> { let mut sub = self.fields.sub(self.a_is_expected); - sub.relate(&a, &v)?; - sub.relate(&b, &v)?; + sub.relate(a, v)?; + sub.relate(b, v)?; Ok(()) } } diff --git a/src/librustc_infer/infer/nll_relate/mod.rs b/src/librustc_infer/infer/nll_relate/mod.rs index 2350c28dfaaff..cb1f1c08d88f8 100644 --- a/src/librustc_infer/infer/nll_relate/mod.rs +++ b/src/librustc_infer/infer/nll_relate/mod.rs @@ -161,7 +161,7 @@ where fn create_scope( &mut self, - value: &ty::Binder>, + value: ty::Binder>, universally_quantified: UniversallyQuantified, ) -> BoundRegionScope<'tcx> { let mut scope = BoundRegionScope::default(); @@ -369,7 +369,7 @@ where universe, }; - generalizer.relate(&value, &value) + generalizer.relate(value, value) } } @@ -495,8 +495,8 @@ where fn relate_with_variance>( &mut self, variance: ty::Variance, - a: &T, - b: &T, + a: T, + b: T, ) -> RelateResult<'tcx, T> { debug!("relate_with_variance(variance={:?}, a={:?}, b={:?})", variance, a, b); @@ -613,8 +613,8 @@ where fn binders( &mut self, - a: &ty::Binder, - b: &ty::Binder, + a: ty::Binder, + b: ty::Binder, ) -> RelateResult<'tcx, ty::Binder> where T: Relate<'tcx>, @@ -640,11 +640,10 @@ where debug!("binders({:?}: {:?}, ambient_variance={:?})", a, b, self.ambient_variance); - if !a.skip_binder().has_escaping_bound_vars() && !b.skip_binder().has_escaping_bound_vars() - { + if let (Some(a), Some(b)) = (a.no_bound_vars(), b.no_bound_vars()) { // Fast path for the common case. - self.relate(a.skip_binder(), b.skip_binder())?; - return Ok(a.clone()); + self.relate(a, b)?; + return Ok(ty::Binder::bind(a)); } if self.ambient_covariance() { @@ -839,8 +838,8 @@ where fn relate_with_variance>( &mut self, variance: ty::Variance, - a: &T, - b: &T, + a: T, + b: T, ) -> RelateResult<'tcx, T> { debug!( "TypeGeneralizer::relate_with_variance(variance={:?}, a={:?}, b={:?})", @@ -890,7 +889,7 @@ where match variables.probe(vid) { TypeVariableValue::Known { value: u } => { drop(variables); - self.relate(&u, &u) + self.relate(u, u) } TypeVariableValue::Unknown { universe: _universe } => { if self.ambient_variance == ty::Bivariant { @@ -984,7 +983,7 @@ where let variable_table = &mut inner.const_unification_table(); let var_value = variable_table.probe_value(vid); match var_value.val.known() { - Some(u) => self.relate(&u, &u), + Some(u) => self.relate(u, u), None => { let new_var_id = variable_table.new_key(ConstVarValue { origin: var_value.origin, @@ -1001,8 +1000,8 @@ where fn binders( &mut self, - a: &ty::Binder, - _: &ty::Binder, + a: ty::Binder, + _: ty::Binder, ) -> RelateResult<'tcx, ty::Binder> where T: Relate<'tcx>, diff --git a/src/librustc_infer/infer/sub.rs b/src/librustc_infer/infer/sub.rs index 90962d210b5b4..d190f7e434298 100644 --- a/src/librustc_infer/infer/sub.rs +++ b/src/librustc_infer/infer/sub.rs @@ -62,8 +62,8 @@ impl TypeRelation<'tcx> for Sub<'combine, 'infcx, 'tcx> { fn relate_with_variance>( &mut self, variance: ty::Variance, - a: &T, - b: &T, + a: T, + b: T, ) -> RelateResult<'tcx, T> { match variance { ty::Invariant => self.fields.equate(self.a_is_expected).relate(a, b), @@ -162,8 +162,8 @@ impl TypeRelation<'tcx> for Sub<'combine, 'infcx, 'tcx> { fn binders( &mut self, - a: &ty::Binder, - b: &ty::Binder, + a: ty::Binder, + b: ty::Binder, ) -> RelateResult<'tcx, ty::Binder> where T: Relate<'tcx>, diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 36d2954ac6ef7..d55cbbe19c279 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -911,7 +911,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes { } let sig = cx.tables().node_type(expr.hir_id).fn_sig(cx.tcx); let from = sig.inputs().skip_binder()[0]; - let to = *sig.output().skip_binder(); + let to = sig.output().skip_binder(); return Some((from, to)); } None diff --git a/src/librustc_middle/ich/impls_ty.rs b/src/librustc_middle/ich/impls_ty.rs index ef6247881c0be..8f15c99f951fe 100644 --- a/src/librustc_middle/ich/impls_ty.rs +++ b/src/librustc_middle/ich/impls_ty.rs @@ -123,7 +123,7 @@ where T: HashStable>, { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - self.skip_binder().hash_stable(hcx, hasher); + self.as_ref().skip_binder().hash_stable(hcx, hasher); } } diff --git a/src/librustc_middle/lib.rs b/src/librustc_middle/lib.rs index 676346fbebdd1..96b8ca27183ed 100644 --- a/src/librustc_middle/lib.rs +++ b/src/librustc_middle/lib.rs @@ -42,7 +42,7 @@ #![feature(or_patterns)] #![feature(range_is_empty)] #![feature(min_specialization)] -#![feature(track_caller)] +#![cfg_attr(bootstrap, feature(track_caller))] #![feature(trusted_len)] #![feature(stmt_expr_attributes)] #![feature(test)] diff --git a/src/librustc_middle/mir/mod.rs b/src/librustc_middle/mir/mod.rs index 0ed0d9050078c..ae59f8c542d8c 100644 --- a/src/librustc_middle/mir/mod.rs +++ b/src/librustc_middle/mir/mod.rs @@ -19,7 +19,6 @@ use rustc_target::abi::VariantIdx; use polonius_engine::Atom; pub use rustc_ast::ast::Mutability; -use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::graph::dominators::{dominators, Dominators}; use rustc_data_structures::graph::{self, GraphSuccessors}; @@ -45,6 +44,8 @@ pub mod mono; mod predecessors; mod query; pub mod tcx; +pub mod terminator; +pub use terminator::*; pub mod traversal; mod type_foldable; pub mod visit; @@ -1046,191 +1047,6 @@ pub struct BasicBlockData<'tcx> { pub is_cleanup: bool, } -#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] -pub struct Terminator<'tcx> { - pub source_info: SourceInfo, - pub kind: TerminatorKind<'tcx>, -} - -#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, PartialEq)] -pub enum TerminatorKind<'tcx> { - /// Block should have one successor in the graph; we jump there. - Goto { target: BasicBlock }, - - /// Operand evaluates to an integer; jump depending on its value - /// to one of the targets, and otherwise fallback to `otherwise`. - SwitchInt { - /// The discriminant value being tested. - discr: Operand<'tcx>, - - /// The type of value being tested. - /// This is always the same as the type of `discr`. - /// FIXME: remove this redundant information. Currently, it is relied on by pretty-printing. - switch_ty: Ty<'tcx>, - - /// Possible values. The locations to branch to in each case - /// are found in the corresponding indices from the `targets` vector. - values: Cow<'tcx, [u128]>, - - /// Possible branch sites. The last element of this vector is used - /// for the otherwise branch, so targets.len() == values.len() + 1 - /// should hold. - // - // This invariant is quite non-obvious and also could be improved. - // One way to make this invariant is to have something like this instead: - // - // branches: Vec<(ConstInt, BasicBlock)>, - // otherwise: Option // exhaustive if None - // - // However we’ve decided to keep this as-is until we figure a case - // where some other approach seems to be strictly better than other. - targets: Vec, - }, - - /// Indicates that the landing pad is finished and unwinding should - /// continue. Emitted by `build::scope::diverge_cleanup`. - Resume, - - /// Indicates that the landing pad is finished and that the process - /// should abort. Used to prevent unwinding for foreign items. - Abort, - - /// Indicates a normal return. The return place should have - /// been filled in before this executes. This can occur multiple times - /// in different basic blocks. - Return, - - /// Indicates a terminator that can never be reached. - Unreachable, - - /// Drop the `Place`. - Drop { place: Place<'tcx>, target: BasicBlock, unwind: Option }, - - /// Drop the `Place` and assign the new value over it. This ensures - /// that the assignment to `P` occurs *even if* the destructor for - /// place unwinds. Its semantics are best explained by the - /// elaboration: - /// - /// ``` - /// BB0 { - /// DropAndReplace(P <- V, goto BB1, unwind BB2) - /// } - /// ``` - /// - /// becomes - /// - /// ``` - /// BB0 { - /// Drop(P, goto BB1, unwind BB2) - /// } - /// BB1 { - /// // P is now uninitialized - /// P <- V - /// } - /// BB2 { - /// // P is now uninitialized -- its dtor panicked - /// P <- V - /// } - /// ``` - DropAndReplace { - place: Place<'tcx>, - value: Operand<'tcx>, - target: BasicBlock, - unwind: Option, - }, - - /// Block ends with a call of a converging function. - Call { - /// The function that’s being called. - func: Operand<'tcx>, - /// Arguments the function is called with. - /// These are owned by the callee, which is free to modify them. - /// This allows the memory occupied by "by-value" arguments to be - /// reused across function calls without duplicating the contents. - args: Vec>, - /// Destination for the return value. If some, the call is converging. - destination: Option<(Place<'tcx>, BasicBlock)>, - /// Cleanups to be done if the call unwinds. - cleanup: Option, - /// `true` if this is from a call in HIR rather than from an overloaded - /// operator. True for overloaded function call. - from_hir_call: bool, - /// This `Span` is the span of the function, without the dot and receiver - /// (e.g. `foo(a, b)` in `x.foo(a, b)` - fn_span: Span, - }, - - /// Jump to the target if the condition has the expected value, - /// otherwise panic with a message and a cleanup target. - Assert { - cond: Operand<'tcx>, - expected: bool, - msg: AssertMessage<'tcx>, - target: BasicBlock, - cleanup: Option, - }, - - /// A suspend point. - Yield { - /// The value to return. - value: Operand<'tcx>, - /// Where to resume to. - resume: BasicBlock, - /// The place to store the resume argument in. - resume_arg: Place<'tcx>, - /// Cleanup to be done if the generator is dropped at this suspend point. - drop: Option, - }, - - /// Indicates the end of the dropping of a generator. - GeneratorDrop, - - /// A block where control flow only ever takes one real path, but borrowck - /// needs to be more conservative. - FalseEdge { - /// The target normal control flow will take. - real_target: BasicBlock, - /// A block control flow could conceptually jump to, but won't in - /// practice. - imaginary_target: BasicBlock, - }, - /// A terminator for blocks that only take one path in reality, but where we - /// reserve the right to unwind in borrowck, even if it won't happen in practice. - /// This can arise in infinite loops with no function calls for example. - FalseUnwind { - /// The target normal control flow will take. - real_target: BasicBlock, - /// The imaginary cleanup block link. This particular path will never be taken - /// in practice, but in order to avoid fragility we want to always - /// consider it in borrowck. We don't want to accept programs which - /// pass borrowck only when `panic=abort` or some assertions are disabled - /// due to release vs. debug mode builds. This needs to be an `Option` because - /// of the `remove_noop_landing_pads` and `no_landing_pads` passes. - unwind: Option, - }, - - /// Block ends with an inline assembly block. This is a terminator since - /// inline assembly is allowed to diverge. - InlineAsm { - /// The template for the inline assembly, with placeholders. - template: &'tcx [InlineAsmTemplatePiece], - - /// The operands for the inline assembly, as `Operand`s or `Place`s. - operands: Vec>, - - /// Miscellaneous options for the inline assembly. - options: InlineAsmOptions, - - /// Source spans for each line of the inline assembly code. These are - /// used to map assembler errors back to the line in the source code. - line_spans: &'tcx [Span], - - /// Destination block after the inline assembly returns, unless it is - /// diverging (InlineAsmOptions::NORETURN). - destination: Option, - }, -} - /// Information about an assertion failure. #[derive(Clone, RustcEncodable, RustcDecodable, HashStable, PartialEq)] pub enum AssertKind { @@ -1279,149 +1095,6 @@ pub type Successors<'a> = pub type SuccessorsMut<'a> = iter::Chain, slice::IterMut<'a, BasicBlock>>; -impl<'tcx> Terminator<'tcx> { - pub fn successors(&self) -> Successors<'_> { - self.kind.successors() - } - - pub fn successors_mut(&mut self) -> SuccessorsMut<'_> { - self.kind.successors_mut() - } - - pub fn unwind(&self) -> Option<&Option> { - self.kind.unwind() - } - - pub fn unwind_mut(&mut self) -> Option<&mut Option> { - self.kind.unwind_mut() - } -} - -impl<'tcx> TerminatorKind<'tcx> { - pub fn if_( - tcx: TyCtxt<'tcx>, - cond: Operand<'tcx>, - t: BasicBlock, - f: BasicBlock, - ) -> TerminatorKind<'tcx> { - static BOOL_SWITCH_FALSE: &[u128] = &[0]; - TerminatorKind::SwitchInt { - discr: cond, - switch_ty: tcx.types.bool, - values: From::from(BOOL_SWITCH_FALSE), - targets: vec![f, t], - } - } - - pub fn successors(&self) -> Successors<'_> { - use self::TerminatorKind::*; - match *self { - Resume - | Abort - | GeneratorDrop - | Return - | Unreachable - | Call { destination: None, cleanup: None, .. } - | InlineAsm { destination: None, .. } => None.into_iter().chain(&[]), - Goto { target: ref t } - | Call { destination: None, cleanup: Some(ref t), .. } - | Call { destination: Some((_, ref t)), cleanup: None, .. } - | Yield { resume: ref t, drop: None, .. } - | DropAndReplace { target: ref t, unwind: None, .. } - | Drop { target: ref t, unwind: None, .. } - | Assert { target: ref t, cleanup: None, .. } - | FalseUnwind { real_target: ref t, unwind: None } - | InlineAsm { destination: Some(ref t), .. } => Some(t).into_iter().chain(&[]), - Call { destination: Some((_, ref t)), cleanup: Some(ref u), .. } - | Yield { resume: ref t, drop: Some(ref u), .. } - | DropAndReplace { target: ref t, unwind: Some(ref u), .. } - | Drop { target: ref t, unwind: Some(ref u), .. } - | Assert { target: ref t, cleanup: Some(ref u), .. } - | FalseUnwind { real_target: ref t, unwind: Some(ref u) } => { - Some(t).into_iter().chain(slice::from_ref(u)) - } - SwitchInt { ref targets, .. } => None.into_iter().chain(&targets[..]), - FalseEdge { ref real_target, ref imaginary_target } => { - Some(real_target).into_iter().chain(slice::from_ref(imaginary_target)) - } - } - } - - pub fn successors_mut(&mut self) -> SuccessorsMut<'_> { - use self::TerminatorKind::*; - match *self { - Resume - | Abort - | GeneratorDrop - | Return - | Unreachable - | Call { destination: None, cleanup: None, .. } - | InlineAsm { destination: None, .. } => None.into_iter().chain(&mut []), - Goto { target: ref mut t } - | Call { destination: None, cleanup: Some(ref mut t), .. } - | Call { destination: Some((_, ref mut t)), cleanup: None, .. } - | Yield { resume: ref mut t, drop: None, .. } - | DropAndReplace { target: ref mut t, unwind: None, .. } - | Drop { target: ref mut t, unwind: None, .. } - | Assert { target: ref mut t, cleanup: None, .. } - | FalseUnwind { real_target: ref mut t, unwind: None } - | InlineAsm { destination: Some(ref mut t), .. } => Some(t).into_iter().chain(&mut []), - Call { destination: Some((_, ref mut t)), cleanup: Some(ref mut u), .. } - | Yield { resume: ref mut t, drop: Some(ref mut u), .. } - | DropAndReplace { target: ref mut t, unwind: Some(ref mut u), .. } - | Drop { target: ref mut t, unwind: Some(ref mut u), .. } - | Assert { target: ref mut t, cleanup: Some(ref mut u), .. } - | FalseUnwind { real_target: ref mut t, unwind: Some(ref mut u) } => { - Some(t).into_iter().chain(slice::from_mut(u)) - } - SwitchInt { ref mut targets, .. } => None.into_iter().chain(&mut targets[..]), - FalseEdge { ref mut real_target, ref mut imaginary_target } => { - Some(real_target).into_iter().chain(slice::from_mut(imaginary_target)) - } - } - } - - pub fn unwind(&self) -> Option<&Option> { - match *self { - TerminatorKind::Goto { .. } - | TerminatorKind::Resume - | TerminatorKind::Abort - | TerminatorKind::Return - | TerminatorKind::Unreachable - | TerminatorKind::GeneratorDrop - | TerminatorKind::Yield { .. } - | TerminatorKind::SwitchInt { .. } - | TerminatorKind::FalseEdge { .. } - | TerminatorKind::InlineAsm { .. } => None, - TerminatorKind::Call { cleanup: ref unwind, .. } - | TerminatorKind::Assert { cleanup: ref unwind, .. } - | TerminatorKind::DropAndReplace { ref unwind, .. } - | TerminatorKind::Drop { ref unwind, .. } - | TerminatorKind::FalseUnwind { ref unwind, .. } => Some(unwind), - } - } - - pub fn unwind_mut(&mut self) -> Option<&mut Option> { - match *self { - TerminatorKind::Goto { .. } - | TerminatorKind::Resume - | TerminatorKind::Abort - | TerminatorKind::Return - | TerminatorKind::Unreachable - | TerminatorKind::GeneratorDrop - | TerminatorKind::Yield { .. } - | TerminatorKind::SwitchInt { .. } - | TerminatorKind::FalseEdge { .. } - | TerminatorKind::InlineAsm { .. } => None, - TerminatorKind::Call { cleanup: ref mut unwind, .. } - | TerminatorKind::Assert { cleanup: ref mut unwind, .. } - | TerminatorKind::DropAndReplace { ref mut unwind, .. } - | TerminatorKind::Drop { ref mut unwind, .. } - | TerminatorKind::FalseUnwind { ref mut unwind, .. } => Some(unwind), - } - } -} - impl<'tcx> BasicBlockData<'tcx> { pub fn new(terminator: Option>) -> BasicBlockData<'tcx> { BasicBlockData { statements: vec![], terminator, is_cleanup: false } @@ -1628,169 +1301,6 @@ impl fmt::Debug for AssertKind { } } -impl<'tcx> Debug for TerminatorKind<'tcx> { - fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { - self.fmt_head(fmt)?; - let successor_count = self.successors().count(); - let labels = self.fmt_successor_labels(); - assert_eq!(successor_count, labels.len()); - - match successor_count { - 0 => Ok(()), - - 1 => write!(fmt, " -> {:?}", self.successors().next().unwrap()), - - _ => { - write!(fmt, " -> [")?; - for (i, target) in self.successors().enumerate() { - if i > 0 { - write!(fmt, ", ")?; - } - write!(fmt, "{}: {:?}", labels[i], target)?; - } - write!(fmt, "]") - } - } - } -} - -impl<'tcx> TerminatorKind<'tcx> { - /// Writes the "head" part of the terminator; that is, its name and the data it uses to pick the - /// successor basic block, if any. The only information not included is the list of possible - /// successors, which may be rendered differently between the text and the graphviz format. - pub fn fmt_head(&self, fmt: &mut W) -> fmt::Result { - use self::TerminatorKind::*; - match self { - Goto { .. } => write!(fmt, "goto"), - SwitchInt { discr, .. } => write!(fmt, "switchInt({:?})", discr), - Return => write!(fmt, "return"), - GeneratorDrop => write!(fmt, "generator_drop"), - Resume => write!(fmt, "resume"), - Abort => write!(fmt, "abort"), - Yield { value, resume_arg, .. } => write!(fmt, "{:?} = yield({:?})", resume_arg, value), - Unreachable => write!(fmt, "unreachable"), - Drop { place, .. } => write!(fmt, "drop({:?})", place), - DropAndReplace { place, value, .. } => { - write!(fmt, "replace({:?} <- {:?})", place, value) - } - Call { func, args, destination, .. } => { - if let Some((destination, _)) = destination { - write!(fmt, "{:?} = ", destination)?; - } - write!(fmt, "{:?}(", func)?; - for (index, arg) in args.iter().enumerate() { - if index > 0 { - write!(fmt, ", ")?; - } - write!(fmt, "{:?}", arg)?; - } - write!(fmt, ")") - } - Assert { cond, expected, msg, .. } => { - write!(fmt, "assert(")?; - if !expected { - write!(fmt, "!")?; - } - write!(fmt, "{:?}, ", cond)?; - msg.fmt_assert_args(fmt)?; - write!(fmt, ")") - } - FalseEdge { .. } => write!(fmt, "falseEdge"), - FalseUnwind { .. } => write!(fmt, "falseUnwind"), - InlineAsm { template, ref operands, options, .. } => { - write!(fmt, "asm!(\"{}\"", InlineAsmTemplatePiece::to_string(template))?; - for op in operands { - write!(fmt, ", ")?; - let print_late = |&late| if late { "late" } else { "" }; - match op { - InlineAsmOperand::In { reg, value } => { - write!(fmt, "in({}) {:?}", reg, value)?; - } - InlineAsmOperand::Out { reg, late, place: Some(place) } => { - write!(fmt, "{}out({}) {:?}", print_late(late), reg, place)?; - } - InlineAsmOperand::Out { reg, late, place: None } => { - write!(fmt, "{}out({}) _", print_late(late), reg)?; - } - InlineAsmOperand::InOut { - reg, - late, - in_value, - out_place: Some(out_place), - } => { - write!( - fmt, - "in{}out({}) {:?} => {:?}", - print_late(late), - reg, - in_value, - out_place - )?; - } - InlineAsmOperand::InOut { reg, late, in_value, out_place: None } => { - write!(fmt, "in{}out({}) {:?} => _", print_late(late), reg, in_value)?; - } - InlineAsmOperand::Const { value } => { - write!(fmt, "const {:?}", value)?; - } - InlineAsmOperand::SymFn { value } => { - write!(fmt, "sym_fn {:?}", value)?; - } - InlineAsmOperand::SymStatic { def_id } => { - write!(fmt, "sym_static {:?}", def_id)?; - } - } - } - write!(fmt, ", options({:?}))", options) - } - } - } - - /// Returns the list of labels for the edges to the successor basic blocks. - pub fn fmt_successor_labels(&self) -> Vec> { - use self::TerminatorKind::*; - match *self { - Return | Resume | Abort | Unreachable | GeneratorDrop => vec![], - Goto { .. } => vec!["".into()], - SwitchInt { ref values, switch_ty, .. } => ty::tls::with(|tcx| { - let param_env = ty::ParamEnv::empty(); - let switch_ty = tcx.lift(&switch_ty).unwrap(); - let size = tcx.layout_of(param_env.and(switch_ty)).unwrap().size; - values - .iter() - .map(|&u| { - ty::Const::from_scalar(tcx, Scalar::from_uint(u, size), switch_ty) - .to_string() - .into() - }) - .chain(iter::once("otherwise".into())) - .collect() - }), - Call { destination: Some(_), cleanup: Some(_), .. } => { - vec!["return".into(), "unwind".into()] - } - Call { destination: Some(_), cleanup: None, .. } => vec!["return".into()], - Call { destination: None, cleanup: Some(_), .. } => vec!["unwind".into()], - Call { destination: None, cleanup: None, .. } => vec![], - Yield { drop: Some(_), .. } => vec!["resume".into(), "drop".into()], - Yield { drop: None, .. } => vec!["resume".into()], - DropAndReplace { unwind: None, .. } | Drop { unwind: None, .. } => { - vec!["return".into()] - } - DropAndReplace { unwind: Some(_), .. } | Drop { unwind: Some(_), .. } => { - vec!["return".into(), "unwind".into()] - } - Assert { cleanup: None, .. } => vec!["".into()], - Assert { .. } => vec!["success".into(), "unwind".into()], - FalseEdge { .. } => vec!["real".into(), "imaginary".into()], - FalseUnwind { unwind: Some(_), .. } => vec!["real".into(), "cleanup".into()], - FalseUnwind { unwind: None, .. } => vec!["real".into()], - InlineAsm { destination: Some(_), .. } => vec!["".into()], - InlineAsm { destination: None, .. } => vec![], - } - } -} - /////////////////////////////////////////////////////////////////////////// // Statements diff --git a/src/librustc_middle/mir/terminator/mod.rs b/src/librustc_middle/mir/terminator/mod.rs new file mode 100644 index 0000000000000..1f5041141d55b --- /dev/null +++ b/src/librustc_middle/mir/terminator/mod.rs @@ -0,0 +1,507 @@ +use crate::mir::interpret::Scalar; +use crate::ty::{self, Ty, TyCtxt}; +use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece}; + +use super::{ + AssertMessage, BasicBlock, InlineAsmOperand, Operand, Place, SourceInfo, Successors, + SuccessorsMut, +}; +pub use rustc_ast::ast::Mutability; +use rustc_macros::HashStable; +use rustc_span::Span; +use std::borrow::Cow; +use std::fmt::{self, Debug, Formatter, Write}; +use std::iter; +use std::slice; + +pub use super::query::*; + +#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, PartialEq)] +pub enum TerminatorKind<'tcx> { + /// Block should have one successor in the graph; we jump there. + Goto { target: BasicBlock }, + + /// Operand evaluates to an integer; jump depending on its value + /// to one of the targets, and otherwise fallback to `otherwise`. + SwitchInt { + /// The discriminant value being tested. + discr: Operand<'tcx>, + + /// The type of value being tested. + /// This is always the same as the type of `discr`. + /// FIXME: remove this redundant information. Currently, it is relied on by pretty-printing. + switch_ty: Ty<'tcx>, + + /// Possible values. The locations to branch to in each case + /// are found in the corresponding indices from the `targets` vector. + values: Cow<'tcx, [u128]>, + + /// Possible branch sites. The last element of this vector is used + /// for the otherwise branch, so targets.len() == values.len() + 1 + /// should hold. + // + // This invariant is quite non-obvious and also could be improved. + // One way to make this invariant is to have something like this instead: + // + // branches: Vec<(ConstInt, BasicBlock)>, + // otherwise: Option // exhaustive if None + // + // However we’ve decided to keep this as-is until we figure a case + // where some other approach seems to be strictly better than other. + targets: Vec, + }, + + /// Indicates that the landing pad is finished and unwinding should + /// continue. Emitted by `build::scope::diverge_cleanup`. + Resume, + + /// Indicates that the landing pad is finished and that the process + /// should abort. Used to prevent unwinding for foreign items. + Abort, + + /// Indicates a normal return. The return place should have + /// been filled in before this executes. This can occur multiple times + /// in different basic blocks. + Return, + + /// Indicates a terminator that can never be reached. + Unreachable, + + /// Drop the `Place`. + Drop { place: Place<'tcx>, target: BasicBlock, unwind: Option }, + + /// Drop the `Place` and assign the new value over it. This ensures + /// that the assignment to `P` occurs *even if* the destructor for + /// place unwinds. Its semantics are best explained by the + /// elaboration: + /// + /// ``` + /// BB0 { + /// DropAndReplace(P <- V, goto BB1, unwind BB2) + /// } + /// ``` + /// + /// becomes + /// + /// ``` + /// BB0 { + /// Drop(P, goto BB1, unwind BB2) + /// } + /// BB1 { + /// // P is now uninitialized + /// P <- V + /// } + /// BB2 { + /// // P is now uninitialized -- its dtor panicked + /// P <- V + /// } + /// ``` + DropAndReplace { + place: Place<'tcx>, + value: Operand<'tcx>, + target: BasicBlock, + unwind: Option, + }, + + /// Block ends with a call of a converging function. + Call { + /// The function that’s being called. + func: Operand<'tcx>, + /// Arguments the function is called with. + /// These are owned by the callee, which is free to modify them. + /// This allows the memory occupied by "by-value" arguments to be + /// reused across function calls without duplicating the contents. + args: Vec>, + /// Destination for the return value. If some, the call is converging. + destination: Option<(Place<'tcx>, BasicBlock)>, + /// Cleanups to be done if the call unwinds. + cleanup: Option, + /// `true` if this is from a call in HIR rather than from an overloaded + /// operator. True for overloaded function call. + from_hir_call: bool, + /// This `Span` is the span of the function, without the dot and receiver + /// (e.g. `foo(a, b)` in `x.foo(a, b)` + fn_span: Span, + }, + + /// Jump to the target if the condition has the expected value, + /// otherwise panic with a message and a cleanup target. + Assert { + cond: Operand<'tcx>, + expected: bool, + msg: AssertMessage<'tcx>, + target: BasicBlock, + cleanup: Option, + }, + + /// A suspend point. + Yield { + /// The value to return. + value: Operand<'tcx>, + /// Where to resume to. + resume: BasicBlock, + /// The place to store the resume argument in. + resume_arg: Place<'tcx>, + /// Cleanup to be done if the generator is dropped at this suspend point. + drop: Option, + }, + + /// Indicates the end of the dropping of a generator. + GeneratorDrop, + + /// A block where control flow only ever takes one real path, but borrowck + /// needs to be more conservative. + FalseEdge { + /// The target normal control flow will take. + real_target: BasicBlock, + /// A block control flow could conceptually jump to, but won't in + /// practice. + imaginary_target: BasicBlock, + }, + /// A terminator for blocks that only take one path in reality, but where we + /// reserve the right to unwind in borrowck, even if it won't happen in practice. + /// This can arise in infinite loops with no function calls for example. + FalseUnwind { + /// The target normal control flow will take. + real_target: BasicBlock, + /// The imaginary cleanup block link. This particular path will never be taken + /// in practice, but in order to avoid fragility we want to always + /// consider it in borrowck. We don't want to accept programs which + /// pass borrowck only when `panic=abort` or some assertions are disabled + /// due to release vs. debug mode builds. This needs to be an `Option` because + /// of the `remove_noop_landing_pads` and `no_landing_pads` passes. + unwind: Option, + }, + + /// Block ends with an inline assembly block. This is a terminator since + /// inline assembly is allowed to diverge. + InlineAsm { + /// The template for the inline assembly, with placeholders. + template: &'tcx [InlineAsmTemplatePiece], + + /// The operands for the inline assembly, as `Operand`s or `Place`s. + operands: Vec>, + + /// Miscellaneous options for the inline assembly. + options: InlineAsmOptions, + + /// Source spans for each line of the inline assembly code. These are + /// used to map assembler errors back to the line in the source code. + line_spans: &'tcx [Span], + + /// Destination block after the inline assembly returns, unless it is + /// diverging (InlineAsmOptions::NORETURN). + destination: Option, + }, +} +#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] +pub struct Terminator<'tcx> { + pub source_info: SourceInfo, + pub kind: TerminatorKind<'tcx>, +} + +impl<'tcx> Terminator<'tcx> { + pub fn successors(&self) -> Successors<'_> { + self.kind.successors() + } + + pub fn successors_mut(&mut self) -> SuccessorsMut<'_> { + self.kind.successors_mut() + } + + pub fn unwind(&self) -> Option<&Option> { + self.kind.unwind() + } + + pub fn unwind_mut(&mut self) -> Option<&mut Option> { + self.kind.unwind_mut() + } +} + +impl<'tcx> TerminatorKind<'tcx> { + pub fn if_( + tcx: TyCtxt<'tcx>, + cond: Operand<'tcx>, + t: BasicBlock, + f: BasicBlock, + ) -> TerminatorKind<'tcx> { + static BOOL_SWITCH_FALSE: &[u128] = &[0]; + TerminatorKind::SwitchInt { + discr: cond, + switch_ty: tcx.types.bool, + values: From::from(BOOL_SWITCH_FALSE), + targets: vec![f, t], + } + } + + pub fn successors(&self) -> Successors<'_> { + use self::TerminatorKind::*; + match *self { + Resume + | Abort + | GeneratorDrop + | Return + | Unreachable + | Call { destination: None, cleanup: None, .. } + | InlineAsm { destination: None, .. } => None.into_iter().chain(&[]), + Goto { target: ref t } + | Call { destination: None, cleanup: Some(ref t), .. } + | Call { destination: Some((_, ref t)), cleanup: None, .. } + | Yield { resume: ref t, drop: None, .. } + | DropAndReplace { target: ref t, unwind: None, .. } + | Drop { target: ref t, unwind: None, .. } + | Assert { target: ref t, cleanup: None, .. } + | FalseUnwind { real_target: ref t, unwind: None } + | InlineAsm { destination: Some(ref t), .. } => Some(t).into_iter().chain(&[]), + Call { destination: Some((_, ref t)), cleanup: Some(ref u), .. } + | Yield { resume: ref t, drop: Some(ref u), .. } + | DropAndReplace { target: ref t, unwind: Some(ref u), .. } + | Drop { target: ref t, unwind: Some(ref u), .. } + | Assert { target: ref t, cleanup: Some(ref u), .. } + | FalseUnwind { real_target: ref t, unwind: Some(ref u) } => { + Some(t).into_iter().chain(slice::from_ref(u)) + } + SwitchInt { ref targets, .. } => None.into_iter().chain(&targets[..]), + FalseEdge { ref real_target, ref imaginary_target } => { + Some(real_target).into_iter().chain(slice::from_ref(imaginary_target)) + } + } + } + + pub fn successors_mut(&mut self) -> SuccessorsMut<'_> { + use self::TerminatorKind::*; + match *self { + Resume + | Abort + | GeneratorDrop + | Return + | Unreachable + | Call { destination: None, cleanup: None, .. } + | InlineAsm { destination: None, .. } => None.into_iter().chain(&mut []), + Goto { target: ref mut t } + | Call { destination: None, cleanup: Some(ref mut t), .. } + | Call { destination: Some((_, ref mut t)), cleanup: None, .. } + | Yield { resume: ref mut t, drop: None, .. } + | DropAndReplace { target: ref mut t, unwind: None, .. } + | Drop { target: ref mut t, unwind: None, .. } + | Assert { target: ref mut t, cleanup: None, .. } + | FalseUnwind { real_target: ref mut t, unwind: None } + | InlineAsm { destination: Some(ref mut t), .. } => Some(t).into_iter().chain(&mut []), + Call { destination: Some((_, ref mut t)), cleanup: Some(ref mut u), .. } + | Yield { resume: ref mut t, drop: Some(ref mut u), .. } + | DropAndReplace { target: ref mut t, unwind: Some(ref mut u), .. } + | Drop { target: ref mut t, unwind: Some(ref mut u), .. } + | Assert { target: ref mut t, cleanup: Some(ref mut u), .. } + | FalseUnwind { real_target: ref mut t, unwind: Some(ref mut u) } => { + Some(t).into_iter().chain(slice::from_mut(u)) + } + SwitchInt { ref mut targets, .. } => None.into_iter().chain(&mut targets[..]), + FalseEdge { ref mut real_target, ref mut imaginary_target } => { + Some(real_target).into_iter().chain(slice::from_mut(imaginary_target)) + } + } + } + + pub fn unwind(&self) -> Option<&Option> { + match *self { + TerminatorKind::Goto { .. } + | TerminatorKind::Resume + | TerminatorKind::Abort + | TerminatorKind::Return + | TerminatorKind::Unreachable + | TerminatorKind::GeneratorDrop + | TerminatorKind::Yield { .. } + | TerminatorKind::SwitchInt { .. } + | TerminatorKind::FalseEdge { .. } + | TerminatorKind::InlineAsm { .. } => None, + TerminatorKind::Call { cleanup: ref unwind, .. } + | TerminatorKind::Assert { cleanup: ref unwind, .. } + | TerminatorKind::DropAndReplace { ref unwind, .. } + | TerminatorKind::Drop { ref unwind, .. } + | TerminatorKind::FalseUnwind { ref unwind, .. } => Some(unwind), + } + } + + pub fn unwind_mut(&mut self) -> Option<&mut Option> { + match *self { + TerminatorKind::Goto { .. } + | TerminatorKind::Resume + | TerminatorKind::Abort + | TerminatorKind::Return + | TerminatorKind::Unreachable + | TerminatorKind::GeneratorDrop + | TerminatorKind::Yield { .. } + | TerminatorKind::SwitchInt { .. } + | TerminatorKind::FalseEdge { .. } + | TerminatorKind::InlineAsm { .. } => None, + TerminatorKind::Call { cleanup: ref mut unwind, .. } + | TerminatorKind::Assert { cleanup: ref mut unwind, .. } + | TerminatorKind::DropAndReplace { ref mut unwind, .. } + | TerminatorKind::Drop { ref mut unwind, .. } + | TerminatorKind::FalseUnwind { ref mut unwind, .. } => Some(unwind), + } + } +} + +impl<'tcx> Debug for TerminatorKind<'tcx> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { + self.fmt_head(fmt)?; + let successor_count = self.successors().count(); + let labels = self.fmt_successor_labels(); + assert_eq!(successor_count, labels.len()); + + match successor_count { + 0 => Ok(()), + + 1 => write!(fmt, " -> {:?}", self.successors().next().unwrap()), + + _ => { + write!(fmt, " -> [")?; + for (i, target) in self.successors().enumerate() { + if i > 0 { + write!(fmt, ", ")?; + } + write!(fmt, "{}: {:?}", labels[i], target)?; + } + write!(fmt, "]") + } + } + } +} + +impl<'tcx> TerminatorKind<'tcx> { + /// Writes the "head" part of the terminator; that is, its name and the data it uses to pick the + /// successor basic block, if any. The only information not included is the list of possible + /// successors, which may be rendered differently between the text and the graphviz format. + pub fn fmt_head(&self, fmt: &mut W) -> fmt::Result { + use self::TerminatorKind::*; + match self { + Goto { .. } => write!(fmt, "goto"), + SwitchInt { discr, .. } => write!(fmt, "switchInt({:?})", discr), + Return => write!(fmt, "return"), + GeneratorDrop => write!(fmt, "generator_drop"), + Resume => write!(fmt, "resume"), + Abort => write!(fmt, "abort"), + Yield { value, resume_arg, .. } => write!(fmt, "{:?} = yield({:?})", resume_arg, value), + Unreachable => write!(fmt, "unreachable"), + Drop { place, .. } => write!(fmt, "drop({:?})", place), + DropAndReplace { place, value, .. } => { + write!(fmt, "replace({:?} <- {:?})", place, value) + } + Call { func, args, destination, .. } => { + if let Some((destination, _)) = destination { + write!(fmt, "{:?} = ", destination)?; + } + write!(fmt, "{:?}(", func)?; + for (index, arg) in args.iter().enumerate() { + if index > 0 { + write!(fmt, ", ")?; + } + write!(fmt, "{:?}", arg)?; + } + write!(fmt, ")") + } + Assert { cond, expected, msg, .. } => { + write!(fmt, "assert(")?; + if !expected { + write!(fmt, "!")?; + } + write!(fmt, "{:?}, ", cond)?; + msg.fmt_assert_args(fmt)?; + write!(fmt, ")") + } + FalseEdge { .. } => write!(fmt, "falseEdge"), + FalseUnwind { .. } => write!(fmt, "falseUnwind"), + InlineAsm { template, ref operands, options, .. } => { + write!(fmt, "asm!(\"{}\"", InlineAsmTemplatePiece::to_string(template))?; + for op in operands { + write!(fmt, ", ")?; + let print_late = |&late| if late { "late" } else { "" }; + match op { + InlineAsmOperand::In { reg, value } => { + write!(fmt, "in({}) {:?}", reg, value)?; + } + InlineAsmOperand::Out { reg, late, place: Some(place) } => { + write!(fmt, "{}out({}) {:?}", print_late(late), reg, place)?; + } + InlineAsmOperand::Out { reg, late, place: None } => { + write!(fmt, "{}out({}) _", print_late(late), reg)?; + } + InlineAsmOperand::InOut { + reg, + late, + in_value, + out_place: Some(out_place), + } => { + write!( + fmt, + "in{}out({}) {:?} => {:?}", + print_late(late), + reg, + in_value, + out_place + )?; + } + InlineAsmOperand::InOut { reg, late, in_value, out_place: None } => { + write!(fmt, "in{}out({}) {:?} => _", print_late(late), reg, in_value)?; + } + InlineAsmOperand::Const { value } => { + write!(fmt, "const {:?}", value)?; + } + InlineAsmOperand::SymFn { value } => { + write!(fmt, "sym_fn {:?}", value)?; + } + InlineAsmOperand::SymStatic { def_id } => { + write!(fmt, "sym_static {:?}", def_id)?; + } + } + } + write!(fmt, ", options({:?}))", options) + } + } + } + + /// Returns the list of labels for the edges to the successor basic blocks. + pub fn fmt_successor_labels(&self) -> Vec> { + use self::TerminatorKind::*; + match *self { + Return | Resume | Abort | Unreachable | GeneratorDrop => vec![], + Goto { .. } => vec!["".into()], + SwitchInt { ref values, switch_ty, .. } => ty::tls::with(|tcx| { + let param_env = ty::ParamEnv::empty(); + let switch_ty = tcx.lift(&switch_ty).unwrap(); + let size = tcx.layout_of(param_env.and(switch_ty)).unwrap().size; + values + .iter() + .map(|&u| { + ty::Const::from_scalar(tcx, Scalar::from_uint(u, size), switch_ty) + .to_string() + .into() + }) + .chain(iter::once("otherwise".into())) + .collect() + }), + Call { destination: Some(_), cleanup: Some(_), .. } => { + vec!["return".into(), "unwind".into()] + } + Call { destination: Some(_), cleanup: None, .. } => vec!["return".into()], + Call { destination: None, cleanup: Some(_), .. } => vec!["unwind".into()], + Call { destination: None, cleanup: None, .. } => vec![], + Yield { drop: Some(_), .. } => vec!["resume".into(), "drop".into()], + Yield { drop: None, .. } => vec!["resume".into()], + DropAndReplace { unwind: None, .. } | Drop { unwind: None, .. } => { + vec!["return".into()] + } + DropAndReplace { unwind: Some(_), .. } | Drop { unwind: Some(_), .. } => { + vec!["return".into(), "unwind".into()] + } + Assert { cleanup: None, .. } => vec!["".into()], + Assert { .. } => vec!["success".into(), "unwind".into()], + FalseEdge { .. } => vec!["real".into(), "imaginary".into()], + FalseUnwind { unwind: Some(_), .. } => vec!["real".into(), "cleanup".into()], + FalseUnwind { unwind: None, .. } => vec!["real".into()], + InlineAsm { destination: Some(_), .. } => vec!["".into()], + InlineAsm { destination: None, .. } => vec![], + } + } +} diff --git a/src/librustc_middle/ty/_match.rs b/src/librustc_middle/ty/_match.rs index db9229ae3d214..4693a2f66fb4c 100644 --- a/src/librustc_middle/ty/_match.rs +++ b/src/librustc_middle/ty/_match.rs @@ -46,8 +46,8 @@ impl TypeRelation<'tcx> for Match<'tcx> { fn relate_with_variance>( &mut self, _: ty::Variance, - a: &T, - b: &T, + a: T, + b: T, ) -> RelateResult<'tcx, T> { self.relate(a, b) } @@ -112,8 +112,8 @@ impl TypeRelation<'tcx> for Match<'tcx> { fn binders( &mut self, - a: &ty::Binder, - b: &ty::Binder, + a: ty::Binder, + b: ty::Binder, ) -> RelateResult<'tcx, ty::Binder> where T: Relate<'tcx>, diff --git a/src/librustc_middle/ty/error.rs b/src/librustc_middle/ty/error.rs index 6113359ca93a7..30ff5a2d9ebdf 100644 --- a/src/librustc_middle/ty/error.rs +++ b/src/librustc_middle/ty/error.rs @@ -57,7 +57,6 @@ pub enum TypeError<'tcx> { /// type). CyclicTy(Ty<'tcx>), ProjectionMismatched(ExpectedFound), - ProjectionBoundsLength(ExpectedFound), ExistentialMismatch(ExpectedFound<&'tcx ty::List>>), ObjectUnsafeCoercion(DefId), ConstMismatch(ExpectedFound<&'tcx ty::Const<'tcx>>), @@ -174,13 +173,6 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { tcx.def_path_str(values.found) ) }), - ProjectionBoundsLength(ref values) => write!( - f, - "expected {} associated type binding{}, found {}", - values.expected, - pluralize!(values.expected), - values.found - ), ExistentialMismatch(ref values) => report_maybe_different( f, &format!("trait `{}`", values.expected), @@ -216,7 +208,6 @@ impl<'tcx> TypeError<'tcx> { | RegionsPlaceholderMismatch | Traits(_) | ProjectionMismatched(_) - | ProjectionBoundsLength(_) | ExistentialMismatch(_) | ConstMismatch(_) | IntrinsicCast diff --git a/src/librustc_middle/ty/flags.rs b/src/librustc_middle/ty/flags.rs index c782eee938721..0e86fcf53b247 100644 --- a/src/librustc_middle/ty/flags.rs +++ b/src/librustc_middle/ty/flags.rs @@ -88,13 +88,13 @@ impl FlagComputation { self.add_substs(substs); } - &ty::GeneratorWitness(ref ts) => { + &ty::GeneratorWitness(ts) => { let mut computation = FlagComputation::new(); - computation.add_tys(&ts.skip_binder()[..]); + computation.add_tys(ts.skip_binder()); self.add_bound_computation(computation); } - &ty::Closure(_, ref substs) => { + &ty::Closure(_, substs) => { self.add_substs(substs); } @@ -122,7 +122,7 @@ impl FlagComputation { self.add_substs(substs); } - &ty::Projection(ref data) => { + &ty::Projection(data) => { self.add_flags(TypeFlags::HAS_TY_PROJECTION); self.add_projection_ty(data); } @@ -211,7 +211,7 @@ impl FlagComputation { self.add_bound_computation(computation); } - ty::PredicateKind::Projection(projection) => { + &ty::PredicateKind::Projection(projection) => { let mut computation = FlagComputation::new(); let ty::ProjectionPredicate { projection_ty, ty } = projection.skip_binder(); computation.add_projection_ty(projection_ty); @@ -298,7 +298,7 @@ impl FlagComputation { self.add_ty(projection.ty); } - fn add_projection_ty(&mut self, projection_ty: &ty::ProjectionTy<'_>) { + fn add_projection_ty(&mut self, projection_ty: ty::ProjectionTy<'_>) { self.add_substs(projection_ty.substs); } diff --git a/src/librustc_middle/ty/fold.rs b/src/librustc_middle/ty/fold.rs index 2d25c7c6ac983..492f8ce9ef1a9 100644 --- a/src/librustc_middle/ty/fold.rs +++ b/src/librustc_middle/ty/fold.rs @@ -336,7 +336,7 @@ impl<'tcx> TyCtxt<'tcx> { { fn visit_binder>(&mut self, t: &Binder) -> bool { self.outer_index.shift_in(1); - let result = t.skip_binder().visit_with(self); + let result = t.as_ref().skip_binder().visit_with(self); self.outer_index.shift_out(1); result } @@ -558,7 +558,7 @@ impl<'tcx> TyCtxt<'tcx> { let fld_c = |bound_ct, ty| { self.mk_const(ty::Const { val: ty::ConstKind::Bound(ty::INNERMOST, bound_ct), ty }) }; - self.replace_escaping_bound_vars(value.skip_binder(), fld_r, fld_t, fld_c) + self.replace_escaping_bound_vars(value.as_ref().skip_binder(), fld_r, fld_t, fld_c) } /// Replaces all escaping bound vars. The `fld_r` closure replaces escaping @@ -617,7 +617,7 @@ impl<'tcx> TyCtxt<'tcx> { H: FnMut(ty::BoundVar, Ty<'tcx>) -> &'tcx ty::Const<'tcx>, T: TypeFoldable<'tcx>, { - self.replace_escaping_bound_vars(value.skip_binder(), fld_r, fld_t, fld_c) + self.replace_escaping_bound_vars(value.as_ref().skip_binder(), fld_r, fld_t, fld_c) } /// Replaces any late-bound regions bound in `value` with @@ -673,7 +673,7 @@ impl<'tcx> TyCtxt<'tcx> { T: TypeFoldable<'tcx>, { let mut collector = LateBoundRegionsCollector::new(just_constraint); - let result = value.skip_binder().visit_with(&mut collector); + let result = value.as_ref().skip_binder().visit_with(&mut collector); assert!(!result); // should never have stopped early collector.regions } diff --git a/src/librustc_middle/ty/layout.rs b/src/librustc_middle/ty/layout.rs index e4cc96dd83bfb..39b8566e7a873 100644 --- a/src/librustc_middle/ty/layout.rs +++ b/src/librustc_middle/ty/layout.rs @@ -2303,7 +2303,7 @@ impl<'tcx> ty::Instance<'tcx> { let env_ty = tcx.closure_env_ty(def_id, substs).unwrap(); sig.map_bound(|sig| tcx.mk_fn_sig( - iter::once(*env_ty.skip_binder()).chain(sig.inputs().iter().cloned()), + iter::once(env_ty.skip_binder()).chain(sig.inputs().iter().cloned()), sig.output(), sig.c_variadic, sig.unsafety, diff --git a/src/librustc_middle/ty/print/pretty.rs b/src/librustc_middle/ty/print/pretty.rs index 061214249713d..9fa1260f64d74 100644 --- a/src/librustc_middle/ty/print/pretty.rs +++ b/src/librustc_middle/ty/print/pretty.rs @@ -189,7 +189,7 @@ pub trait PrettyPrinter<'tcx>: where T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx>, { - value.skip_binder().print(self) + value.as_ref().skip_binder().print(self) } /// Prints comma-separated elements. diff --git a/src/librustc_middle/ty/relate.rs b/src/librustc_middle/ty/relate.rs index e9a8b9095bf72..cee04ce8c6a83 100644 --- a/src/librustc_middle/ty/relate.rs +++ b/src/librustc_middle/ty/relate.rs @@ -13,7 +13,6 @@ use rustc_hir::def_id::DefId; use rustc_span::DUMMY_SP; use rustc_target::spec::abi; use std::iter; -use std::rc::Rc; pub type RelateResult<'tcx, T> = Result>; @@ -42,7 +41,7 @@ pub trait TypeRelation<'tcx>: Sized { } /// Generic relation routine suitable for most anything. - fn relate>(&mut self, a: &T, b: &T) -> RelateResult<'tcx, T> { + fn relate>(&mut self, a: T, b: T) -> RelateResult<'tcx, T> { Relate::relate(self, a, b) } @@ -68,8 +67,8 @@ pub trait TypeRelation<'tcx>: Sized { fn relate_with_variance>( &mut self, variance: ty::Variance, - a: &T, - b: &T, + a: T, + b: T, ) -> RelateResult<'tcx, T>; // Overridable relations. You shouldn't typically call these @@ -94,18 +93,18 @@ pub trait TypeRelation<'tcx>: Sized { fn binders( &mut self, - a: &ty::Binder, - b: &ty::Binder, + a: ty::Binder, + b: ty::Binder, ) -> RelateResult<'tcx, ty::Binder> where T: Relate<'tcx>; } -pub trait Relate<'tcx>: TypeFoldable<'tcx> { +pub trait Relate<'tcx>: TypeFoldable<'tcx> + Copy { fn relate>( relation: &mut R, - a: &Self, - b: &Self, + a: Self, + b: Self, ) -> RelateResult<'tcx, Self>; } @@ -115,8 +114,8 @@ pub trait Relate<'tcx>: TypeFoldable<'tcx> { impl<'tcx> Relate<'tcx> for ty::TypeAndMut<'tcx> { fn relate>( relation: &mut R, - a: &ty::TypeAndMut<'tcx>, - b: &ty::TypeAndMut<'tcx>, + a: ty::TypeAndMut<'tcx>, + b: ty::TypeAndMut<'tcx>, ) -> RelateResult<'tcx, ty::TypeAndMut<'tcx>> { debug!("{}.mts({:?}, {:?})", relation.tag(), a, b); if a.mutbl != b.mutbl { @@ -127,7 +126,7 @@ impl<'tcx> Relate<'tcx> for ty::TypeAndMut<'tcx> { ast::Mutability::Not => ty::Covariant, ast::Mutability::Mut => ty::Invariant, }; - let ty = relation.relate_with_variance(variance, &a.ty, &b.ty)?; + let ty = relation.relate_with_variance(variance, a.ty, b.ty)?; Ok(ty::TypeAndMut { ty, mutbl }) } } @@ -143,7 +142,7 @@ pub fn relate_substs>( let params = a_subst.iter().zip(b_subst).enumerate().map(|(i, (a, b))| { let variance = variances.map_or(ty::Invariant, |v| v[i]); - relation.relate_with_variance(variance, &a, &b) + relation.relate_with_variance(variance, a, b) }); Ok(tcx.mk_substs(params)?) @@ -152,8 +151,8 @@ pub fn relate_substs>( impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> { fn relate>( relation: &mut R, - a: &ty::FnSig<'tcx>, - b: &ty::FnSig<'tcx>, + a: ty::FnSig<'tcx>, + b: ty::FnSig<'tcx>, ) -> RelateResult<'tcx, ty::FnSig<'tcx>> { let tcx = relation.tcx(); @@ -164,8 +163,8 @@ impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> { &b.c_variadic, ))); } - let unsafety = relation.relate(&a.unsafety, &b.unsafety)?; - let abi = relation.relate(&a.abi, &b.abi)?; + let unsafety = relation.relate(a.unsafety, b.unsafety)?; + let abi = relation.relate(a.abi, b.abi)?; if a.inputs().len() != b.inputs().len() { return Err(TypeError::ArgCount); @@ -180,9 +179,9 @@ impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> { .chain(iter::once(((a.output(), b.output()), true))) .map(|((a, b), is_output)| { if is_output { - relation.relate(&a, &b) + relation.relate(a, b) } else { - relation.relate_with_variance(ty::Contravariant, &a, &b) + relation.relate_with_variance(ty::Contravariant, a, b) } }); Ok(ty::FnSig { @@ -197,13 +196,13 @@ impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> { impl<'tcx> Relate<'tcx> for ast::Unsafety { fn relate>( relation: &mut R, - a: &ast::Unsafety, - b: &ast::Unsafety, + a: ast::Unsafety, + b: ast::Unsafety, ) -> RelateResult<'tcx, ast::Unsafety> { if a != b { - Err(TypeError::UnsafetyMismatch(expected_found(relation, a, b))) + Err(TypeError::UnsafetyMismatch(expected_found(relation, &a, &b))) } else { - Ok(*a) + Ok(a) } } } @@ -211,18 +210,18 @@ impl<'tcx> Relate<'tcx> for ast::Unsafety { impl<'tcx> Relate<'tcx> for abi::Abi { fn relate>( relation: &mut R, - a: &abi::Abi, - b: &abi::Abi, + a: abi::Abi, + b: abi::Abi, ) -> RelateResult<'tcx, abi::Abi> { - if a == b { Ok(*a) } else { Err(TypeError::AbiMismatch(expected_found(relation, a, b))) } + if a == b { Ok(a) } else { Err(TypeError::AbiMismatch(expected_found(relation, &a, &b))) } } } impl<'tcx> Relate<'tcx> for ty::ProjectionTy<'tcx> { fn relate>( relation: &mut R, - a: &ty::ProjectionTy<'tcx>, - b: &ty::ProjectionTy<'tcx>, + a: ty::ProjectionTy<'tcx>, + b: ty::ProjectionTy<'tcx>, ) -> RelateResult<'tcx, ty::ProjectionTy<'tcx>> { if a.item_def_id != b.item_def_id { Err(TypeError::ProjectionMismatched(expected_found( @@ -231,7 +230,7 @@ impl<'tcx> Relate<'tcx> for ty::ProjectionTy<'tcx> { &b.item_def_id, ))) } else { - let substs = relation.relate(&a.substs, &b.substs)?; + let substs = relation.relate(a.substs, b.substs)?; Ok(ty::ProjectionTy { item_def_id: a.item_def_id, substs: &substs }) } } @@ -240,8 +239,8 @@ impl<'tcx> Relate<'tcx> for ty::ProjectionTy<'tcx> { impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> { fn relate>( relation: &mut R, - a: &ty::ExistentialProjection<'tcx>, - b: &ty::ExistentialProjection<'tcx>, + a: ty::ExistentialProjection<'tcx>, + b: ty::ExistentialProjection<'tcx>, ) -> RelateResult<'tcx, ty::ExistentialProjection<'tcx>> { if a.item_def_id != b.item_def_id { Err(TypeError::ProjectionMismatched(expected_found( @@ -250,37 +249,18 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> { &b.item_def_id, ))) } else { - let ty = relation.relate_with_variance(ty::Invariant, &a.ty, &b.ty)?; - let substs = relation.relate_with_variance(ty::Invariant, &a.substs, &b.substs)?; + let ty = relation.relate_with_variance(ty::Invariant, a.ty, b.ty)?; + let substs = relation.relate_with_variance(ty::Invariant, a.substs, b.substs)?; Ok(ty::ExistentialProjection { item_def_id: a.item_def_id, substs, ty }) } } } -impl<'tcx> Relate<'tcx> for Vec> { - fn relate>( - relation: &mut R, - a: &Vec>, - b: &Vec>, - ) -> RelateResult<'tcx, Vec>> { - // To be compatible, `a` and `b` must be for precisely the - // same set of traits and item names. We always require that - // projection bounds lists are sorted by trait-def-id and item-name, - // so we can just iterate through the lists pairwise, so long as they are the - // same length. - if a.len() != b.len() { - Err(TypeError::ProjectionBoundsLength(expected_found(relation, &a.len(), &b.len()))) - } else { - a.iter().zip(b).map(|(a, b)| relation.relate(a, b)).collect() - } - } -} - impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> { fn relate>( relation: &mut R, - a: &ty::TraitRef<'tcx>, - b: &ty::TraitRef<'tcx>, + a: ty::TraitRef<'tcx>, + b: ty::TraitRef<'tcx>, ) -> RelateResult<'tcx, ty::TraitRef<'tcx>> { // Different traits cannot be related. if a.def_id != b.def_id { @@ -295,8 +275,8 @@ impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> { impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> { fn relate>( relation: &mut R, - a: &ty::ExistentialTraitRef<'tcx>, - b: &ty::ExistentialTraitRef<'tcx>, + a: ty::ExistentialTraitRef<'tcx>, + b: ty::ExistentialTraitRef<'tcx>, ) -> RelateResult<'tcx, ty::ExistentialTraitRef<'tcx>> { // Different traits cannot be related. if a.def_id != b.def_id { @@ -308,18 +288,18 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> { } } -#[derive(Debug, Clone, TypeFoldable)] +#[derive(Copy, Debug, Clone, TypeFoldable)] struct GeneratorWitness<'tcx>(&'tcx ty::List>); impl<'tcx> Relate<'tcx> for GeneratorWitness<'tcx> { fn relate>( relation: &mut R, - a: &GeneratorWitness<'tcx>, - b: &GeneratorWitness<'tcx>, + a: GeneratorWitness<'tcx>, + b: GeneratorWitness<'tcx>, ) -> RelateResult<'tcx, GeneratorWitness<'tcx>> { assert_eq!(a.0.len(), b.0.len()); let tcx = relation.tcx(); - let types = tcx.mk_type_list(a.0.iter().zip(b.0).map(|(a, b)| relation.relate(&a, &b)))?; + let types = tcx.mk_type_list(a.0.iter().zip(b.0).map(|(a, b)| relation.relate(a, b)))?; Ok(GeneratorWitness(types)) } } @@ -327,8 +307,8 @@ impl<'tcx> Relate<'tcx> for GeneratorWitness<'tcx> { impl<'tcx> Relate<'tcx> for Ty<'tcx> { fn relate>( relation: &mut R, - a: &Ty<'tcx>, - b: &Ty<'tcx>, + a: Ty<'tcx>, + b: Ty<'tcx>, ) -> RelateResult<'tcx, Ty<'tcx>> { relation.tys(a, b) } @@ -379,7 +359,7 @@ pub fn super_relate_tys>( (&ty::Foreign(a_id), &ty::Foreign(b_id)) if a_id == b_id => Ok(tcx.mk_foreign(a_id)), - (&ty::Dynamic(ref a_obj, ref a_region), &ty::Dynamic(ref b_obj, ref b_region)) => { + (&ty::Dynamic(a_obj, a_region), &ty::Dynamic(b_obj, b_region)) => { let region_bound = relation.with_cause(Cause::ExistentialRegionBound, |relation| { relation.relate_with_variance(ty::Contravariant, a_region, b_region) })?; @@ -392,7 +372,7 @@ pub fn super_relate_tys>( // All Generator types with the same id represent // the (anonymous) type of the same generator expression. So // all of their regions should be equated. - let substs = relation.relate(&a_substs, &b_substs)?; + let substs = relation.relate(a_substs, b_substs)?; Ok(tcx.mk_generator(a_id, substs, movability)) } @@ -402,7 +382,7 @@ pub fn super_relate_tys>( let a_types = a_types.map_bound(GeneratorWitness); let b_types = b_types.map_bound(GeneratorWitness); // Then remove the GeneratorWitness for the result - let types = relation.relate(&a_types, &b_types)?.map_bound(|witness| witness.0); + let types = relation.relate(a_types, b_types)?.map_bound(|witness| witness.0); Ok(tcx.mk_generator_witness(types)) } @@ -410,26 +390,26 @@ pub fn super_relate_tys>( // All Closure types with the same id represent // the (anonymous) type of the same closure expression. So // all of their regions should be equated. - let substs = relation.relate(&a_substs, &b_substs)?; + let substs = relation.relate(a_substs, b_substs)?; Ok(tcx.mk_closure(a_id, &substs)) } - (&ty::RawPtr(ref a_mt), &ty::RawPtr(ref b_mt)) => { + (&ty::RawPtr(a_mt), &ty::RawPtr(b_mt)) => { let mt = relation.relate(a_mt, b_mt)?; Ok(tcx.mk_ptr(mt)) } (&ty::Ref(a_r, a_ty, a_mutbl), &ty::Ref(b_r, b_ty, b_mutbl)) => { - let r = relation.relate_with_variance(ty::Contravariant, &a_r, &b_r)?; + let r = relation.relate_with_variance(ty::Contravariant, a_r, b_r)?; let a_mt = ty::TypeAndMut { ty: a_ty, mutbl: a_mutbl }; let b_mt = ty::TypeAndMut { ty: b_ty, mutbl: b_mutbl }; - let mt = relation.relate(&a_mt, &b_mt)?; + let mt = relation.relate(a_mt, b_mt)?; Ok(tcx.mk_ref(r, mt)) } (&ty::Array(a_t, sz_a), &ty::Array(b_t, sz_b)) => { - let t = relation.relate(&a_t, &b_t)?; - match relation.relate(&sz_a, &sz_b) { + let t = relation.relate(a_t, b_t)?; + match relation.relate(sz_a, sz_b) { Ok(sz) => Ok(tcx.mk_ty(ty::Array(t, sz))), // FIXME(#72219) Implement improved diagnostics for mismatched array // length? @@ -450,16 +430,14 @@ pub fn super_relate_tys>( } (&ty::Slice(a_t), &ty::Slice(b_t)) => { - let t = relation.relate(&a_t, &b_t)?; + let t = relation.relate(a_t, b_t)?; Ok(tcx.mk_slice(t)) } (&ty::Tuple(as_), &ty::Tuple(bs)) => { if as_.len() == bs.len() { Ok(tcx.mk_tup( - as_.iter() - .zip(bs) - .map(|(a, b)| relation.relate(&a.expect_ty(), &b.expect_ty())), + as_.iter().zip(bs).map(|(a, b)| relation.relate(a.expect_ty(), b.expect_ty())), )?) } else if !(as_.is_empty() || bs.is_empty()) { Err(TypeError::TupleSize(expected_found(relation, &as_.len(), &bs.len()))) @@ -476,12 +454,12 @@ pub fn super_relate_tys>( } (&ty::FnPtr(a_fty), &ty::FnPtr(b_fty)) => { - let fty = relation.relate(&a_fty, &b_fty)?; + let fty = relation.relate(a_fty, b_fty)?; Ok(tcx.mk_fn_ptr(fty)) } // these two are already handled downstream in case of lazy normalization - (ty::Projection(a_data), ty::Projection(b_data)) => { + (&ty::Projection(a_data), &ty::Projection(b_data)) => { let projection_ty = relation.relate(a_data, b_data)?; Ok(tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs)) } @@ -603,8 +581,8 @@ pub fn super_relate_consts>( ty::ConstKind::Unevaluated(b_def_id, b_substs, b_promoted), ) if a_def_id == b_def_id && a_promoted == b_promoted => { let substs = - relation.relate_with_variance(ty::Variance::Invariant, &a_substs, &b_substs)?; - Ok(ty::ConstKind::Unevaluated(a_def_id, &substs, a_promoted)) + relation.relate_with_variance(ty::Variance::Invariant, a_substs, b_substs)?; + Ok(ty::ConstKind::Unevaluated(a_def_id, substs, a_promoted)) } _ => Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))), }; @@ -614,8 +592,8 @@ pub fn super_relate_consts>( impl<'tcx> Relate<'tcx> for &'tcx ty::List> { fn relate>( relation: &mut R, - a: &Self, - b: &Self, + a: Self, + b: Self, ) -> RelateResult<'tcx, Self> { let tcx = relation.tcx(); @@ -629,16 +607,16 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List> { b_v.sort_by(|a, b| a.stable_cmp(tcx, b)); b_v.dedup(); if a_v.len() != b_v.len() { - return Err(TypeError::ExistentialMismatch(expected_found(relation, a, b))); + return Err(TypeError::ExistentialMismatch(expected_found(relation, &a, &b))); } let v = a_v.into_iter().zip(b_v.into_iter()).map(|(ep_a, ep_b)| { use crate::ty::ExistentialPredicate::*; match (ep_a, ep_b) { - (Trait(ref a), Trait(ref b)) => Ok(Trait(relation.relate(a, b)?)), - (Projection(ref a), Projection(ref b)) => Ok(Projection(relation.relate(a, b)?)), - (AutoTrait(ref a), AutoTrait(ref b)) if a == b => Ok(AutoTrait(*a)), - _ => Err(TypeError::ExistentialMismatch(expected_found(relation, a, b))), + (Trait(a), Trait(b)) => Ok(Trait(relation.relate(a, b)?)), + (Projection(a), Projection(b)) => Ok(Projection(relation.relate(a, b)?)), + (AutoTrait(a), AutoTrait(b)) if a == b => Ok(AutoTrait(a)), + _ => Err(TypeError::ExistentialMismatch(expected_found(relation, &a, &b))), } }); Ok(tcx.mk_existential_predicates(v)?) @@ -648,8 +626,8 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List> { impl<'tcx> Relate<'tcx> for ty::ClosureSubsts<'tcx> { fn relate>( relation: &mut R, - a: &ty::ClosureSubsts<'tcx>, - b: &ty::ClosureSubsts<'tcx>, + a: ty::ClosureSubsts<'tcx>, + b: ty::ClosureSubsts<'tcx>, ) -> RelateResult<'tcx, ty::ClosureSubsts<'tcx>> { let substs = relate_substs(relation, None, a.substs, b.substs)?; Ok(ty::ClosureSubsts { substs }) @@ -659,8 +637,8 @@ impl<'tcx> Relate<'tcx> for ty::ClosureSubsts<'tcx> { impl<'tcx> Relate<'tcx> for ty::GeneratorSubsts<'tcx> { fn relate>( relation: &mut R, - a: &ty::GeneratorSubsts<'tcx>, - b: &ty::GeneratorSubsts<'tcx>, + a: ty::GeneratorSubsts<'tcx>, + b: ty::GeneratorSubsts<'tcx>, ) -> RelateResult<'tcx, ty::GeneratorSubsts<'tcx>> { let substs = relate_substs(relation, None, a.substs, b.substs)?; Ok(ty::GeneratorSubsts { substs }) @@ -670,8 +648,8 @@ impl<'tcx> Relate<'tcx> for ty::GeneratorSubsts<'tcx> { impl<'tcx> Relate<'tcx> for SubstsRef<'tcx> { fn relate>( relation: &mut R, - a: &SubstsRef<'tcx>, - b: &SubstsRef<'tcx>, + a: SubstsRef<'tcx>, + b: SubstsRef<'tcx>, ) -> RelateResult<'tcx, SubstsRef<'tcx>> { relate_substs(relation, None, a, b) } @@ -680,72 +658,48 @@ impl<'tcx> Relate<'tcx> for SubstsRef<'tcx> { impl<'tcx> Relate<'tcx> for ty::Region<'tcx> { fn relate>( relation: &mut R, - a: &ty::Region<'tcx>, - b: &ty::Region<'tcx>, + a: ty::Region<'tcx>, + b: ty::Region<'tcx>, ) -> RelateResult<'tcx, ty::Region<'tcx>> { - relation.regions(*a, *b) + relation.regions(a, b) } } impl<'tcx> Relate<'tcx> for &'tcx ty::Const<'tcx> { fn relate>( relation: &mut R, - a: &&'tcx ty::Const<'tcx>, - b: &&'tcx ty::Const<'tcx>, + a: &'tcx ty::Const<'tcx>, + b: &'tcx ty::Const<'tcx>, ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { - relation.consts(*a, *b) + relation.consts(a, b) } } impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for ty::Binder { fn relate>( relation: &mut R, - a: &ty::Binder, - b: &ty::Binder, + a: ty::Binder, + b: ty::Binder, ) -> RelateResult<'tcx, ty::Binder> { relation.binders(a, b) } } -impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for Rc { - fn relate>( - relation: &mut R, - a: &Rc, - b: &Rc, - ) -> RelateResult<'tcx, Rc> { - let a: &T = a; - let b: &T = b; - Ok(Rc::new(relation.relate(a, b)?)) - } -} - -impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for Box { - fn relate>( - relation: &mut R, - a: &Box, - b: &Box, - ) -> RelateResult<'tcx, Box> { - let a: &T = a; - let b: &T = b; - Ok(Box::new(relation.relate(a, b)?)) - } -} - impl<'tcx> Relate<'tcx> for GenericArg<'tcx> { fn relate>( relation: &mut R, - a: &GenericArg<'tcx>, - b: &GenericArg<'tcx>, + a: GenericArg<'tcx>, + b: GenericArg<'tcx>, ) -> RelateResult<'tcx, GenericArg<'tcx>> { match (a.unpack(), b.unpack()) { (GenericArgKind::Lifetime(a_lt), GenericArgKind::Lifetime(b_lt)) => { - Ok(relation.relate(&a_lt, &b_lt)?.into()) + Ok(relation.relate(a_lt, b_lt)?.into()) } (GenericArgKind::Type(a_ty), GenericArgKind::Type(b_ty)) => { - Ok(relation.relate(&a_ty, &b_ty)?.into()) + Ok(relation.relate(a_ty, b_ty)?.into()) } (GenericArgKind::Const(a_ct), GenericArgKind::Const(b_ct)) => { - Ok(relation.relate(&a_ct, &b_ct)?.into()) + Ok(relation.relate(a_ct, b_ct)?.into()) } (GenericArgKind::Lifetime(unpacked), x) => { bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x) @@ -763,22 +717,22 @@ impl<'tcx> Relate<'tcx> for GenericArg<'tcx> { impl<'tcx> Relate<'tcx> for ty::TraitPredicate<'tcx> { fn relate>( relation: &mut R, - a: &ty::TraitPredicate<'tcx>, - b: &ty::TraitPredicate<'tcx>, + a: ty::TraitPredicate<'tcx>, + b: ty::TraitPredicate<'tcx>, ) -> RelateResult<'tcx, ty::TraitPredicate<'tcx>> { - Ok(ty::TraitPredicate { trait_ref: relation.relate(&a.trait_ref, &b.trait_ref)? }) + Ok(ty::TraitPredicate { trait_ref: relation.relate(a.trait_ref, b.trait_ref)? }) } } impl<'tcx> Relate<'tcx> for ty::ProjectionPredicate<'tcx> { fn relate>( relation: &mut R, - a: &ty::ProjectionPredicate<'tcx>, - b: &ty::ProjectionPredicate<'tcx>, + a: ty::ProjectionPredicate<'tcx>, + b: ty::ProjectionPredicate<'tcx>, ) -> RelateResult<'tcx, ty::ProjectionPredicate<'tcx>> { Ok(ty::ProjectionPredicate { - projection_ty: relation.relate(&a.projection_ty, &b.projection_ty)?, - ty: relation.relate(&a.ty, &b.ty)?, + projection_ty: relation.relate(a.projection_ty, b.projection_ty)?, + ty: relation.relate(a.ty, b.ty)?, }) } } diff --git a/src/librustc_middle/ty/structural_impls.rs b/src/librustc_middle/ty/structural_impls.rs index f736037b5c15a..1d3607fe32ffc 100644 --- a/src/librustc_middle/ty/structural_impls.rs +++ b/src/librustc_middle/ty/structural_impls.rs @@ -514,7 +514,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::PredicateKind<'a> { impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for ty::Binder { type Lifted = ty::Binder; fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option { - tcx.lift(self.skip_binder()).map(ty::Binder::bind) + tcx.lift(self.as_ref().skip_binder()).map(ty::Binder::bind) } } @@ -655,7 +655,6 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> { VariadicMismatch(x) => VariadicMismatch(x), CyclicTy(t) => return tcx.lift(&t).map(|t| CyclicTy(t)), ProjectionMismatched(x) => ProjectionMismatched(x), - ProjectionBoundsLength(x) => ProjectionBoundsLength(x), Sorts(ref x) => return tcx.lift(x).map(Sorts), ExistentialMismatch(ref x) => return tcx.lift(x).map(ExistentialMismatch), ConstMismatch(ref x) => return tcx.lift(x).map(ConstMismatch), @@ -798,7 +797,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder { } fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.skip_binder().visit_with(visitor) + self.as_ref().skip_binder().visit_with(visitor) } fn visit_with>(&self, visitor: &mut V) -> bool { diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs index 8f86d2ef522d3..c7683cefd82f6 100644 --- a/src/librustc_middle/ty/sty.rs +++ b/src/librustc_middle/ty/sty.rs @@ -615,7 +615,7 @@ impl<'tcx> ExistentialPredicate<'tcx> { impl<'tcx> Binder> { pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::Predicate<'tcx> { use crate::ty::ToPredicate; - match *self.skip_binder() { + match self.skip_binder() { ExistentialPredicate::Trait(tr) => { Binder(tr).with_self_ty(tcx, self_ty).without_const().to_predicate(tcx) } @@ -776,7 +776,7 @@ impl<'tcx> PolyTraitRef<'tcx> { pub fn to_poly_trait_predicate(&self) -> ty::PolyTraitPredicate<'tcx> { // Note that we preserve binding levels - Binder(ty::TraitPredicate { trait_ref: *self.skip_binder() }) + Binder(ty::TraitPredicate { trait_ref: self.skip_binder() }) } } @@ -880,8 +880,8 @@ impl Binder { /// - extracting the `DefId` from a PolyTraitRef; /// - comparing the self type of a PolyTraitRef to see if it is equal to /// a type parameter `X`, since the type `X` does not reference any regions - pub fn skip_binder(&self) -> &T { - &self.0 + pub fn skip_binder(self) -> T { + self.0 } pub fn as_ref(&self) -> Binder<&T> { @@ -916,11 +916,7 @@ impl Binder { where T: TypeFoldable<'tcx>, { - if self.skip_binder().has_escaping_bound_vars() { - None - } else { - Some(self.skip_binder().clone()) - } + if self.0.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) } } /// Given two things that have the same binder level, @@ -997,7 +993,7 @@ impl<'tcx> ProjectionTy<'tcx> { } } -#[derive(Clone, Debug, TypeFoldable)] +#[derive(Copy, Clone, Debug, TypeFoldable)] pub struct GenSig<'tcx> { pub resume_ty: Ty<'tcx>, pub yield_ty: Ty<'tcx>, diff --git a/src/librustc_middle/ty/walk.rs b/src/librustc_middle/ty/walk.rs index 633d4fda8a46d..82c649b8f543b 100644 --- a/src/librustc_middle/ty/walk.rs +++ b/src/librustc_middle/ty/walk.rs @@ -133,7 +133,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) ty::Dynamic(obj, lt) => { stack.push(lt.into()); stack.extend(obj.iter().rev().flat_map(|predicate| { - let (substs, opt_ty) = match *predicate.skip_binder() { + let (substs, opt_ty) = match predicate.skip_binder() { ty::ExistentialPredicate::Trait(tr) => (tr.substs, None), ty::ExistentialPredicate::Projection(p) => (p.substs, Some(p.ty)), ty::ExistentialPredicate::AutoTrait(_) => diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs index e85f69554d0c8..17846055f6c96 100644 --- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs @@ -1923,7 +1923,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // We use a mix of the HIR and the Ty types to get information // as the HIR doesn't have full types for closure arguments. - let return_ty = *sig.output().skip_binder(); + let return_ty = sig.output().skip_binder(); let mut return_span = fn_decl.output.span(); if let hir::FnRetTy::Return(ty) = &fn_decl.output { if let hir::TyKind::Rptr(lifetime, _) = ty.kind { @@ -1965,7 +1965,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let argument_ty = sig.inputs().skip_binder().first()?; let return_span = fn_decl.output.span(); - let return_ty = *sig.output().skip_binder(); + let return_ty = sig.output().skip_binder(); // We expect the first argument to be a reference. match argument_ty.kind { diff --git a/src/librustc_mir/borrow_check/type_check/relate_tys.rs b/src/librustc_mir/borrow_check/type_check/relate_tys.rs index 285d9ed64691a..91b1a1fbd9705 100644 --- a/src/librustc_mir/borrow_check/type_check/relate_tys.rs +++ b/src/librustc_mir/borrow_check/type_check/relate_tys.rs @@ -31,7 +31,7 @@ pub(super) fn relate_types<'tcx>( NllTypeRelatingDelegate::new(infcx, borrowck_context, locations, category), v, ) - .relate(&a, &b)?; + .relate(a, b)?; Ok(()) } diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 88ba28dab82e1..01eb2d0b8e266 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -409,6 +409,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ); self.copy_op(self.operand_index(args[0], index)?, dest)?; } + sym::likely | sym::unlikely => { + // These just return their argument + self.copy_op(args[0], dest)?; + } // FIXME(#73156): Handle source code coverage in const eval sym::count_code_region => (), _ => return Ok(false), diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs index ca1f0aecd048a..f00fc96e5915a 100644 --- a/src/librustc_mir/transform/check_consts/validation.rs +++ b/src/librustc_mir/transform/check_consts/validation.rs @@ -531,9 +531,12 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> { if is_lang_panic_fn(self.tcx, def_id) { self.check_op(ops::Panic); } else if let Some(feature) = is_unstable_const_fn(self.tcx, def_id) { - // Exempt unstable const fns inside of macros with + // Exempt unstable const fns inside of macros or functions with // `#[allow_internal_unstable]`. - if !self.span.allows_unstable(feature) { + use crate::transform::qualify_min_const_fn::lib_feature_allowed; + if !self.span.allows_unstable(feature) + && !lib_feature_allowed(self.tcx, self.def_id, feature) + { self.check_op(ops::FnCallUnstable(def_id, feature)); } } else { diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index 5a3663384fb87..2f5257080cd5c 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -328,6 +328,26 @@ fn feature_allowed(tcx: TyCtxt<'tcx>, def_id: DefId, feature_gate: Symbol) -> bo .map_or(false, |mut features| features.any(|name| name == feature_gate)) } +/// Returns `true` if the given library feature gate is allowed within the function with the given `DefId`. +pub fn lib_feature_allowed(tcx: TyCtxt<'tcx>, def_id: DefId, feature_gate: Symbol) -> bool { + // All features require that the corresponding gate be enabled, + // even if the function has `#[allow_internal_unstable(the_gate)]`. + if !tcx.features().declared_lib_features.iter().any(|&(sym, _)| sym == feature_gate) { + return false; + } + + // If this crate is not using stability attributes, or this function is not claiming to be a + // stable `const fn`, that is all that is required. + if !tcx.features().staged_api || tcx.has_attr(def_id, sym::rustc_const_unstable) { + return true; + } + + // However, we cannot allow stable `const fn`s to use unstable features without an explicit + // opt-in via `allow_internal_unstable`. + attr::allow_internal_unstable(&tcx.get_attrs(def_id), &tcx.sess.diagnostic()) + .map_or(false, |mut features| features.any(|name| name == feature_gate)) +} + fn check_terminator( tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, @@ -367,8 +387,17 @@ fn check_terminator( fn_span: _, } => { let fn_ty = func.ty(body, tcx); - if let ty::FnDef(def_id, _) = fn_ty.kind { - if !crate::const_eval::is_min_const_fn(tcx, def_id) { + if let ty::FnDef(fn_def_id, _) = fn_ty.kind { + // Allow unstable const if we opt in by using #[allow_internal_unstable] + // on function or macro declaration. + if !crate::const_eval::is_min_const_fn(tcx, fn_def_id) + && !crate::const_eval::is_unstable_const_fn(tcx, fn_def_id) + .map(|feature| { + span.allows_unstable(feature) + || lib_feature_allowed(tcx, def_id, feature) + }) + .unwrap_or(false) + { return Err(( span, format!( @@ -380,10 +409,10 @@ fn check_terminator( )); } - check_operand(tcx, func, span, def_id, body)?; + check_operand(tcx, func, span, fn_def_id, body)?; for arg in args { - check_operand(tcx, arg, span, def_id, body)?; + check_operand(tcx, arg, span, fn_def_id, body)?; } Ok(()) } else { diff --git a/src/librustc_mir/transform/validate.rs b/src/librustc_mir/transform/validate.rs index d3f486c815e6c..e794a6949d2f0 100644 --- a/src/librustc_mir/transform/validate.rs +++ b/src/librustc_mir/transform/validate.rs @@ -74,8 +74,8 @@ pub fn equal_up_to_regions( fn relate_with_variance>( &mut self, _: ty::Variance, - a: &T, - b: &T, + a: T, + b: T, ) -> RelateResult<'tcx, T> { // Ignore variance, require types to be exactly the same. self.relate(a, b) @@ -108,8 +108,8 @@ pub fn equal_up_to_regions( fn binders( &mut self, - a: &ty::Binder, - b: &ty::Binder, + a: ty::Binder, + b: ty::Binder, ) -> RelateResult<'tcx, ty::Binder> where T: Relate<'tcx>, @@ -121,7 +121,7 @@ pub fn equal_up_to_regions( // Instantiate and run relation. let mut relator: LifetimeIgnoreRelation<'tcx> = LifetimeIgnoreRelation { tcx: tcx, param_env }; - relator.relate(&src, &dest).is_ok() + relator.relate(src, dest).is_ok() } struct TypeChecker<'a, 'tcx> { diff --git a/src/librustc_mir_build/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs index 6ac5d41ec6135..18b92bf29bf1b 100644 --- a/src/librustc_mir_build/hair/pattern/_match.rs +++ b/src/librustc_mir_build/hair/pattern/_match.rs @@ -4,8 +4,8 @@ //! This file includes the logic for exhaustiveness and usefulness checking for //! pattern-matching. Specifically, given a list of patterns for a type, we can //! tell whether: -//! (a) the patterns cover every possible constructor for the type [exhaustiveness] -//! (b) each pattern is necessary [usefulness] +//! (a) the patterns cover every possible constructor for the type (exhaustiveness) +//! (b) each pattern is necessary (usefulness) //! //! The algorithm implemented here is a modified version of the one described in: //! http://moscova.inria.fr/~maranget/papers/warn/index.html @@ -101,53 +101,54 @@ //! To match the paper, the top of the stack is at the beginning / on the left. //! //! There are two important operations on pattern-stacks necessary to understand the algorithm: -//! 1. We can pop a given constructor off the top of a stack. This operation is called -//! `specialize`, and is denoted `S(c, p)` where `c` is a constructor (like `Some` or -//! `None`) and `p` a pattern-stack. -//! If the pattern on top of the stack can cover `c`, this removes the constructor and -//! pushes its arguments onto the stack. It also expands OR-patterns into distinct patterns. -//! Otherwise the pattern-stack is discarded. -//! This essentially filters those pattern-stacks whose top covers the constructor `c` and -//! discards the others. //! -//! For example, the first pattern above initially gives a stack `[(Some(true), _)]`. If we -//! pop the tuple constructor, we are left with `[Some(true), _]`, and if we then pop the -//! `Some` constructor we get `[true, _]`. If we had popped `None` instead, we would get -//! nothing back. +//! 1. We can pop a given constructor off the top of a stack. This operation is called +//! `specialize`, and is denoted `S(c, p)` where `c` is a constructor (like `Some` or +//! `None`) and `p` a pattern-stack. +//! If the pattern on top of the stack can cover `c`, this removes the constructor and +//! pushes its arguments onto the stack. It also expands OR-patterns into distinct patterns. +//! Otherwise the pattern-stack is discarded. +//! This essentially filters those pattern-stacks whose top covers the constructor `c` and +//! discards the others. //! -//! This returns zero or more new pattern-stacks, as follows. We look at the pattern `p_1` -//! on top of the stack, and we have four cases: -//! 1.1. `p_1 = c(r_1, .., r_a)`, i.e. the top of the stack has constructor `c`. We -//! push onto the stack the arguments of this constructor, and return the result: -//! r_1, .., r_a, p_2, .., p_n -//! 1.2. `p_1 = c'(r_1, .., r_a')` where `c ≠ c'`. We discard the current stack and -//! return nothing. -//! 1.3. `p_1 = _`. We push onto the stack as many wildcards as the constructor `c` has -//! arguments (its arity), and return the resulting stack: -//! _, .., _, p_2, .., p_n -//! 1.4. `p_1 = r_1 | r_2`. We expand the OR-pattern and then recurse on each resulting -//! stack: -//! S(c, (r_1, p_2, .., p_n)) -//! S(c, (r_2, p_2, .., p_n)) +//! For example, the first pattern above initially gives a stack `[(Some(true), _)]`. If we +//! pop the tuple constructor, we are left with `[Some(true), _]`, and if we then pop the +//! `Some` constructor we get `[true, _]`. If we had popped `None` instead, we would get +//! nothing back. //! -//! 2. We can pop a wildcard off the top of the stack. This is called `D(p)`, where `p` is -//! a pattern-stack. -//! This is used when we know there are missing constructor cases, but there might be -//! existing wildcard patterns, so to check the usefulness of the matrix, we have to check -//! all its *other* components. +//! This returns zero or more new pattern-stacks, as follows. We look at the pattern `p_1` +//! on top of the stack, and we have four cases: +//! 1.1. `p_1 = c(r_1, .., r_a)`, i.e. the top of the stack has constructor `c`. We +//! push onto the stack the arguments of this constructor, and return the result: +//! r_1, .., r_a, p_2, .., p_n +//! 1.2. `p_1 = c'(r_1, .., r_a')` where `c ≠ c'`. We discard the current stack and +//! return nothing. +//! 1.3. `p_1 = _`. We push onto the stack as many wildcards as the constructor `c` has +//! arguments (its arity), and return the resulting stack: +//! _, .., _, p_2, .., p_n +//! 1.4. `p_1 = r_1 | r_2`. We expand the OR-pattern and then recurse on each resulting +//! stack: +//! S(c, (r_1, p_2, .., p_n)) +//! S(c, (r_2, p_2, .., p_n)) //! -//! It is computed as follows. We look at the pattern `p_1` on top of the stack, -//! and we have three cases: -//! 1.1. `p_1 = c(r_1, .., r_a)`. We discard the current stack and return nothing. -//! 1.2. `p_1 = _`. We return the rest of the stack: -//! p_2, .., p_n -//! 1.3. `p_1 = r_1 | r_2`. We expand the OR-pattern and then recurse on each resulting -//! stack. -//! D((r_1, p_2, .., p_n)) -//! D((r_2, p_2, .., p_n)) +//! 2. We can pop a wildcard off the top of the stack. This is called `D(p)`, where `p` is +//! a pattern-stack. +//! This is used when we know there are missing constructor cases, but there might be +//! existing wildcard patterns, so to check the usefulness of the matrix, we have to check +//! all its *other* components. //! -//! Note that the OR-patterns are not always used directly in Rust, but are used to derive the -//! exhaustive integer matching rules, so they're written here for posterity. +//! It is computed as follows. We look at the pattern `p_1` on top of the stack, +//! and we have three cases: +//! 1.1. `p_1 = c(r_1, .., r_a)`. We discard the current stack and return nothing. +//! 1.2. `p_1 = _`. We return the rest of the stack: +//! p_2, .., p_n +//! 1.3. `p_1 = r_1 | r_2`. We expand the OR-pattern and then recurse on each resulting +//! stack. +//! D((r_1, p_2, .., p_n)) +//! D((r_2, p_2, .., p_n)) +//! +//! Note that the OR-patterns are not always used directly in Rust, but are used to derive the +//! exhaustive integer matching rules, so they're written here for posterity. //! //! Both those operations extend straightforwardly to a list or pattern-stacks, i.e. a matrix, by //! working row-by-row. Popping a constructor ends up keeping only the matrix rows that start with @@ -168,66 +169,66 @@ //! //! Inductive step. (`n > 0`, i.e., whether there's at least one column //! [which may then be expanded into further columns later]) -//! We're going to match on the top of the new pattern-stack, `p_1`. -//! - If `p_1 == c(r_1, .., r_a)`, i.e. we have a constructor pattern. -//! Then, the usefulness of `p_1` can be reduced to whether it is useful when -//! we ignore all the patterns in the first column of `P` that involve other constructors. -//! This is where `S(c, P)` comes in: -//! `U(P, p) := U(S(c, P), S(c, p))` -//! This special case is handled in `is_useful_specialized`. +//! We're going to match on the top of the new pattern-stack, `p_1`. +//! - If `p_1 == c(r_1, .., r_a)`, i.e. we have a constructor pattern. +//! Then, the usefulness of `p_1` can be reduced to whether it is useful when +//! we ignore all the patterns in the first column of `P` that involve other constructors. +//! This is where `S(c, P)` comes in: +//! `U(P, p) := U(S(c, P), S(c, p))` +//! This special case is handled in `is_useful_specialized`. //! -//! For example, if `P` is: -//! [ -//! [Some(true), _], -//! [None, 0], -//! ] -//! and `p` is [Some(false), 0], then we don't care about row 2 since we know `p` only -//! matches values that row 2 doesn't. For row 1 however, we need to dig into the -//! arguments of `Some` to know whether some new value is covered. So we compute -//! `U([[true, _]], [false, 0])`. +//! For example, if `P` is: +//! [ +//! [Some(true), _], +//! [None, 0], +//! ] +//! and `p` is [Some(false), 0], then we don't care about row 2 since we know `p` only +//! matches values that row 2 doesn't. For row 1 however, we need to dig into the +//! arguments of `Some` to know whether some new value is covered. So we compute +//! `U([[true, _]], [false, 0])`. //! -//! - If `p_1 == _`, then we look at the list of constructors that appear in the first -//! component of the rows of `P`: -//! + If there are some constructors that aren't present, then we might think that the -//! wildcard `_` is useful, since it covers those constructors that weren't covered -//! before. -//! That's almost correct, but only works if there were no wildcards in those first -//! components. So we need to check that `p` is useful with respect to the rows that -//! start with a wildcard, if there are any. This is where `D` comes in: -//! `U(P, p) := U(D(P), D(p))` +//! - If `p_1 == _`, then we look at the list of constructors that appear in the first +//! component of the rows of `P`: +//! + If there are some constructors that aren't present, then we might think that the +//! wildcard `_` is useful, since it covers those constructors that weren't covered +//! before. +//! That's almost correct, but only works if there were no wildcards in those first +//! components. So we need to check that `p` is useful with respect to the rows that +//! start with a wildcard, if there are any. This is where `D` comes in: +//! `U(P, p) := U(D(P), D(p))` //! -//! For example, if `P` is: -//! [ -//! [_, true, _], -//! [None, false, 1], -//! ] -//! and `p` is [_, false, _], the `Some` constructor doesn't appear in `P`. So if we -//! only had row 2, we'd know that `p` is useful. However row 1 starts with a -//! wildcard, so we need to check whether `U([[true, _]], [false, 1])`. +//! For example, if `P` is: +//! [ +//! [_, true, _], +//! [None, false, 1], +//! ] +//! and `p` is [_, false, _], the `Some` constructor doesn't appear in `P`. So if we +//! only had row 2, we'd know that `p` is useful. However row 1 starts with a +//! wildcard, so we need to check whether `U([[true, _]], [false, 1])`. //! -//! + Otherwise, all possible constructors (for the relevant type) are present. In this -//! case we must check whether the wildcard pattern covers any unmatched value. For -//! that, we can think of the `_` pattern as a big OR-pattern that covers all -//! possible constructors. For `Option`, that would mean `_ = None | Some(_)` for -//! example. The wildcard pattern is useful in this case if it is useful when -//! specialized to one of the possible constructors. So we compute: -//! `U(P, p) := ∃(k ϵ constructors) U(S(k, P), S(k, p))` +//! + Otherwise, all possible constructors (for the relevant type) are present. In this +//! case we must check whether the wildcard pattern covers any unmatched value. For +//! that, we can think of the `_` pattern as a big OR-pattern that covers all +//! possible constructors. For `Option`, that would mean `_ = None | Some(_)` for +//! example. The wildcard pattern is useful in this case if it is useful when +//! specialized to one of the possible constructors. So we compute: +//! `U(P, p) := ∃(k ϵ constructors) U(S(k, P), S(k, p))` //! -//! For example, if `P` is: -//! [ -//! [Some(true), _], -//! [None, false], -//! ] -//! and `p` is [_, false], both `None` and `Some` constructors appear in the first -//! components of `P`. We will therefore try popping both constructors in turn: we -//! compute U([[true, _]], [_, false]) for the `Some` constructor, and U([[false]], -//! [false]) for the `None` constructor. The first case returns true, so we know that -//! `p` is useful for `P`. Indeed, it matches `[Some(false), _]` that wasn't matched -//! before. +//! For example, if `P` is: +//! [ +//! [Some(true), _], +//! [None, false], +//! ] +//! and `p` is [_, false], both `None` and `Some` constructors appear in the first +//! components of `P`. We will therefore try popping both constructors in turn: we +//! compute `U([[true, _]], [_, false])` for the `Some` constructor, and `U([[false]], +//! [false])` for the `None` constructor. The first case returns true, so we know that +//! `p` is useful for `P`. Indeed, it matches `[Some(false), _]` that wasn't matched +//! before. //! -//! - If `p_1 == r_1 | r_2`, then the usefulness depends on each `r_i` separately: -//! `U(P, p) := U(P, (r_1, p_2, .., p_n)) -//! || U(P, (r_2, p_2, .., p_n))` +//! - If `p_1 == r_1 | r_2`, then the usefulness depends on each `r_i` separately: +//! `U(P, p) := U(P, (r_1, p_2, .., p_n)) +//! || U(P, (r_2, p_2, .., p_n))` //! //! Modifications to the algorithm //! ------------------------------ diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs index fc9ffc3092447..16a118cb48c91 100644 --- a/src/librustc_parse/parser/diagnostics.rs +++ b/src/librustc_parse/parser/diagnostics.rs @@ -376,7 +376,14 @@ impl<'a> Parser<'a> { /// let _ = vec![1, 2, 3].into_iter().collect::>>>(); /// ^^ help: remove extra angle brackets /// ``` - pub(super) fn check_trailing_angle_brackets(&mut self, segment: &PathSegment, end: TokenKind) { + /// + /// If `true` is returned, then trailing brackets were recovered, tokens were consumed + /// up until one of the tokens in 'end' was encountered, and an error was emitted. + pub(super) fn check_trailing_angle_brackets( + &mut self, + segment: &PathSegment, + end: &[&TokenKind], + ) -> bool { // This function is intended to be invoked after parsing a path segment where there are two // cases: // @@ -409,7 +416,7 @@ impl<'a> Parser<'a> { parsed_angle_bracket_args, ); if !parsed_angle_bracket_args { - return; + return false; } // Keep the span at the start so we can highlight the sequence of `>` characters to be @@ -447,18 +454,18 @@ impl<'a> Parser<'a> { number_of_gt, number_of_shr, ); if number_of_gt < 1 && number_of_shr < 1 { - return; + return false; } // Finally, double check that we have our end token as otherwise this is the // second case. if self.look_ahead(position, |t| { trace!("check_trailing_angle_brackets: t={:?}", t); - *t == end + end.contains(&&t.kind) }) { // Eat from where we started until the end token so that parsing can continue // as if we didn't have those extra angle brackets. - self.eat_to_tokens(&[&end]); + self.eat_to_tokens(end); let span = lo.until(self.token.span); let total_num_of_gt = number_of_gt + number_of_shr * 2; @@ -473,7 +480,9 @@ impl<'a> Parser<'a> { Applicability::MachineApplicable, ) .emit(); + return true; } + false } /// Check to see if a pair of chained operators looks like an attempt at chained comparison, @@ -1415,7 +1424,7 @@ impl<'a> Parser<'a> { if self.token != token::Lt { err.span_suggestion( pat.span, - "if this was a parameter name, give it a type", + "if this is a parameter name, give it a type", format!("{}: TypeName", ident), Applicability::HasPlaceholders, ); diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 2745b18a8cd51..fb38fdc26c782 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -867,7 +867,7 @@ impl<'a> Parser<'a> { let fn_span_lo = self.token.span; let segment = self.parse_path_segment(PathStyle::Expr)?; - self.check_trailing_angle_brackets(&segment, token::OpenDelim(token::Paren)); + self.check_trailing_angle_brackets(&segment, &[&token::OpenDelim(token::Paren)]); if self.check(&token::OpenDelim(token::Paren)) { // Method call `expr.f()` diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 10df16964da08..fa6264c98e4f0 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -9,7 +9,7 @@ use rustc_ast::ast::{AssocItem, AssocItemKind, ForeignItemKind, Item, ItemKind, use rustc_ast::ast::{Async, Const, Defaultness, IsAuto, Mutability, Unsafe, UseTree, UseTreeKind}; use rustc_ast::ast::{BindingMode, Block, FnDecl, FnSig, Param, SelfKind}; use rustc_ast::ast::{EnumDef, Generics, StructField, TraitRef, Ty, TyKind, Variant, VariantData}; -use rustc_ast::ast::{FnHeader, ForeignItem, PathSegment, Visibility, VisibilityKind}; +use rustc_ast::ast::{FnHeader, ForeignItem, Path, PathSegment, Visibility, VisibilityKind}; use rustc_ast::ast::{MacArgs, MacCall, MacDelimiter}; use rustc_ast::ptr::P; use rustc_ast::token::{self, TokenKind}; @@ -1262,6 +1262,25 @@ impl<'a> Parser<'a> { sp, &format!("expected `,`, or `}}`, found {}", super::token_descr(&self.token)), ); + + // Try to recover extra trailing angle brackets + let mut recovered = false; + if let TyKind::Path(_, Path { segments, .. }) = &a_var.ty.kind { + if let Some(last_segment) = segments.last() { + recovered = self.check_trailing_angle_brackets( + last_segment, + &[&token::Comma, &token::CloseDelim(token::Brace)], + ); + if recovered { + // Handle a case like `Vec>,` where we can continue parsing fields + // after the comma + self.eat(&token::Comma); + // `check_trailing_angle_brackets` already emitted a nicer error + err.cancel(); + } + } + } + if self.token.is_ident() { // This is likely another field; emit the diagnostic and keep going err.span_suggestion( @@ -1271,6 +1290,14 @@ impl<'a> Parser<'a> { Applicability::MachineApplicable, ); err.emit(); + recovered = true; + } + + if recovered { + // Make sure an error was emitted (either by recovering an angle bracket, + // or by finding an identifier as the next token), since we're + // going to continue parsing + assert!(self.sess.span_diagnostic.has_errors()); } else { return Err(err); } diff --git a/src/librustc_parse/parser/path.rs b/src/librustc_parse/parser/path.rs index 5210614548da3..67e9b3af4a8cf 100644 --- a/src/librustc_parse/parser/path.rs +++ b/src/librustc_parse/parser/path.rs @@ -169,7 +169,7 @@ impl<'a> Parser<'a> { // `PathStyle::Expr` is only provided at the root invocation and never in // `parse_path_segment` to recurse and therefore can be checked to maintain // this invariant. - self.check_trailing_angle_brackets(&segment, token::ModSep); + self.check_trailing_angle_brackets(&segment, &[&token::ModSep]); } segments.push(segment); diff --git a/src/librustc_passes/intrinsicck.rs b/src/librustc_passes/intrinsicck.rs index 683039df15ac6..e4f4885690fd9 100644 --- a/src/librustc_passes/intrinsicck.rs +++ b/src/librustc_passes/intrinsicck.rs @@ -422,7 +422,7 @@ impl Visitor<'tcx> for ExprVisitor<'tcx> { let typ = self.tables.node_type(expr.hir_id); let sig = typ.fn_sig(self.tcx); let from = sig.inputs().skip_binder()[0]; - let to = *sig.output().skip_binder(); + let to = sig.output().skip_binder(); self.check_transmute(expr.span, from, to); } } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 9e6e7ea962bc3..20f09ef52f00b 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -92,14 +92,14 @@ where for (predicate, _span) in predicates { match predicate.kind() { ty::PredicateKind::Trait(poly_predicate, _) => { - let ty::TraitPredicate { trait_ref } = *poly_predicate.skip_binder(); + let ty::TraitPredicate { trait_ref } = poly_predicate.skip_binder(); if self.visit_trait(trait_ref) { return true; } } ty::PredicateKind::Projection(poly_predicate) => { let ty::ProjectionPredicate { projection_ty, ty } = - *poly_predicate.skip_binder(); + poly_predicate.skip_binder(); if ty.visit_with(self) { return true; } @@ -108,7 +108,7 @@ where } } ty::PredicateKind::TypeOutlives(poly_predicate) => { - let ty::OutlivesPredicate(ty, _region) = *poly_predicate.skip_binder(); + let ty::OutlivesPredicate(ty, _region) = poly_predicate.skip_binder(); if ty.visit_with(self) { return true; } @@ -175,7 +175,7 @@ where ty::Dynamic(predicates, ..) => { // All traits in the list are considered the "primary" part of the type // and are visited by shallow visitors. - for predicate in *predicates.skip_binder() { + for predicate in predicates.skip_binder() { let trait_ref = match predicate { ty::ExistentialPredicate::Trait(trait_ref) => trait_ref, ty::ExistentialPredicate::Projection(proj) => proj.trait_ref(tcx), @@ -1270,7 +1270,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { ); for (trait_predicate, _, _) in bounds.trait_bounds { - if self.visit_trait(*trait_predicate.skip_binder()) { + if self.visit_trait(trait_predicate.skip_binder()) { return; } } diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index 857734037afe7..e67ca3259ff6b 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -152,10 +152,14 @@ symbols! { arm_target_feature, asm, assert, + assert_inhabited, + assert_uninit_valid, + assert_zero_valid, associated_consts, associated_type_bounds, associated_type_defaults, associated_types, + assume, assume_init, async_await, async_closure, @@ -181,11 +185,14 @@ symbols! { box_patterns, box_syntax, braced_empty_structs, + breakpoint, bswap, bitreverse, C, caller_location, cdylib, + ceilf32, + ceilf64, cfg, cfg_accessible, cfg_attr, @@ -239,8 +246,14 @@ symbols! { convert, Copy, copy_closures, + copy, + copy_nonoverlapping, + copysignf32, + copysignf64, core, core_intrinsics, + cosf32, + cosf64, count_code_region, crate_id, crate_in_paths, @@ -296,6 +309,7 @@ symbols! { dropck_eyepatch, dropck_parametricity, drop_types_in_const, + drop_in_place, dylib, dyn_trait, eh_personality, @@ -308,11 +322,16 @@ symbols! { Eq, Equal, enclosing_scope, + exact_div, except, exclusive_range_pattern, exhaustive_integer_patterns, exhaustive_patterns, existential_type, + expf32, + expf64, + exp2f32, + exp2f64, expected, export_name, expr, @@ -326,6 +345,10 @@ symbols! { f16c_target_feature, f32, f64, + fadd_fast, + fabsf32, + fabsf64, + fdiv_fast, feature, ffi_const, ffi_pure, @@ -333,12 +356,20 @@ symbols! { field, field_init_shorthand, file, + float_to_int_unchecked, + floorf64, + floorf32, + fmaf32, + fmaf64, fmt, fmt_internals, + fmul_fast, fn_must_use, forbid, + forget, format_args, format_args_nl, + frem_fast, from, From, from_desugaring, @@ -348,6 +379,7 @@ symbols! { from_ok, from_usize, from_trait, + fsub_fast, fundamental, future, Future, @@ -427,6 +459,7 @@ symbols! { lhs, lib, lifetime, + likely, line, link, linkage, @@ -442,6 +475,12 @@ symbols! { llvm_asm, local_inner_macros, log_syntax, + logf32, + logf64, + log10f32, + log10f64, + log2f32, + log2f64, loop_break_value, macro_at_most_once_rep, macro_escape, @@ -469,10 +508,16 @@ symbols! { message, meta, min_align_of, + min_align_of_val, min_const_fn, min_const_unsafe_fn, min_specialization, + minnumf32, + minnumf64, + maxnumf32, + maxnumf64, mips_target_feature, + miri_start_panic, mmx_target_feature, module, module_path, @@ -485,6 +530,8 @@ symbols! { naked, naked_functions, name, + nearbyintf32, + nearbyintf64, needs_allocator, needs_drop, needs_panic_runtime, @@ -512,6 +559,7 @@ symbols! { None, non_exhaustive, non_modrs_mods, + nontemporal_store, noreturn, no_niche, no_sanitize, @@ -570,8 +618,16 @@ symbols! { poll, Poll, powerpc_target_feature, + powf32, + powf64, + powif32, + powif64, precise_pointer_size_matching, pref_align_of, + prefetch_read_data, + prefetch_read_instruction, + prefetch_write_data, + prefetch_write_instruction, prelude, prelude_import, preserves_flags, @@ -631,10 +687,14 @@ symbols! { Result, Return, rhs, + rintf32, + rintf64, riscv_target_feature, rlib, rotate_left, rotate_right, + roundf32, + roundf64, rt, rtm_target_feature, rust, @@ -717,14 +777,19 @@ symbols! { simd_ffi, simd_insert, since, + sinf32, + sinf64, size, size_of, + size_of_val, slice_patterns, slicing_syntax, soft, Some, specialization, speed, + sqrtf32, + sqrtf64, sse4a_target_feature, stable, staged_api, @@ -778,6 +843,8 @@ symbols! { transparent_enums, transparent_unions, trivial_bounds, + truncf32, + truncf64, Try, try_blocks, try_trait, @@ -800,6 +867,8 @@ symbols! { u32, u64, u8, + unaligned_volatile_load, + unaligned_volatile_store, unboxed_closures, unchecked_add, unchecked_div, @@ -813,7 +882,9 @@ symbols! { underscore_lifetimes, uniform_paths, universal_impl_trait, + unlikely, unmarked_api, + unreachable, unreachable_code, unrestricted_attribute_tokens, unsafe_block_in_unsafe_fn, @@ -833,12 +904,21 @@ symbols! { val, var, variant_count, + va_arg, + va_copy, + va_end, + va_start, vec, Vec, version, vis, visible_private_types, volatile, + volatile_copy_memory, + volatile_copy_nonoverlapping_memory, + volatile_load, + volatile_set_memory, + volatile_store, warn, wasm_import_module, wasm_target_feature, @@ -848,6 +928,7 @@ symbols! { wrapping_add, wrapping_sub, wrapping_mul, + write_bytes, Yield, } } diff --git a/src/librustc_symbol_mangling/v0.rs b/src/librustc_symbol_mangling/v0.rs index 7d117b77cf5e5..ecf27fbf54220 100644 --- a/src/librustc_symbol_mangling/v0.rs +++ b/src/librustc_symbol_mangling/v0.rs @@ -219,7 +219,7 @@ impl SymbolMangler<'tcx> { lifetime_depths.end += lifetimes; self.binders.push(BinderLevel { lifetime_depths }); - self = print_value(self, value.skip_binder())?; + self = print_value(self, value.as_ref().skip_binder())?; self.binders.pop(); Ok(self) diff --git a/src/librustc_trait_selection/opaque_types.rs b/src/librustc_trait_selection/opaque_types.rs index adccdd0b2617a..ce478de7c755c 100644 --- a/src/librustc_trait_selection/opaque_types.rs +++ b/src/librustc_trait_selection/opaque_types.rs @@ -691,7 +691,7 @@ where OP: FnMut(ty::Region<'tcx>), { fn visit_binder>(&mut self, t: &ty::Binder) -> bool { - t.skip_binder().visit_with(self); + t.as_ref().skip_binder().visit_with(self); false // keep visiting } diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs index fd0c1a54d27ad..49e43873df759 100644 --- a/src/librustc_trait_selection/traits/error_reporting/mod.rs +++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs @@ -1569,7 +1569,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { // no need to overload user in such cases return; } - let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder(); + let SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder(); // both must be type variables, or the other would've been instantiated assert!(a.is_ty_var() && b.is_ty_var()); self.need_type_info_err(body_id, span, a, ErrorCode::E0282) diff --git a/src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs b/src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs index fd87759a7621f..ec51dddc2c810 100644 --- a/src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs +++ b/src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs @@ -122,7 +122,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ) -> OnUnimplementedNote { let def_id = self.impl_similar_to(trait_ref, obligation).unwrap_or_else(|| trait_ref.def_id()); - let trait_ref = *trait_ref.skip_binder(); + let trait_ref = trait_ref.skip_binder(); let mut flags = vec![]; flags.push(( @@ -219,7 +219,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } } if let ty::Dynamic(traits, _) = self_ty.kind { - for t in *traits.skip_binder() { + for t in traits.skip_binder() { if let ty::ExistentialPredicate::Trait(trait_ref) = t { flags.push((sym::_Self, Some(self.tcx.def_path_str(trait_ref.def_id)))) } diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index 176bd90303ddd..1fafa9ec035ce 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -1179,7 +1179,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ) -> DiagnosticBuilder<'tcx> { crate fn build_fn_sig_string<'tcx>( tcx: TyCtxt<'tcx>, - trait_ref: &ty::TraitRef<'tcx>, + trait_ref: ty::TraitRef<'tcx>, ) -> String { let inputs = trait_ref.substs.type_at(1); let sig = if let ty::Tuple(inputs) = inputs.kind { @@ -1360,7 +1360,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } ty::GeneratorWitness(..) => {} _ if generator.is_none() => { - trait_ref = Some(*derived_obligation.parent_trait_ref.skip_binder()); + trait_ref = Some(derived_obligation.parent_trait_ref.skip_binder()); target_ty = Some(ty); } _ => {} diff --git a/src/librustc_trait_selection/traits/select/candidate_assembly.rs b/src/librustc_trait_selection/traits/select/candidate_assembly.rs index 4dab5814f7b7e..91c162872b215 100644 --- a/src/librustc_trait_selection/traits/select/candidate_assembly.rs +++ b/src/librustc_trait_selection/traits/select/candidate_assembly.rs @@ -220,7 +220,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Okay to skip binder because the substs on generator types never // touch bound regions, they just capture the in-scope // type/region parameters. - let self_ty = *obligation.self_ty().skip_binder(); + let self_ty = obligation.self_ty().skip_binder(); match self_ty.kind { ty::Generator(..) => { debug!( @@ -299,7 +299,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } // Okay to skip binder because what we are inspecting doesn't involve bound regions. - let self_ty = *obligation.self_ty().skip_binder(); + let self_ty = obligation.self_ty().skip_binder(); match self_ty.kind { ty::Infer(ty::TyVar(_)) => { debug!("assemble_fn_pointer_candidates: ambiguous self-type"); @@ -362,7 +362,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidates: &mut SelectionCandidateSet<'tcx>, ) -> Result<(), SelectionError<'tcx>> { // Okay to skip binder here because the tests we do below do not involve bound regions. - let self_ty = *obligation.self_ty().skip_binder(); + let self_ty = obligation.self_ty().skip_binder(); debug!("assemble_candidates_from_auto_impls(self_ty={:?})", self_ty); let def_id = obligation.predicate.def_id(); @@ -583,7 +583,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidates: &mut SelectionCandidateSet<'tcx>, ) -> Result<(), SelectionError<'tcx>> { // Okay to skip binder here because the tests we do below do not involve bound regions. - let self_ty = *obligation.self_ty().skip_binder(); + let self_ty = obligation.self_ty().skip_binder(); debug!("assemble_candidates_for_trait_alias(self_ty={:?})", self_ty); let def_id = obligation.predicate.def_id(); diff --git a/src/librustc_trait_selection/traits/select/confirmation.rs b/src/librustc_trait_selection/traits/select/confirmation.rs index 834bf17227d2e..fa970589bbbf6 100644 --- a/src/librustc_trait_selection/traits/select/confirmation.rs +++ b/src/librustc_trait_selection/traits/select/confirmation.rs @@ -326,7 +326,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // probably flatten the binder from the obligation and the binder // from the object. Have to try to make a broken test case that // results. - let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder()); + let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder()); let poly_trait_ref = match self_ty.kind { ty::Dynamic(ref data, ..) => data .principal() @@ -379,7 +379,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!("confirm_fn_pointer_candidate({:?})", obligation); // Okay to skip binder; it is reintroduced below. - let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder()); + let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder()); let sig = self_ty.fn_sig(self.tcx()); let trait_ref = closure_trait_ref_and_return_type( self.tcx(), @@ -448,7 +448,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Okay to skip binder because the substs on generator types never // touch bound regions, they just capture the in-scope // type/region parameters. - let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder()); + let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder()); let (generator_def_id, substs) = match self_ty.kind { ty::Generator(id, substs, _) => (id, substs), _ => bug!("closure candidate for non-closure {:?}", obligation), @@ -497,7 +497,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Okay to skip binder because the substs on closure types never // touch bound regions, they just capture the in-scope // type/region parameters. - let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder()); + let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder()); let (closure_def_id, substs) = match self_ty.kind { ty::Closure(id, substs) => (id, substs), _ => bug!("closure candidate for non-closure {:?}", obligation), diff --git a/src/librustc_trait_selection/traits/select/mod.rs b/src/librustc_trait_selection/traits/select/mod.rs index cff5efbfd0fd1..c41a27c6f431f 100644 --- a/src/librustc_trait_selection/traits/select/mod.rs +++ b/src/librustc_trait_selection/traits/select/mod.rs @@ -748,8 +748,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { && stack.iter().skip(1).any(|prev| { stack.obligation.param_env == prev.obligation.param_env && self.match_fresh_trait_refs( - &stack.fresh_trait_ref, - &prev.fresh_trait_ref, + stack.fresh_trait_ref, + prev.fresh_trait_ref, prev.obligation.param_env, ) }) @@ -1944,8 +1944,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn match_fresh_trait_refs( &self, - previous: &ty::PolyTraitRef<'tcx>, - current: &ty::PolyTraitRef<'tcx>, + previous: ty::PolyTraitRef<'tcx>, + current: ty::PolyTraitRef<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> bool { let mut matcher = ty::_match::Match::new(self.tcx(), param_env); diff --git a/src/librustc_trait_selection/traits/wf.rs b/src/librustc_trait_selection/traits/wf.rs index 1825c159ff3fb..ebff2dd9b23c1 100644 --- a/src/librustc_trait_selection/traits/wf.rs +++ b/src/librustc_trait_selection/traits/wf.rs @@ -695,7 +695,7 @@ pub fn object_region_bounds<'tcx>( let open_ty = tcx.mk_ty_infer(ty::FreshTy(0)); let predicates = existential_predicates.iter().filter_map(|predicate| { - if let ty::ExistentialPredicate::Projection(_) = *predicate.skip_binder() { + if let ty::ExistentialPredicate::Projection(_) = predicate.skip_binder() { None } else { Some(predicate.with_self_ty(tcx, open_ty)) diff --git a/src/librustc_traits/chalk/lowering.rs b/src/librustc_traits/chalk/lowering.rs index e09359b8b3fc1..ed021e5b9de1b 100644 --- a/src/librustc_traits/chalk/lowering.rs +++ b/src/librustc_traits/chalk/lowering.rs @@ -615,7 +615,7 @@ crate fn collect_bound_vars<'a, 'tcx, T: TypeFoldable<'tcx>>( ty: &'a Binder, ) -> (T, chalk_ir::VariableKinds>, BTreeMap) { let mut bound_vars_collector = BoundVarsCollector::new(); - ty.skip_binder().visit_with(&mut bound_vars_collector); + ty.as_ref().skip_binder().visit_with(&mut bound_vars_collector); let mut parameters = bound_vars_collector.parameters; let named_parameters: BTreeMap = bound_vars_collector .named_parameters @@ -625,7 +625,7 @@ crate fn collect_bound_vars<'a, 'tcx, T: TypeFoldable<'tcx>>( .collect(); let mut bound_var_substitutor = NamedBoundVarSubstitutor::new(tcx, &named_parameters); - let new_ty = ty.skip_binder().fold_with(&mut bound_var_substitutor); + let new_ty = ty.as_ref().skip_binder().fold_with(&mut bound_var_substitutor); for var in named_parameters.values() { parameters.insert(*var, chalk_ir::VariableKind::Lifetime); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 1b08bf2fc7710..5d1949626dd84 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1802,7 +1802,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Calling `skip_binder` is okay because the predicates are re-bound. let regular_trait_predicates = existential_trait_refs - .map(|trait_ref| ty::ExistentialPredicate::Trait(*trait_ref.skip_binder())); + .map(|trait_ref| ty::ExistentialPredicate::Trait(trait_ref.skip_binder())); let auto_trait_predicates = auto_traits .into_iter() .map(|trait_ref| ty::ExistentialPredicate::AutoTrait(trait_ref.trait_ref().def_id())); @@ -1810,7 +1810,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .chain(auto_trait_predicates) .chain( existential_projections - .map(|x| ty::ExistentialPredicate::Projection(*x.skip_binder())), + .map(|x| ty::ExistentialPredicate::Projection(x.skip_binder())), ) .collect::>(); v.sort_by(|a, b| a.stable_cmp(tcx, b)); diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 6d09ddc925ffe..fce2b18b782fb 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -188,7 +188,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } ty::Infer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid), ty::FnPtr(sig) => { - let expected_sig = ExpectedSig { cause_span: None, sig: *sig.skip_binder() }; + let expected_sig = ExpectedSig { cause_span: None, sig: sig.skip_binder() }; (Some(expected_sig), Some(ty::ClosureKind::Fn)) } _ => (None, None), @@ -501,7 +501,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for ((hir_ty, &supplied_ty), expected_ty) in decl .inputs .iter() - .zip(*supplied_sig.inputs().skip_binder()) // binder moved to (*) below + .zip(supplied_sig.inputs().skip_binder()) // binder moved to (*) below .zip(expected_sigs.liberated_sig.inputs()) // `liberated_sig` is E'. { diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index b6cd8da236260..e6b3224050e9b 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -964,7 +964,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let sig = self .at(cause, self.param_env) .trace(prev_ty, new_ty) - .lub(&a_sig, &b_sig) + .lub(a_sig, b_sig) .map(|ok| self.register_infer_ok_obligations(ok))?; // Reify both sides and return the reified fn pointer type. diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 4e97ba41dcbb3..e6217e0cc1b6e 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -502,7 +502,7 @@ fn compare_self_type<'tcx>( ty::ImplContainer(_) => impl_trait_ref.self_ty(), ty::TraitContainer(_) => tcx.types.self_param, }; - let self_arg_ty = *tcx.fn_sig(method.def_id).input(0).skip_binder(); + let self_arg_ty = tcx.fn_sig(method.def_id).input(0).skip_binder(); let param_env = ty::ParamEnv::reveal_all(); tcx.infer_ctxt().enter(|infcx| { diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index e27c2e4503910..f6991120f3479 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -227,10 +227,10 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( let predicate_matches_closure = |p: Predicate<'tcx>| { let mut relator: SimpleEqRelation<'tcx> = SimpleEqRelation::new(tcx, self_param_env); match (predicate.kind(), p.kind()) { - (ty::PredicateKind::Trait(a, _), ty::PredicateKind::Trait(b, _)) => { + (&ty::PredicateKind::Trait(a, _), &ty::PredicateKind::Trait(b, _)) => { relator.relate(a, b).is_ok() } - (ty::PredicateKind::Projection(a), ty::PredicateKind::Projection(b)) => { + (&ty::PredicateKind::Projection(a), &ty::PredicateKind::Projection(b)) => { relator.relate(a, b).is_ok() } _ => predicate == p, @@ -310,8 +310,8 @@ impl TypeRelation<'tcx> for SimpleEqRelation<'tcx> { fn relate_with_variance>( &mut self, _: ty::Variance, - a: &T, - b: &T, + a: T, + b: T, ) -> RelateResult<'tcx, T> { // Here we ignore variance because we require drop impl's types // to be *exactly* the same as to the ones in the struct definition. @@ -354,8 +354,8 @@ impl TypeRelation<'tcx> for SimpleEqRelation<'tcx> { fn binders( &mut self, - a: &ty::Binder, - b: &ty::Binder, + a: ty::Binder, + b: ty::Binder, ) -> RelateResult<'tcx, ty::Binder> where T: Relate<'tcx>, @@ -364,8 +364,8 @@ impl TypeRelation<'tcx> for SimpleEqRelation<'tcx> { // Anonymizing the LBRs is necessary to solve (Issue #59497). // After we do so, it should be totally fine to skip the binders. - let anon_a = self.tcx.anonymize_late_bound_regions(a); - let anon_b = self.tcx.anonymize_late_bound_regions(b); + let anon_a = self.tcx.anonymize_late_bound_regions(&a); + let anon_b = self.tcx.anonymize_late_bound_regions(&b); self.relate(anon_a.skip_binder(), anon_b.skip_binder())?; Ok(a.clone()) diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 1c0b22ca7370b..62e62435a08ea 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -5,10 +5,11 @@ use crate::require_same_types; use rustc_errors::struct_span_err; use rustc_hir as hir; +use rustc_hir::def_id::DefId; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_span::symbol::Symbol; +use rustc_span::symbol::{kw, sym, Symbol}; use rustc_target::spec::abi::Abi; use std::iter; @@ -16,14 +17,13 @@ use std::iter; fn equate_intrinsic_type<'tcx>( tcx: TyCtxt<'tcx>, it: &hir::ForeignItem<'_>, + def_id: DefId, n_tps: usize, abi: Abi, safety: hir::Unsafety, inputs: Vec>, output: Ty<'tcx>, ) { - let def_id = tcx.hir().local_def_id(it.hir_id); - match it.kind { hir::ForeignItemKind::Fn(..) => {} _ => { @@ -67,15 +67,43 @@ fn equate_intrinsic_type<'tcx>( } /// Returns `true` if the given intrinsic is unsafe to call or not. -pub fn intrinsic_operation_unsafety(intrinsic: &str) -> hir::Unsafety { +pub fn intrinsic_operation_unsafety(intrinsic: Symbol) -> hir::Unsafety { match intrinsic { - "abort" | "size_of" | "min_align_of" | "needs_drop" | "caller_location" | "size_of_val" - | "min_align_of_val" | "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" - | "wrapping_add" | "wrapping_sub" | "wrapping_mul" | "saturating_add" - | "saturating_sub" | "rotate_left" | "rotate_right" | "ctpop" | "ctlz" | "cttz" - | "bswap" | "bitreverse" | "discriminant_value" | "type_id" | "likely" | "unlikely" - | "ptr_guaranteed_eq" | "ptr_guaranteed_ne" | "minnumf32" | "minnumf64" | "maxnumf32" - | "maxnumf64" | "type_name" | "variant_count" => hir::Unsafety::Normal, + sym::abort + | sym::size_of + | sym::min_align_of + | sym::needs_drop + | sym::caller_location + | sym::size_of_val + | sym::min_align_of_val + | sym::add_with_overflow + | sym::sub_with_overflow + | sym::mul_with_overflow + | sym::wrapping_add + | sym::wrapping_sub + | sym::wrapping_mul + | sym::saturating_add + | sym::saturating_sub + | sym::rotate_left + | sym::rotate_right + | sym::ctpop + | sym::ctlz + | sym::cttz + | sym::bswap + | sym::bitreverse + | sym::discriminant_value + | sym::type_id + | sym::likely + | sym::unlikely + | sym::ptr_guaranteed_eq + | sym::ptr_guaranteed_ne + | sym::minnumf32 + | sym::minnumf64 + | sym::maxnumf32 + | sym::rustc_peek + | sym::maxnumf64 + | sym::type_name + | sym::variant_count => hir::Unsafety::Normal, _ => hir::Unsafety::Unsafe, } } @@ -84,7 +112,9 @@ pub fn intrinsic_operation_unsafety(intrinsic: &str) -> hir::Unsafety { /// and in libcore/intrinsics.rs pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { let param = |n| tcx.mk_ty_param(n, Symbol::intern(&format!("P{}", n))); - let name = it.ident.as_str(); + let def_id = tcx.hir().local_def_id(it.hir_id).to_def_id(); + let intrinsic_name = tcx.item_name(def_id); + let name_str = intrinsic_name.as_str(); let mk_va_list_ty = |mutbl| { tcx.lang_items().va_list().map(|did| { @@ -98,8 +128,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { }) }; - let (n_tps, inputs, output, unsafety) = if name.starts_with("atomic_") { - let split: Vec<&str> = name.split('_').collect(); + let (n_tps, inputs, output, unsafety) = if name_str.starts_with("atomic_") { + let split: Vec<&str> = name_str.split('_').collect(); assert!(split.len() >= 2, "Atomic intrinsic in an incorrect format"); //We only care about the operation here @@ -129,32 +159,30 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { } }; (n_tps, inputs, output, hir::Unsafety::Unsafe) - } else if &name[..] == "abort" { - (0, Vec::new(), tcx.types.never, hir::Unsafety::Normal) - } else if &name[..] == "unreachable" { - (0, Vec::new(), tcx.types.never, hir::Unsafety::Unsafe) } else { - let unsafety = intrinsic_operation_unsafety(&name[..]); - let (n_tps, inputs, output) = match &name[..] { - "breakpoint" => (0, Vec::new(), tcx.mk_unit()), - "size_of" | "pref_align_of" | "min_align_of" | "variant_count" => { + let unsafety = intrinsic_operation_unsafety(intrinsic_name); + let (n_tps, inputs, output) = match intrinsic_name { + sym::abort => (0, Vec::new(), tcx.types.never), + sym::unreachable => (0, Vec::new(), tcx.types.never), + sym::breakpoint => (0, Vec::new(), tcx.mk_unit()), + sym::size_of | sym::pref_align_of | sym::min_align_of | sym::variant_count => { (1, Vec::new(), tcx.types.usize) } - "size_of_val" | "min_align_of_val" => { + sym::size_of_val | sym::min_align_of_val => { (1, vec![tcx.mk_imm_ptr(param(0))], tcx.types.usize) } - "rustc_peek" => (1, vec![param(0)], param(0)), - "caller_location" => (0, vec![], tcx.caller_location_ty()), - "assert_inhabited" | "assert_zero_valid" | "assert_uninit_valid" => { + sym::rustc_peek => (1, vec![param(0)], param(0)), + sym::caller_location => (0, vec![], tcx.caller_location_ty()), + sym::assert_inhabited | sym::assert_zero_valid | sym::assert_uninit_valid => { (1, Vec::new(), tcx.mk_unit()) } - "forget" => (1, vec![param(0)], tcx.mk_unit()), - "transmute" => (2, vec![param(0)], param(1)), - "move_val_init" => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()), - "prefetch_read_data" - | "prefetch_write_data" - | "prefetch_read_instruction" - | "prefetch_write_instruction" => ( + sym::forget => (1, vec![param(0)], tcx.mk_unit()), + sym::transmute => (2, vec![param(0)], param(1)), + sym::move_val_init => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()), + sym::prefetch_read_data + | sym::prefetch_write_data + | sym::prefetch_read_instruction + | sym::prefetch_write_instruction => ( 1, vec![ tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }), @@ -162,12 +190,12 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { ], tcx.mk_unit(), ), - "drop_in_place" => (1, vec![tcx.mk_mut_ptr(param(0))], tcx.mk_unit()), - "needs_drop" => (1, Vec::new(), tcx.types.bool), + sym::drop_in_place => (1, vec![tcx.mk_mut_ptr(param(0))], tcx.mk_unit()), + sym::needs_drop => (1, Vec::new(), tcx.types.bool), - "type_name" => (1, Vec::new(), tcx.mk_static_str()), - "type_id" => (1, Vec::new(), tcx.types.u64), - "offset" | "arith_offset" => ( + sym::type_name => (1, Vec::new(), tcx.mk_static_str()), + sym::type_id => (1, Vec::new(), tcx.types.u64), + sym::offset | sym::arith_offset => ( 1, vec![ tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }), @@ -175,7 +203,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { ], tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }), ), - "copy" | "copy_nonoverlapping" => ( + sym::copy | sym::copy_nonoverlapping => ( 1, vec![ tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }), @@ -184,7 +212,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { ], tcx.mk_unit(), ), - "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => ( + sym::volatile_copy_memory | sym::volatile_copy_nonoverlapping_memory => ( 1, vec![ tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Mut }), @@ -193,7 +221,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { ], tcx.mk_unit(), ), - "write_bytes" | "volatile_set_memory" => ( + sym::write_bytes | sym::volatile_set_memory => ( 1, vec![ tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Mut }), @@ -202,93 +230,98 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { ], tcx.mk_unit(), ), - "sqrtf32" => (0, vec![tcx.types.f32], tcx.types.f32), - "sqrtf64" => (0, vec![tcx.types.f64], tcx.types.f64), - "powif32" => (0, vec![tcx.types.f32, tcx.types.i32], tcx.types.f32), - "powif64" => (0, vec![tcx.types.f64, tcx.types.i32], tcx.types.f64), - "sinf32" => (0, vec![tcx.types.f32], tcx.types.f32), - "sinf64" => (0, vec![tcx.types.f64], tcx.types.f64), - "cosf32" => (0, vec![tcx.types.f32], tcx.types.f32), - "cosf64" => (0, vec![tcx.types.f64], tcx.types.f64), - "powf32" => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32), - "powf64" => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), - "expf32" => (0, vec![tcx.types.f32], tcx.types.f32), - "expf64" => (0, vec![tcx.types.f64], tcx.types.f64), - "exp2f32" => (0, vec![tcx.types.f32], tcx.types.f32), - "exp2f64" => (0, vec![tcx.types.f64], tcx.types.f64), - "logf32" => (0, vec![tcx.types.f32], tcx.types.f32), - "logf64" => (0, vec![tcx.types.f64], tcx.types.f64), - "log10f32" => (0, vec![tcx.types.f32], tcx.types.f32), - "log10f64" => (0, vec![tcx.types.f64], tcx.types.f64), - "log2f32" => (0, vec![tcx.types.f32], tcx.types.f32), - "log2f64" => (0, vec![tcx.types.f64], tcx.types.f64), - "fmaf32" => (0, vec![tcx.types.f32, tcx.types.f32, tcx.types.f32], tcx.types.f32), - "fmaf64" => (0, vec![tcx.types.f64, tcx.types.f64, tcx.types.f64], tcx.types.f64), - "fabsf32" => (0, vec![tcx.types.f32], tcx.types.f32), - "fabsf64" => (0, vec![tcx.types.f64], tcx.types.f64), - "minnumf32" => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32), - "minnumf64" => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), - "maxnumf32" => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32), - "maxnumf64" => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), - "copysignf32" => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32), - "copysignf64" => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), - "floorf32" => (0, vec![tcx.types.f32], tcx.types.f32), - "floorf64" => (0, vec![tcx.types.f64], tcx.types.f64), - "ceilf32" => (0, vec![tcx.types.f32], tcx.types.f32), - "ceilf64" => (0, vec![tcx.types.f64], tcx.types.f64), - "truncf32" => (0, vec![tcx.types.f32], tcx.types.f32), - "truncf64" => (0, vec![tcx.types.f64], tcx.types.f64), - "rintf32" => (0, vec![tcx.types.f32], tcx.types.f32), - "rintf64" => (0, vec![tcx.types.f64], tcx.types.f64), - "nearbyintf32" => (0, vec![tcx.types.f32], tcx.types.f32), - "nearbyintf64" => (0, vec![tcx.types.f64], tcx.types.f64), - "roundf32" => (0, vec![tcx.types.f32], tcx.types.f32), - "roundf64" => (0, vec![tcx.types.f64], tcx.types.f64), - - "volatile_load" | "unaligned_volatile_load" => { + sym::sqrtf32 => (0, vec![tcx.types.f32], tcx.types.f32), + sym::sqrtf64 => (0, vec![tcx.types.f64], tcx.types.f64), + sym::powif32 => (0, vec![tcx.types.f32, tcx.types.i32], tcx.types.f32), + sym::powif64 => (0, vec![tcx.types.f64, tcx.types.i32], tcx.types.f64), + sym::sinf32 => (0, vec![tcx.types.f32], tcx.types.f32), + sym::sinf64 => (0, vec![tcx.types.f64], tcx.types.f64), + sym::cosf32 => (0, vec![tcx.types.f32], tcx.types.f32), + sym::cosf64 => (0, vec![tcx.types.f64], tcx.types.f64), + sym::powf32 => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32), + sym::powf64 => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), + sym::expf32 => (0, vec![tcx.types.f32], tcx.types.f32), + sym::expf64 => (0, vec![tcx.types.f64], tcx.types.f64), + sym::exp2f32 => (0, vec![tcx.types.f32], tcx.types.f32), + sym::exp2f64 => (0, vec![tcx.types.f64], tcx.types.f64), + sym::logf32 => (0, vec![tcx.types.f32], tcx.types.f32), + sym::logf64 => (0, vec![tcx.types.f64], tcx.types.f64), + sym::log10f32 => (0, vec![tcx.types.f32], tcx.types.f32), + sym::log10f64 => (0, vec![tcx.types.f64], tcx.types.f64), + sym::log2f32 => (0, vec![tcx.types.f32], tcx.types.f32), + sym::log2f64 => (0, vec![tcx.types.f64], tcx.types.f64), + sym::fmaf32 => (0, vec![tcx.types.f32, tcx.types.f32, tcx.types.f32], tcx.types.f32), + sym::fmaf64 => (0, vec![tcx.types.f64, tcx.types.f64, tcx.types.f64], tcx.types.f64), + sym::fabsf32 => (0, vec![tcx.types.f32], tcx.types.f32), + sym::fabsf64 => (0, vec![tcx.types.f64], tcx.types.f64), + sym::minnumf32 => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32), + sym::minnumf64 => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), + sym::maxnumf32 => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32), + sym::maxnumf64 => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), + sym::copysignf32 => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32), + sym::copysignf64 => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), + sym::floorf32 => (0, vec![tcx.types.f32], tcx.types.f32), + sym::floorf64 => (0, vec![tcx.types.f64], tcx.types.f64), + sym::ceilf32 => (0, vec![tcx.types.f32], tcx.types.f32), + sym::ceilf64 => (0, vec![tcx.types.f64], tcx.types.f64), + sym::truncf32 => (0, vec![tcx.types.f32], tcx.types.f32), + sym::truncf64 => (0, vec![tcx.types.f64], tcx.types.f64), + sym::rintf32 => (0, vec![tcx.types.f32], tcx.types.f32), + sym::rintf64 => (0, vec![tcx.types.f64], tcx.types.f64), + sym::nearbyintf32 => (0, vec![tcx.types.f32], tcx.types.f32), + sym::nearbyintf64 => (0, vec![tcx.types.f64], tcx.types.f64), + sym::roundf32 => (0, vec![tcx.types.f32], tcx.types.f32), + sym::roundf64 => (0, vec![tcx.types.f64], tcx.types.f64), + + sym::volatile_load | sym::unaligned_volatile_load => { (1, vec![tcx.mk_imm_ptr(param(0))], param(0)) } - "volatile_store" | "unaligned_volatile_store" => { + sym::volatile_store | sym::unaligned_volatile_store => { (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()) } - "ctpop" | "ctlz" | "ctlz_nonzero" | "cttz" | "cttz_nonzero" | "bswap" - | "bitreverse" => (1, vec![param(0)], param(0)), + sym::ctpop + | sym::ctlz + | sym::ctlz_nonzero + | sym::cttz + | sym::cttz_nonzero + | sym::bswap + | sym::bitreverse => (1, vec![param(0)], param(0)), - "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" => { + sym::add_with_overflow | sym::sub_with_overflow | sym::mul_with_overflow => { (1, vec![param(0), param(0)], tcx.intern_tup(&[param(0), tcx.types.bool])) } - "ptr_guaranteed_eq" | "ptr_guaranteed_ne" => { + sym::ptr_guaranteed_eq | sym::ptr_guaranteed_ne => { (1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.bool) } - "ptr_offset_from" => { + sym::ptr_offset_from => { (1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.isize) } - "unchecked_div" | "unchecked_rem" | "exact_div" => { + sym::unchecked_div | sym::unchecked_rem | sym::exact_div => { (1, vec![param(0), param(0)], param(0)) } - "unchecked_shl" | "unchecked_shr" | "rotate_left" | "rotate_right" => { + sym::unchecked_shl | sym::unchecked_shr | sym::rotate_left | sym::rotate_right => { (1, vec![param(0), param(0)], param(0)) } - "unchecked_add" | "unchecked_sub" | "unchecked_mul" => { + sym::unchecked_add | sym::unchecked_sub | sym::unchecked_mul => { (1, vec![param(0), param(0)], param(0)) } - "wrapping_add" | "wrapping_sub" | "wrapping_mul" => { + sym::wrapping_add | sym::wrapping_sub | sym::wrapping_mul => { (1, vec![param(0), param(0)], param(0)) } - "saturating_add" | "saturating_sub" => (1, vec![param(0), param(0)], param(0)), - "fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" => { + sym::saturating_add | sym::saturating_sub => (1, vec![param(0), param(0)], param(0)), + sym::fadd_fast | sym::fsub_fast | sym::fmul_fast | sym::fdiv_fast | sym::frem_fast => { (1, vec![param(0), param(0)], param(0)) } - "float_to_int_unchecked" => (2, vec![param(0)], param(1)), + sym::float_to_int_unchecked => (2, vec![param(0)], param(1)), - "assume" => (0, vec![tcx.types.bool], tcx.mk_unit()), - "likely" => (0, vec![tcx.types.bool], tcx.types.bool), - "unlikely" => (0, vec![tcx.types.bool], tcx.types.bool), + sym::assume => (0, vec![tcx.types.bool], tcx.mk_unit()), + sym::likely => (0, vec![tcx.types.bool], tcx.types.bool), + sym::unlikely => (0, vec![tcx.types.bool], tcx.types.bool), - "discriminant_value" => { + sym::discriminant_value => { let assoc_items = tcx.associated_items(tcx.lang_items().discriminant_kind_trait().unwrap()); let discriminant_def_id = assoc_items.in_definition_order().next().unwrap().def_id; @@ -303,7 +336,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { ) } - "try" => { + kw::Try => { let mut_u8 = tcx.mk_mut_ptr(tcx.types.u8); let try_fn_ty = ty::Binder::bind(tcx.mk_fn_sig( iter::once(mut_u8), @@ -326,12 +359,12 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { ) } - "va_start" | "va_end" => match mk_va_list_ty(hir::Mutability::Mut) { + sym::va_start | sym::va_end => match mk_va_list_ty(hir::Mutability::Mut) { Some((va_list_ref_ty, _)) => (0, vec![va_list_ref_ty], tcx.mk_unit()), None => bug!("`va_list` language item needed for C-variadic intrinsics"), }, - "va_copy" => match mk_va_list_ty(hir::Mutability::Not) { + sym::va_copy => match mk_va_list_ty(hir::Mutability::Not) { Some((va_list_ref_ty, va_list_ty)) => { let va_list_ptr_ty = tcx.mk_mut_ptr(va_list_ty); (0, vec![va_list_ptr_ty, va_list_ref_ty], tcx.mk_unit()) @@ -339,28 +372,28 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { None => bug!("`va_list` language item needed for C-variadic intrinsics"), }, - "va_arg" => match mk_va_list_ty(hir::Mutability::Mut) { + sym::va_arg => match mk_va_list_ty(hir::Mutability::Mut) { Some((va_list_ref_ty, _)) => (1, vec![va_list_ref_ty], param(0)), None => bug!("`va_list` language item needed for C-variadic intrinsics"), }, - "nontemporal_store" => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()), + sym::nontemporal_store => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()), - "miri_start_panic" => { + sym::miri_start_panic => { // FIXME - the relevant types aren't lang items, // so it's not trivial to check this return; } - "count_code_region" => (0, vec![tcx.types.u32], tcx.mk_unit()), + sym::count_code_region => (0, vec![tcx.types.u32], tcx.mk_unit()), - ref other => { + other => { struct_span_err!( tcx.sess, it.span, E0093, "unrecognized intrinsic function: `{}`", - *other + other, ) .span_label(it.span, "unrecognized intrinsic") .emit(); @@ -369,7 +402,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { }; (n_tps, inputs, output, unsafety) }; - equate_intrinsic_type(tcx, it, n_tps, Abi::RustIntrinsic, unsafety, inputs, output) + equate_intrinsic_type(tcx, it, def_id, n_tps, Abi::RustIntrinsic, unsafety, inputs, output) } /// Type-check `extern "platform-intrinsic" { ... }` functions. @@ -379,6 +412,7 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) tcx.mk_ty_param(n, name) }; + let def_id = tcx.hir().local_def_id(it.hir_id).to_def_id(); let name = it.ident.as_str(); let (n_tps, inputs, output) = match &*name { @@ -453,6 +487,7 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) equate_intrinsic_type( tcx, it, + def_id, n_tps, Abi::PlatformIntrinsic, hir::Unsafety::Unsafe, diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 67bdd04d3715c..b75dac52b93e5 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -608,7 +608,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Adt(def, _) => bound_spans.push((def_span(def.did), msg)), // Point at the trait object that couldn't satisfy the bound. ty::Dynamic(preds, _) => { - for pred in *preds.skip_binder() { + for pred in preds.skip_binder() { match pred { ty::ExistentialPredicate::Trait(tr) => { bound_spans.push((def_span(tr.def_id), msg.clone())) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 7c4048ab22302..b617937d6bd54 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2446,7 +2446,7 @@ fn bounds_from_generic_predicates( /// Return placeholder code for the given function. fn fn_sig_suggestion( tcx: TyCtxt<'_>, - sig: &ty::FnSig<'_>, + sig: ty::FnSig<'_>, ident: Ident, predicates: ty::GenericPredicates<'_>, assoc: &ty::AssocItem, diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index 94a5685a992fe..a1e060b97ad28 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -500,7 +500,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return false; } // We're emitting a suggestion, so we can just ignore regions - let fn_sig = *self.tcx.fn_sig(def_id).skip_binder(); + let fn_sig = self.tcx.fn_sig(def_id).skip_binder(); let other_ty = if let FnDef(def_id, _) = other_ty.kind { if !self.tcx.has_typeck_tables(def_id) { diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index a45a44a6801e8..3b203dd222afb 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -216,7 +216,7 @@ fn check_object_overlap<'tcx>( let component_def_ids = data.iter().flat_map(|predicate| { match predicate.skip_binder() { ty::ExistentialPredicate::Trait(tr) => Some(tr.def_id), - ty::ExistentialPredicate::AutoTrait(def_id) => Some(*def_id), + ty::ExistentialPredicate::AutoTrait(def_id) => Some(def_id), // An associated type projection necessarily comes with // an additional `Trait` requirement. ty::ExistentialPredicate::Projection(..) => None, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index b486e3d3536c9..cc491c527db0b 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -2063,7 +2063,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>( ident: Ident, ) -> ty::PolyFnSig<'tcx> { let unsafety = if abi == abi::Abi::RustIntrinsic { - intrinsic_operation_unsafety(&tcx.item_name(def_id).as_str()) + intrinsic_operation_unsafety(tcx.item_name(def_id)) } else { hir::Unsafety::Unsafe }; @@ -2102,11 +2102,11 @@ fn compute_sig_of_foreign_fn_decl<'tcx>( .emit(); } }; - for (input, ty) in decl.inputs.iter().zip(*fty.inputs().skip_binder()) { + for (input, ty) in decl.inputs.iter().zip(fty.inputs().skip_binder()) { check(&input, ty) } if let hir::FnRetTy::Return(ref ty) = decl.output { - check(&ty, *fty.output().skip_binder()) + check(&ty, fty.output().skip_binder()) } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 73fe87b05d477..bfe8464347d29 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -347,7 +347,7 @@ impl Clean for (ty::PolyTraitRef<'_>, &[TypeBinding]) { GenericBound::TraitBound( PolyTrait { - trait_: (*poly_trait_ref.skip_binder(), bounds).clean(cx), + trait_: (poly_trait_ref.skip_binder(), bounds).clean(cx), generic_params: late_bound_regions, }, hir::TraitBoundModifier::None, @@ -549,7 +549,7 @@ impl<'tcx> Clean> for ty::PolyOutlivesPredicate, impl<'tcx> Clean for ty::PolyProjectionPredicate<'tcx> { fn clean(&self, cx: &DocContext<'_>) -> WherePredicate { - let ty::ProjectionPredicate { projection_ty, ty } = *self.skip_binder(); + let ty::ProjectionPredicate { projection_ty, ty } = self.skip_binder(); WherePredicate::EqPredicate { lhs: projection_ty.clean(cx), rhs: ty.clean(cx) } } } @@ -1177,7 +1177,7 @@ impl Clean for ty::AssocItem { ty::ImplContainer(def_id) => cx.tcx.type_of(def_id), ty::TraitContainer(_) => cx.tcx.types.self_param, }; - let self_arg_ty = *sig.input(0).skip_binder(); + let self_arg_ty = sig.input(0).skip_binder(); if self_arg_ty == self_ty { decl.inputs.values[0].type_ = Generic(String::from("Self")); } else if let ty::Ref(_, ty, _) = self_arg_ty.kind { @@ -1679,7 +1679,7 @@ impl<'tcx> Clean for Ty<'tcx> { if let ty::PredicateKind::Projection(proj) = pred.kind() { let proj = proj.skip_binder(); if proj.projection_ty.trait_ref(cx.tcx) - == *trait_ref.skip_binder() + == trait_ref.skip_binder() { Some(TypeBinding { name: cx diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index d972cf6db18cf..0b3386c05d54b 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -1281,11 +1281,84 @@ mod self_upper_keyword {} #[doc(keyword = "static")] // -/// A place that is valid for the duration of a program. +/// A static item is a value which is valid for the entire duration of your +/// program (a `'static` lifetime). /// -/// The documentation for this keyword is [not yet complete]. Pull requests welcome! +/// On the surface, `static` items seem very similar to [`const`]s: both contain +/// a value, both require type annotations and both can only be initialized with +/// constant functions and values. However, `static`s are notably different in +/// that they represent a location in memory. That means that you can have +/// references to `static` items and potentially even modify them, making them +/// essentially global variables. /// -/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601 +/// Static items do not call [`drop`] at the end of the program. +/// +/// There are two types of `static` items: those declared in association with +/// the [`mut`] keyword and those without. +/// +/// Static items cannot be moved: +/// +/// ```rust,compile_fail,E0507 +/// static VEC: Vec = vec![]; +/// +/// fn move_vec(v: Vec) -> Vec { +/// v +/// } +/// +/// // This line causes an error +/// move_vec(VEC); +/// ``` +/// +/// # Simple `static`s +/// +/// Accessing non-[`mut`] `static` items is considered safe, but some +/// restrictions apply. Most notably, the type of a `static` value needs to +/// implement the [`Sync`] trait, ruling out interior mutability containers +/// like [`RefCell`]. See the [Reference] for more information. +/// +/// ```rust +/// static FOO: [i32; 5] = [1, 2, 3, 4, 5]; +/// +/// let r1 = &FOO as *const _; +/// let r2 = &FOO as *const _; +/// // With a strictly read-only static, references will have the same adress +/// assert_eq!(r1, r2); +/// // A static item can be used just like a variable in many cases +/// println!("{:?}", FOO); +/// ``` +/// +/// # Mutable `static`s +/// +/// If a `static` item is declared with the [`mut`] keyword, then it is allowed +/// to be modified by the program. However, accessing mutable `static`s can +/// cause undefined behavior in a number of ways, for example due to data races +/// in a multithreaded context. As such, all accesses to mutable `static`s +/// require an [`unsafe`] block. +/// +/// Despite their unsafety, mutable `static`s are necessary in many contexts: +/// they can be used to represent global state shared by the whole program or in +/// [`extern`] blocks to bind to variables from C libraries. +/// +/// In an [`extern`] block: +/// +/// ```rust,no_run +/// # #![allow(dead_code)] +/// extern "C" { +/// static mut ERROR_MESSAGE: *mut std::os::raw::c_char; +/// } +/// ``` +/// +/// Mutable `static`s, just like simple `static`s, have some restrictions that +/// apply to them. See the [Reference] for more information. +/// +/// [`const`]: keyword.const.html +/// [`extern`]: keyword.extern.html +/// [`mut`]: keyword.mut.html +/// [`unsafe`]: keyword.unsafe.html +/// [`drop`]: mem/fn.drop.html +/// [`Sync`]: marker/trait.Sync.html +/// [`RefCell`]: cell/struct.RefCell.html +/// [Reference]: ../reference/items/static-items.html mod static_keyword {} #[doc(keyword = "struct")] @@ -1463,9 +1536,44 @@ mod true_keyword {} // /// Define an alias for an existing type. /// -/// The documentation for this keyword is [not yet complete]. Pull requests welcome! +/// The syntax is `type Name = ExistingType;`. /// -/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601 +/// # Examples +/// +/// `type` does **not** create a new type: +/// +/// ```rust +/// type Meters = u32; +/// type Kilograms = u32; +/// +/// let m: Meters = 3; +/// let k: Kilograms = 3; +/// +/// assert_eq!(m, k); +/// ``` +/// +/// In traits, `type` is used to declare an [associated type]: +/// +/// ```rust +/// trait Iterator { +/// // associated type declaration +/// type Item; +/// fn next(&mut self) -> Option; +/// } +/// +/// struct Once(Option); +/// +/// impl Iterator for Once { +/// // associated type definition +/// type Item = T; +/// fn next(&mut self) -> Option { +/// self.0.take() +/// } +/// } +/// ``` +/// +/// [`trait`]: keyword.trait.html +/// [associated type]: ../reference/items/associated-items.html#associated-types mod type_keyword {} #[doc(keyword = "unsafe")] diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index ef699ede2a140..372038df54f2e 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -316,7 +316,7 @@ #![feature(toowned_clone_into)] #![feature(total_cmp)] #![feature(trace_macros)] -#![feature(track_caller)] +#![cfg_attr(bootstrap, feature(track_caller))] #![feature(try_reserve)] #![feature(unboxed_closures)] #![feature(untagged_unions)] diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index 640c9f3636d4b..193ab5b47ef13 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -61,6 +61,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { c::ERROR_FILE_NOT_FOUND => return ErrorKind::NotFound, c::ERROR_PATH_NOT_FOUND => return ErrorKind::NotFound, c::ERROR_NO_DATA => return ErrorKind::BrokenPipe, + c::ERROR_INVALID_PARAMETER => return ErrorKind::InvalidInput, c::ERROR_SEM_TIMEOUT | c::WAIT_TIMEOUT | c::ERROR_DRIVER_CANCEL_TIMEOUT diff --git a/src/test/ui/anon-params/anon-params-denied-2018.stderr b/src/test/ui/anon-params/anon-params-denied-2018.stderr index e7a806a846820..840294db0830a 100644 --- a/src/test/ui/anon-params/anon-params-denied-2018.stderr +++ b/src/test/ui/anon-params/anon-params-denied-2018.stderr @@ -9,7 +9,7 @@ help: if this is a `self` type, give it a parameter name | LL | fn foo(self: i32); | ^^^^^^^^^ -help: if this was a parameter name, give it a type +help: if this is a parameter name, give it a type | LL | fn foo(i32: TypeName); | ^^^^^^^^^^^^^ @@ -29,7 +29,7 @@ help: if this is a `self` type, give it a parameter name | LL | fn bar_with_default_impl(self: String, String) {} | ^^^^^^^^^^^^ -help: if this was a parameter name, give it a type +help: if this is a parameter name, give it a type | LL | fn bar_with_default_impl(String: TypeName, String) {} | ^^^^^^^^^^^^^^^^ @@ -45,7 +45,7 @@ LL | fn bar_with_default_impl(String, String) {} | ^ expected one of `:`, `@`, or `|` | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) -help: if this was a parameter name, give it a type +help: if this is a parameter name, give it a type | LL | fn bar_with_default_impl(String, String: TypeName) {} | ^^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL | fn baz(a:usize, b, c: usize) -> usize { | ^ expected one of `:`, `@`, or `|` | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) -help: if this was a parameter name, give it a type +help: if this is a parameter name, give it a type | LL | fn baz(a:usize, b: TypeName, c: usize) -> usize { | ^^^^^^^^^^^ diff --git a/src/test/ui/asm/sym.rs b/src/test/ui/asm/sym.rs index 8cff16aa75f69..9931697e4129c 100644 --- a/src/test/ui/asm/sym.rs +++ b/src/test/ui/asm/sym.rs @@ -3,7 +3,7 @@ // only-linux // run-pass -#![feature(asm, track_caller, thread_local)] +#![feature(asm, thread_local)] extern "C" fn f1() -> i32 { 111 diff --git a/src/test/ui/feature-gates/feature-gate-track_caller.rs b/src/test/ui/feature-gates/feature-gate-track_caller.rs deleted file mode 100644 index 5865cf0a4f754..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-track_caller.rs +++ /dev/null @@ -1,5 +0,0 @@ -#[track_caller] -fn f() {} -//~^^ ERROR the `#[track_caller]` attribute is an experimental feature - -fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-track_caller.stderr b/src/test/ui/feature-gates/feature-gate-track_caller.stderr deleted file mode 100644 index 8ceab501617ee..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-track_caller.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0658]: the `#[track_caller]` attribute is an experimental feature - --> $DIR/feature-gate-track_caller.rs:1:1 - | -LL | #[track_caller] - | ^^^^^^^^^^^^^^^ - | - = note: see issue #47809 for more information - = help: add `#![feature(track_caller)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/macros/issue-68060.rs b/src/test/ui/macros/issue-68060.rs index bc70f8ffec2b2..8772e98b6e9bb 100644 --- a/src/test/ui/macros/issue-68060.rs +++ b/src/test/ui/macros/issue-68060.rs @@ -1,5 +1,3 @@ -#![feature(track_caller)] - fn main() { (0..) .map( diff --git a/src/test/ui/macros/issue-68060.stderr b/src/test/ui/macros/issue-68060.stderr index 22187c4a4098a..b9b2f946c5967 100644 --- a/src/test/ui/macros/issue-68060.stderr +++ b/src/test/ui/macros/issue-68060.stderr @@ -1,5 +1,5 @@ error[E0658]: `#[target_feature(..)]` can only be applied to `unsafe` functions - --> $DIR/issue-68060.rs:6:13 + --> $DIR/issue-68060.rs:4:13 | LL | #[target_feature(enable = "")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -11,13 +11,13 @@ LL | |_| (), = help: add `#![feature(target_feature_11)]` to the crate attributes to enable error: the feature named `` is not valid for this target - --> $DIR/issue-68060.rs:6:30 + --> $DIR/issue-68060.rs:4:30 | LL | #[target_feature(enable = "")] | ^^^^^^^^^^^ `` is not valid for this target error[E0737]: `#[track_caller]` requires Rust ABI - --> $DIR/issue-68060.rs:9:13 + --> $DIR/issue-68060.rs:7:13 | LL | #[track_caller] | ^^^^^^^^^^^^^^^ diff --git a/src/test/ui/mir-dataflow/def-inits-1.rs b/src/test/ui/mir-dataflow/def-inits-1.rs index 91d41e9b5794e..30460824a1678 100644 --- a/src/test/ui/mir-dataflow/def-inits-1.rs +++ b/src/test/ui/mir-dataflow/def-inits-1.rs @@ -11,13 +11,13 @@ struct S(i32); fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S { let ret; // `ret` starts off uninitialized - unsafe { rustc_peek(&ret); } //~ ERROR rustc_peek: bit not set + rustc_peek(&ret); //~ ERROR rustc_peek: bit not set // All function formal parameters start off initialized. - unsafe { rustc_peek(&x) }; - unsafe { rustc_peek(&y) }; - unsafe { rustc_peek(&z) }; + rustc_peek(&x); + rustc_peek(&y); + rustc_peek(&z); ret = if test { ::std::mem::replace(x, y) @@ -27,21 +27,21 @@ fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S { }; // `z` may be uninitialized here. - unsafe { rustc_peek(&z); } //~ ERROR rustc_peek: bit not set + rustc_peek(&z); //~ ERROR rustc_peek: bit not set // `y` is definitely uninitialized here. - unsafe { rustc_peek(&y); } //~ ERROR rustc_peek: bit not set + rustc_peek(&y); //~ ERROR rustc_peek: bit not set // `x` is still (definitely) initialized (replace above is a reborrow). - unsafe { rustc_peek(&x); } + rustc_peek(&x); ::std::mem::drop(x); // `x` is *definitely* uninitialized here - unsafe { rustc_peek(&x); } //~ ERROR rustc_peek: bit not set + rustc_peek(&x); //~ ERROR rustc_peek: bit not set // `ret` is now definitely initialized (via `if` above). - unsafe { rustc_peek(&ret); } + rustc_peek(&ret); ret } diff --git a/src/test/ui/mir-dataflow/def-inits-1.stderr b/src/test/ui/mir-dataflow/def-inits-1.stderr index 48d8450489488..e2bddb54d9ba8 100644 --- a/src/test/ui/mir-dataflow/def-inits-1.stderr +++ b/src/test/ui/mir-dataflow/def-inits-1.stderr @@ -1,26 +1,26 @@ error: rustc_peek: bit not set - --> $DIR/def-inits-1.rs:14:14 + --> $DIR/def-inits-1.rs:14:5 | -LL | unsafe { rustc_peek(&ret); } - | ^^^^^^^^^^^^^^^^ +LL | rustc_peek(&ret); + | ^^^^^^^^^^^^^^^^ error: rustc_peek: bit not set - --> $DIR/def-inits-1.rs:30:14 + --> $DIR/def-inits-1.rs:30:5 | -LL | unsafe { rustc_peek(&z); } - | ^^^^^^^^^^^^^^ +LL | rustc_peek(&z); + | ^^^^^^^^^^^^^^ error: rustc_peek: bit not set - --> $DIR/def-inits-1.rs:33:14 + --> $DIR/def-inits-1.rs:33:5 | -LL | unsafe { rustc_peek(&y); } - | ^^^^^^^^^^^^^^ +LL | rustc_peek(&y); + | ^^^^^^^^^^^^^^ error: rustc_peek: bit not set - --> $DIR/def-inits-1.rs:41:14 + --> $DIR/def-inits-1.rs:41:5 | -LL | unsafe { rustc_peek(&x); } - | ^^^^^^^^^^^^^^ +LL | rustc_peek(&x); + | ^^^^^^^^^^^^^^ error: stop_after_dataflow ended compilation diff --git a/src/test/ui/mir-dataflow/indirect-mutation-offset.rs b/src/test/ui/mir-dataflow/indirect-mutation-offset.rs index caa307e269fe7..374a9f75a134b 100644 --- a/src/test/ui/mir-dataflow/indirect-mutation-offset.rs +++ b/src/test/ui/mir-dataflow/indirect-mutation-offset.rs @@ -38,7 +38,7 @@ const BOO: i32 = { *rmut_cell = 42; // Mutates `x` indirectly even though `x` is not marked indirectly mutable!!! let val = *rmut_cell; - unsafe { rustc_peek(x) }; //~ ERROR rustc_peek: bit not set + rustc_peek(x); //~ ERROR rustc_peek: bit not set val }; diff --git a/src/test/ui/mir-dataflow/indirect-mutation-offset.stderr b/src/test/ui/mir-dataflow/indirect-mutation-offset.stderr index 8d3548ececdd9..1d5287c15ab79 100644 --- a/src/test/ui/mir-dataflow/indirect-mutation-offset.stderr +++ b/src/test/ui/mir-dataflow/indirect-mutation-offset.stderr @@ -1,8 +1,8 @@ error: rustc_peek: bit not set - --> $DIR/indirect-mutation-offset.rs:41:14 + --> $DIR/indirect-mutation-offset.rs:41:5 | -LL | unsafe { rustc_peek(x) }; - | ^^^^^^^^^^^^^ +LL | rustc_peek(x); + | ^^^^^^^^^^^^^ error: stop_after_dataflow ended compilation diff --git a/src/test/ui/mir-dataflow/inits-1.rs b/src/test/ui/mir-dataflow/inits-1.rs index 4a4786a2a7378..8fb1d4bc736d6 100644 --- a/src/test/ui/mir-dataflow/inits-1.rs +++ b/src/test/ui/mir-dataflow/inits-1.rs @@ -11,13 +11,13 @@ struct S(i32); fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S { let ret; // `ret` starts off uninitialized, so we get an error report here. - unsafe { rustc_peek(&ret); } //~ ERROR rustc_peek: bit not set + rustc_peek(&ret); //~ ERROR rustc_peek: bit not set // All function formal parameters start off initialized. - unsafe { rustc_peek(&x) }; - unsafe { rustc_peek(&y) }; - unsafe { rustc_peek(&z) }; + rustc_peek(&x); + rustc_peek(&y); + rustc_peek(&z); ret = if test { ::std::mem::replace(x, y) @@ -28,21 +28,21 @@ fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S { // `z` may be initialized here. - unsafe { rustc_peek(&z); } + rustc_peek(&z); // `y` is definitely uninitialized here. - unsafe { rustc_peek(&y); } //~ ERROR rustc_peek: bit not set + rustc_peek(&y); //~ ERROR rustc_peek: bit not set // `x` is still (definitely) initialized (replace above is a reborrow). - unsafe { rustc_peek(&x); } + rustc_peek(&x); ::std::mem::drop(x); // `x` is *definitely* uninitialized here - unsafe { rustc_peek(&x); } //~ ERROR rustc_peek: bit not set + rustc_peek(&x); //~ ERROR rustc_peek: bit not set // `ret` is now definitely initialized (via `if` above). - unsafe { rustc_peek(&ret); } + rustc_peek(&ret); ret } diff --git a/src/test/ui/mir-dataflow/inits-1.stderr b/src/test/ui/mir-dataflow/inits-1.stderr index 23d0679cb1ac1..7a00a70af6f84 100644 --- a/src/test/ui/mir-dataflow/inits-1.stderr +++ b/src/test/ui/mir-dataflow/inits-1.stderr @@ -1,20 +1,20 @@ error: rustc_peek: bit not set - --> $DIR/inits-1.rs:14:14 + --> $DIR/inits-1.rs:14:5 | -LL | unsafe { rustc_peek(&ret); } - | ^^^^^^^^^^^^^^^^ +LL | rustc_peek(&ret); + | ^^^^^^^^^^^^^^^^ error: rustc_peek: bit not set - --> $DIR/inits-1.rs:34:14 + --> $DIR/inits-1.rs:34:5 | -LL | unsafe { rustc_peek(&y); } - | ^^^^^^^^^^^^^^ +LL | rustc_peek(&y); + | ^^^^^^^^^^^^^^ error: rustc_peek: bit not set - --> $DIR/inits-1.rs:42:14 + --> $DIR/inits-1.rs:42:5 | -LL | unsafe { rustc_peek(&x); } - | ^^^^^^^^^^^^^^ +LL | rustc_peek(&x); + | ^^^^^^^^^^^^^^ error: stop_after_dataflow ended compilation diff --git a/src/test/ui/mir-dataflow/liveness-ptr.rs b/src/test/ui/mir-dataflow/liveness-ptr.rs index 34097d7526a6e..786da523a3391 100644 --- a/src/test/ui/mir-dataflow/liveness-ptr.rs +++ b/src/test/ui/mir-dataflow/liveness-ptr.rs @@ -10,17 +10,17 @@ fn foo() -> i32 { x = 0; // `x` is live here since it is used in the next statement... - unsafe { rustc_peek(x); } + rustc_peek(x); p = &x; // ... but not here, even while it can be accessed through `p`. - unsafe { rustc_peek(x); } //~ ERROR rustc_peek: bit not set + rustc_peek(x); //~ ERROR rustc_peek: bit not set let tmp = unsafe { *p }; x = tmp + 1; - unsafe { rustc_peek(x); } + rustc_peek(x); x } diff --git a/src/test/ui/mir-dataflow/liveness-ptr.stderr b/src/test/ui/mir-dataflow/liveness-ptr.stderr index 3397d0c5a121d..858cdbac3d312 100644 --- a/src/test/ui/mir-dataflow/liveness-ptr.stderr +++ b/src/test/ui/mir-dataflow/liveness-ptr.stderr @@ -1,8 +1,8 @@ error: rustc_peek: bit not set - --> $DIR/liveness-ptr.rs:18:14 + --> $DIR/liveness-ptr.rs:18:5 | -LL | unsafe { rustc_peek(x); } - | ^^^^^^^^^^^^^ +LL | rustc_peek(x); + | ^^^^^^^^^^^^^ error: stop_after_dataflow ended compilation diff --git a/src/test/ui/mir-dataflow/uninits-1.rs b/src/test/ui/mir-dataflow/uninits-1.rs index 66b3f458a5159..c2b4284a7b4f8 100644 --- a/src/test/ui/mir-dataflow/uninits-1.rs +++ b/src/test/ui/mir-dataflow/uninits-1.rs @@ -11,13 +11,13 @@ struct S(i32); fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S { let ret; // `ret` starts off uninitialized - unsafe { rustc_peek(&ret); } + rustc_peek(&ret); // All function formal parameters start off initialized. - unsafe { rustc_peek(&x) }; //~ ERROR rustc_peek: bit not set - unsafe { rustc_peek(&y) }; //~ ERROR rustc_peek: bit not set - unsafe { rustc_peek(&z) }; //~ ERROR rustc_peek: bit not set + rustc_peek(&x); //~ ERROR rustc_peek: bit not set + rustc_peek(&y); //~ ERROR rustc_peek: bit not set + rustc_peek(&z); //~ ERROR rustc_peek: bit not set ret = if test { ::std::mem::replace(x, y) @@ -27,21 +27,21 @@ fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S { }; // `z` may be uninitialized here. - unsafe { rustc_peek(&z); } + rustc_peek(&z); // `y` is definitely uninitialized here. - unsafe { rustc_peek(&y); } + rustc_peek(&y); // `x` is still (definitely) initialized (replace above is a reborrow). - unsafe { rustc_peek(&x); } //~ ERROR rustc_peek: bit not set + rustc_peek(&x); //~ ERROR rustc_peek: bit not set ::std::mem::drop(x); // `x` is *definitely* uninitialized here - unsafe { rustc_peek(&x); } + rustc_peek(&x); // `ret` is now definitely initialized (via `if` above). - unsafe { rustc_peek(&ret); } //~ ERROR rustc_peek: bit not set + rustc_peek(&ret); //~ ERROR rustc_peek: bit not set ret } diff --git a/src/test/ui/mir-dataflow/uninits-1.stderr b/src/test/ui/mir-dataflow/uninits-1.stderr index 5f6dbde212d0a..c52f5ac7bd9b6 100644 --- a/src/test/ui/mir-dataflow/uninits-1.stderr +++ b/src/test/ui/mir-dataflow/uninits-1.stderr @@ -1,32 +1,32 @@ error: rustc_peek: bit not set - --> $DIR/uninits-1.rs:18:14 + --> $DIR/uninits-1.rs:18:5 | -LL | unsafe { rustc_peek(&x) }; - | ^^^^^^^^^^^^^^ +LL | rustc_peek(&x); + | ^^^^^^^^^^^^^^ error: rustc_peek: bit not set - --> $DIR/uninits-1.rs:19:14 + --> $DIR/uninits-1.rs:19:5 | -LL | unsafe { rustc_peek(&y) }; - | ^^^^^^^^^^^^^^ +LL | rustc_peek(&y); + | ^^^^^^^^^^^^^^ error: rustc_peek: bit not set - --> $DIR/uninits-1.rs:20:14 + --> $DIR/uninits-1.rs:20:5 | -LL | unsafe { rustc_peek(&z) }; - | ^^^^^^^^^^^^^^ +LL | rustc_peek(&z); + | ^^^^^^^^^^^^^^ error: rustc_peek: bit not set - --> $DIR/uninits-1.rs:36:14 + --> $DIR/uninits-1.rs:36:5 | -LL | unsafe { rustc_peek(&x); } - | ^^^^^^^^^^^^^^ +LL | rustc_peek(&x); + | ^^^^^^^^^^^^^^ error: rustc_peek: bit not set - --> $DIR/uninits-1.rs:44:14 + --> $DIR/uninits-1.rs:44:5 | -LL | unsafe { rustc_peek(&ret); } - | ^^^^^^^^^^^^^^^^ +LL | rustc_peek(&ret); + | ^^^^^^^^^^^^^^^^ error: stop_after_dataflow ended compilation diff --git a/src/test/ui/mir-dataflow/uninits-2.rs b/src/test/ui/mir-dataflow/uninits-2.rs index 2ccf1c7f9d6c6..c584ee74afb48 100644 --- a/src/test/ui/mir-dataflow/uninits-2.rs +++ b/src/test/ui/mir-dataflow/uninits-2.rs @@ -11,12 +11,12 @@ struct S(i32); fn foo(x: &mut S) { // `x` is initialized here, so maybe-uninit bit is 0. - unsafe { rustc_peek(&x) }; //~ ERROR rustc_peek: bit not set + rustc_peek(&x); //~ ERROR rustc_peek: bit not set ::std::mem::drop(x); // `x` definitely uninitialized here, so maybe-uninit bit is 1. - unsafe { rustc_peek(&x) }; + rustc_peek(&x); } fn main() { foo(&mut S(13)); diff --git a/src/test/ui/mir-dataflow/uninits-2.stderr b/src/test/ui/mir-dataflow/uninits-2.stderr index dcb61371994db..0ef954e35a4d8 100644 --- a/src/test/ui/mir-dataflow/uninits-2.stderr +++ b/src/test/ui/mir-dataflow/uninits-2.stderr @@ -1,8 +1,8 @@ error: rustc_peek: bit not set - --> $DIR/uninits-2.rs:14:14 + --> $DIR/uninits-2.rs:14:5 | -LL | unsafe { rustc_peek(&x) }; - | ^^^^^^^^^^^^^^ +LL | rustc_peek(&x); + | ^^^^^^^^^^^^^^ error: stop_after_dataflow ended compilation diff --git a/src/test/ui/numbers-arithmetic/saturating-float-casts.rs b/src/test/ui/numbers-arithmetic/saturating-float-casts.rs index e6d0c94a02fac..825a11972aeeb 100644 --- a/src/test/ui/numbers-arithmetic/saturating-float-casts.rs +++ b/src/test/ui/numbers-arithmetic/saturating-float-casts.rs @@ -9,7 +9,6 @@ // merged. #![feature(test, stmt_expr_attributes)] -#![feature(track_caller)] #![deny(overflowing_literals)] extern crate test; diff --git a/src/test/ui/parser/inverted-parameters.rs b/src/test/ui/parser/inverted-parameters.rs index 6f19ee9c7dc0d..5c4272504e061 100644 --- a/src/test/ui/parser/inverted-parameters.rs +++ b/src/test/ui/parser/inverted-parameters.rs @@ -20,7 +20,7 @@ fn pattern((i32, i32) (a, b)) {} fn fizz(i32) {} //~^ ERROR expected one of `:`, `@` -//~| HELP if this was a parameter name, give it a type +//~| HELP if this is a parameter name, give it a type //~| HELP if this is a `self` type, give it a parameter name //~| HELP if this is a type, explicitly ignore the parameter name diff --git a/src/test/ui/parser/inverted-parameters.stderr b/src/test/ui/parser/inverted-parameters.stderr index 043ff65f74e1a..ae180af93e373 100644 --- a/src/test/ui/parser/inverted-parameters.stderr +++ b/src/test/ui/parser/inverted-parameters.stderr @@ -39,7 +39,7 @@ help: if this is a `self` type, give it a parameter name | LL | fn fizz(self: i32) {} | ^^^^^^^^^ -help: if this was a parameter name, give it a type +help: if this is a parameter name, give it a type | LL | fn fizz(i32: TypeName) {} | ^^^^^^^^^^^^^ diff --git a/src/test/ui/parser/omitted-arg-in-item-fn.stderr b/src/test/ui/parser/omitted-arg-in-item-fn.stderr index 9f138bf84ce19..bc3329dcbc23d 100644 --- a/src/test/ui/parser/omitted-arg-in-item-fn.stderr +++ b/src/test/ui/parser/omitted-arg-in-item-fn.stderr @@ -9,7 +9,7 @@ help: if this is a `self` type, give it a parameter name | LL | fn foo(self: x) { | ^^^^^^^ -help: if this was a parameter name, give it a type +help: if this is a parameter name, give it a type | LL | fn foo(x: TypeName) { | ^^^^^^^^^^^ diff --git a/src/test/ui/parser/recover-field-extra-angle-brackets.rs b/src/test/ui/parser/recover-field-extra-angle-brackets.rs new file mode 100644 index 0000000000000..5e0e00bcb5e8d --- /dev/null +++ b/src/test/ui/parser/recover-field-extra-angle-brackets.rs @@ -0,0 +1,14 @@ +// Tests that we recover from extra trailing angle brackets +// in a struct field + +struct BadStruct { + first: Vec>, //~ ERROR unmatched angle bracket + second: bool +} + +fn bar(val: BadStruct) { + val.first; + val.second; +} + +fn main() {} diff --git a/src/test/ui/parser/recover-field-extra-angle-brackets.stderr b/src/test/ui/parser/recover-field-extra-angle-brackets.stderr new file mode 100644 index 0000000000000..318e55f6e99ac --- /dev/null +++ b/src/test/ui/parser/recover-field-extra-angle-brackets.stderr @@ -0,0 +1,8 @@ +error: unmatched angle bracket + --> $DIR/recover-field-extra-angle-brackets.rs:5:19 + | +LL | first: Vec>, + | ^ help: remove extra angle bracket + +error: aborting due to previous error + diff --git a/src/test/ui/rfc-2091-track-caller/call-chain.rs b/src/test/ui/rfc-2091-track-caller/call-chain.rs index 3f1c8f7abe8b8..fefb84de729fe 100644 --- a/src/test/ui/rfc-2091-track-caller/call-chain.rs +++ b/src/test/ui/rfc-2091-track-caller/call-chain.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(track_caller)] - use std::panic::Location; struct Foo; diff --git a/src/test/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs b/src/test/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs index edf9ba2c41a15..05240908917bc 100644 --- a/src/test/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs +++ b/src/test/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs @@ -6,7 +6,7 @@ // run-pass // compile-flags: -Z unleash-the-miri-inside-of-you -#![feature(core_intrinsics, const_caller_location, track_caller, const_fn)] +#![feature(core_intrinsics, const_caller_location, const_fn)] type L = &'static std::panic::Location<'static>; diff --git a/src/test/ui/rfc-2091-track-caller/caller-location-intrinsic.rs b/src/test/ui/rfc-2091-track-caller/caller-location-intrinsic.rs index 090e912c1d0ba..f244b74e391ff 100644 --- a/src/test/ui/rfc-2091-track-caller/caller-location-intrinsic.rs +++ b/src/test/ui/rfc-2091-track-caller/caller-location-intrinsic.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(track_caller)] - #[inline(never)] #[track_caller] fn codegen_caller_loc() -> &'static core::panic::Location<'static> { @@ -15,13 +13,13 @@ macro_rules! caller_location_from_macro { fn main() { let loc = codegen_caller_loc(); assert_eq!(loc.file(), file!()); - assert_eq!(loc.line(), 16); + assert_eq!(loc.line(), 14); assert_eq!(loc.column(), 15); // `Location::caller()` in a macro should behave similarly to `file!` and `line!`, // i.e. point to where the macro was invoked, instead of the macro itself. let loc2 = caller_location_from_macro!(); assert_eq!(loc2.file(), file!()); - assert_eq!(loc2.line(), 23); + assert_eq!(loc2.line(), 21); assert_eq!(loc2.column(), 16); } diff --git a/src/test/ui/rfc-2091-track-caller/const-caller-location.rs b/src/test/ui/rfc-2091-track-caller/const-caller-location.rs index 0614c52c66036..8030a4d967a67 100644 --- a/src/test/ui/rfc-2091-track-caller/const-caller-location.rs +++ b/src/test/ui/rfc-2091-track-caller/const-caller-location.rs @@ -1,6 +1,6 @@ // run-pass -#![feature(const_fn, track_caller)] +#![feature(const_caller_location, const_fn)] use std::panic::Location; diff --git a/src/test/ui/rfc-2091-track-caller/diverging-caller-location.rs b/src/test/ui/rfc-2091-track-caller/diverging-caller-location.rs index 1fb75ef35ffc1..6681119557d79 100644 --- a/src/test/ui/rfc-2091-track-caller/diverging-caller-location.rs +++ b/src/test/ui/rfc-2091-track-caller/diverging-caller-location.rs @@ -6,8 +6,6 @@ //! we don't inspect the location returned -- it would be difficult to distinguish between the //! explicit panic and a failed assertion. That it compiles and runs is enough for this one. -#![feature(track_caller)] - #[track_caller] fn doesnt_return() -> ! { let _location = core::panic::Location::caller(); diff --git a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs index d6560231871c9..6f4290e2a5ee9 100644 --- a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs +++ b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs @@ -1,5 +1,3 @@ -#![feature(track_caller)] - #[track_caller(1)] fn f() {} //~^^ ERROR malformed `track_caller` attribute input diff --git a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr index 8906fa59506a7..e7ddf8df4ab53 100644 --- a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr +++ b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr @@ -1,5 +1,5 @@ error: malformed `track_caller` attribute input - --> $DIR/error-odd-syntax.rs:3:1 + --> $DIR/error-odd-syntax.rs:1:1 | LL | #[track_caller(1)] | ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[track_caller]` diff --git a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs index 1145f7786c78b..074e1ceb791ce 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs +++ b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs @@ -1,5 +1,3 @@ -#![feature(track_caller)] - #[track_caller] extern "C" fn f() {} //~^^ ERROR `#[track_caller]` requires Rust ABI diff --git a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr index e08c52fabd6b7..bcc0c8170e655 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr +++ b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr @@ -1,11 +1,11 @@ error[E0737]: `#[track_caller]` requires Rust ABI - --> $DIR/error-with-invalid-abi.rs:3:1 + --> $DIR/error-with-invalid-abi.rs:1:1 | LL | #[track_caller] | ^^^^^^^^^^^^^^^ error[E0737]: `#[track_caller]` requires Rust ABI - --> $DIR/error-with-invalid-abi.rs:8:5 + --> $DIR/error-with-invalid-abi.rs:6:5 | LL | #[track_caller] | ^^^^^^^^^^^^^^^ diff --git a/src/test/ui/rfc-2091-track-caller/error-with-naked.rs b/src/test/ui/rfc-2091-track-caller/error-with-naked.rs index f457384833335..2b110c9a32515 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-naked.rs +++ b/src/test/ui/rfc-2091-track-caller/error-with-naked.rs @@ -1,4 +1,4 @@ -#![feature(naked_functions, track_caller)] +#![feature(naked_functions)] #[track_caller] //~ ERROR cannot use `#[track_caller]` with `#[naked]` #[naked] diff --git a/src/test/ui/rfc-2091-track-caller/intrinsic-wrapper.rs b/src/test/ui/rfc-2091-track-caller/intrinsic-wrapper.rs index 76e62b89ab818..74217f47084a3 100644 --- a/src/test/ui/rfc-2091-track-caller/intrinsic-wrapper.rs +++ b/src/test/ui/rfc-2091-track-caller/intrinsic-wrapper.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(track_caller)] - macro_rules! caller_location_from_macro { () => (core::panic::Location::caller()); } @@ -9,13 +7,13 @@ macro_rules! caller_location_from_macro { fn main() { let loc = core::panic::Location::caller(); assert_eq!(loc.file(), file!()); - assert_eq!(loc.line(), 10); + assert_eq!(loc.line(), 8); assert_eq!(loc.column(), 15); // `Location::caller()` in a macro should behave similarly to `file!` and `line!`, // i.e. point to where the macro was invoked, instead of the macro itself. let loc2 = caller_location_from_macro!(); assert_eq!(loc2.file(), file!()); - assert_eq!(loc2.line(), 17); + assert_eq!(loc2.line(), 15); assert_eq!(loc2.column(), 16); } diff --git a/src/test/ui/rfc-2091-track-caller/only-for-fns.rs b/src/test/ui/rfc-2091-track-caller/only-for-fns.rs index 0fd59b4bf4918..bc0ca9552806f 100644 --- a/src/test/ui/rfc-2091-track-caller/only-for-fns.rs +++ b/src/test/ui/rfc-2091-track-caller/only-for-fns.rs @@ -1,5 +1,3 @@ -#![feature(track_caller)] - #[track_caller] struct S; //~^^ ERROR attribute should be applied to function diff --git a/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr b/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr index c2fb8fa1eb6ca..6666dcfa6e599 100644 --- a/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr +++ b/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr @@ -1,5 +1,5 @@ error[E0739]: attribute should be applied to function - --> $DIR/only-for-fns.rs:3:1 + --> $DIR/only-for-fns.rs:1:1 | LL | #[track_caller] | ^^^^^^^^^^^^^^^ diff --git a/src/test/ui/rfc-2091-track-caller/pass.rs b/src/test/ui/rfc-2091-track-caller/pass.rs index eef83b3d68f97..ada150b25cf2c 100644 --- a/src/test/ui/rfc-2091-track-caller/pass.rs +++ b/src/test/ui/rfc-2091-track-caller/pass.rs @@ -1,6 +1,4 @@ // run-pass -#![feature(track_caller)] - #[track_caller] fn f() {} diff --git a/src/test/ui/rfc-2091-track-caller/track-caller-attribute.rs b/src/test/ui/rfc-2091-track-caller/track-caller-attribute.rs index 76a380ed3e30d..efcc1f6942de1 100644 --- a/src/test/ui/rfc-2091-track-caller/track-caller-attribute.rs +++ b/src/test/ui/rfc-2091-track-caller/track-caller-attribute.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(track_caller)] - use std::panic::Location; #[track_caller] @@ -20,21 +18,21 @@ fn nested_tracked() -> &'static Location<'static> { fn main() { let location = Location::caller(); assert_eq!(location.file(), file!()); - assert_eq!(location.line(), 21); + assert_eq!(location.line(), 19); assert_eq!(location.column(), 20); let tracked = tracked(); assert_eq!(tracked.file(), file!()); - assert_eq!(tracked.line(), 26); + assert_eq!(tracked.line(), 24); assert_eq!(tracked.column(), 19); let nested = nested_intrinsic(); assert_eq!(nested.file(), file!()); - assert_eq!(nested.line(), 13); + assert_eq!(nested.line(), 11); assert_eq!(nested.column(), 5); let contained = nested_tracked(); assert_eq!(contained.file(), file!()); - assert_eq!(contained.line(), 17); + assert_eq!(contained.line(), 15); assert_eq!(contained.column(), 5); } diff --git a/src/test/ui/rfc-2091-track-caller/track-caller-ffi.rs b/src/test/ui/rfc-2091-track-caller/track-caller-ffi.rs index 23c17d743c43c..5115f687c2632 100644 --- a/src/test/ui/rfc-2091-track-caller/track-caller-ffi.rs +++ b/src/test/ui/rfc-2091-track-caller/track-caller-ffi.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(track_caller)] - use std::panic::Location; extern "Rust" { @@ -30,21 +28,21 @@ mod provides { fn main() { let location = Location::caller(); assert_eq!(location.file(), file!()); - assert_eq!(location.line(), 31); + assert_eq!(location.line(), 29); assert_eq!(location.column(), 20); let tracked = unsafe { rust_track_caller_ffi_test_tracked() }; assert_eq!(tracked.file(), file!()); - assert_eq!(tracked.line(), 36); + assert_eq!(tracked.line(), 34); assert_eq!(tracked.column(), 28); let untracked = unsafe { rust_track_caller_ffi_test_untracked() }; assert_eq!(untracked.file(), file!()); - assert_eq!(untracked.line(), 26); + assert_eq!(untracked.line(), 24); assert_eq!(untracked.column(), 9); let contained = rust_track_caller_ffi_test_nested_tracked(); assert_eq!(contained.file(), file!()); - assert_eq!(contained.line(), 14); + assert_eq!(contained.line(), 12); assert_eq!(contained.column(), 14); } diff --git a/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs b/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs index b17c1efb3d38c..5fcfea96d547a 100644 --- a/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs +++ b/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(track_caller)] - fn pass_to_ptr_call(f: fn(T), x: T) { f(x); } diff --git a/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr.rs b/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr.rs index 8ee4d4fa16871..4415d850c241c 100644 --- a/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr.rs +++ b/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(track_caller)] - fn ptr_call(f: fn()) { f(); } diff --git a/src/test/ui/rfc-2091-track-caller/tracked-trait-impls.rs b/src/test/ui/rfc-2091-track-caller/tracked-trait-impls.rs index 0a5f92bb635e5..4db4c29e53d58 100644 --- a/src/test/ui/rfc-2091-track-caller/tracked-trait-impls.rs +++ b/src/test/ui/rfc-2091-track-caller/tracked-trait-impls.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(track_caller)] - macro_rules! assert_expansion_site_is_tracked { () => {{ let location = std::panic::Location::caller(); diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr b/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr index 1e51567a9b1c4..5516d4a4c1c1c 100644 --- a/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr +++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr @@ -9,7 +9,7 @@ help: if this is a `self` type, give it a parameter name | LL | trait Trait2015 { fn foo(#[allow(C)] self: i32); } | ^^^^^^^^^ -help: if this was a parameter name, give it a type +help: if this is a parameter name, give it a type | LL | trait Trait2015 { fn foo(#[allow(C)] i32: TypeName); } | ^^^^^^^^^^^^^ diff --git a/src/test/ui/span/issue-34264.stderr b/src/test/ui/span/issue-34264.stderr index 116f5ddd5b4b2..40c3219bf27b0 100644 --- a/src/test/ui/span/issue-34264.stderr +++ b/src/test/ui/span/issue-34264.stderr @@ -21,7 +21,7 @@ LL | fn foo(Option, String) {} | ^ expected one of `:`, `@`, or `|` | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) -help: if this was a parameter name, give it a type +help: if this is a parameter name, give it a type | LL | fn foo(Option, String: TypeName) {} | ^^^^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ help: if this is a `self` type, give it a parameter name | LL | fn bar(self: x, y: usize) {} | ^^^^^^^ -help: if this was a parameter name, give it a type +help: if this is a parameter name, give it a type | LL | fn bar(x: TypeName, y: usize) {} | ^^^^^^^^^^^