diff --git a/Cargo.lock b/Cargo.lock index 440def727685..ef5811c6901d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -714,9 +714,9 @@ checksum = "55b672471b4e9f9e95499ea597ff64941a309b2cdbffcc46f2cc5e2d971fd335" [[package]] name = "compiler_builtins" -version = "0.1.104" +version = "0.1.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99c3f9035afc33f4358773239573f7d121099856753e1bbd2a6a5207098fc741" +checksum = "3686cc48897ce1950aa70fd595bd2dc9f767a3c4cca4cd17b2cb52a2d37e6eb4" dependencies = [ "cc", "rustc-std-workspace-core", @@ -2187,16 +2187,6 @@ dependencies = [ "cc", ] -[[package]] -name = "libloading" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" -dependencies = [ - "cfg-if", - "winapi", -] - [[package]] name = "libloading" version = "0.8.1" @@ -2366,9 +2356,9 @@ dependencies = [ [[package]] name = "measureme" -version = "10.1.2" +version = "11.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45e381dcdad44c3c435f8052b08c5c4a1449c48ab56f312345eae12d7a693dbe" +checksum = "dfa4a40f09af7aa6faef38285402a78847d0d72bf8827006cd2a332e1e6e4a8d" dependencies = [ "log", "memmap2", @@ -2479,7 +2469,7 @@ dependencies = [ "lazy_static", "libc", "libffi", - "libloading 0.8.1", + "libloading", "log", "measureme", "rand", @@ -3879,6 +3869,7 @@ dependencies = [ name = "rustc_hir_analysis" version = "0.0.0" dependencies = [ + "itertools", "rustc_arena", "rustc_ast", "rustc_attr", @@ -3917,6 +3908,7 @@ dependencies = [ name = "rustc_hir_typeck" version = "0.0.0" dependencies = [ + "itertools", "rustc_ast", "rustc_attr", "rustc_data_structures", @@ -4003,7 +3995,7 @@ dependencies = [ name = "rustc_interface" version = "0.0.0" dependencies = [ - "libloading 0.7.4", + "libloading", "rustc-rayon", "rustc-rayon-core", "rustc_ast", @@ -4133,7 +4125,7 @@ name = "rustc_metadata" version = "0.0.0" dependencies = [ "bitflags 2.4.1", - "libloading 0.7.4", + "libloading", "odht", "rustc_ast", "rustc_attr", @@ -4200,6 +4192,7 @@ name = "rustc_mir_build" version = "0.0.0" dependencies = [ "either", + "itertools", "rustc_apfloat", "rustc_arena", "rustc_ast", @@ -4352,6 +4345,7 @@ name = "rustc_pattern_analysis" version = "0.0.0" dependencies = [ "derivative", + "rustc-hash", "rustc_apfloat", "rustc_arena", "rustc_data_structures", @@ -4366,7 +4360,6 @@ dependencies = [ "rustc_target", "smallvec", "tracing", - "typed-arena", ] [[package]] @@ -5351,9 +5344,9 @@ dependencies = [ [[package]] name = "thin-vec" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aac81b6fd6beb5884b0cf3321b8117e6e5d47ecb6fc89f414cfdcca8b2fe2dd8" +checksum = "a38c90d48152c236a3ab59271da4f4ae63d678c5d7ad6b7714d7cb9760be5e4b" [[package]] name = "thiserror" @@ -5705,12 +5698,6 @@ dependencies = [ "rustc-hash", ] -[[package]] -name = "typed-arena" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" - [[package]] name = "typenum" version = "1.16.0" diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index ea194e10defd..c45a4a410f96 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -49,7 +49,14 @@ bitflags! { | ReprFlags::IS_LINEAR.bits(); } } -rustc_data_structures::external_bitflags_debug! { ReprFlags } + +// This is the same as `rustc_data_structures::external_bitflags_debug` but without the +// `rustc_data_structures` to make it build on stable. +impl std::fmt::Debug for ReprFlags { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + bitflags::parser::to_writer(self, f) + } +} #[derive(Copy, Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "nightly", derive(Encodable_Generic, Decodable_Generic, HashStable_Generic))] diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 21077c312bdc..7f5213431f7d 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -625,7 +625,8 @@ impl Pat { | PatKind::Range(..) | PatKind::Ident(..) | PatKind::Path(..) - | PatKind::MacCall(_) => {} + | PatKind::MacCall(_) + | PatKind::Err(_) => {} } } @@ -809,6 +810,9 @@ pub enum PatKind { /// A macro pattern; pre-expansion. MacCall(P), + + /// Placeholder for a pattern that wasn't syntactically well formed in some way. + Err(ErrorGuaranteed), } /// Whether the `..` is present in a struct fields pattern. @@ -3300,9 +3304,13 @@ mod size_asserts { static_assert_size!(Impl, 136); static_assert_size!(Item, 136); static_assert_size!(ItemKind, 64); - static_assert_size!(LitKind, 24); + // This can be removed after i128:128 is in the bootstrap compiler's target. + #[cfg(not(bootstrap))] + static_assert_size!(LitKind, 32); static_assert_size!(Local, 72); - static_assert_size!(MetaItemLit, 40); + // This can be removed after i128:128 is in the bootstrap compiler's target. + #[cfg(not(bootstrap))] + static_assert_size!(MetaItemLit, 48); static_assert_size!(Param, 40); static_assert_size!(Pat, 72); static_assert_size!(Path, 24); diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 450555d0cb56..90677151d250 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1267,7 +1267,7 @@ pub fn noop_visit_pat(pat: &mut P, vis: &mut T) { let Pat { id, kind, span, tokens } = pat.deref_mut(); vis.visit_id(id); match kind { - PatKind::Wild | PatKind::Rest | PatKind::Never => {} + PatKind::Wild | PatKind::Rest | PatKind::Never | PatKind::Err(_) => {} PatKind::Ident(_binding_mode, ident, sub) => { vis.visit_ident(ident); visit_opt(sub, |sub| vis.visit_pat(sub)); diff --git a/compiler/rustc_ast/src/util/classify.rs b/compiler/rustc_ast/src/util/classify.rs index 65036bcdc36f..098b8f2d6d03 100644 --- a/compiler/rustc_ast/src/util/classify.rs +++ b/compiler/rustc_ast/src/util/classify.rs @@ -2,7 +2,7 @@ // Predicates on exprs and stmts that the pretty-printer and parser use -use crate::ast; +use crate::{ast, token::Delimiter}; /// Does this expression require a semicolon to be treated /// as a statement? The negation of this: 'can this expression @@ -59,8 +59,12 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> { | While(..) | ConstBlock(_) => break Some(expr), - // FIXME: These can end in `}`, but changing these would break stable code. - InlineAsm(_) | OffsetOf(_, _) | MacCall(_) | IncludedBytes(_) | FormatArgs(_) => { + MacCall(mac) => { + break (mac.args.delim == Delimiter::Brace).then_some(expr); + } + + InlineAsm(_) | OffsetOf(_, _) | IncludedBytes(_) | FormatArgs(_) => { + // These should have been denied pre-expansion. break None; } diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index 92b9adf1db75..fbae49645881 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -8,7 +8,6 @@ use rustc_lexer::unescape::{ }; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::Span; -use std::ops::Range; use std::{ascii, fmt, str}; // Escapes a string, represented as a symbol. Reuses the original symbol, @@ -39,7 +38,6 @@ pub enum LitError { InvalidFloatSuffix, NonDecimalFloat(u32), IntTooLarge(u32), - NulInCStr(Range), } impl LitKind { @@ -156,10 +154,7 @@ impl LitKind { let s = symbol.as_str(); let mut buf = Vec::with_capacity(s.len()); let mut error = Ok(()); - unescape_c_string(s, Mode::CStr, &mut |span, c| match c { - Ok(CStrUnit::Byte(0) | CStrUnit::Char('\0')) => { - error = Err(LitError::NulInCStr(span)); - } + unescape_c_string(s, Mode::CStr, &mut |_span, c| match c { Ok(CStrUnit::Byte(b)) => buf.push(b), Ok(CStrUnit::Char(c)) => { buf.extend_from_slice(c.encode_utf8(&mut [0; 4]).as_bytes()) @@ -179,10 +174,7 @@ impl LitKind { // can convert the symbol directly to a `Lrc` on success. let s = symbol.as_str(); let mut error = Ok(()); - unescape_c_string(s, Mode::RawCStr, &mut |span, c| match c { - Ok(CStrUnit::Byte(0) | CStrUnit::Char('\0')) => { - error = Err(LitError::NulInCStr(span)); - } + unescape_c_string(s, Mode::RawCStr, &mut |_, c| match c { Ok(_) => {} Err(err) => { if err.is_fatal() { diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 3617df931e2a..89f50d3a0a7b 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -568,7 +568,7 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) { walk_list!(visitor, visit_expr, lower_bound); walk_list!(visitor, visit_expr, upper_bound); } - PatKind::Wild | PatKind::Rest | PatKind::Never => {} + PatKind::Wild | PatKind::Rest | PatKind::Never | PatKind::Err(_) => {} PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => { walk_list!(visitor, visit_pat, elems); } diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index e7177402db1d..8615016cda59 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -14,10 +14,6 @@ ast_lowering_assoc_ty_parentheses = ast_lowering_async_coroutines_not_supported = `async` coroutines are not yet supported -ast_lowering_async_non_move_closure_not_supported = - `async` non-`move` closures with parameters are not currently supported - .help = consider using `let` statements to manually capture variables by reference before entering an `async move` closure - ast_lowering_att_syntax_only_x86 = the `att_syntax` option is only supported on x86 diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index 2811fe104cd0..4843d36372dc 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -145,14 +145,6 @@ pub struct ClosureCannotBeStatic { pub fn_decl_span: Span, } -#[derive(Diagnostic, Clone, Copy)] -#[help] -#[diag(ast_lowering_async_non_move_closure_not_supported, code = "E0708")] -pub struct AsyncNonMoveClosureNotSupported { - #[primary_span] - pub fn_decl_span: Span, -} - #[derive(Diagnostic, Clone, Copy)] #[diag(ast_lowering_functional_record_update_destructuring_assignment)] pub struct FunctionalRecordUpdateDestructuringAssignment { diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index e0b1a10c82e7..0920de48eb87 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1,6 +1,6 @@ use super::errors::{ - AsyncCoroutinesNotSupported, AsyncNonMoveClosureNotSupported, AwaitOnlyInAsyncFnAndBlocks, - BaseExpressionDoubleDot, ClosureCannotBeStatic, CoroutineTooManyParameters, + AsyncCoroutinesNotSupported, AwaitOnlyInAsyncFnAndBlocks, BaseExpressionDoubleDot, + ClosureCannotBeStatic, CoroutineTooManyParameters, FunctionalRecordUpdateDestructuringAssignment, InclusiveRangeWithNoEnd, MatchArmWithNoBody, NeverPatternWithBody, NeverPatternWithGuard, NotSupportedForLifetimeBinderAsyncClosure, UnderscoreExprLhsAssign, @@ -13,7 +13,6 @@ use rustc_ast::*; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_middle::span_bug; use rustc_session::errors::report_lit_error; use rustc_span::source_map::{respan, Spanned}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; @@ -1028,28 +1027,16 @@ impl<'hir> LoweringContext<'_, 'hir> { fn_decl_span: Span, fn_arg_span: Span, ) -> hir::ExprKind<'hir> { - let CoroutineKind::Async { closure_id: inner_closure_id, .. } = coroutine_kind else { - span_bug!(fn_decl_span, "`async gen` and `gen` closures are not supported, yet"); - }; - if let &ClosureBinder::For { span, .. } = binder { self.dcx().emit_err(NotSupportedForLifetimeBinderAsyncClosure { span }); } let (binder_clause, generic_params) = self.lower_closure_binder(binder); - let outer_decl = - FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) }; - let body = self.with_new_scopes(fn_decl_span, |this| { - // FIXME(cramertj): allow `async` non-`move` closures with arguments. - if capture_clause == CaptureBy::Ref && !decl.inputs.is_empty() { - this.dcx().emit_err(AsyncNonMoveClosureNotSupported { fn_decl_span }); - } - // Transform `async |x: u8| -> X { ... }` into // `|x: u8| || -> X { ... }`. - let body_id = this.lower_fn_body(&outer_decl, |this| { + let body_id = this.lower_body(|this| { let async_ret_ty = if let FnRetTy::Ty(ty) = &decl.output { let itctx = ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock); Some(hir::FnRetTy::Return(this.lower_ty(ty, &itctx))) @@ -1057,22 +1044,26 @@ impl<'hir> LoweringContext<'_, 'hir> { None }; - let async_body = this.make_desugared_coroutine_expr( - capture_clause, - inner_closure_id, - async_ret_ty, - body.span, - hir::CoroutineDesugaring::Async, - hir::CoroutineSource::Closure, + let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments( + decl, |this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)), + body.span, + coroutine_kind, + hir::CoroutineSource::Closure, + async_ret_ty, ); - let hir_id = this.lower_node_id(inner_closure_id); + + let hir_id = this.lower_node_id(coroutine_kind.closure_id()); this.maybe_forward_track_caller(body.span, closure_hir_id, hir_id); - hir::Expr { hir_id, kind: async_body, span: this.lower_span(body.span) } + + (parameters, expr) }); body_id }); + let outer_decl = + FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) }; + let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params); // We need to lower the declaration outside the new scope, because we // have to conserve the state of being inside a loop condition for the diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index a3ff02f5f695..dd3f7289a60b 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1082,196 +1082,226 @@ impl<'hir> LoweringContext<'_, 'hir> { let (Some(coroutine_kind), Some(body)) = (coroutine_kind, body) else { return self.lower_fn_body_block(span, decl, body); }; - let closure_id = coroutine_kind.closure_id(); - self.lower_body(|this| { - let mut parameters: Vec> = Vec::new(); - let mut statements: Vec> = Vec::new(); - - // Async function parameters are lowered into the closure body so that they are - // captured and so that the drop order matches the equivalent non-async functions. - // - // from: - // - // async fn foo(: , : , : ) { - // - // } - // - // into: - // - // fn foo(__arg0: , __arg1: , __arg2: ) { - // async move { - // let __arg2 = __arg2; - // let = __arg2; - // let __arg1 = __arg1; - // let = __arg1; - // let __arg0 = __arg0; - // let = __arg0; - // drop-temps { } // see comments later in fn for details - // } - // } - // - // If `` is a simple ident, then it is lowered to a single - // `let = ;` statement as an optimization. - // - // Note that the body is embedded in `drop-temps`; an - // equivalent desugaring would be `return { - // };`. The key point is that we wish to drop all the - // let-bound variables and temporaries created in the body - // (and its tail expression!) before we drop the - // parameters (c.f. rust-lang/rust#64512). - for (index, parameter) in decl.inputs.iter().enumerate() { - let parameter = this.lower_param(parameter); - let span = parameter.pat.span; - - // Check if this is a binding pattern, if so, we can optimize and avoid adding a - // `let = __argN;` statement. In this case, we do not rename the parameter. - let (ident, is_simple_parameter) = match parameter.pat.kind { - hir::PatKind::Binding(hir::BindingAnnotation(ByRef::No, _), _, ident, _) => { - (ident, true) - } - // For `ref mut` or wildcard arguments, we can't reuse the binding, but - // we can keep the same name for the parameter. - // This lets rustdoc render it correctly in documentation. - hir::PatKind::Binding(_, _, ident, _) => (ident, false), - hir::PatKind::Wild => { - (Ident::with_dummy_span(rustc_span::symbol::kw::Underscore), false) - } - _ => { - // Replace the ident for bindings that aren't simple. - let name = format!("__arg{index}"); - let ident = Ident::from_str(&name); - - (ident, false) - } - }; - - let desugared_span = this.mark_span_with_reason(DesugaringKind::Async, span, None); - - // Construct a parameter representing `__argN: ` to replace the parameter of the - // async function. - // - // If this is the simple case, this parameter will end up being the same as the - // original parameter, but with a different pattern id. - let stmt_attrs = this.attrs.get(¶meter.hir_id.local_id).copied(); - let (new_parameter_pat, new_parameter_id) = this.pat_ident(desugared_span, ident); - let new_parameter = hir::Param { - hir_id: parameter.hir_id, - pat: new_parameter_pat, - ty_span: this.lower_span(parameter.ty_span), - span: this.lower_span(parameter.span), - }; - - if is_simple_parameter { - // If this is the simple case, then we only insert one statement that is - // `let = ;`. We re-use the original argument's pattern so that - // `HirId`s are densely assigned. - let expr = this.expr_ident(desugared_span, ident, new_parameter_id); - let stmt = this.stmt_let_pat( - stmt_attrs, - desugared_span, - Some(expr), - parameter.pat, - hir::LocalSource::AsyncFn, - ); - statements.push(stmt); - } else { - // If this is not the simple case, then we construct two statements: - // - // ``` - // let __argN = __argN; - // let = __argN; - // ``` - // - // The first statement moves the parameter into the closure and thus ensures - // that the drop order is correct. - // - // The second statement creates the bindings that the user wrote. - - // Construct the `let mut __argN = __argN;` statement. It must be a mut binding - // because the user may have specified a `ref mut` binding in the next - // statement. - let (move_pat, move_id) = this.pat_ident_binding_mode( - desugared_span, - ident, - hir::BindingAnnotation::MUT, - ); - let move_expr = this.expr_ident(desugared_span, ident, new_parameter_id); - let move_stmt = this.stmt_let_pat( - None, - desugared_span, - Some(move_expr), - move_pat, - hir::LocalSource::AsyncFn, - ); - - // Construct the `let = __argN;` statement. We re-use the original - // parameter's pattern so that `HirId`s are densely assigned. - let pattern_expr = this.expr_ident(desugared_span, ident, move_id); - let pattern_stmt = this.stmt_let_pat( - stmt_attrs, - desugared_span, - Some(pattern_expr), - parameter.pat, - hir::LocalSource::AsyncFn, - ); - - statements.push(move_stmt); - statements.push(pattern_stmt); - }; - - parameters.push(new_parameter); - } - - let mkbody = |this: &mut LoweringContext<'_, 'hir>| { - // Create a block from the user's function body: - let user_body = this.lower_block_expr(body); - - // Transform into `drop-temps { }`, an expression: - let desugared_span = - this.mark_span_with_reason(DesugaringKind::Async, user_body.span, None); - let user_body = this.expr_drop_temps(desugared_span, this.arena.alloc(user_body)); - - // As noted above, create the final block like - // - // ``` - // { - // let $param_pattern = $raw_param; - // ... - // drop-temps { } - // } - // ``` - let body = this.block_all( - desugared_span, - this.arena.alloc_from_iter(statements), - Some(user_body), - ); - - this.expr_block(body) - }; - let desugaring_kind = match coroutine_kind { - CoroutineKind::Async { .. } => hir::CoroutineDesugaring::Async, - CoroutineKind::Gen { .. } => hir::CoroutineDesugaring::Gen, - CoroutineKind::AsyncGen { .. } => hir::CoroutineDesugaring::AsyncGen, - }; - let coroutine_expr = this.make_desugared_coroutine_expr( - CaptureBy::Value { move_kw: rustc_span::DUMMY_SP }, - closure_id, - None, + let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments( + decl, + |this| this.lower_block_expr(body), body.span, - desugaring_kind, + coroutine_kind, hir::CoroutineSource::Fn, - mkbody, + None, ); - let hir_id = this.lower_node_id(closure_id); + // FIXME(async_fn_track_caller): Can this be moved above? + let hir_id = this.lower_node_id(coroutine_kind.closure_id()); this.maybe_forward_track_caller(body.span, fn_id, hir_id); - let expr = hir::Expr { hir_id, kind: coroutine_expr, span: this.lower_span(body.span) }; - (this.arena.alloc_from_iter(parameters), expr) + (parameters, expr) }) } + /// Lowers a desugared coroutine body after moving all of the arguments + /// into the body. This is to make sure that the future actually owns the + /// arguments that are passed to the function, and to ensure things like + /// drop order are stable. + pub fn lower_coroutine_body_with_moved_arguments( + &mut self, + decl: &FnDecl, + lower_body: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::Expr<'hir>, + body_span: Span, + coroutine_kind: CoroutineKind, + coroutine_source: hir::CoroutineSource, + return_type_hint: Option>, + ) -> (&'hir [hir::Param<'hir>], hir::Expr<'hir>) { + let mut parameters: Vec> = Vec::new(); + let mut statements: Vec> = Vec::new(); + + // Async function parameters are lowered into the closure body so that they are + // captured and so that the drop order matches the equivalent non-async functions. + // + // from: + // + // async fn foo(: , : , : ) { + // + // } + // + // into: + // + // fn foo(__arg0: , __arg1: , __arg2: ) { + // async move { + // let __arg2 = __arg2; + // let = __arg2; + // let __arg1 = __arg1; + // let = __arg1; + // let __arg0 = __arg0; + // let = __arg0; + // drop-temps { } // see comments later in fn for details + // } + // } + // + // If `` is a simple ident, then it is lowered to a single + // `let = ;` statement as an optimization. + // + // Note that the body is embedded in `drop-temps`; an + // equivalent desugaring would be `return { + // };`. The key point is that we wish to drop all the + // let-bound variables and temporaries created in the body + // (and its tail expression!) before we drop the + // parameters (c.f. rust-lang/rust#64512). + for (index, parameter) in decl.inputs.iter().enumerate() { + let parameter = self.lower_param(parameter); + let span = parameter.pat.span; + + // Check if this is a binding pattern, if so, we can optimize and avoid adding a + // `let = __argN;` statement. In this case, we do not rename the parameter. + let (ident, is_simple_parameter) = match parameter.pat.kind { + hir::PatKind::Binding(hir::BindingAnnotation(ByRef::No, _), _, ident, _) => { + (ident, true) + } + // For `ref mut` or wildcard arguments, we can't reuse the binding, but + // we can keep the same name for the parameter. + // This lets rustdoc render it correctly in documentation. + hir::PatKind::Binding(_, _, ident, _) => (ident, false), + hir::PatKind::Wild => { + (Ident::with_dummy_span(rustc_span::symbol::kw::Underscore), false) + } + _ => { + // Replace the ident for bindings that aren't simple. + let name = format!("__arg{index}"); + let ident = Ident::from_str(&name); + + (ident, false) + } + }; + + let desugared_span = self.mark_span_with_reason(DesugaringKind::Async, span, None); + + // Construct a parameter representing `__argN: ` to replace the parameter of the + // async function. + // + // If this is the simple case, this parameter will end up being the same as the + // original parameter, but with a different pattern id. + let stmt_attrs = self.attrs.get(¶meter.hir_id.local_id).copied(); + let (new_parameter_pat, new_parameter_id) = self.pat_ident(desugared_span, ident); + let new_parameter = hir::Param { + hir_id: parameter.hir_id, + pat: new_parameter_pat, + ty_span: self.lower_span(parameter.ty_span), + span: self.lower_span(parameter.span), + }; + + if is_simple_parameter { + // If this is the simple case, then we only insert one statement that is + // `let = ;`. We re-use the original argument's pattern so that + // `HirId`s are densely assigned. + let expr = self.expr_ident(desugared_span, ident, new_parameter_id); + let stmt = self.stmt_let_pat( + stmt_attrs, + desugared_span, + Some(expr), + parameter.pat, + hir::LocalSource::AsyncFn, + ); + statements.push(stmt); + } else { + // If this is not the simple case, then we construct two statements: + // + // ``` + // let __argN = __argN; + // let = __argN; + // ``` + // + // The first statement moves the parameter into the closure and thus ensures + // that the drop order is correct. + // + // The second statement creates the bindings that the user wrote. + + // Construct the `let mut __argN = __argN;` statement. It must be a mut binding + // because the user may have specified a `ref mut` binding in the next + // statement. + let (move_pat, move_id) = + self.pat_ident_binding_mode(desugared_span, ident, hir::BindingAnnotation::MUT); + let move_expr = self.expr_ident(desugared_span, ident, new_parameter_id); + let move_stmt = self.stmt_let_pat( + None, + desugared_span, + Some(move_expr), + move_pat, + hir::LocalSource::AsyncFn, + ); + + // Construct the `let = __argN;` statement. We re-use the original + // parameter's pattern so that `HirId`s are densely assigned. + let pattern_expr = self.expr_ident(desugared_span, ident, move_id); + let pattern_stmt = self.stmt_let_pat( + stmt_attrs, + desugared_span, + Some(pattern_expr), + parameter.pat, + hir::LocalSource::AsyncFn, + ); + + statements.push(move_stmt); + statements.push(pattern_stmt); + }; + + parameters.push(new_parameter); + } + + let mkbody = |this: &mut LoweringContext<'_, 'hir>| { + // Create a block from the user's function body: + let user_body = lower_body(this); + + // Transform into `drop-temps { }`, an expression: + let desugared_span = + this.mark_span_with_reason(DesugaringKind::Async, user_body.span, None); + let user_body = this.expr_drop_temps(desugared_span, this.arena.alloc(user_body)); + + // As noted above, create the final block like + // + // ``` + // { + // let $param_pattern = $raw_param; + // ... + // drop-temps { } + // } + // ``` + let body = this.block_all( + desugared_span, + this.arena.alloc_from_iter(statements), + Some(user_body), + ); + + this.expr_block(body) + }; + let desugaring_kind = match coroutine_kind { + CoroutineKind::Async { .. } => hir::CoroutineDesugaring::Async, + CoroutineKind::Gen { .. } => hir::CoroutineDesugaring::Gen, + CoroutineKind::AsyncGen { .. } => hir::CoroutineDesugaring::AsyncGen, + }; + let closure_id = coroutine_kind.closure_id(); + let coroutine_expr = self.make_desugared_coroutine_expr( + // FIXME(async_closures): This should only move locals, + // and not upvars. Capturing closure upvars by ref doesn't + // work right now anyways, so whatever. + CaptureBy::Value { move_kw: rustc_span::DUMMY_SP }, + closure_id, + return_type_hint, + body_span, + desugaring_kind, + coroutine_source, + mkbody, + ); + + let expr = hir::Expr { + hir_id: self.lower_node_id(closure_id), + kind: coroutine_expr, + span: self.lower_span(body_span), + }; + + (self.arena.alloc_from_iter(parameters), expr) + } + fn lower_method_sig( &mut self, generics: &Generics, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 5387880b6e62..057fe65d0afa 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -662,9 +662,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let (opt_hash_including_bodies, attrs_hash) = if self.tcx.needs_crate_hash() { self.tcx.with_stable_hashing_context(|mut hcx| { let mut stable_hasher = StableHasher::new(); - hcx.with_hir_bodies(node.def_id(), &bodies, |hcx| { - node.hash_stable(hcx, &mut stable_hasher) - }); + node.hash_stable(&mut hcx, &mut stable_hasher); + // Bodies are stored out of line, so we need to pull them explicitly in the hash. + bodies.hash_stable(&mut hcx, &mut stable_hasher); let h1 = stable_hasher.finish(); let mut stable_hasher = StableHasher::new(); diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index 1c405fac7e40..0af141ff99a2 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -109,6 +109,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // return inner to be processed in next loop PatKind::Paren(inner) => pattern = inner, PatKind::MacCall(_) => panic!("{:?} shouldn't exist here", pattern.span), + PatKind::Err(guar) => break hir::PatKind::Err(*guar), } }; diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index f4b424259dee..c2fd4558fd76 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1519,6 +1519,11 @@ impl<'a> State<'a> { self.pclose(); } PatKind::MacCall(m) => self.print_mac(m), + PatKind::Err(_) => { + self.popen(); + self.word("/*ERROR*/"); + self.pclose(); + } } self.ann.post(self, AnnNode::Pat(pat)) } diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index b4a73574aa2e..da67862a48dc 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -26,6 +26,7 @@ use rustc_span::hygiene::DesugaringKind; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{BytePos, Span, Symbol}; use rustc_trait_selection::infer::InferCtxtExt; +use rustc_trait_selection::traits::error_reporting::FindExprBySpan; use rustc_trait_selection::traits::ObligationCtxt; use std::iter; @@ -1257,7 +1258,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { return None; }; debug!("checking call args for uses of inner_param: {:?}", args); - args.contains(&Operand::Move(inner_param)).then_some((loc, term)) + args.iter() + .map(|a| &a.node) + .any(|a| a == &Operand::Move(inner_param)) + .then_some((loc, term)) }) else { debug!("no uses of inner_param found as a by-move call arg"); @@ -1301,14 +1305,96 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { place: Place<'tcx>, borrowed_place: Place<'tcx>, ) { - if let ([ProjectionElem::Index(_)], [ProjectionElem::Index(_)]) = - (&place.projection[..], &borrowed_place.projection[..]) + let tcx = self.infcx.tcx; + let hir = tcx.hir(); + + if let ([ProjectionElem::Index(index1)], [ProjectionElem::Index(index2)]) + | ( + [ProjectionElem::Deref, ProjectionElem::Index(index1)], + [ProjectionElem::Deref, ProjectionElem::Index(index2)], + ) = (&place.projection[..], &borrowed_place.projection[..]) { - err.help( - "consider using `.split_at_mut(position)` or similar method to obtain \ - two mutable non-overlapping sub-slices", - ) - .help("consider using `.swap(index_1, index_2)` to swap elements at the specified indices"); + let mut note_default_suggestion = || { + err.help( + "consider using `.split_at_mut(position)` or similar method to obtain \ + two mutable non-overlapping sub-slices", + ) + .help("consider using `.swap(index_1, index_2)` to swap elements at the specified indices"); + }; + + let Some(body_id) = tcx.hir_node(self.mir_hir_id()).body_id() else { + note_default_suggestion(); + return; + }; + + let mut expr_finder = + FindExprBySpan::new(self.body.local_decls[*index1].source_info.span); + expr_finder.visit_expr(hir.body(body_id).value); + let Some(index1) = expr_finder.result else { + note_default_suggestion(); + return; + }; + + expr_finder = FindExprBySpan::new(self.body.local_decls[*index2].source_info.span); + expr_finder.visit_expr(hir.body(body_id).value); + let Some(index2) = expr_finder.result else { + note_default_suggestion(); + return; + }; + + let sm = tcx.sess.source_map(); + + let Ok(index1_str) = sm.span_to_snippet(index1.span) else { + note_default_suggestion(); + return; + }; + + let Ok(index2_str) = sm.span_to_snippet(index2.span) else { + note_default_suggestion(); + return; + }; + + let Some(object) = hir.parent_id_iter(index1.hir_id).find_map(|id| { + if let hir::Node::Expr(expr) = tcx.hir_node(id) + && let hir::ExprKind::Index(obj, ..) = expr.kind + { + Some(obj) + } else { + None + } + }) else { + note_default_suggestion(); + return; + }; + + let Ok(obj_str) = sm.span_to_snippet(object.span) else { + note_default_suggestion(); + return; + }; + + let Some(swap_call) = hir.parent_id_iter(object.hir_id).find_map(|id| { + if let hir::Node::Expr(call) = tcx.hir_node(id) + && let hir::ExprKind::Call(callee, ..) = call.kind + && let hir::ExprKind::Path(qpath) = callee.kind + && let hir::QPath::Resolved(None, res) = qpath + && let hir::def::Res::Def(_, did) = res.res + && tcx.is_diagnostic_item(sym::mem_swap, did) + { + Some(call) + } else { + None + } + }) else { + note_default_suggestion(); + return; + }; + + err.span_suggestion( + swap_call.span, + "use `.swap()` to swap elements at the specified indices instead", + format!("{obj_str}.swap({index1_str}, {index2_str})"), + Applicability::MachineApplicable, + ); } } @@ -3242,7 +3328,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { assigned_to, args ); for operand in args { - let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) = operand + let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) = + &operand.node else { continue; }; diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 6606be2f9f42..4f66468a865f 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -691,7 +691,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); // Check if one of the arguments to this function is the target place. let found_target = args.iter().any(|arg| { - if let Operand::Move(place) = arg { + if let Operand::Move(place) = arg.node { if let Some(potential) = place.as_local() { potential == target } else { diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index b31325485db9..b35d4e16eccb 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -23,6 +23,7 @@ use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_middle::util::{call_kind, CallDesugaringKind}; use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult}; use rustc_span::def_id::LocalDefId; +use rustc_span::source_map::Spanned; use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP}; use rustc_target::abi::{FieldIdx, VariantIdx}; use rustc_trait_selection::infer::InferCtxtExt; @@ -111,9 +112,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { debug!("add_moved_or_invoked_closure_note: id={:?}", id); if Some(self.infcx.tcx.parent(id)) == self.infcx.tcx.lang_items().fn_once_trait() { let closure = match args.first() { - Some(Operand::Copy(place) | Operand::Move(place)) - if target == place.local_or_deref_local() => - { + Some(Spanned { + node: Operand::Copy(place) | Operand::Move(place), .. + }) if target == place.local_or_deref_local() => { place.local_or_deref_local().unwrap() } _ => return false, @@ -1178,9 +1179,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } else { vec![(move_span.shrink_to_hi(), ".clone()".to_string())] }; - if let Some(errors) = - self.infcx.could_impl_trait(clone_trait, ty, self.param_env) - && !has_sugg + if let Some(errors) = self.infcx.type_implements_trait_shallow( + clone_trait, + ty, + self.param_env, + ) && !has_sugg { let msg = match &errors[..] { [] => "you can `clone` the value and consume it, but this \ @@ -1213,7 +1216,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Applicability::MaybeIncorrect, ); for error in errors { - if let FulfillmentErrorCode::CodeSelectionError( + if let FulfillmentErrorCode::SelectionError( SelectionError::Unimplemented, ) = error.code && let ty::PredicateKind::Clause(ty::ClauseKind::Trait( diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 3b3d440df97b..0a6b758efa56 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -1217,19 +1217,22 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { { match self .infcx - .could_impl_trait(clone_trait, ty.peel_refs(), self.param_env) + .type_implements_trait_shallow( + clone_trait, + ty.peel_refs(), + self.param_env, + ) .as_deref() { Some([]) => { - // The type implements Clone. - err.span_help( - expr.span, - format!( - "you can `clone` the `{}` value and consume it, but this \ - might not be your desired behavior", - ty.peel_refs(), - ), - ); + // FIXME: This error message isn't useful, since we're just + // vaguely suggesting to clone a value that already + // implements `Clone`. + // + // A correct suggestion here would take into account the fact + // that inference may be affected by missing types on bindings, + // etc., to improve "tests/ui/borrowck/issue-91206.stderr", for + // example. } None => { if let hir::ExprKind::MethodCall(segment, _rcvr, [], span) = @@ -1288,7 +1291,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } // The type doesn't implement Clone because of unmet obligations. for error in errors { - if let traits::FulfillmentErrorCode::CodeSelectionError( + if let traits::FulfillmentErrorCode::SelectionError( traits::SelectionError::Unimplemented, ) = error.code && let ty::PredicateKind::Clause(ty::ClauseKind::Trait( diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 0457b4e6ddc7..b304fb5589f3 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -703,7 +703,7 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro } => { self.consume_operand(loc, (func, span), flow_state); for arg in args { - self.consume_operand(loc, (arg, span), flow_state); + self.consume_operand(loc, (&arg.node, arg.span), flow_state); } self.mutate_place(loc, (*destination, span), Deep, flow_state); } diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 5b764495922b..cc8208e9dc30 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -12,6 +12,7 @@ use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, OpaqueHiddenType, TyCtxt}; use rustc_mir_dataflow::impls::MaybeInitializedPlaces; use rustc_mir_dataflow::move_paths::MoveData; +use rustc_mir_dataflow::points::DenseLocationMap; use rustc_mir_dataflow::ResultsCursor; use rustc_span::symbol::sym; use std::env; @@ -27,7 +28,7 @@ use crate::{ facts::{AllFacts, AllFactsExt, RustcFacts}, location::LocationTable, polonius, - region_infer::{values::RegionValueElements, RegionInferenceContext}, + region_infer::RegionInferenceContext, renumber, type_check::{self, MirTypeckRegionConstraints, MirTypeckResults}, universal_regions::UniversalRegions, @@ -98,7 +99,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>( let universal_regions = Rc::new(universal_regions); - let elements = &Rc::new(RegionValueElements::new(body)); + let elements = &Rc::new(DenseLocationMap::new(body)); // Run the MIR type-checker. let MirTypeckResults { constraints, universal_region_relations, opaque_type_values } = diff --git a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs index 232bd7418259..5c9056272cc0 100644 --- a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs +++ b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs @@ -120,7 +120,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'cx, 'tcx> { } => { self.consume_operand(location, func); for arg in args { - self.consume_operand(location, arg); + self.consume_operand(location, &arg.node); } self.mutate_place(location, *destination, Deep); } diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 948221e94073..89b203f80a43 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -18,7 +18,8 @@ use rustc_middle::mir::{ }; use rustc_middle::traits::ObligationCause; use rustc_middle::traits::ObligationCauseCode; -use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; +use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable}; +use rustc_mir_dataflow::points::DenseLocationMap; use rustc_span::Span; use crate::constraints::graph::{self, NormalConstraintGraph, RegionGraph}; @@ -30,8 +31,7 @@ use crate::{ nll::PoloniusOutput, region_infer::reverse_sccs::ReverseSccGraph, region_infer::values::{ - LivenessValues, PlaceholderIndices, RegionElement, RegionValueElements, RegionValues, - ToElementIndex, + LivenessValues, PlaceholderIndices, RegionElement, RegionValues, ToElementIndex, }, type_check::{free_region_relations::UniversalRegionRelations, Locations}, universal_regions::UniversalRegions, @@ -330,7 +330,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { universe_causes: FxIndexMap>, type_tests: Vec>, liveness_constraints: LivenessValues, - elements: &Rc, + elements: &Rc, ) -> Self { debug!("universal_regions: {:#?}", universal_regions); debug!("outlives constraints: {:#?}", outlives_constraints); @@ -1145,6 +1145,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { } let ty = ty.fold_with(&mut OpaqueFolder { tcx }); + let mut failed = false; let ty = tcx.fold_regions(ty, |r, _depth| { let r_vid = self.to_region_vid(r); @@ -1160,15 +1161,18 @@ impl<'tcx> RegionInferenceContext<'tcx> { .filter(|&u_r| !self.universal_regions.is_local_free_region(u_r)) .find(|&u_r| self.eval_equal(u_r, r_vid)) .map(|u_r| ty::Region::new_var(tcx, u_r)) - // In the case of a failure, use `ReErased`. We will eventually - // return `None` in this case. - .unwrap_or(tcx.lifetimes.re_erased) + // In case we could not find a named region to map to, + // we will return `None` below. + .unwrap_or_else(|| { + failed = true; + r + }) }); debug!("try_promote_type_test_subject: folded ty = {:?}", ty); // This will be true if we failed to promote some region. - if ty.has_erased_regions() { + if failed { return None; } diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs index dc3ee849d004..e147f62011db 100644 --- a/compiler/rustc_borrowck/src/region_infer/values.rs +++ b/compiler/rustc_borrowck/src/region_infer/values.rs @@ -1,101 +1,18 @@ #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] +use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxIndexSet; use rustc_index::bit_set::SparseBitMatrix; use rustc_index::interval::IntervalSet; use rustc_index::interval::SparseIntervalMatrix; use rustc_index::Idx; -use rustc_index::IndexVec; -use rustc_middle::mir::{BasicBlock, Body, Location}; +use rustc_middle::mir::{BasicBlock, Location}; use rustc_middle::ty::{self, RegionVid}; +use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex}; use std::fmt::Debug; use std::rc::Rc; -use crate::dataflow::BorrowIndex; - -/// Maps between a `Location` and a `PointIndex` (and vice versa). -pub(crate) struct RegionValueElements { - /// For each basic block, how many points are contained within? - statements_before_block: IndexVec, - - /// Map backward from each point to the basic block that it - /// belongs to. - basic_blocks: IndexVec, - - num_points: usize, -} - -impl RegionValueElements { - pub(crate) fn new(body: &Body<'_>) -> Self { - let mut num_points = 0; - let statements_before_block: IndexVec = body - .basic_blocks - .iter() - .map(|block_data| { - let v = num_points; - num_points += block_data.statements.len() + 1; - v - }) - .collect(); - debug!("RegionValueElements: statements_before_block={:#?}", statements_before_block); - debug!("RegionValueElements: num_points={:#?}", num_points); - - let mut basic_blocks = IndexVec::with_capacity(num_points); - for (bb, bb_data) in body.basic_blocks.iter_enumerated() { - basic_blocks.extend((0..=bb_data.statements.len()).map(|_| bb)); - } - - Self { statements_before_block, basic_blocks, num_points } - } - - /// Total number of point indices - pub(crate) fn num_points(&self) -> usize { - self.num_points - } - - /// Converts a `Location` into a `PointIndex`. O(1). - pub(crate) fn point_from_location(&self, location: Location) -> PointIndex { - let Location { block, statement_index } = location; - let start_index = self.statements_before_block[block]; - PointIndex::new(start_index + statement_index) - } - - /// Converts a `Location` into a `PointIndex`. O(1). - pub(crate) fn entry_point(&self, block: BasicBlock) -> PointIndex { - let start_index = self.statements_before_block[block]; - PointIndex::new(start_index) - } - - /// Return the PointIndex for the block start of this index. - pub(crate) fn to_block_start(&self, index: PointIndex) -> PointIndex { - PointIndex::new(self.statements_before_block[self.basic_blocks[index]]) - } - - /// Converts a `PointIndex` back to a location. O(1). - pub(crate) fn to_location(&self, index: PointIndex) -> Location { - assert!(index.index() < self.num_points); - let block = self.basic_blocks[index]; - let start_index = self.statements_before_block[block]; - let statement_index = index.index() - start_index; - Location { block, statement_index } - } - - /// Sometimes we get point-indices back from bitsets that may be - /// out of range (because they round up to the nearest 2^N number - /// of bits). Use this function to filter such points out if you - /// like. - pub(crate) fn point_in_range(&self, index: PointIndex) -> bool { - index.index() < self.num_points - } -} - -rustc_index::newtype_index! { - /// A single integer representing a `Location` in the MIR control-flow - /// graph. Constructed efficiently from `RegionValueElements`. - #[orderable] - #[debug_format = "PointIndex({})"] - pub struct PointIndex {} -} +use crate::BorrowIndex; rustc_index::newtype_index! { /// A single integer representing a `ty::Placeholder`. @@ -123,10 +40,17 @@ pub(crate) enum RegionElement { /// an interval matrix storing liveness ranges for each region-vid. pub(crate) struct LivenessValues { /// The map from locations to points. - elements: Rc, + elements: Rc, + + /// Which regions are live. This is exclusive with the fine-grained tracking in `points`, and + /// currently only used for validating promoteds (which don't care about more precise tracking). + live_regions: Option>, /// For each region: the points where it is live. - points: SparseIntervalMatrix, + /// + /// This is not initialized for promoteds, because we don't care *where* within a promoted a + /// region is live, only that it is. + points: Option>, /// When using `-Zpolonius=next`, for each point: the loans flowing into the live regions at /// that point. @@ -155,24 +79,52 @@ impl LiveLoans { impl LivenessValues { /// Create an empty map of regions to locations where they're live. - pub(crate) fn new(elements: Rc) -> Self { + pub(crate) fn with_specific_points(elements: Rc) -> Self { LivenessValues { - points: SparseIntervalMatrix::new(elements.num_points), + live_regions: None, + points: Some(SparseIntervalMatrix::new(elements.num_points())), + elements, + loans: None, + } + } + + /// Create an empty map of regions to locations where they're live. + /// + /// Unlike `with_specific_points`, does not track exact locations where something is live, only + /// which regions are live. + pub(crate) fn without_specific_points(elements: Rc) -> Self { + LivenessValues { + live_regions: Some(Default::default()), + points: None, elements, loans: None, } } /// Iterate through each region that has a value in this set. - pub(crate) fn regions(&self) -> impl Iterator { - self.points.rows() + pub(crate) fn regions(&self) -> impl Iterator + '_ { + self.points.as_ref().expect("use with_specific_points").rows() + } + + /// Iterate through each region that has a value in this set. + // We are passing query instability implications to the caller. + #[rustc_lint_query_instability] + #[allow(rustc::potential_query_instability)] + pub(crate) fn live_regions_unordered(&self) -> impl Iterator + '_ { + self.live_regions.as_ref().unwrap().iter().copied() } /// Records `region` as being live at the given `location`. pub(crate) fn add_location(&mut self, region: RegionVid, location: Location) { - debug!("LivenessValues::add_location(region={:?}, location={:?})", region, location); let point = self.elements.point_from_location(location); - self.points.insert(region, point); + debug!("LivenessValues::add_location(region={:?}, location={:?})", region, location); + if let Some(points) = &mut self.points { + points.insert(region, point); + } else { + if self.elements.point_in_range(point) { + self.live_regions.as_mut().unwrap().insert(region); + } + } // When available, record the loans flowing into this region as live at the given point. if let Some(loans) = self.loans.as_mut() { @@ -185,7 +137,13 @@ impl LivenessValues { /// Records `region` as being live at all the given `points`. pub(crate) fn add_points(&mut self, region: RegionVid, points: &IntervalSet) { debug!("LivenessValues::add_points(region={:?}, points={:?})", region, points); - self.points.union_row(region, points); + if let Some(this) = &mut self.points { + this.union_row(region, points); + } else { + if points.iter().any(|point| self.elements.point_in_range(point)) { + self.live_regions.as_mut().unwrap().insert(region); + } + } // When available, record the loans flowing into this region as live at the given points. if let Some(loans) = self.loans.as_mut() { @@ -201,23 +159,33 @@ impl LivenessValues { /// Records `region` as being live at all the control-flow points. pub(crate) fn add_all_points(&mut self, region: RegionVid) { - self.points.insert_all_into_row(region); + if let Some(points) = &mut self.points { + points.insert_all_into_row(region); + } else { + self.live_regions.as_mut().unwrap().insert(region); + } } /// Returns whether `region` is marked live at the given `location`. pub(crate) fn is_live_at(&self, region: RegionVid, location: Location) -> bool { let point = self.elements.point_from_location(location); - self.points.row(region).is_some_and(|r| r.contains(point)) - } - - /// Returns whether `region` is marked live at any location. - pub(crate) fn is_live_anywhere(&self, region: RegionVid) -> bool { - self.live_points(region).next().is_some() + if let Some(points) = &self.points { + points.row(region).is_some_and(|r| r.contains(point)) + } else { + unreachable!( + "Should be using LivenessValues::with_specific_points to ask whether live at a location" + ) + } } /// Returns an iterator of all the points where `region` is live. fn live_points(&self, region: RegionVid) -> impl Iterator + '_ { - self.points + let Some(points) = &self.points else { + unreachable!( + "Should be using LivenessValues::with_specific_points to ask whether live at a location" + ) + }; + points .row(region) .into_iter() .flat_map(|set| set.iter()) @@ -298,7 +266,7 @@ impl PlaceholderIndices { /// it would also contain various points from within the function. #[derive(Clone)] pub(crate) struct RegionValues { - elements: Rc, + elements: Rc, placeholder_indices: Rc, points: SparseIntervalMatrix, free_regions: SparseBitMatrix, @@ -313,14 +281,14 @@ impl RegionValues { /// Each of the regions in num_region_variables will be initialized with an /// empty set of points and no causal information. pub(crate) fn new( - elements: &Rc, + elements: &Rc, num_universal_regions: usize, placeholder_indices: &Rc, ) -> Self { let num_placeholders = placeholder_indices.len(); Self { elements: elements.clone(), - points: SparseIntervalMatrix::new(elements.num_points), + points: SparseIntervalMatrix::new(elements.num_points()), placeholder_indices: placeholder_indices.clone(), free_regions: SparseBitMatrix::new(num_universal_regions), placeholders: SparseBitMatrix::new(num_placeholders), @@ -372,7 +340,10 @@ impl RegionValues { /// elements for the region `from` from `values` and add them to /// the region `to` in `self`. pub(crate) fn merge_liveness(&mut self, to: N, from: RegionVid, values: &LivenessValues) { - if let Some(set) = values.points.row(from) { + let Some(value_points) = &values.points else { + panic!("LivenessValues must track specific points for use in merge_liveness"); + }; + if let Some(set) = value_points.row(from) { self.points.union_row(to, set); } } @@ -486,7 +457,7 @@ impl ToElementIndex for ty::PlaceholderRegion { /// For debugging purposes, returns a pretty-printed string of the given points. pub(crate) fn pretty_print_points( - elements: &RegionValueElements, + elements: &DenseLocationMap, points: impl IntoIterator, ) -> String { pretty_print_region_elements( diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index 4a76d877af0f..011b5b760c23 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -1,5 +1,6 @@ use rustc_data_structures::frozen::Frozen; use rustc_data_structures::transitive_relation::{TransitiveRelation, TransitiveRelationBuilder}; +use rustc_hir::def::DefKind; use rustc_infer::infer::canonical::QueryRegionConstraints; use rustc_infer::infer::outlives; use rustc_infer::infer::outlives::env::RegionBoundPairs; @@ -195,7 +196,9 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { #[instrument(level = "debug", skip(self))] pub(crate) fn create(mut self) -> CreateResult<'tcx> { - let span = self.infcx.tcx.def_span(self.universal_regions.defining_ty.def_id()); + let tcx = self.infcx.tcx; + let defining_ty_def_id = self.universal_regions.defining_ty.def_id().expect_local(); + let span = tcx.def_span(defining_ty_def_id); // Insert the facts we know from the predicates. Why? Why not. let param_env = self.param_env; @@ -275,6 +278,26 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { normalized_inputs_and_output.push(norm_ty); } + // Add implied bounds from impl header. + if matches!(tcx.def_kind(defining_ty_def_id), DefKind::AssocFn | DefKind::AssocConst) { + for &(ty, _) in tcx.assumed_wf_types(tcx.local_parent(defining_ty_def_id)) { + let Ok(TypeOpOutput { output: norm_ty, constraints: c, .. }) = self + .param_env + .and(type_op::normalize::Normalize::new(ty)) + .fully_perform(self.infcx, span) + else { + tcx.dcx().span_delayed_bug(span, format!("failed to normalize {ty:?}")); + continue; + }; + constraints.extend(c); + + // We currently add implied bounds from the normalized ty only. + // This is more conservative and matches wfcheck behavior. + let c = self.add_implied_bounds(norm_ty); + constraints.extend(c); + } + } + for c in constraints { self.push_region_constraints(c, span); } diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index 61b6bef3b87b..59518f68ab14 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -7,6 +7,7 @@ //! `RETURN_PLACE` the MIR arguments) are always fully normalized (and //! contain revealed `impl Trait` values). +use itertools::Itertools; use rustc_infer::infer::BoundRegionConversionTime; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty}; @@ -39,9 +40,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { user_provided_sig, ); - for (&user_ty, arg_decl) in user_provided_sig.inputs().iter().zip( - // In MIR, closure args begin with an implicit `self`. Skip it! - body.args_iter().skip(1).map(|local| &body.local_decls[local]), + let is_coroutine_with_implicit_resume_ty = self.tcx().is_coroutine(mir_def_id.to_def_id()) + && user_provided_sig.inputs().is_empty(); + + for (&user_ty, arg_decl) in user_provided_sig.inputs().iter().zip_eq( + // In MIR, closure args begin with an implicit `self`. + // Also, coroutines have a resume type which may be implicitly `()`. + body.args_iter() + .skip(1 + if is_coroutine_with_implicit_resume_ty { 1 } else { 0 }) + .map(|local| &body.local_decls[local]), ) { self.ascribe_user_type_skip_wf( arg_decl.ty, diff --git a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs index 7433c94a0bcd..da5456692ab1 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs @@ -2,9 +2,9 @@ use rustc_data_structures::vec_linked_list as vll; use rustc_index::IndexVec; use rustc_middle::mir::visit::{PlaceContext, Visitor}; use rustc_middle::mir::{Body, Local, Location}; +use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex}; use crate::def_use::{self, DefUse}; -use crate::region_infer::values::{PointIndex, RegionValueElements}; /// A map that cross references each local with the locations where it /// is defined (assigned), used, or dropped. Used during liveness @@ -60,7 +60,7 @@ impl vll::LinkElem for Appearance { impl LocalUseMap { pub(crate) fn build( live_locals: &[Local], - elements: &RegionValueElements, + elements: &DenseLocationMap, body: &Body<'_>, ) -> Self { let nones = IndexVec::from_elem(None, &body.local_decls); @@ -103,7 +103,7 @@ impl LocalUseMap { struct LocalUseMapBuild<'me> { local_use_map: &'me mut LocalUseMap, - elements: &'me RegionValueElements, + elements: &'me DenseLocationMap, // Vector used in `visit_local` to signal which `Local`s do we need // def/use/drop information on, constructed from `live_locals` (that @@ -144,7 +144,7 @@ impl LocalUseMapBuild<'_> { } fn insert( - elements: &RegionValueElements, + elements: &DenseLocationMap, first_appearance: &mut Option, appearances: &mut IndexVec, location: Location, diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs index e137bc1be0ae..51ae7d14e438 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs @@ -6,6 +6,7 @@ use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{GenericArgsRef, Region, RegionVid, Ty, TyCtxt}; use rustc_mir_dataflow::impls::MaybeInitializedPlaces; use rustc_mir_dataflow::move_paths::MoveData; +use rustc_mir_dataflow::points::DenseLocationMap; use rustc_mir_dataflow::ResultsCursor; use std::rc::Rc; @@ -13,7 +14,7 @@ use crate::{ constraints::OutlivesConstraintSet, facts::{AllFacts, AllFactsExt}, location::LocationTable, - region_infer::values::{LivenessValues, RegionValueElements}, + region_infer::values::LivenessValues, universal_regions::UniversalRegions, }; @@ -34,7 +35,7 @@ mod trace; pub(super) fn generate<'mir, 'tcx>( typeck: &mut TypeChecker<'_, 'tcx>, body: &Body<'tcx>, - elements: &Rc, + elements: &Rc, flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>, move_data: &MoveData<'tcx>, location_table: &LocationTable, diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index c718d57bec39..eec128b5f1d5 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -7,6 +7,7 @@ use rustc_infer::infer::outlives::for_liveness; use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, Local, Location}; use rustc_middle::traits::query::DropckOutlivesResult; use rustc_middle::ty::{Ty, TyCtxt, TypeVisitable, TypeVisitableExt}; +use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex}; use rustc_span::DUMMY_SP; use rustc_trait_selection::traits::query::type_op::outlives::DropckOutlives; use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput}; @@ -17,7 +18,7 @@ use rustc_mir_dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex}; use rustc_mir_dataflow::ResultsCursor; use crate::{ - region_infer::values::{self, LiveLoans, PointIndex, RegionValueElements}, + region_infer::values::{self, LiveLoans}, type_check::liveness::local_use_map::LocalUseMap, type_check::liveness::polonius, type_check::NormalizeLocation, @@ -41,7 +42,7 @@ use crate::{ pub(super) fn trace<'mir, 'tcx>( typeck: &mut TypeChecker<'_, 'tcx>, body: &Body<'tcx>, - elements: &Rc, + elements: &Rc, flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>, move_data: &MoveData<'tcx>, relevant_live_locals: Vec, @@ -105,7 +106,7 @@ struct LivenessContext<'me, 'typeck, 'flow, 'tcx> { typeck: &'me mut TypeChecker<'typeck, 'tcx>, /// Defines the `PointIndex` mapping - elements: &'me RegionValueElements, + elements: &'me DenseLocationMap, /// MIR we are analyzing. body: &'me Body<'tcx>, @@ -570,7 +571,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> { } fn make_all_regions_live( - elements: &RegionValueElements, + elements: &DenseLocationMap, typeck: &mut TypeChecker<'_, 'tcx>, value: impl TypeVisitable>, live_at: &IntervalSet, diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 9c0f53ddb86f..cf28e62177fb 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -35,7 +35,9 @@ use rustc_middle::ty::{ OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, UserType, UserTypeAnnotationIndex, }; use rustc_middle::ty::{GenericArgsRef, UserArgs}; +use rustc_mir_dataflow::points::DenseLocationMap; use rustc_span::def_id::CRATE_DEF_ID; +use rustc_span::source_map::Spanned; use rustc_span::symbol::sym; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{FieldIdx, FIRST_VARIANT}; @@ -58,9 +60,7 @@ use crate::{ location::LocationTable, member_constraints::MemberConstraintSet, path_utils, - region_infer::values::{ - LivenessValues, PlaceholderIndex, PlaceholderIndices, RegionValueElements, - }, + region_infer::values::{LivenessValues, PlaceholderIndex, PlaceholderIndices}, region_infer::TypeTest, type_check::free_region_relations::{CreateResult, UniversalRegionRelations}, universal_regions::{DefiningTy, UniversalRegions}, @@ -133,7 +133,7 @@ pub(crate) fn type_check<'mir, 'tcx>( all_facts: &mut Option, flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>, move_data: &MoveData<'tcx>, - elements: &Rc, + elements: &Rc, upvars: &[&ty::CapturedPlace<'tcx>], use_polonius: bool, ) -> MirTypeckResults<'tcx> { @@ -141,7 +141,7 @@ pub(crate) fn type_check<'mir, 'tcx>( let mut constraints = MirTypeckRegionConstraints { placeholder_indices: PlaceholderIndices::default(), placeholder_index_to_region: IndexVec::default(), - liveness_constraints: LivenessValues::new(elements.clone()), + liveness_constraints: LivenessValues::with_specific_points(elements.clone()), outlives_constraints: OutlivesConstraintSet::default(), member_constraints: MemberConstraintSet::default(), type_tests: Vec::default(), @@ -406,6 +406,16 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { instantiated_predicates, locations, ); + + assert!(!matches!( + tcx.impl_of_method(def_id).map(|imp| tcx.def_kind(imp)), + Some(DefKind::Impl { of_trait: true }) + )); + self.cx.prove_predicates( + args.types().map(|ty| ty::ClauseKind::WellFormed(ty.into())), + locations, + ConstraintCategory::Boring, + ); } } } @@ -545,7 +555,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { let all_facts = &mut None; let mut constraints = Default::default(); let mut liveness_constraints = - LivenessValues::new(Rc::new(RegionValueElements::new(promoted_body))); + LivenessValues::without_specific_points(Rc::new(DenseLocationMap::new(promoted_body))); // Don't try to add borrow_region facts for the promoted MIR let mut swap_constraints = |this: &mut Self| { @@ -584,17 +594,19 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { } self.cx.borrowck_context.constraints.outlives_constraints.push(constraint) } - for region in liveness_constraints.regions() { - // If the region is live at at least one location in the promoted MIR, - // then add a liveness constraint to the main MIR for this region - // at the location provided as an argument to this method - if liveness_constraints.is_live_anywhere(region) { - self.cx - .borrowck_context - .constraints - .liveness_constraints - .add_location(region, location); - } + // If the region is live at at least one location in the promoted MIR, + // then add a liveness constraint to the main MIR for this region + // at the location provided as an argument to this method + // + // add_location doesn't care about ordering so not a problem for the live regions to be + // unordered. + #[allow(rustc::potential_query_instability)] + for region in liveness_constraints.live_regions_unordered() { + self.cx + .borrowck_context + .constraints + .liveness_constraints + .add_location(region, location); } } @@ -1359,7 +1371,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { TerminatorKind::Call { func, args, destination, call_source, target, .. } => { self.check_operand(func, term_location); for arg in args { - self.check_operand(arg, term_location); + self.check_operand(&arg.node, term_location); } let func_ty = func.ty(body, tcx); @@ -1580,7 +1592,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { term: &Terminator<'tcx>, func: &Operand<'tcx>, sig: &ty::FnSig<'tcx>, - args: &[Operand<'tcx>], + args: &[Spanned>], term_location: Location, call_source: CallSource, ) { @@ -1593,7 +1605,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if self.tcx().is_intrinsic(def_id) { match self.tcx().item_name(def_id) { sym::simd_shuffle => { - if !matches!(args[2], Operand::Constant(_)) { + if !matches!(args[2], Spanned { node: Operand::Constant(_), .. }) { self.tcx() .dcx() .emit_err(SimdShuffleLastConst { span: term.source_info.span }); @@ -1606,7 +1618,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { debug!(?func_ty); for (n, (fn_arg, op_arg)) in iter::zip(sig.inputs(), args).enumerate() { - let op_arg_ty = op_arg.ty(body, self.tcx()); + let op_arg_ty = op_arg.node.ty(body, self.tcx()); let op_arg_ty = self.normalize(op_arg_ty, term_location); let category = if call_source.from_hir_call() { diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index addb41ff5fc8..ae8a135f0905 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -668,7 +668,11 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { kind: ty::BrEnv, }; let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br); - let closure_ty = tcx.closure_env_ty(def_id, args, env_region).unwrap(); + let closure_ty = tcx.closure_env_ty( + Ty::new_closure(tcx, def_id, args), + args.as_closure().kind(), + env_region, + ); // The "inputs" of the closure in the // signature appear as a tuple. The MIR side diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index f60b73fbe9b1..3e9b06a5b054 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -6,6 +6,7 @@ #![doc(rust_logo)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(array_windows)] +#![feature(assert_matches)] #![feature(box_patterns)] #![feature(decl_macro)] #![feature(if_let_guard)] diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index 4d44e340ae14..0631f796894b 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -9,6 +9,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder, Level}; use rustc_expand::base::*; use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::{ErrorGuaranteed, FileNameDisplayPreference, Span}; +use std::assert_matches::assert_matches; use std::iter; use thin_vec::{thin_vec, ThinVec}; @@ -182,6 +183,16 @@ pub fn expand_test_or_bench( // creates $name: $expr let field = |name, expr| cx.field_imm(sp, Ident::from_str_and_span(name, sp), expr); + // Adds `#[coverage(off)]` to a closure, so it won't be instrumented in + // `-Cinstrument-coverage` builds. + // This requires `#[allow_internal_unstable(coverage_attribute)]` on the + // corresponding macro declaration in `core::macros`. + let coverage_off = |mut expr: P| { + assert_matches!(expr.kind, ast::ExprKind::Closure(_)); + expr.attrs.push(cx.attr_nested_word(sym::coverage, sym::off, sp)); + expr + }; + let test_fn = if is_bench { // A simple ident for a lambda let b = Ident::from_str_and_span("b", attr_sp); @@ -190,8 +201,9 @@ pub fn expand_test_or_bench( sp, cx.expr_path(test_path("StaticBenchFn")), thin_vec![ + // #[coverage(off)] // |b| self::test::assert_test_result( - cx.lambda1( + coverage_off(cx.lambda1( sp, cx.expr_call( sp, @@ -206,7 +218,7 @@ pub fn expand_test_or_bench( ], ), b, - ), // ) + )), // ) ], ) } else { @@ -214,8 +226,9 @@ pub fn expand_test_or_bench( sp, cx.expr_path(test_path("StaticTestFn")), thin_vec![ + // #[coverage(off)] // || { - cx.lambda0( + coverage_off(cx.lambda0( sp, // test::assert_test_result( cx.expr_call( @@ -230,7 +243,7 @@ pub fn expand_test_or_bench( ), // ) ], ), // } - ), // ) + )), // ) ], ) }; diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock index 74e7afee7bcb..6d6a1200f502 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.lock +++ b/compiler/rustc_codegen_cranelift/Cargo.lock @@ -246,12 +246,12 @@ checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" [[package]] name = "libloading" -version = "0.7.4" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" dependencies = [ "cfg-if", - "winapi", + "windows-sys", ] [[package]] diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml index fdac789423c9..c57e964168f4 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.toml +++ b/compiler/rustc_codegen_cranelift/Cargo.toml @@ -19,7 +19,7 @@ gimli = { version = "0.28", default-features = false, features = ["write"]} object = { version = "0.32", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } indexmap = "2.0.0" -libloading = { version = "0.7.3", optional = true } +libloading = { version = "0.8.0", optional = true } smallvec = "1.8.1" [patch.crates-io] diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index 795c8daec6a3..abd70dd4458f 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -11,6 +11,7 @@ use cranelift_module::ModuleError; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::ty::layout::FnAbiOf; use rustc_session::Session; +use rustc_span::source_map::Spanned; use rustc_target::abi::call::{Conv, FnAbi}; use rustc_target::spec::abi::Abi; @@ -360,7 +361,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, source_info: mir::SourceInfo, func: &Operand<'tcx>, - args: &[Operand<'tcx>], + args: &[Spanned>], destination: Place<'tcx>, target: Option, ) { @@ -415,7 +416,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( let extra_args = &args[fn_sig.inputs().skip_binder().len()..]; let extra_args = fx.tcx.mk_type_list_from_iter( - extra_args.iter().map(|op_arg| fx.monomorphize(op_arg.ty(fx.mir, fx.tcx))), + extra_args.iter().map(|op_arg| fx.monomorphize(op_arg.node.ty(fx.mir, fx.tcx))), ); let fn_abi = if let Some(instance) = instance { RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(instance, extra_args) @@ -440,10 +441,10 @@ pub(crate) fn codegen_terminator_call<'tcx>( // Unpack arguments tuple for closures let mut args = if fn_sig.abi() == Abi::RustCall { let (self_arg, pack_arg) = match args { - [pack_arg] => (None, codegen_call_argument_operand(fx, pack_arg)), + [pack_arg] => (None, codegen_call_argument_operand(fx, &pack_arg.node)), [self_arg, pack_arg] => ( - Some(codegen_call_argument_operand(fx, self_arg)), - codegen_call_argument_operand(fx, pack_arg), + Some(codegen_call_argument_operand(fx, &self_arg.node)), + codegen_call_argument_operand(fx, &pack_arg.node), ), _ => panic!("rust-call abi requires one or two arguments"), }; @@ -463,7 +464,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( } args } else { - args.iter().map(|arg| codegen_call_argument_operand(fx, arg)).collect::>() + args.iter().map(|arg| codegen_call_argument_operand(fx, &arg.node)).collect::>() }; // Pass the caller location for `#[track_caller]`. diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs index a38a728c926d..1345c4614e25 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs @@ -7,7 +7,7 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, intrinsic: &str, generic_args: GenericArgsRef<'tcx>, - args: &[mir::Operand<'tcx>], + args: &[Spanned>], ret: CPlace<'tcx>, target: Option, span: Span, diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs index c8f9c3997a63..f6f3b85d3ef8 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs @@ -7,7 +7,7 @@ pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, intrinsic: &str, _args: GenericArgsRef<'tcx>, - args: &[mir::Operand<'tcx>], + args: &[Spanned>], ret: CPlace<'tcx>, target: Option, ) { diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs index 81114cbf40d8..994dc66835cd 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs @@ -11,7 +11,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, intrinsic: &str, _args: GenericArgsRef<'tcx>, - args: &[mir::Operand<'tcx>], + args: &[Spanned>], ret: CPlace<'tcx>, target: Option, span: Span, @@ -175,9 +175,9 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( [x, y, kind] => (x, y, kind), _ => bug!("wrong number of args for intrinsic {intrinsic}"), }; - let x = codegen_operand(fx, x); - let y = codegen_operand(fx, y); - let kind = match kind { + let x = codegen_operand(fx, &x.node); + let y = codegen_operand(fx, &y.node); + let kind = match &kind.node { Operand::Constant(const_) => crate::constant::eval_mir_constant(fx, const_).0, Operand::Copy(_) | Operand::Move(_) => unreachable!("{kind:?}"), }; @@ -287,8 +287,8 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( [a, b] => (a, b), _ => bug!("wrong number of args for intrinsic {intrinsic}"), }; - let a = codegen_operand(fx, a); - let b = codegen_operand(fx, b); + let a = codegen_operand(fx, &a.node); + let b = codegen_operand(fx, &b.node); // Based on the pseudocode at https://github.com/rust-lang/stdarch/blob/1cfbca8b38fd9b4282b2f054f61c6ca69fc7ce29/crates/core_arch/src/x86/avx2.rs#L2319-L2332 let zero = fx.bcx.ins().iconst(types::I8, 0); @@ -325,9 +325,9 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( [a, b, imm8] => (a, b, imm8), _ => bug!("wrong number of args for intrinsic {intrinsic}"), }; - let a = codegen_operand(fx, a); - let b = codegen_operand(fx, b); - let imm8 = codegen_operand(fx, imm8).load_scalar(fx); + let a = codegen_operand(fx, &a.node); + let b = codegen_operand(fx, &b.node); + let imm8 = codegen_operand(fx, &imm8.node).load_scalar(fx); let a_low = a.value_typed_lane(fx, fx.tcx.types.u128, 0).load_scalar(fx); let a_high = a.value_typed_lane(fx, fx.tcx.types.u128, 1).load_scalar(fx); @@ -956,14 +956,14 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( let b = b.load_scalar(fx); let lb = lb.load_scalar(fx); - let imm8 = if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[4]) - { - imm8 - } else { - fx.tcx - .dcx() - .span_fatal(span, "Index argument for `_mm_cmpestri` is not a constant"); - }; + let imm8 = + if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[4].node) { + imm8 + } else { + fx.tcx + .dcx() + .span_fatal(span, "Index argument for `_mm_cmpestri` is not a constant"); + }; let imm8 = imm8.try_to_u8().unwrap_or_else(|_| panic!("kind not scalar: {:?}", imm8)); @@ -1009,14 +1009,14 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( let b = b.load_scalar(fx); let lb = lb.load_scalar(fx); - let imm8 = if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[4]) - { - imm8 - } else { - fx.tcx - .dcx() - .span_fatal(span, "Index argument for `_mm_cmpestrm` is not a constant"); - }; + let imm8 = + if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[4].node) { + imm8 + } else { + fx.tcx + .dcx() + .span_fatal(span, "Index argument for `_mm_cmpestrm` is not a constant"); + }; let imm8 = imm8.try_to_u8().unwrap_or_else(|_| panic!("kind not scalar: {:?}", imm8)); @@ -1056,15 +1056,15 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( let a = a.load_scalar(fx); let b = b.load_scalar(fx); - let imm8 = if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[2]) - { - imm8 - } else { - fx.tcx.dcx().span_fatal( - span, - "Index argument for `_mm_clmulepi64_si128` is not a constant", - ); - }; + let imm8 = + if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[2].node) { + imm8 + } else { + fx.tcx.dcx().span_fatal( + span, + "Index argument for `_mm_clmulepi64_si128` is not a constant", + ); + }; let imm8 = imm8.try_to_u8().unwrap_or_else(|_| panic!("kind not scalar: {:?}", imm8)); @@ -1093,15 +1093,15 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( let a = a.load_scalar(fx); - let imm8 = if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[1]) - { - imm8 - } else { - fx.tcx.dcx().span_fatal( - span, - "Index argument for `_mm_aeskeygenassist_si128` is not a constant", - ); - }; + let imm8 = + if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[1].node) { + imm8 + } else { + fx.tcx.dcx().span_fatal( + span, + "Index argument for `_mm_aeskeygenassist_si128` is not a constant", + ); + }; let imm8 = imm8.try_to_u8().unwrap_or_else(|_| panic!("kind not scalar: {:?}", imm8)); diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 15249402a63e..a27853fa0a82 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -5,7 +5,7 @@ macro_rules! intrinsic_args { ($fx:expr, $args:expr => ($($arg:tt),*); $intrinsic:expr) => { #[allow(unused_parens)] let ($($arg),*) = if let [$($arg),*] = $args { - ($(codegen_operand($fx, $arg)),*) + ($(codegen_operand($fx, &($arg).node)),*) } else { $crate::intrinsics::bug_on_incorrect_arg_count($intrinsic); }; @@ -22,6 +22,7 @@ use rustc_middle::ty; use rustc_middle::ty::layout::{HasParamEnv, ValidityRequirement}; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::GenericArgsRef; +use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Symbol}; pub(crate) use self::llvm::codegen_llvm_intrinsic_call; @@ -263,7 +264,7 @@ fn bool_to_zero_or_max_uint<'tcx>( pub(crate) fn codegen_intrinsic_call<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, instance: Instance<'tcx>, - args: &[mir::Operand<'tcx>], + args: &[Spanned>], destination: CPlace<'tcx>, target: Option, source_info: mir::SourceInfo, @@ -301,7 +302,7 @@ pub(crate) fn codegen_intrinsic_call<'tcx>( fn codegen_float_intrinsic_call<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, intrinsic: Symbol, - args: &[mir::Operand<'tcx>], + args: &[Spanned>], ret: CPlace<'tcx>, ) -> bool { let (name, arg_count, ty, clif_ty) = match intrinsic { @@ -353,18 +354,21 @@ fn codegen_float_intrinsic_call<'tcx>( let (a, b, c); let args = match args { [x] => { - a = [codegen_operand(fx, x).load_scalar(fx)]; + a = [codegen_operand(fx, &x.node).load_scalar(fx)]; &a as &[_] } [x, y] => { - b = [codegen_operand(fx, x).load_scalar(fx), codegen_operand(fx, y).load_scalar(fx)]; + b = [ + codegen_operand(fx, &x.node).load_scalar(fx), + codegen_operand(fx, &y.node).load_scalar(fx), + ]; &b } [x, y, z] => { c = [ - codegen_operand(fx, x).load_scalar(fx), - codegen_operand(fx, y).load_scalar(fx), - codegen_operand(fx, z).load_scalar(fx), + codegen_operand(fx, &x.node).load_scalar(fx), + codegen_operand(fx, &y.node).load_scalar(fx), + codegen_operand(fx, &z.node).load_scalar(fx), ]; &c } @@ -422,7 +426,7 @@ fn codegen_regular_intrinsic_call<'tcx>( instance: Instance<'tcx>, intrinsic: Symbol, generic_args: GenericArgsRef<'tcx>, - args: &[mir::Operand<'tcx>], + args: &[Spanned>], ret: CPlace<'tcx>, destination: Option, source_info: mir::SourceInfo, diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index 78ea7c2dbfc3..d56d17892d5b 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -21,7 +21,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, intrinsic: Symbol, generic_args: GenericArgsRef<'tcx>, - args: &[mir::Operand<'tcx>], + args: &[Spanned>], ret: CPlace<'tcx>, target: BasicBlock, span: Span, @@ -121,8 +121,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let [x, y] = args else { bug!("wrong number of args for intrinsic {intrinsic}"); }; - let x = codegen_operand(fx, x); - let y = codegen_operand(fx, y); + let x = codegen_operand(fx, &x.node); + let y = codegen_operand(fx, &y.node); if !x.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, x.layout().ty); @@ -172,8 +172,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( bug!("wrong number of args for intrinsic {intrinsic}"); } }; - let x = codegen_operand(fx, x); - let y = codegen_operand(fx, y); + let x = codegen_operand(fx, &x.node); + let y = codegen_operand(fx, &y.node); if !x.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, x.layout().ty); @@ -182,7 +182,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( // Make sure this is actually an array, since typeck only checks the length-suffixed // version of this intrinsic. - let idx_ty = fx.monomorphize(idx.ty(fx.mir, fx.tcx)); + let idx_ty = fx.monomorphize(idx.node.ty(fx.mir, fx.tcx)); let n: u16 = match idx_ty.kind() { ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => len .try_eval_target_usize(fx.tcx, ty::ParamEnv::reveal_all()) @@ -215,7 +215,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let indexes = { use rustc_middle::mir::interpret::*; - let idx_const = match idx { + let idx_const = match &idx.node { Operand::Constant(const_) => crate::constant::eval_mir_constant(fx, const_).0, Operand::Copy(_) | Operand::Move(_) => unreachable!("{idx:?}"), }; @@ -269,12 +269,12 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( bug!("wrong number of args for intrinsic {intrinsic}"); } }; - let base = codegen_operand(fx, base); - let val = codegen_operand(fx, val); + let base = codegen_operand(fx, &base.node); + let val = codegen_operand(fx, &val.node); // FIXME validate let idx_const = if let Some(idx_const) = - crate::constant::mir_operand_get_const_val(fx, idx) + crate::constant::mir_operand_get_const_val(fx, &idx.node) { idx_const } else { @@ -304,7 +304,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( bug!("wrong number of args for intrinsic {intrinsic}"); } }; - let v = codegen_operand(fx, v); + let v = codegen_operand(fx, &v.node); if !v.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, v.layout().ty); @@ -312,7 +312,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( } let idx_const = if let Some(idx_const) = - crate::constant::mir_operand_get_const_val(fx, idx) + crate::constant::mir_operand_get_const_val(fx, &idx.node) { idx_const } else { diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index c12142e302d3..3948a49ee2aa 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -11,7 +11,7 @@ test = false bitflags = "2.4.1" itertools = "0.11" libc = "0.2" -measureme = "10.0.0" +measureme = "11" object = { version = "0.32.0", default-features = false, features = ["std", "read"] } rustc-demangle = "0.1.21" rustc_ast = { path = "../rustc_ast" } diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 1d1b6e6148dd..f3b2caf9b803 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -145,6 +145,14 @@ pub unsafe fn create_module<'ll>( .replace("-Fi64", ""); } } + if llvm_version < (18, 0, 0) { + if sess.target.arch == "x86" || sess.target.arch == "x86_64" { + // LLVM 18 adjusts i128 to be 128-bit aligned on x86 variants. + // Earlier LLVMs leave this as default alignment, so remove it. + // See https://reviews.llvm.org/D86310 + target_data_layout = target_data_layout.replace("-i128:128", ""); + } + } // Ensure the data-layout values hardcoded remain the defaults. if sess.target.is_builtin { diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index af1c65944460..5d497d4a1883 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -14,7 +14,7 @@ use rustc_data_structures::memmap::Mmap; use rustc_data_structures::profiling::{SelfProfilerRef, VerboseTimingGuard}; use rustc_data_structures::sync::Lrc; use rustc_errors::emitter::Emitter; -use rustc_errors::{translation::Translate, DiagCtxt, DiagnosticId, FatalError, Level}; +use rustc_errors::{translation::Translate, DiagCtxt, FatalError, Level}; use rustc_errors::{DiagnosticBuilder, DiagnosticMessage, Style}; use rustc_fs_util::link_or_copy; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; @@ -1000,7 +1000,7 @@ type DiagnosticArgName<'source> = Cow<'source, str>; struct Diagnostic { msgs: Vec<(DiagnosticMessage, Style)>, args: FxHashMap, rustc_errors::DiagnosticArgValue<'static>>, - code: Option, + code: Option, lvl: Level, } diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index a1662f25e149..e35b4029b450 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -17,7 +17,7 @@ use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement}; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::{self, Instance, Ty}; use rustc_session::config::OptLevel; -use rustc_span::{sym, Span, Symbol}; +use rustc_span::{source_map::Spanned, sym, Span, Symbol}; use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode, Reg}; use rustc_target::abi::{self, HasDataLayout, WrappingRange}; use rustc_target::spec::abi::Abi; @@ -742,7 +742,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx: &mut Bx, terminator: &mir::Terminator<'tcx>, func: &mir::Operand<'tcx>, - args: &[mir::Operand<'tcx>], + args: &[Spanned>], destination: mir::Place<'tcx>, target: Option, unwind: mir::UnwindAction, @@ -793,7 +793,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let extra_args = &args[sig.inputs().skip_binder().len()..]; let extra_args = bx.tcx().mk_type_list_from_iter(extra_args.iter().map(|op_arg| { - let op_ty = op_arg.ty(self.mir, bx.tcx()); + let op_ty = op_arg.node.ty(self.mir, bx.tcx()); self.monomorphize(op_ty) })); @@ -863,7 +863,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // checked by const-qualification, which also // promotes any complex rvalues to constants. if i == 2 && intrinsic == sym::simd_shuffle { - if let mir::Operand::Constant(constant) = arg { + if let mir::Operand::Constant(constant) = &arg.node { let (llval, ty) = self.simd_shuffle_indices(bx, constant); return OperandRef { val: Immediate(llval), @@ -874,7 +874,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } - self.codegen_operand(bx, arg) + self.codegen_operand(bx, &arg.node) }) .collect(); @@ -910,7 +910,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let mut copied_constant_arguments = vec![]; 'make_args: for (i, arg) in first_args.iter().enumerate() { - let mut op = self.codegen_operand(bx, arg); + let mut op = self.codegen_operand(bx, &arg.node); if let (0, Some(ty::InstanceDef::Virtual(_, idx))) = (i, def) { match op.val { @@ -988,7 +988,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // The callee needs to own the argument memory if we pass it // by-ref, so make a local copy of non-immediate constants. - match (arg, op.val) { + match (&arg.node, op.val) { (&mir::Operand::Copy(_), Ref(_, None, _)) | (&mir::Operand::Constant(_), Ref(_, None, _)) => { let tmp = PlaceRef::alloca(bx, op.layout); @@ -1003,7 +1003,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.codegen_argument(bx, op, &mut llargs, &fn_abi.args[i]); } let num_untupled = untuple.map(|tup| { - self.codegen_arguments_untupled(bx, tup, &mut llargs, &fn_abi.args[first_args.len()..]) + self.codegen_arguments_untupled( + bx, + &tup.node, + &mut llargs, + &fn_abi.args[first_args.len()..], + ) }); let needs_location = diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 9d22df50d4f3..4236117d75b9 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -225,17 +225,10 @@ pub fn eval_to_const_value_raw_provider<'tcx>( tcx: TyCtxt<'tcx>, key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, ) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> { - // see comment in eval_to_allocation_raw_provider for what we're doing here - if key.param_env.reveal() == Reveal::All { - let mut key = key; - key.param_env = key.param_env.with_user_facing(); - match tcx.eval_to_const_value_raw(key) { - // try again with reveal all as requested - Err(ErrorHandled::TooGeneric(_)) => {} - // deduplicate calls - other => return other, - } - } + // Const eval always happens in Reveal::All mode in order to be able to use the hidden types of + // opaque types. This is needed for trivial things like `size_of`, but also for using associated + // types that are not specified in the opaque type. + assert_eq!(key.param_env.reveal(), Reveal::All); // We call `const_eval` for zero arg intrinsics, too, in order to cache their value. // Catch such calls and evaluate them instead of trying to load a constant's MIR. @@ -265,24 +258,11 @@ pub fn eval_to_allocation_raw_provider<'tcx>( tcx: TyCtxt<'tcx>, key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, ) -> ::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> { - // Because the constant is computed twice (once per value of `Reveal`), we are at risk of - // reporting the same error twice here. To resolve this, we check whether we can evaluate the - // constant in the more restrictive `Reveal::UserFacing`, which most likely already was - // computed. For a large percentage of constants that will already have succeeded. Only - // associated constants of generic functions will fail due to not enough monomorphization - // information being available. + // Const eval always happens in Reveal::All mode in order to be able to use the hidden types of + // opaque types. This is needed for trivial things like `size_of`, but also for using associated + // types that are not specified in the opaque type. - // In case we fail in the `UserFacing` variant, we just do the real computation. - if key.param_env.reveal() == Reveal::All { - let mut key = key; - key.param_env = key.param_env.with_user_facing(); - match tcx.eval_to_allocation_raw(key) { - // try again with reveal all as requested - Err(ErrorHandled::TooGeneric(_)) => {} - // deduplicate calls - other => return other, - } - } + assert_eq!(key.param_env.reveal(), Reveal::All); if cfg!(debug_assertions) { // Make sure we format the instance even if we do not print it. // This serves as a regression test against an ICE on printing. diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 7ff970661d6f..3afd14eb5743 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -1209,21 +1209,28 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { throw_ub_custom!(fluent::const_eval_copy_nonoverlapping_overlapping); } } + } - for i in 0..num_copies { - ptr::copy( - src_bytes, - dest_bytes.add((size * i).bytes_usize()), // `Size` multiplication - size.bytes_usize(), - ); + let size_in_bytes = size.bytes_usize(); + // For particularly large arrays (where this is perf-sensitive) it's common that + // we're writing a single byte repeatedly. So, optimize that case to a memset. + if size_in_bytes == 1 && num_copies >= 1 { + // SAFETY: `src_bytes` would be read from anyway by copies below (num_copies >= 1). + // Since size_in_bytes = 1, then the `init.no_bytes_init()` check above guarantees + // that this read at type `u8` is OK -- it must be an initialized byte. + let value = *src_bytes; + dest_bytes.write_bytes(value, (size * num_copies).bytes_usize()); + } else if src_alloc_id == dest_alloc_id { + let mut dest_ptr = dest_bytes; + for _ in 0..num_copies { + ptr::copy(src_bytes, dest_ptr, size_in_bytes); + dest_ptr = dest_ptr.add(size_in_bytes); } } else { - for i in 0..num_copies { - ptr::copy_nonoverlapping( - src_bytes, - dest_bytes.add((size * i).bytes_usize()), // `Size` multiplication - size.bytes_usize(), - ); + let mut dest_ptr = dest_bytes; + for _ in 0..num_copies { + ptr::copy_nonoverlapping(src_bytes, dest_ptr, size_in_bytes); + dest_ptr = dest_ptr.add(size_in_bytes); } } } diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index 2358caffc9b4..7b993279f18e 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -9,7 +9,7 @@ use rustc_middle::{ AdtDef, Instance, Ty, }, }; -use rustc_span::sym; +use rustc_span::{source_map::Spanned, sym}; use rustc_target::abi::{self, FieldIdx}; use rustc_target::abi::{ call::{ArgAbi, FnAbi, PassMode}, @@ -242,13 +242,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Evaluate the arguments of a function call pub(super) fn eval_fn_call_arguments( &self, - ops: &[mir::Operand<'tcx>], + ops: &[Spanned>], ) -> InterpResult<'tcx, Vec>> { ops.iter() .map(|op| { - Ok(match op { + Ok(match &op.node { mir::Operand::Move(place) => FnArg::InPlace(self.eval_place(*place)?), - _ => FnArg::Copy(self.eval_operand(op, None)?), + _ => FnArg::Copy(self.eval_operand(&op.node, None)?), }) }) .collect() diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index ae9595d7e644..89c65d923258 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -804,7 +804,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { // const-eval of the `begin_panic` fn assumes the argument is `&str` if Some(callee) == tcx.lang_items().begin_panic_fn() { - match args[0].ty(&self.ccx.body.local_decls, tcx).kind() { + match args[0].node.ty(&self.ccx.body.local_decls, tcx).kind() { ty::Ref(_, ty, _) if ty.is_str() => return, _ => self.check_op(ops::PanicNonStr), } @@ -812,7 +812,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { // const-eval of `#[rustc_const_panic_str]` functions assumes the argument is `&&str` if tcx.has_attr(callee, sym::rustc_const_panic_str) { - match args[0].ty(&self.ccx.body.local_decls, tcx).kind() { + match args[0].node.ty(&self.ccx.body.local_decls, tcx).kind() { ty::Ref(_, ty, _) if matches!(ty.kind(), ty::Ref(_, ty, _) if ty.is_str()) => { return; diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 0b73691204d5..9c2f336e9128 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -402,7 +402,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { ); } for arg in args { - if let Operand::Move(place) = arg { + if let Operand::Move(place) = &arg.node { if is_within_packed(self.tcx, &self.body.local_decls, *place).is_some() { // This is bad! The callee will expect the memory to be aligned. self.fail( diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml index 23949deaade8..9d598c32e6fc 100644 --- a/compiler/rustc_data_structures/Cargo.toml +++ b/compiler/rustc_data_structures/Cargo.toml @@ -13,7 +13,7 @@ indexmap = { version = "2.0.0" } itertools = "0.11" jobserver_crate = { version = "0.1.27", package = "jobserver" } libc = "0.2" -measureme = "10.0.0" +measureme = "11" rustc-hash = "1.1.0" rustc-rayon = { version = "0.5.0", optional = true } rustc-rayon-core = { version = "0.5.0", optional = true } diff --git a/compiler/rustc_data_structures/src/binary_search_util/mod.rs b/compiler/rustc_data_structures/src/binary_search_util/mod.rs index bc8a6b9eac0c..1c6e227cec40 100644 --- a/compiler/rustc_data_structures/src/binary_search_util/mod.rs +++ b/compiler/rustc_data_structures/src/binary_search_util/mod.rs @@ -18,27 +18,10 @@ where return &[]; }; - // Now search forward to find the *last* one. - let mut end = start; - let mut previous = start; - let mut step = 1; - loop { - end = end.saturating_add(step).min(size); - if end == size || key_fn(&data[end]) != *key { - break; - } - previous = end; - step *= 2; - } - step = end - previous; - while step > 1 { - let half = step / 2; - let mid = end - half; - if key_fn(&data[mid]) != *key { - end = mid; - } - step -= half; - } + // Find the first entry with key > `key`. Skip `start` entries since + // key_fn(&data[start]) == *key + let offset = start + 1; + let end = data[offset..].partition_point(|x| key_fn(x) <= *key) + offset; &data[start..end] } diff --git a/compiler/rustc_data_structures/src/hashes.rs b/compiler/rustc_data_structures/src/hashes.rs index 291ee5bbe26e..1564eeb4baee 100644 --- a/compiler/rustc_data_structures/src/hashes.rs +++ b/compiler/rustc_data_structures/src/hashes.rs @@ -75,11 +75,21 @@ impl fmt::LowerHex for Hash64 { } } -#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)] pub struct Hash128 { inner: u128, } +// We expect Hash128 to be well mixed. So there's no point in hashing both parts. +// +// This also allows using Hash128-containing types in UnHash-based hashmaps, which would otherwise +// debug_assert! that we're hashing more than a single u64. +impl std::hash::Hash for Hash128 { + fn hash(&self, h: &mut H) { + h.write_u64(self.truncate().as_u64()); + } +} + impl Hash128 { #[inline] pub fn truncate(self) -> Hash64 { diff --git a/compiler/rustc_data_structures/src/marker.rs b/compiler/rustc_data_structures/src/marker.rs index 266e54604a6b..a9ccfbed4116 100644 --- a/compiler/rustc_data_structures/src/marker.rs +++ b/compiler/rustc_data_structures/src/marker.rs @@ -177,7 +177,6 @@ cfg_match! { [Vec where T: DynSync, A: std::alloc::Allocator + DynSync] [Box where T: ?Sized + DynSync, A: std::alloc::Allocator + DynSync] [crate::sync::RwLock where T: DynSend + DynSync] - [crate::sync::OneThread where T] [crate::sync::WorkerLocal where T: DynSend] [crate::intern::Interned<'a, T> where 'a, T: DynSync] [crate::tagged_ptr::CopyTaggedPtr where P: Sync + crate::tagged_ptr::Pointer, T: Sync + crate::tagged_ptr::Tag, const CP: bool] diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs index afe26f80de8c..52304c72a2f8 100644 --- a/compiler/rustc_data_structures/src/stable_hasher.rs +++ b/compiler/rustc_data_structures/src/stable_hasher.rs @@ -314,7 +314,19 @@ impl_stable_traits_for_trivial_type!(char); impl_stable_traits_for_trivial_type!(()); impl_stable_traits_for_trivial_type!(Hash64); -impl_stable_traits_for_trivial_type!(Hash128); + +// We need a custom impl as the default hash function will only hash half the bits. For stable +// hashing we want to hash the full 128-bit hash. +impl HashStable for Hash128 { + #[inline] + fn hash_stable(&self, _: &mut CTX, hasher: &mut StableHasher) { + self.as_u128().hash(hasher); + } +} + +unsafe impl StableOrd for Hash128 { + const CAN_USE_UNSTABLE_SORT: bool = true; +} impl HashStable for ! { fn hash_stable(&self, _ctx: &mut CTX, _hasher: &mut StableHasher) { diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index 48edfba8da08..adcb6ceaebf8 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -43,7 +43,6 @@ pub use crate::marker::*; use std::collections::HashMap; use std::hash::{BuildHasher, Hash}; -use std::ops::{Deref, DerefMut}; mod lock; pub use lock::{Lock, LockGuard, Mode}; @@ -309,8 +308,6 @@ cfg_match! { use parking_lot::RwLock as InnerRwLock; - use std::thread; - /// This makes locks panic if they are already held. /// It is only useful when you are running in a single thread const ERROR_CHECKING: bool = false; @@ -445,56 +442,3 @@ impl Clone for RwLock { RwLock::new(self.borrow().clone()) } } - -/// A type which only allows its inner value to be used in one thread. -/// It will panic if it is used on multiple threads. -#[derive(Debug)] -pub struct OneThread { - #[cfg(parallel_compiler)] - thread: thread::ThreadId, - inner: T, -} - -#[cfg(parallel_compiler)] -unsafe impl std::marker::Sync for OneThread {} -#[cfg(parallel_compiler)] -unsafe impl std::marker::Send for OneThread {} - -impl OneThread { - #[inline(always)] - fn check(&self) { - #[cfg(parallel_compiler)] - assert_eq!(thread::current().id(), self.thread); - } - - #[inline(always)] - pub fn new(inner: T) -> Self { - OneThread { - #[cfg(parallel_compiler)] - thread: thread::current().id(), - inner, - } - } - - #[inline(always)] - pub fn into_inner(value: Self) -> T { - value.check(); - value.inner - } -} - -impl Deref for OneThread { - type Target = T; - - fn deref(&self) -> &T { - self.check(); - &self.inner - } -} - -impl DerefMut for OneThread { - fn deref_mut(&mut self) -> &mut T { - self.check(); - &mut self.inner - } -} diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 2e4baf26176c..11dcf4108d4e 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -35,7 +35,7 @@ use rustc_lint::unerased_lint_store; use rustc_metadata::creader::MetadataLoader; use rustc_metadata::locator; use rustc_session::config::{nightly_options, CG_OPTIONS, Z_OPTIONS}; -use rustc_session::config::{ErrorOutputType, Input, OutFileName, OutputType, TrimmedDefPaths}; +use rustc_session::config::{ErrorOutputType, Input, OutFileName, OutputType}; use rustc_session::getopts::{self, Matches}; use rustc_session::lint::{Lint, LintId}; use rustc_session::{config, EarlyDiagCtxt, Session}; @@ -204,7 +204,7 @@ impl Callbacks for TimePassesCallbacks { // self.time_passes = (config.opts.prints.is_empty() && config.opts.unstable_opts.time_passes) .then(|| config.opts.unstable_opts.time_passes_format); - config.opts.trimmed_def_paths = TrimmedDefPaths::GoodPath; + config.opts.trimmed_def_paths = true; } } diff --git a/compiler/rustc_error_codes/src/error_codes/E0708.md b/compiler/rustc_error_codes/src/error_codes/E0708.md index 9287fc803d1d..61a853ac4460 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0708.md +++ b/compiler/rustc_error_codes/src/error_codes/E0708.md @@ -1,12 +1,14 @@ +#### Note: this error code is no longer emitted by the compiler. + `async` non-`move` closures with parameters are currently not supported. Erroneous code example: -```compile_fail,edition2018,E0708 +```edition2018 #![feature(async_closure)] fn main() { - let add_one = async |num: u8| { // error! + let add_one = async |num: u8| { num + 1 }; } diff --git a/compiler/rustc_error_codes/src/error_codes/E0795.md b/compiler/rustc_error_codes/src/error_codes/E0795.md index 20f51441c291..ad77d72c913a 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0795.md +++ b/compiler/rustc_error_codes/src/error_codes/E0795.md @@ -3,7 +3,7 @@ Invalid argument for the `offset_of!` macro. Erroneous code example: ```compile_fail,E0795 -#![feature(offset_of, offset_of_enum)] +#![feature(offset_of_enum, offset_of_nested)] let x = std::mem::offset_of!(Option, Some); ``` @@ -16,7 +16,7 @@ The offset of the contained `u8` in the `Option` can be found by specifying the field name `0`: ``` -#![feature(offset_of, offset_of_enum)] +#![feature(offset_of_enum, offset_of_nested)] let x: usize = std::mem::offset_of!(Option, Some.0); ``` diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index 648c9118400e..f0699a56f98e 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -9,8 +9,8 @@ use crate::emitter::FileWithAnnotatedLines; use crate::snippet::Line; use crate::translation::{to_fluent_args, Translate}; use crate::{ - CodeSuggestion, Diagnostic, DiagnosticId, DiagnosticMessage, Emitter, FluentBundle, - LazyFallbackBundle, Level, MultiSpan, Style, SubDiagnostic, + CodeSuggestion, Diagnostic, DiagnosticMessage, Emitter, FluentBundle, LazyFallbackBundle, + Level, MultiSpan, Style, SubDiagnostic, }; use annotate_snippets::{Annotation, AnnotationType, Renderer, Slice, Snippet, SourceAnnotation}; use rustc_data_structures::sync::Lrc; @@ -127,7 +127,7 @@ impl AnnotateSnippetEmitter { level: &Level, messages: &[(DiagnosticMessage, Style)], args: &FluentArgs<'_>, - code: &Option, + code: &Option, msp: &MultiSpan, _children: &[SubDiagnostic], _suggestions: &[CodeSuggestion], @@ -181,11 +181,7 @@ impl AnnotateSnippetEmitter { let snippet = Snippet { title: Some(Annotation { label: Some(&message), - id: code.as_ref().map(|c| match c { - DiagnosticId::Error(val) | DiagnosticId::Lint { name: val, .. } => { - val.as_str() - } - }), + id: code.as_deref(), annotation_type: annotation_type_for_level(*level), }), footer: vec![], diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 786aced5b4f9..4934bc2450c7 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -104,7 +104,7 @@ pub struct Diagnostic { pub(crate) level: Level, pub messages: Vec<(DiagnosticMessage, Style)>, - pub code: Option, + pub code: Option, pub span: MultiSpan, pub children: Vec, pub suggestions: Result, SuggestionsDisabled>, @@ -115,9 +115,9 @@ pub struct Diagnostic { /// `span` if there is one. Otherwise, it is `DUMMY_SP`. pub sort_span: Span, - /// If diagnostic is from Lint, custom hash function ignores notes - /// otherwise hash is based on the all the fields - pub is_lint: bool, + /// If diagnostic is from Lint, custom hash function ignores children. + /// Otherwise hash is based on the all the fields. + pub is_lint: Option, /// With `-Ztrack_diagnostics` enabled, /// we print where in rustc this error was emitted. @@ -146,13 +146,11 @@ impl fmt::Display for DiagnosticLocation { } #[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)] -pub enum DiagnosticId { - Error(String), - Lint { - name: String, - /// Indicates whether this lint should show up in cargo's future breakage report. - has_future_breakage: bool, - }, +pub struct IsLint { + /// The lint name. + pub(crate) name: String, + /// Indicates whether this lint should show up in cargo's future breakage report. + has_future_breakage: bool, } /// A "sub"-diagnostic attached to a parent diagnostic. @@ -231,7 +229,7 @@ impl Diagnostic { suggestions: Ok(vec![]), args: Default::default(), sort_span: DUMMY_SP, - is_lint: false, + is_lint: None, emitted_at: DiagnosticLocation::caller(), } } @@ -288,16 +286,13 @@ impl Diagnostic { /// Indicates whether this diagnostic should show up in cargo's future breakage report. pub(crate) fn has_future_breakage(&self) -> bool { - match self.code { - Some(DiagnosticId::Lint { has_future_breakage, .. }) => has_future_breakage, - _ => false, - } + matches!(self.is_lint, Some(IsLint { has_future_breakage: true, .. })) } pub(crate) fn is_force_warn(&self) -> bool { match self.level { Level::ForceWarning(_) => { - assert!(self.is_lint); + assert!(self.is_lint.is_some()); true } _ => false, @@ -893,12 +888,12 @@ impl Diagnostic { self } - pub fn is_lint(&mut self) -> &mut Self { - self.is_lint = true; + pub fn is_lint(&mut self, name: String, has_future_breakage: bool) -> &mut Self { + self.is_lint = Some(IsLint { name, has_future_breakage }); self } - pub fn code(&mut self, s: DiagnosticId) -> &mut Self { + pub fn code(&mut self, s: String) -> &mut Self { self.code = Some(s); self } @@ -908,8 +903,8 @@ impl Diagnostic { self } - pub fn get_code(&self) -> Option { - self.code.clone() + pub fn get_code(&self) -> Option<&str> { + self.code.as_deref() } pub fn primary_message(&mut self, msg: impl Into) -> &mut Self { @@ -995,7 +990,8 @@ impl Diagnostic { &Level, &[(DiagnosticMessage, Style)], Vec<(&Cow<'static, str>, &DiagnosticArgValue<'static>)>, - &Option, + &Option, + &Option, &MultiSpan, &Result, SuggestionsDisabled>, Option<&[SubDiagnostic]>, @@ -1005,9 +1001,10 @@ impl Diagnostic { &self.messages, self.args().collect(), &self.code, + &self.is_lint, &self.span, &self.suggestions, - (if self.is_lint { None } else { Some(&self.children) }), + (if self.is_lint.is_some() { None } else { Some(&self.children) }), ) } } diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index bd7c58d904e7..87e2d295c7f4 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -1,8 +1,8 @@ use crate::diagnostic::IntoDiagnosticArg; use crate::{DiagCtxt, Level, MultiSpan, StashKey}; use crate::{ - Diagnostic, DiagnosticId, DiagnosticMessage, DiagnosticStyledString, ErrorGuaranteed, - ExplicitBug, SubdiagnosticMessage, + Diagnostic, DiagnosticMessage, DiagnosticStyledString, ErrorGuaranteed, ExplicitBug, + SubdiagnosticMessage, }; use rustc_lint_defs::Applicability; use rustc_span::source_map::Spanned; @@ -395,8 +395,11 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { forward!((span, with_span)( sp: impl Into, )); + forward!((is_lint, with_is_lint)( + name: String, has_future_breakage: bool, + )); forward!((code, with_code)( - s: DiagnosticId, + s: String, )); forward!((arg, with_arg)( name: impl Into>, arg: impl IntoDiagnosticArg, @@ -437,15 +440,11 @@ impl Drop for DiagnosticBuilder<'_, G> { #[macro_export] macro_rules! struct_span_code_err { ($dcx:expr, $span:expr, $code:ident, $($message:tt)*) => ({ - $dcx.struct_span_err( - $span, - format!($($message)*), - ) - .with_code($crate::error_code!($code)) + $dcx.struct_span_err($span, format!($($message)*)).with_code($crate::error_code!($code)) }) } #[macro_export] macro_rules! error_code { - ($code:ident) => {{ $crate::DiagnosticId::Error(stringify!($code).to_owned()) }}; + ($code:ident) => {{ stringify!($code).to_owned() }}; } diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 987832e6937b..23efdaea0ebb 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -16,9 +16,9 @@ use crate::snippet::{ use crate::styled_buffer::StyledBuffer; use crate::translation::{to_fluent_args, Translate}; use crate::{ - diagnostic::DiagnosticLocation, CodeSuggestion, DiagCtxt, Diagnostic, DiagnosticId, - DiagnosticMessage, FluentBundle, LazyFallbackBundle, Level, MultiSpan, SubDiagnostic, - SubstitutionHighlight, SuggestionStyle, TerminalUrl, + diagnostic::DiagnosticLocation, CodeSuggestion, DiagCtxt, Diagnostic, DiagnosticMessage, + FluentBundle, LazyFallbackBundle, Level, MultiSpan, SubDiagnostic, SubstitutionHighlight, + SuggestionStyle, TerminalUrl, }; use rustc_lint_defs::pluralize; @@ -1309,7 +1309,7 @@ impl HumanEmitter { msp: &MultiSpan, msgs: &[(DiagnosticMessage, Style)], args: &FluentArgs<'_>, - code: &Option, + code: &Option, level: &Level, max_line_num_len: usize, is_secondary: bool, @@ -1336,14 +1336,13 @@ impl HumanEmitter { buffer.append(0, level.to_str(), Style::Level(*level)); label_width += level.to_str().len(); } - // only render error codes, not lint codes - if let Some(DiagnosticId::Error(ref code)) = *code { + if let Some(code) = code { buffer.append(0, "[", Style::Level(*level)); let code = if let TerminalUrl::Yes = self.terminal_url { let path = "https://doc.rust-lang.org/error_codes"; - format!("\x1b]8;;{path}/{code}.html\x07{code}\x1b]8;;\x07") + Cow::Owned(format!("\x1b]8;;{path}/{code}.html\x07{code}\x1b]8;;\x07")) } else { - code.clone() + Cow::Borrowed(code) }; buffer.append(0, &code, Style::Level(*level)); buffer.append(0, "]", Style::Level(*level)); @@ -2077,7 +2076,7 @@ impl HumanEmitter { level: &Level, messages: &[(DiagnosticMessage, Style)], args: &FluentArgs<'_>, - code: &Option, + code: &Option, span: &MultiSpan, children: &[SubDiagnostic], suggestions: &[CodeSuggestion], diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index 87bf9c234564..51b064f4c617 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -15,10 +15,9 @@ use termcolor::{ColorSpec, WriteColor}; use crate::emitter::{should_show_source_code, Emitter, HumanReadableErrorType}; use crate::registry::Registry; use crate::translation::{to_fluent_args, Translate}; -use crate::DiagnosticId; use crate::{ - CodeSuggestion, FluentBundle, LazyFallbackBundle, MultiSpan, SpanLabel, SubDiagnostic, - TerminalUrl, + diagnostic::IsLint, CodeSuggestion, FluentBundle, LazyFallbackBundle, MultiSpan, SpanLabel, + SubDiagnostic, TerminalUrl, }; use rustc_lint_defs::Applicability; @@ -301,7 +300,8 @@ struct DiagnosticSpanMacroExpansion { #[derive(Serialize)] struct DiagnosticCode { - /// The code itself. + /// The error code (e.g. "E1234"), if the diagnostic has one. Or the lint + /// name, if it's a lint without an error code. code: String, /// An explanation for the code. explanation: Option<&'static str>, @@ -399,9 +399,21 @@ impl Diagnostic { let output = String::from_utf8(output).unwrap(); let translated_message = je.translate_messages(&diag.messages, &args); + + let code = if let Some(code) = &diag.code { + Some(DiagnosticCode { + code: code.to_string(), + explanation: je.registry.as_ref().unwrap().try_find_description(&code).ok(), + }) + } else if let Some(IsLint { name, .. }) = &diag.is_lint { + Some(DiagnosticCode { code: name.to_string(), explanation: None }) + } else { + None + }; + Diagnostic { message: translated_message.to_string(), - code: DiagnosticCode::map_opt_string(diag.code.clone(), je), + code, level: diag.level.to_str(), spans: DiagnosticSpan::from_multispan(&diag.span, &args, je), children: diag @@ -592,18 +604,3 @@ impl DiagnosticSpanLine { .unwrap_or_else(|_| vec![]) } } - -impl DiagnosticCode { - fn map_opt_string(s: Option, je: &JsonEmitter) -> Option { - s.map(|s| { - let s = match s { - DiagnosticId::Error(s) => s, - DiagnosticId::Lint { name, .. } => name, - }; - let je_result = - je.registry.as_ref().map(|registry| registry.try_find_description(&s)).unwrap(); - - DiagnosticCode { code: s, explanation: je_result.ok() } - }) - } -} diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 63391a0faa6b..141547b537de 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -30,7 +30,7 @@ extern crate tracing; extern crate self as rustc_errors; pub use diagnostic::{ - AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgValue, DiagnosticId, + AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgValue, DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic, }; pub use diagnostic_builder::{ @@ -442,13 +442,13 @@ struct DiagCtxtInner { /// This is used for the `good_path_delayed_bugs` check. suppressed_expected_diag: bool, - /// This set contains the `DiagnosticId` of all emitted diagnostics to avoid + /// This set contains the code of all emitted diagnostics to avoid /// emitting the same diagnostic with extended help (`--teach`) twice, which /// would be unnecessary repetition. - taught_diagnostics: FxHashSet, + taught_diagnostics: FxHashSet, /// Used to suggest rustc --explain `` - emitted_diagnostic_codes: FxIndexSet, + emitted_diagnostic_codes: FxIndexSet, /// This set contains a hash of every diagnostic that has been emitted by /// this `DiagCtxt`. These hashes is used to avoid emitting the same error @@ -676,7 +676,7 @@ impl DiagCtxt { let key = (span.with_parent(None), key); if diag.is_error() { - if diag.is_lint { + if diag.is_lint.is_some() { inner.lint_err_count += 1; } else { inner.err_count += 1; @@ -695,7 +695,7 @@ impl DiagCtxt { let key = (span.with_parent(None), key); let diag = inner.stashed_diagnostics.remove(&key)?; if diag.is_error() { - if diag.is_lint { + if diag.is_lint.is_some() { inner.lint_err_count -= 1; } else { inner.err_count -= 1; @@ -715,9 +715,7 @@ impl DiagCtxt { /// Construct a builder at the `Warning` level at the given `span` and with the `msg`. /// - /// Attempting to `.emit()` the builder will only emit if either: - /// * `can_emit_warnings` is `true` - /// * `is_force_warn` was set in `DiagnosticId::Lint` + /// An `emit` call on the builder will only emit if `can_emit_warnings` is `true`. #[rustc_lint_diagnostics] #[track_caller] pub fn struct_span_warn( @@ -730,9 +728,7 @@ impl DiagCtxt { /// Construct a builder at the `Warning` level with the `msg`. /// - /// Attempting to `.emit()` the builder will only emit if either: - /// * `can_emit_warnings` is `true` - /// * `is_force_warn` was set in `DiagnosticId::Lint` + /// An `emit` call on the builder will only emit if `can_emit_warnings` is `true`. #[rustc_lint_diagnostics] #[track_caller] pub fn struct_warn(&self, msg: impl Into) -> DiagnosticBuilder<'_, ()> { @@ -1011,11 +1007,12 @@ impl DiagCtxt { let mut error_codes = inner .emitted_diagnostic_codes .iter() - .filter_map(|x| match &x { - DiagnosticId::Error(s) if registry.try_find_description(s).is_ok() => { - Some(s.clone()) + .filter_map(|code| { + if registry.try_find_description(code).is_ok().clone() { + Some(code.clone()) + } else { + None } - _ => None, }) .collect::>(); if !error_codes.is_empty() { @@ -1058,8 +1055,8 @@ impl DiagCtxt { /// /// Used to suppress emitting the same error multiple times with extended explanation when /// calling `-Zteach`. - pub fn must_teach(&self, code: &DiagnosticId) -> bool { - self.inner.borrow_mut().taught_diagnostics.insert(code.clone()) + pub fn must_teach(&self, code: &str) -> bool { + self.inner.borrow_mut().taught_diagnostics.insert(code.to_string()) } pub fn force_print_diagnostic(&self, db: Diagnostic) { @@ -1231,7 +1228,7 @@ impl DiagCtxtInner { for diag in diags { // Decrement the count tracking the stash; emitting will increment it. if diag.is_error() { - if diag.is_lint { + if diag.is_lint.is_some() { self.lint_err_count -= 1; } else { self.err_count -= 1; @@ -1363,7 +1360,7 @@ impl DiagCtxtInner { self.has_printed = true; } if diagnostic.is_error() { - if diagnostic.is_lint { + if diagnostic.is_lint.is_some() { self.lint_err_count += 1; } else { self.err_count += 1; diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl index 475dd348e7b6..3e3b48143004 100644 --- a/compiler/rustc_expand/messages.ftl +++ b/compiler/rustc_expand/messages.ftl @@ -16,6 +16,9 @@ expand_attributes_wrong_form = expand_cannot_be_name_of_macro = `{$trait_ident}` cannot be a name of {$macro_type} macro +expand_collapse_debuginfo_illegal = + illegal value for attribute #[collapse_debuginfo(no|external|yes)] + expand_count_repetition_misplaced = `count` can not be placed inside the inner-most repetition diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 0a1c44303970..29b70f33a6c7 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1,5 +1,6 @@ #![deny(rustc::untranslatable_diagnostic)] +use crate::base::ast::NestedMetaItem; use crate::errors; use crate::expand::{self, AstFragment, Invocation}; use crate::module::DirOwnership; @@ -19,6 +20,7 @@ use rustc_feature::Features; use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT; use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiagnostics, RegisteredTools}; use rustc_parse::{parser, MACRO_ARGUMENTS}; +use rustc_session::config::CollapseMacroDebuginfo; use rustc_session::errors::report_lit_error; use rustc_session::{parse::ParseSess, Limit, Session}; use rustc_span::def_id::{CrateNum, DefId, LocalDefId}; @@ -664,8 +666,8 @@ pub enum SyntaxExtensionKind { /// A token-based attribute macro. Attr( /// An expander with signature (TokenStream, TokenStream) -> TokenStream. - /// The first TokenSteam is the attribute itself, the second is the annotated item. - /// The produced TokenSteam replaces the input TokenSteam. + /// The first TokenStream is the attribute itself, the second is the annotated item. + /// The produced TokenStream replaces the input TokenStream. Box, ), @@ -685,7 +687,7 @@ pub enum SyntaxExtensionKind { /// A token-based derive macro. Derive( /// An expander with signature TokenStream -> TokenStream. - /// The produced TokenSteam is appended to the input TokenSteam. + /// The produced TokenStream is appended to the input TokenStream. /// /// FIXME: The text above describes how this should work. Currently it /// is handled identically to `LegacyDerive`. It should be migrated to @@ -761,6 +763,55 @@ impl SyntaxExtension { } } + fn collapse_debuginfo_by_name(sess: &Session, attr: &Attribute) -> CollapseMacroDebuginfo { + use crate::errors::CollapseMacroDebuginfoIllegal; + // #[collapse_debuginfo] without enum value (#[collapse_debuginfo(no/external/yes)]) + // considered as `yes` + attr.meta_item_list().map_or(CollapseMacroDebuginfo::Yes, |l| { + let [NestedMetaItem::MetaItem(item)] = &l[..] else { + sess.dcx().emit_err(CollapseMacroDebuginfoIllegal { span: attr.span }); + return CollapseMacroDebuginfo::Unspecified; + }; + if !item.is_word() { + sess.dcx().emit_err(CollapseMacroDebuginfoIllegal { span: item.span }); + CollapseMacroDebuginfo::Unspecified + } else { + match item.name_or_empty() { + sym::no => CollapseMacroDebuginfo::No, + sym::external => CollapseMacroDebuginfo::External, + sym::yes => CollapseMacroDebuginfo::Yes, + _ => { + sess.dcx().emit_err(CollapseMacroDebuginfoIllegal { span: item.span }); + CollapseMacroDebuginfo::Unspecified + } + } + } + }) + } + + /// if-ext - if macro from different crate (related to callsite code) + /// | cmd \ attr | no | (unspecified) | external | yes | + /// | no | no | no | no | no | + /// | (unspecified) | no | no | if-ext | yes | + /// | external | no | if-ext | if-ext | yes | + /// | yes | yes | yes | yes | yes | + fn get_collapse_debuginfo(sess: &Session, attrs: &[ast::Attribute], is_local: bool) -> bool { + let collapse_debuginfo_attr = attr::find_by_name(attrs, sym::collapse_debuginfo) + .map(|v| Self::collapse_debuginfo_by_name(sess, v)) + .unwrap_or(CollapseMacroDebuginfo::Unspecified); + let flag = sess.opts.unstable_opts.collapse_macro_debuginfo; + let attr = collapse_debuginfo_attr; + let ext = !is_local; + #[rustfmt::skip] + let collapse_table = [ + [false, false, false, false], + [false, false, ext, true], + [false, ext, ext, true], + [true, true, true, true], + ]; + collapse_table[flag as usize][attr as usize] + } + /// Constructs a syntax extension with the given properties /// and other properties converted from attributes. pub fn new( @@ -772,6 +823,7 @@ impl SyntaxExtension { edition: Edition, name: Symbol, attrs: &[ast::Attribute], + is_local: bool, ) -> SyntaxExtension { let allow_internal_unstable = attr::allow_internal_unstable(sess, attrs).collect::>(); @@ -780,8 +832,8 @@ impl SyntaxExtension { let local_inner_macros = attr::find_by_name(attrs, sym::macro_export) .and_then(|macro_export| macro_export.meta_item_list()) .is_some_and(|l| attr::list_contains_name(&l, sym::local_inner_macros)); - let collapse_debuginfo = attr::contains_name(attrs, sym::collapse_debuginfo); - tracing::debug!(?local_inner_macros, ?collapse_debuginfo, ?allow_internal_unsafe); + let collapse_debuginfo = Self::get_collapse_debuginfo(sess, attrs, is_local); + tracing::debug!(?name, ?local_inner_macros, ?collapse_debuginfo, ?allow_internal_unsafe); let (builtin_name, helper_attrs) = attr::find_by_name(attrs, sym::rustc_builtin_macro) .map(|attr| { diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index 2b43fae6852a..4a1c00f0104f 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -58,6 +58,13 @@ pub(crate) struct ResolveRelativePath { pub path: String, } +#[derive(Diagnostic)] +#[diag(expand_collapse_debuginfo_illegal)] +pub(crate) struct CollapseMacroDebuginfoIllegal { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(expand_macro_const_stability)] pub(crate) struct MacroConstStability { diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 363b52aef8a7..1a39708ed8ed 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -367,6 +367,7 @@ pub fn compile_declarative_macro( edition, def.ident.name, &def.attrs, + def.id != DUMMY_NODE_ID, ) }; let dummy_syn_ext = || (mk_syn_ext(Box::new(macro_rules_dummy_expander)), Vec::new()); diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 4442b67df6e2..68b6f69854dd 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -469,7 +469,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // `#[collapse_debuginfo]` gated!( - collapse_debuginfo, Normal, template!(Word), WarnFollowing, + collapse_debuginfo, Normal, template!(Word, List: "no|external|yes"), ErrorFollowing, experimental!(collapse_debuginfo) ), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 2f2b551e6ecf..371b651f5e85 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -549,7 +549,9 @@ declare_features! ( /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden. (unstable, object_safe_for_dispatch, "1.40.0", Some(43561)), /// Allows using enums in offset_of! - (unstable, offset_of_enum, "1.75.0", Some(106655)), + (unstable, offset_of_enum, "1.75.0", Some(120141)), + /// Allows using multiple nested field accesses in offset_of! + (unstable, offset_of_nested, "CURRENT_RUSTC_VERSION", Some(120140)), /// Allows using `#[optimize(X)]`. (unstable, optimize_attribute, "1.34.0", Some(54882)), /// Allows macro attributes on expressions, statements and non-inline modules. diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 6b347f7035a3..23881cfd7dfd 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -248,7 +248,7 @@ pub struct InferArg { } impl InferArg { - pub fn to_ty(&self) -> Ty<'_> { + pub fn to_ty(&self) -> Ty<'static> { Ty { kind: TyKind::Infer, span: self.span, hir_id: self.hir_id } } } @@ -841,7 +841,7 @@ pub struct OwnerNodes<'tcx> { } impl<'tcx> OwnerNodes<'tcx> { - fn node(&self) -> OwnerNode<'tcx> { + pub fn node(&self) -> OwnerNode<'tcx> { use rustc_index::Idx; let node = self.nodes[ItemLocalId::new(0)].as_ref().unwrap().node; let node = node.as_owner().unwrap(); // Indexing must ensure it is an OwnerNode. @@ -1015,7 +1015,7 @@ impl<'hir> Pat<'hir> { use PatKind::*; match self.kind { - Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Path(_) => true, + Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Path(_) | Err(_) => true, Box(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_short_(it), Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_short_(it)), TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().all(|p| p.walk_short_(it)), @@ -1042,7 +1042,7 @@ impl<'hir> Pat<'hir> { use PatKind::*; match self.kind { - Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Path(_) => {} + Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Path(_) | Err(_) => {} Box(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_(it), Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk_(it)), TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().for_each(|p| p.walk_(it)), @@ -1205,6 +1205,9 @@ pub enum PatKind<'hir> { /// PatKind::Slice([Binding(a), Binding(b)], Some(Wild), [Binding(c), Binding(d)]) /// ``` Slice(&'hir [Pat<'hir>], Option<&'hir Pat<'hir>>, &'hir [Pat<'hir>]), + + /// A placeholder for a pattern that wasn't well formed in some way. + Err(ErrorGuaranteed), } /// A statement. @@ -1302,7 +1305,7 @@ pub enum UnsafeSource { UserProvided, } -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub struct BodyId { pub hir_id: HirId, } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index adc090258093..116de6fb04d9 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -655,7 +655,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) { walk_list!(visitor, visit_expr, lower_bound); walk_list!(visitor, visit_expr, upper_bound); } - PatKind::Never | PatKind::Wild => (), + PatKind::Never | PatKind::Wild | PatKind::Err(_) => (), PatKind::Slice(prepatterns, ref slice_pattern, postpatterns) => { walk_list!(visitor, visit_pat, prepatterns); walk_list!(visitor, visit_pat, slice_pattern); diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 3f3b57ba94f9..1cc1f11b3c85 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -374,3 +374,30 @@ pub static OPERATORS: &'static [LangItem] = &[ LangItem::PartialEq, LangItem::PartialOrd, ]; + +pub static BINARY_OPERATORS: &'static [LangItem] = &[ + LangItem::Add, + LangItem::Sub, + LangItem::Mul, + LangItem::Div, + LangItem::Rem, + LangItem::BitXor, + LangItem::BitAnd, + LangItem::BitOr, + LangItem::Shl, + LangItem::Shr, + LangItem::AddAssign, + LangItem::SubAssign, + LangItem::MulAssign, + LangItem::DivAssign, + LangItem::RemAssign, + LangItem::BitXorAssign, + LangItem::BitAndAssign, + LangItem::BitOrAssign, + LangItem::ShlAssign, + LangItem::ShrAssign, + LangItem::Index, + LangItem::IndexMut, + LangItem::PartialEq, + LangItem::PartialOrd, +]; diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs index 97fa710b3549..baa1635f7313 100644 --- a/compiler/rustc_hir/src/stable_hash_impls.rs +++ b/compiler/rustc_hir/src/stable_hash_impls.rs @@ -12,7 +12,6 @@ use rustc_span::def_id::DefPathHash; pub trait HashStableContext: rustc_ast::HashStableContext + rustc_target::HashStableContext { - fn hash_body_id(&mut self, _: BodyId, hasher: &mut StableHasher); } impl ToStableHashKey for HirId { @@ -80,12 +79,6 @@ impl ToStableHashKey for ForeignItemId } } -impl HashStable for BodyId { - fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { - hcx.hash_body_id(*self, hasher) - } -} - // The following implementations of HashStable for `ItemId`, `TraitItemId`, and // `ImplItemId` deserve special attention. Normally we do not hash `NodeId`s within // the HIR, since they just signify a HIR nodes own path. But `ItemId` et al diff --git a/compiler/rustc_hir_analysis/Cargo.toml b/compiler/rustc_hir_analysis/Cargo.toml index b5ebc1fab765..648b569a217f 100644 --- a/compiler/rustc_hir_analysis/Cargo.toml +++ b/compiler/rustc_hir_analysis/Cargo.toml @@ -9,6 +9,7 @@ doctest = false [dependencies] # tidy-alphabetical-start +itertools = "0.11" rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } rustc_attr = { path = "../rustc_attr" } diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs index 2ad96a248912..401efff9242e 100644 --- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs +++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs @@ -108,14 +108,16 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { /// `param_ty` and `ast_bounds`. See `instantiate_poly_trait_ref` /// for more details. #[instrument(level = "debug", skip(self, ast_bounds, bounds))] - pub(crate) fn add_bounds<'hir, I: Iterator>>( + pub(crate) fn add_bounds<'hir, I: Iterator>>( &self, param_ty: Ty<'tcx>, ast_bounds: I, bounds: &mut Bounds<'tcx>, bound_vars: &'tcx ty::List, only_self_bounds: OnlySelfBounds, - ) { + ) where + 'tcx: 'hir, + { for ast_bound in ast_bounds { match ast_bound { hir::GenericBound::Trait(poly_trait_ref, modifier) => { @@ -179,7 +181,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { pub(crate) fn compute_bounds( &self, param_ty: Ty<'tcx>, - ast_bounds: &[hir::GenericBound<'_>], + ast_bounds: &[hir::GenericBound<'tcx>], filter: PredicateFilter, ) -> Bounds<'tcx> { let mut bounds = Bounds::default(); diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs index e2cd4d5f21c7..f9628d1d6f3e 100644 --- a/compiler/rustc_hir_analysis/src/astconv/generics.rs +++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs @@ -168,7 +168,7 @@ fn generic_arg_mismatch_err( /// instantiate a `GenericArg`. /// - `inferred_kind`: if no parameter was provided, and inference is enabled, then /// creates a suitable inference variable. -pub fn create_args_for_parent_generic_args<'tcx, 'a>( +pub fn create_args_for_parent_generic_args<'tcx: 'a, 'a>( tcx: TyCtxt<'tcx>, def_id: DefId, parent_args: &[ty::GenericArg<'tcx>], diff --git a/compiler/rustc_hir_analysis/src/astconv/lint.rs b/compiler/rustc_hir_analysis/src/astconv/lint.rs index 3761d5295170..b5f42e98127e 100644 --- a/compiler/rustc_hir_analysis/src/astconv/lint.rs +++ b/compiler/rustc_hir_analysis/src/astconv/lint.rs @@ -78,14 +78,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { fn maybe_lint_impl_trait(&self, self_ty: &hir::Ty<'_>, diag: &mut Diagnostic) -> bool { let tcx = self.tcx(); let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id; - let (hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, generics, _), .. }) - | hir::Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Fn(sig, _), - generics, - .. - })) = tcx.hir_node_by_def_id(parent_id) - else { - return false; + let (sig, generics, owner) = match tcx.hir_node_by_def_id(parent_id) { + hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, generics, _), .. }) => { + (sig, generics, None) + } + hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Fn(sig, _), + generics, + owner_id, + .. + }) => (sig, generics, Some(tcx.parent(owner_id.to_def_id()))), + _ => return false, }; let Ok(trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else { return false; @@ -94,6 +97,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let is_object_safe = match self_ty.kind { hir::TyKind::TraitObject(objects, ..) => { objects.iter().all(|o| match o.trait_ref.path.res { + Res::Def(DefKind::Trait, id) if Some(id) == owner => { + // When we're dealing with a recursive trait, we don't want to downgrade + // the error, so we consider them to be object safe always. (#119652) + true + } Res::Def(DefKind::Trait, id) => tcx.check_is_object_safe(id), _ => false, }) @@ -122,7 +130,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ], Applicability::MachineApplicable, ); - } else { + } else if diag.is_error() { // We'll emit the object safety error already, with a structured suggestion. diag.downgrade_to_delayed_bug(); } @@ -148,8 +156,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } if !is_object_safe { diag.note(format!("`{trait_name}` it is not object safe, so it can't be `dyn`")); - // We'll emit the object safety error already, with a structured suggestion. - diag.downgrade_to_delayed_bug(); + if diag.is_error() { + // We'll emit the object safety error already, with a structured suggestion. + diag.downgrade_to_delayed_bug(); + } } else { let sugg = if let hir::TyKind::TraitObject([_, _, ..], _, _) = self_ty.kind { // There are more than one trait bound, we need surrounding parentheses. diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 9f4f1413650f..00f0d6e7c224 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -122,7 +122,7 @@ pub trait AstConv<'tcx> { &self, span: Span, item_def_id: DefId, - item_segment: &hir::PathSegment<'_>, + item_segment: &hir::PathSegment<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Ty<'tcx>; @@ -156,14 +156,14 @@ struct ConvertedBinding<'a, 'tcx> { hir_id: hir::HirId, item_name: Ident, kind: ConvertedBindingKind<'a, 'tcx>, - gen_args: &'a GenericArgs<'a>, + gen_args: &'tcx GenericArgs<'tcx>, span: Span, } #[derive(Debug)] enum ConvertedBindingKind<'a, 'tcx> { Equality(Spanned>), - Constraint(&'a [hir::GenericBound<'a>]), + Constraint(&'a [hir::GenericBound<'tcx>]), } /// New-typed boolean indicating whether explicit late-bound lifetimes @@ -215,12 +215,12 @@ pub struct GenericArgCountResult { } pub trait CreateSubstsForGenericArgsCtxt<'a, 'tcx> { - fn args_for_def_id(&mut self, def_id: DefId) -> (Option<&'a GenericArgs<'a>>, bool); + fn args_for_def_id(&mut self, def_id: DefId) -> (Option<&'a GenericArgs<'tcx>>, bool); fn provided_kind( &mut self, param: &ty::GenericParamDef, - arg: &GenericArg<'_>, + arg: &GenericArg<'tcx>, ) -> ty::GenericArg<'tcx>; fn inferred_kind( @@ -294,7 +294,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &self, span: Span, def_id: DefId, - item_segment: &hir::PathSegment<'_>, + item_segment: &hir::PathSegment<'tcx>, ) -> GenericArgsRef<'tcx> { let (args, _) = self.create_args_for_ast_path( span, @@ -351,7 +351,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { def_id: DefId, parent_args: &[ty::GenericArg<'tcx>], seg: &hir::PathSegment<'_>, - generic_args: &'a hir::GenericArgs<'_>, + generic_args: &'a hir::GenericArgs<'tcx>, infer_args: bool, self_ty: Option>, constness: ty::BoundConstness, @@ -406,14 +406,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { struct SubstsForAstPathCtxt<'a, 'tcx> { astconv: &'a (dyn AstConv<'tcx> + 'a), def_id: DefId, - generic_args: &'a GenericArgs<'a>, + generic_args: &'a GenericArgs<'tcx>, span: Span, inferred_params: Vec, infer_args: bool, } impl<'a, 'tcx> CreateSubstsForGenericArgsCtxt<'a, 'tcx> for SubstsForAstPathCtxt<'a, 'tcx> { - fn args_for_def_id(&mut self, did: DefId) -> (Option<&'a GenericArgs<'a>>, bool) { + fn args_for_def_id(&mut self, did: DefId) -> (Option<&'a GenericArgs<'tcx>>, bool) { if did == self.def_id { (Some(self.generic_args), self.infer_args) } else { @@ -425,11 +425,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { fn provided_kind( &mut self, param: &ty::GenericParamDef, - arg: &GenericArg<'_>, + arg: &GenericArg<'tcx>, ) -> ty::GenericArg<'tcx> { let tcx = self.astconv.tcx(); - let mut handle_ty_args = |has_default, ty: &hir::Ty<'_>| { + let mut handle_ty_args = |has_default, ty: &hir::Ty<'tcx>| { if has_default { tcx.check_optional_stability( param.def_id, @@ -592,7 +592,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { fn create_assoc_bindings_for_generic_args<'a>( &self, - generic_args: &'a hir::GenericArgs<'_>, + generic_args: &'a hir::GenericArgs<'tcx>, ) -> Vec> { // Convert associated-type bindings or constraints into a separate vector. // Example: Given this: @@ -640,7 +640,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &self, span: Span, item_def_id: DefId, - item_segment: &hir::PathSegment<'_>, + item_segment: &hir::PathSegment<'tcx>, parent_args: GenericArgsRef<'tcx>, ) -> GenericArgsRef<'tcx> { debug!( @@ -673,7 +673,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// are disallowed. Otherwise, they are pushed onto the vector given. pub fn instantiate_mono_trait_ref( &self, - trait_ref: &hir::TraitRef<'_>, + trait_ref: &hir::TraitRef<'tcx>, self_ty: Ty<'tcx>, ) -> ty::TraitRef<'tcx> { self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1.iter(), |_| {}); @@ -710,7 +710,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { #[instrument(level = "debug", skip(self, span, constness, bounds, speculative))] pub(crate) fn instantiate_poly_trait_ref( &self, - trait_ref: &hir::TraitRef<'_>, + trait_ref: &hir::TraitRef<'tcx>, span: Span, constness: ty::BoundConstness, polarity: ty::ImplPolarity, @@ -788,7 +788,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { span: Span, trait_def_id: DefId, self_ty: Ty<'tcx>, - trait_segment: &hir::PathSegment<'_>, + trait_segment: &hir::PathSegment<'tcx>, is_impl: bool, // FIXME(effects) move all host param things in astconv to hir lowering constness: ty::BoundConstness, @@ -813,7 +813,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { span: Span, trait_def_id: DefId, self_ty: Ty<'tcx>, - trait_segment: &'a hir::PathSegment<'a>, + trait_segment: &'a hir::PathSegment<'tcx>, is_impl: bool, constness: ty::BoundConstness, ) -> (GenericArgsRef<'tcx>, GenericArgCountResult) { @@ -847,7 +847,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &self, span: Span, did: DefId, - item_segment: &hir::PathSegment<'_>, + item_segment: &hir::PathSegment<'tcx>, ) -> Ty<'tcx> { let tcx = self.tcx(); let args = self.ast_path_args_for_ty(span, did, item_segment); @@ -1153,7 +1153,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { span: Span, qself_ty: Ty<'tcx>, qself: &hir::Ty<'_>, - assoc_segment: &hir::PathSegment<'_>, + assoc_segment: &hir::PathSegment<'tcx>, permit_variants: bool, ) -> Result<(Ty<'tcx>, DefKind, DefId), ErrorGuaranteed> { let tcx = self.tcx(); @@ -1428,7 +1428,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { fn lookup_inherent_assoc_ty( &self, name: Ident, - segment: &hir::PathSegment<'_>, + segment: &hir::PathSegment<'tcx>, adt_did: DefId, self_ty: Ty<'tcx>, block: hir::HirId, @@ -1446,7 +1446,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } let candidates: Vec<_> = tcx - .inherent_impls(adt_did) + .inherent_impls(adt_did)? .iter() .filter_map(|&impl_| Some((impl_, self.lookup_assoc_ty_unchecked(name, block, impl_)?))) .collect(); @@ -1702,8 +1702,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { span: Span, opt_self_ty: Option>, item_def_id: DefId, - trait_segment: &hir::PathSegment<'_>, - item_segment: &hir::PathSegment<'_>, + trait_segment: &hir::PathSegment<'tcx>, + item_segment: &hir::PathSegment<'tcx>, constness: ty::BoundConstness, ) -> Ty<'tcx> { let tcx = self.tcx(); @@ -2021,7 +2021,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { pub fn res_to_ty( &self, opt_self_ty: Option>, - path: &hir::Path<'_>, + path: &hir::Path<'tcx>, hir_id: hir::HirId, permit_variants: bool, ) -> Ty<'tcx> { @@ -2311,13 +2311,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// Parses the programmer's textual representation of a type into our /// internal notion of a type. - pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> { + pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { self.ast_ty_to_ty_inner(ast_ty, false, false) } /// Parses the programmer's textual representation of a type into our /// internal notion of a type. This is meant to be used within a path. - pub fn ast_ty_to_ty_in_path(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> { + pub fn ast_ty_to_ty_in_path(&self, ast_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { self.ast_ty_to_ty_inner(ast_ty, false, true) } @@ -2432,7 +2432,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// Turns a `hir::Ty` into a `Ty`. For diagnostics' purposes we keep track of whether trait /// objects are borrowed like `&dyn Trait` to avoid emitting redundant errors. #[instrument(level = "debug", skip(self), ret)] - fn ast_ty_to_ty_inner(&self, ast_ty: &hir::Ty<'_>, borrowed: bool, in_path: bool) -> Ty<'tcx> { + fn ast_ty_to_ty_inner( + &self, + ast_ty: &hir::Ty<'tcx>, + borrowed: bool, + in_path: bool, + ) -> Ty<'tcx> { let tcx = self.tcx(); let result_ty = match &ast_ty.kind { @@ -2609,7 +2614,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } - pub fn ty_of_arg(&self, ty: &hir::Ty<'_>, expected_ty: Option>) -> Ty<'tcx> { + pub fn ty_of_arg(&self, ty: &hir::Ty<'tcx>, expected_ty: Option>) -> Ty<'tcx> { match ty.kind { hir::TyKind::Infer if expected_ty.is_some() => { self.record_ty(ty.hir_id, expected_ty.unwrap(), ty.span); @@ -2625,7 +2630,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { hir_id: hir::HirId, unsafety: hir::Unsafety, abi: abi::Abi, - decl: &hir::FnDecl<'_>, + decl: &hir::FnDecl<'tcx>, generics: Option<&hir::Generics<'_>>, hir_ty: Option<&hir::Ty<'_>>, ) -> ty::PolyFnSig<'tcx> { diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs index f77f250cd288..8967b51749c8 100644 --- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs @@ -22,7 +22,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &self, span: Span, hir_id: hir::HirId, - hir_trait_bounds: &[hir::PolyTraitRef<'_>], + hir_trait_bounds: &[hir::PolyTraitRef<'tcx>], lifetime: &hir::Lifetime, borrowed: bool, representation: DynKind, diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 77914802bf77..03e2b0e00220 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -368,7 +368,7 @@ fn check_opaque_meets_bounds<'tcx>( // Can have different predicates to their defining use hir::OpaqueTyOrigin::TyAlias { .. } => { let wf_tys = ocx.assumed_wf_types_and_report_errors(param_env, def_id)?; - let implied_bounds = infcx.implied_bounds_tys(param_env, def_id, wf_tys); + let implied_bounds = infcx.implied_bounds_tys(param_env, def_id, &wf_tys); let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env)?; } diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 469e7a6a13c5..5b264f6f034c 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -2,7 +2,7 @@ use super::potentially_plural_count; use crate::errors::LifetimesOrBoundsMismatchOnTrait; use hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; -use rustc_errors::{pluralize, struct_span_code_err, Applicability, DiagnosticId, ErrorGuaranteed}; +use rustc_errors::{pluralize, struct_span_code_err, Applicability, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit; @@ -378,7 +378,7 @@ fn compare_method_predicate_entailment<'tcx>( // lifetime parameters. let outlives_env = OutlivesEnvironment::with_bounds( param_env, - infcx.implied_bounds_tys(param_env, impl_m_def_id, wf_tys), + infcx.implied_bounds_tys(param_env, impl_m_def_id, &wf_tys), ); let errors = infcx.resolve_regions(&outlives_env); if !errors.is_empty() { @@ -702,7 +702,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( // lifetime parameters. let outlives_env = OutlivesEnvironment::with_bounds( param_env, - infcx.implied_bounds_tys(param_env, impl_m_def_id, wf_tys), + infcx.implied_bounds_tys(param_env, impl_m_def_id, &wf_tys), ); ocx.resolve_regions_and_report_errors(impl_m_def_id, &outlives_env)?; @@ -1382,7 +1382,7 @@ fn compare_number_of_generics<'tcx>( kind = kind, ), ); - err.code(DiagnosticId::Error("E0049".into())); + err.code("E0049".into()); let msg = format!("expected {trait_count} {kind} parameter{}", pluralize!(trait_count),); @@ -2070,7 +2070,7 @@ pub(super) fn check_type_bounds<'tcx>( // Finally, resolve all regions. This catches wily misuses of // lifetime parameters. - let implied_bounds = infcx.implied_bounds_tys(param_env, impl_ty_def_id, assumed_wf_types); + let implied_bounds = infcx.implied_bounds_tys(param_env, impl_ty_def_id, &assumed_wf_types); let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); ocx.resolve_regions_and_report_errors(impl_ty_def_id, &outlives_env) } diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index f7fc0c81b953..0d8de0cabd1a 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -158,7 +158,7 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( } let outlives_env = OutlivesEnvironment::with_bounds( param_env, - infcx.implied_bounds_tys(param_env, impl_m.def_id.expect_local(), implied_wf_types), + infcx.implied_bounds_tys(param_env, impl_m.def_id.expect_local(), &implied_wf_types), ); let errors = infcx.resolve_regions(&outlives_env); if !errors.is_empty() { diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 5d5a4789734a..1c0a1a695139 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -681,7 +681,8 @@ fn resolve_local<'tcx>( | PatKind::Never | PatKind::Path(_) | PatKind::Lit(_) - | PatKind::Range(_, _, _) => false, + | PatKind::Range(_, _, _) + | PatKind::Err(_) => false, } } diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 4772bae58c47..3b9837ff7c2b 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -15,6 +15,7 @@ use rustc_infer::infer::outlives::obligations::TypeOutlives; use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; use rustc_middle::mir::ConstraintCategory; use rustc_middle::query::Providers; +use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::trait_def::TraitSpecializationKind; use rustc_middle::ty::{ self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, @@ -112,8 +113,6 @@ where let assumed_wf_types = wfcx.ocx.assumed_wf_types_and_report_errors(param_env, body_def_id)?; - let implied_bounds = infcx.implied_bounds_tys(param_env, body_def_id, assumed_wf_types); - let errors = wfcx.select_all_or_error(); if !errors.is_empty() { let err = infcx.err_ctxt().report_fulfillment_errors(errors); @@ -128,10 +127,65 @@ where } } + debug!(?assumed_wf_types); + + let infcx_compat = infcx.fork(); + + // We specifically want to call the non-compat version of `implied_bounds_tys`; we do this always. + let implied_bounds = + infcx.implied_bounds_tys_compat(param_env, body_def_id, &assumed_wf_types, false); let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); - wfcx.ocx.resolve_regions_and_report_errors(body_def_id, &outlives_env)?; - infcx.tainted_by_errors().error_reported() + let errors = infcx.resolve_regions(&outlives_env); + if errors.is_empty() { + return Ok(()); + } + + let is_bevy = 'is_bevy: { + // We don't want to emit this for dependents of Bevy, for now. + // See #119956 + let is_bevy_paramset = |def: ty::AdtDef<'_>| { + let adt_did = with_no_trimmed_paths!(infcx.tcx.def_path_str(def.0.did)); + adt_did.contains("ParamSet") + }; + for ty in assumed_wf_types.iter() { + match ty.kind() { + ty::Adt(def, _) => { + if is_bevy_paramset(*def) { + break 'is_bevy true; + } + } + ty::Ref(_, ty, _) => match ty.kind() { + ty::Adt(def, _) => { + if is_bevy_paramset(*def) { + break 'is_bevy true; + } + } + _ => {} + }, + _ => {} + } + } + false + }; + + // If we have set `no_implied_bounds_compat`, then do not attempt compatibility. + // We could also just always enter if `is_bevy`, and call `implied_bounds_tys`, + // but that does result in slightly more work when this option is set and + // just obscures what we mean here anyways. Let's just be explicit. + if is_bevy && !infcx.tcx.sess.opts.unstable_opts.no_implied_bounds_compat { + let implied_bounds = + infcx_compat.implied_bounds_tys_compat(param_env, body_def_id, &assumed_wf_types, true); + let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); + let errors_compat = infcx_compat.resolve_regions(&outlives_env); + if errors_compat.is_empty() { + Ok(()) + } else { + Err(infcx_compat.err_ctxt().report_region_errors(body_def_id, &errors_compat)) + } + } else { + Err(infcx.err_ctxt().report_region_errors(body_def_id, &errors)) + } } fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) -> Result<(), ErrorGuaranteed> { @@ -723,7 +777,7 @@ fn resolve_regions_with_wf_tys<'tcx>( let infcx = tcx.infer_ctxt().build(); let outlives_environment = OutlivesEnvironment::with_bounds( param_env, - infcx.implied_bounds_tys(param_env, id, wf_tys.clone()), + infcx.implied_bounds_tys(param_env, id, wf_tys), ); let region_bound_pairs = outlives_environment.region_bound_pairs(); @@ -1736,7 +1790,7 @@ fn receiver_is_implemented<'tcx>( fn check_variances_for_type_defn<'tcx>( tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, - hir_generics: &hir::Generics<'_>, + hir_generics: &hir::Generics<'tcx>, ) { let identity_args = ty::GenericArgs::identity_for_item(tcx, item.owner_id); diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs index 3162004a6348..abef365c3ca3 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs @@ -13,32 +13,41 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::ty::fast_reject::{simplify_type, SimplifiedType, TreatParams}; use rustc_middle::ty::{self, CrateInherentImpls, Ty, TyCtxt}; use rustc_span::symbol::sym; +use rustc_span::ErrorGuaranteed; use crate::errors; /// On-demand query: yields a map containing all types mapped to their inherent impls. -pub fn crate_inherent_impls(tcx: TyCtxt<'_>, (): ()) -> CrateInherentImpls { +pub fn crate_inherent_impls( + tcx: TyCtxt<'_>, + (): (), +) -> Result<&'_ CrateInherentImpls, ErrorGuaranteed> { let mut collect = InherentCollect { tcx, impls_map: Default::default() }; + let mut res = Ok(()); for id in tcx.hir().items() { - collect.check_item(id); + res = res.and(collect.check_item(id)); } - collect.impls_map + res?; + Ok(tcx.arena.alloc(collect.impls_map)) } -pub fn crate_incoherent_impls(tcx: TyCtxt<'_>, simp: SimplifiedType) -> &[DefId] { - let crate_map = tcx.crate_inherent_impls(()); - tcx.arena.alloc_from_iter( +pub fn crate_incoherent_impls( + tcx: TyCtxt<'_>, + simp: SimplifiedType, +) -> Result<&[DefId], ErrorGuaranteed> { + let crate_map = tcx.crate_inherent_impls(())?; + Ok(tcx.arena.alloc_from_iter( crate_map.incoherent_impls.get(&simp).unwrap_or(&Vec::new()).iter().map(|d| d.to_def_id()), - ) + )) } /// On-demand query: yields a vector of the inherent impls for a specific type. -pub fn inherent_impls(tcx: TyCtxt<'_>, ty_def_id: LocalDefId) -> &[DefId] { - let crate_map = tcx.crate_inherent_impls(()); - match crate_map.inherent_impls.get(&ty_def_id) { +pub fn inherent_impls(tcx: TyCtxt<'_>, ty_def_id: LocalDefId) -> Result<&[DefId], ErrorGuaranteed> { + let crate_map = tcx.crate_inherent_impls(())?; + Ok(match crate_map.inherent_impls.get(&ty_def_id) { Some(v) => &v[..], None => &[], - } + }) } struct InherentCollect<'tcx> { @@ -47,14 +56,19 @@ struct InherentCollect<'tcx> { } impl<'tcx> InherentCollect<'tcx> { - fn check_def_id(&mut self, impl_def_id: LocalDefId, self_ty: Ty<'tcx>, ty_def_id: DefId) { + fn check_def_id( + &mut self, + impl_def_id: LocalDefId, + self_ty: Ty<'tcx>, + ty_def_id: DefId, + ) -> Result<(), ErrorGuaranteed> { if let Some(ty_def_id) = ty_def_id.as_local() { // Add the implementation to the mapping from implementation to base // type def ID, if there is a base type for this implementation and // the implementation does not have any associated traits. let vec = self.impls_map.inherent_impls.entry(ty_def_id).or_default(); vec.push(impl_def_id.to_def_id()); - return; + return Ok(()); } if self.tcx.features().rustc_attrs { @@ -62,18 +76,16 @@ impl<'tcx> InherentCollect<'tcx> { if !self.tcx.has_attr(ty_def_id, sym::rustc_has_incoherent_inherent_impls) { let impl_span = self.tcx.def_span(impl_def_id); - self.tcx.dcx().emit_err(errors::InherentTyOutside { span: impl_span }); - return; + return Err(self.tcx.dcx().emit_err(errors::InherentTyOutside { span: impl_span })); } for &impl_item in items { if !self.tcx.has_attr(impl_item, sym::rustc_allow_incoherent_impl) { let impl_span = self.tcx.def_span(impl_def_id); - self.tcx.dcx().emit_err(errors::InherentTyOutsideRelevant { + return Err(self.tcx.dcx().emit_err(errors::InherentTyOutsideRelevant { span: impl_span, help_span: self.tcx.def_span(impl_item), - }); - return; + })); } } @@ -82,24 +94,28 @@ impl<'tcx> InherentCollect<'tcx> { } else { bug!("unexpected self type: {:?}", self_ty); } + Ok(()) } else { let impl_span = self.tcx.def_span(impl_def_id); - self.tcx.dcx().emit_err(errors::InherentTyOutsideNew { span: impl_span }); + Err(self.tcx.dcx().emit_err(errors::InherentTyOutsideNew { span: impl_span })) } } - fn check_primitive_impl(&mut self, impl_def_id: LocalDefId, ty: Ty<'tcx>) { + fn check_primitive_impl( + &mut self, + impl_def_id: LocalDefId, + ty: Ty<'tcx>, + ) -> Result<(), ErrorGuaranteed> { let items = self.tcx.associated_item_def_ids(impl_def_id); if !self.tcx.hir().rustc_coherence_is_core() { if self.tcx.features().rustc_attrs { for &impl_item in items { if !self.tcx.has_attr(impl_item, sym::rustc_allow_incoherent_impl) { let span = self.tcx.def_span(impl_def_id); - self.tcx.dcx().emit_err(errors::InherentTyOutsidePrimitive { + return Err(self.tcx.dcx().emit_err(errors::InherentTyOutsidePrimitive { span, help_span: self.tcx.def_span(impl_item), - }); - return; + })); } } } else { @@ -108,8 +124,7 @@ impl<'tcx> InherentCollect<'tcx> { if let ty::Ref(_, subty, _) = ty.kind() { note = Some(errors::InherentPrimitiveTyNote { subty: *subty }); } - self.tcx.dcx().emit_err(errors::InherentPrimitiveTy { span, note }); - return; + return Err(self.tcx.dcx().emit_err(errors::InherentPrimitiveTy { span, note })); } } @@ -118,11 +133,12 @@ impl<'tcx> InherentCollect<'tcx> { } else { bug!("unexpected primitive type: {:?}", ty); } + Ok(()) } - fn check_item(&mut self, id: hir::ItemId) { + fn check_item(&mut self, id: hir::ItemId) -> Result<(), ErrorGuaranteed> { if !matches!(self.tcx.def_kind(id.owner_id), DefKind::Impl { of_trait: false }) { - return; + return Ok(()); } let id = id.owner_id.def_id; @@ -132,10 +148,10 @@ impl<'tcx> InherentCollect<'tcx> { ty::Adt(def, _) => self.check_def_id(id, self_ty, def.did()), ty::Foreign(did) => self.check_def_id(id, self_ty, did), ty::Dynamic(data, ..) if data.principal_def_id().is_some() => { - self.check_def_id(id, self_ty, data.principal_def_id().unwrap()); + self.check_def_id(id, self_ty, data.principal_def_id().unwrap()) } ty::Dynamic(..) => { - self.tcx.dcx().emit_err(errors::InherentDyn { span: item_span }); + Err(self.tcx.dcx().emit_err(errors::InherentDyn { span: item_span })) } ty::Bool | ty::Char @@ -151,7 +167,7 @@ impl<'tcx> InherentCollect<'tcx> { | ty::FnPtr(_) | ty::Tuple(..) => self.check_primitive_impl(id, self_ty), ty::Alias(..) | ty::Param(_) => { - self.tcx.dcx().emit_err(errors::InherentNominal { span: item_span }); + Err(self.tcx.dcx().emit_err(errors::InherentNominal { span: item_span })) } ty::FnDef(..) | ty::Closure(..) @@ -162,7 +178,8 @@ impl<'tcx> InherentCollect<'tcx> { | ty::Infer(_) => { bug!("unexpected impl self type of impl: {:?} {:?}", id, self_ty); } - ty::Error(_) => {} + // We could bail out here, but that will silence other useful errors. + ty::Error(_) => Ok(()), } } } diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs index 4c3455c7240f..63ea02720145 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs @@ -6,16 +6,18 @@ use rustc_hir::def_id::DefId; use rustc_index::IndexVec; use rustc_middle::traits::specialization_graph::OverlapMode; use rustc_middle::ty::{self, TyCtxt}; -use rustc_span::Symbol; +use rustc_span::{ErrorGuaranteed, Symbol}; use rustc_trait_selection::traits::{self, SkipLeakCheck}; use smallvec::SmallVec; use std::collections::hash_map::Entry; -pub fn crate_inherent_impls_overlap_check(tcx: TyCtxt<'_>, (): ()) { +pub fn crate_inherent_impls_overlap_check(tcx: TyCtxt<'_>, (): ()) -> Result<(), ErrorGuaranteed> { let mut inherent_overlap_checker = InherentOverlapChecker { tcx }; + let mut res = Ok(()); for id in tcx.hir().items() { - inherent_overlap_checker.check_item(id); + res = res.and(inherent_overlap_checker.check_item(id)); } + res } struct InherentOverlapChecker<'tcx> { @@ -58,10 +60,11 @@ impl<'tcx> InherentOverlapChecker<'tcx> { == item2.ident(self.tcx).normalize_to_macros_2_0() } - fn check_for_duplicate_items_in_impl(&self, impl_: DefId) { + fn check_for_duplicate_items_in_impl(&self, impl_: DefId) -> Result<(), ErrorGuaranteed> { let impl_items = self.tcx.associated_items(impl_); let mut seen_items = FxHashMap::default(); + let mut res = Ok(()); for impl_item in impl_items.in_definition_order() { let span = self.tcx.def_span(impl_item.def_id); let ident = impl_item.ident(self.tcx); @@ -70,7 +73,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> { match seen_items.entry(norm_ident) { Entry::Occupied(entry) => { let former = entry.get(); - struct_span_code_err!( + res = Err(struct_span_code_err!( self.tcx.dcx(), span, E0592, @@ -79,13 +82,14 @@ impl<'tcx> InherentOverlapChecker<'tcx> { ) .with_span_label(span, format!("duplicate definitions for `{ident}`")) .with_span_label(*former, format!("other definition for `{ident}`")) - .emit(); + .emit()); } Entry::Vacant(entry) => { entry.insert(span); } } } + res } fn check_for_common_items_in_impls( @@ -93,10 +97,11 @@ impl<'tcx> InherentOverlapChecker<'tcx> { impl1: DefId, impl2: DefId, overlap: traits::OverlapResult<'_>, - ) { + ) -> Result<(), ErrorGuaranteed> { let impl_items1 = self.tcx.associated_items(impl1); let impl_items2 = self.tcx.associated_items(impl2); + let mut res = Ok(()); for &item1 in impl_items1.in_definition_order() { let collision = impl_items2 .filter_by_name_unhygienic(item1.name) @@ -128,9 +133,10 @@ impl<'tcx> InherentOverlapChecker<'tcx> { traits::add_placeholder_note(&mut err); } - err.emit(); + res = Err(err.emit()); } } + res } fn check_for_overlapping_inherent_impls( @@ -138,7 +144,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> { overlap_mode: OverlapMode, impl1_def_id: DefId, impl2_def_id: DefId, - ) { + ) -> Result<(), ErrorGuaranteed> { let maybe_overlap = traits::overlapping_impls( self.tcx, impl1_def_id, @@ -150,17 +156,19 @@ impl<'tcx> InherentOverlapChecker<'tcx> { ); if let Some(overlap) = maybe_overlap { - self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id, overlap); + self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id, overlap) + } else { + Ok(()) } } - fn check_item(&mut self, id: hir::ItemId) { + fn check_item(&mut self, id: hir::ItemId) -> Result<(), ErrorGuaranteed> { let def_kind = self.tcx.def_kind(id.owner_id); if !matches!(def_kind, DefKind::Enum | DefKind::Struct | DefKind::Trait | DefKind::Union) { - return; + return Ok(()); } - let impls = self.tcx.inherent_impls(id.owner_id); + let impls = self.tcx.inherent_impls(id.owner_id)?; let overlap_mode = OverlapMode::get(self.tcx, id.owner_id.to_def_id()); @@ -173,17 +181,18 @@ impl<'tcx> InherentOverlapChecker<'tcx> { // otherwise switch to an allocating algorithm with // faster asymptotic runtime. const ALLOCATING_ALGO_THRESHOLD: usize = 500; + let mut res = Ok(()); if impls.len() < ALLOCATING_ALGO_THRESHOLD { for (i, &(&impl1_def_id, impl_items1)) in impls_items.iter().enumerate() { - self.check_for_duplicate_items_in_impl(impl1_def_id); + res = res.and(self.check_for_duplicate_items_in_impl(impl1_def_id)); for &(&impl2_def_id, impl_items2) in &impls_items[(i + 1)..] { if self.impls_have_common_items(impl_items1, impl_items2) { - self.check_for_overlapping_inherent_impls( + res = res.and(self.check_for_overlapping_inherent_impls( overlap_mode, impl1_def_id, impl2_def_id, - ); + )); } } } @@ -315,20 +324,21 @@ impl<'tcx> InherentOverlapChecker<'tcx> { impl_blocks.sort_unstable(); for (i, &impl1_items_idx) in impl_blocks.iter().enumerate() { let &(&impl1_def_id, impl_items1) = &impls_items[impl1_items_idx]; - self.check_for_duplicate_items_in_impl(impl1_def_id); + res = res.and(self.check_for_duplicate_items_in_impl(impl1_def_id)); for &impl2_items_idx in impl_blocks[(i + 1)..].iter() { let &(&impl2_def_id, impl_items2) = &impls_items[impl2_items_idx]; if self.impls_have_common_items(impl_items1, impl_items2) { - self.check_for_overlapping_inherent_impls( + res = res.and(self.check_for_overlapping_inherent_impls( overlap_mode, impl1_def_id, impl2_def_id, - ); + )); } } } } } + res } } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index e557f36037b6..d8ce2307995c 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -348,7 +348,7 @@ impl<'tcx> ItemCtxt<'tcx> { ItemCtxt { tcx, item_def_id, tainted_by_errors: Cell::new(None) } } - pub fn to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> { + pub fn to_ty(&self, ast_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { self.astconv().ast_ty_to_ty(ast_ty) } @@ -412,7 +412,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { &self, span: Span, item_def_id: DefId, - item_segment: &hir::PathSegment<'_>, + item_segment: &hir::PathSegment<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Ty<'tcx> { if let Some(trait_ref) = poly_trait_ref.no_bound_vars() { @@ -1148,7 +1148,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder( tcx: TyCtxt<'tcx>, - sig: &hir::FnSig<'_>, + sig: &hir::FnSig<'tcx>, generics: &hir::Generics<'_>, def_id: LocalDefId, icx: &ItemCtxt<'tcx>, @@ -1352,14 +1352,14 @@ fn impl_trait_ref( let last_arg = args.args.len() - 1; assert!(matches!(args.args[last_arg], hir::GenericArg::Const(anon_const) if anon_const.is_desugared_from_effects)); args.args = &args.args[..args.args.len() - 1]; - path_segments[last_segment].args = Some(&args); + path_segments[last_segment].args = Some(tcx.hir_arena.alloc(args)); let path = hir::Path { span: ast_trait_ref.path.span, res: ast_trait_ref.path.res, - segments: &path_segments, + segments: tcx.hir_arena.alloc_slice(&path_segments), }; - let trait_ref = hir::TraitRef { path: &path, hir_ref_id: ast_trait_ref.hir_ref_id }; - icx.astconv().instantiate_mono_trait_ref(&trait_ref, selfty) + let trait_ref = tcx.hir_arena.alloc(hir::TraitRef { path: tcx.hir_arena.alloc(path), hir_ref_id: ast_trait_ref.hir_ref_id }); + icx.astconv().instantiate_mono_trait_ref(trait_ref, selfty) } else { icx.astconv().instantiate_mono_trait_ref(ast_trait_ref, selfty) } diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs index 1f7ca48234a2..85093bc12b37 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -5,20 +5,22 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{self as hir, def, Expr, ImplItem, Item, Node, TraitItem}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; -use rustc_span::{sym, DUMMY_SP}; +use rustc_span::{sym, ErrorGuaranteed, DUMMY_SP}; use crate::errors::{TaitForwardCompat, TypeOf, UnconstrainedOpaqueType}; -pub fn test_opaque_hidden_types(tcx: TyCtxt<'_>) { +pub fn test_opaque_hidden_types(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { + let mut res = Ok(()); if tcx.has_attr(CRATE_DEF_ID, sym::rustc_hidden_type_of_opaques) { for id in tcx.hir().items() { if matches!(tcx.def_kind(id.owner_id), DefKind::OpaqueTy) { let type_of = tcx.type_of(id.owner_id).instantiate_identity(); - tcx.dcx().emit_err(TypeOf { span: tcx.def_span(id.owner_id), type_of }); + res = Err(tcx.dcx().emit_err(TypeOf { span: tcx.def_span(id.owner_id), type_of })); } } } + res } /// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions @@ -135,18 +137,25 @@ impl TaitConstraintLocator<'_> { return; } - if let Some(hir_sig) = self.tcx.hir_node_by_def_id(item_def_id).fn_decl() { - if hir_sig.output.get_infer_ret_ty().is_some() { - let guar = self.tcx.dcx().span_delayed_bug( - hir_sig.output.span(), - "inferring return types and opaque types do not mix well", - ); - self.found = Some(ty::OpaqueHiddenType { - span: DUMMY_SP, - ty: Ty::new_error(self.tcx, guar), - }); - return; - } + // Function items with `_` in their return type already emit an error, skip any + // "non-defining use" errors for them. + // Note that we use `Node::fn_sig` instead of `Node::fn_decl` here, because the former + // excludes closures, which are allowed to have `_` in their return type. + let hir_node = self.tcx.hir_node_by_def_id(item_def_id); + debug_assert!( + !matches!(hir_node, Node::ForeignItem(..)), + "foreign items cannot constrain opaque types", + ); + if let Some(hir_sig) = hir_node.fn_sig() + && hir_sig.decl.output.get_infer_ret_ty().is_some() + { + let guar = self.tcx.dcx().span_delayed_bug( + hir_sig.decl.output.span(), + "inferring return types and opaque types do not mix well", + ); + self.found = + Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: Ty::new_error(self.tcx, guar) }); + return; } // Calling `mir_borrowck` can lead to cycle errors through diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs index 3f9b1f384d79..2fe08ead72b2 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs @@ -17,7 +17,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::{LocalDefId, LocalModDefId}; use rustc_middle::query::Providers; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; -use rustc_span::{Span, Symbol}; +use rustc_span::{ErrorGuaranteed, Span, Symbol}; mod min_specialization; @@ -51,24 +51,29 @@ mod min_specialization; /// impl<'a> Trait for Bar { type X = &'a i32; } /// // ^ 'a is unused and appears in assoc type, error /// ``` -fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { +fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) -> Result<(), ErrorGuaranteed> { let min_specialization = tcx.features().min_specialization; let module = tcx.hir_module_items(module_def_id); + let mut res = Ok(()); for id in module.items() { if matches!(tcx.def_kind(id.owner_id), DefKind::Impl { .. }) { - enforce_impl_params_are_constrained(tcx, id.owner_id.def_id); + res = res.and(enforce_impl_params_are_constrained(tcx, id.owner_id.def_id)); if min_specialization { - check_min_specialization(tcx, id.owner_id.def_id); + res = res.and(check_min_specialization(tcx, id.owner_id.def_id)); } } } + res } pub fn provide(providers: &mut Providers) { *providers = Providers { check_mod_impl_wf, ..*providers }; } -fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) { +fn enforce_impl_params_are_constrained( + tcx: TyCtxt<'_>, + impl_def_id: LocalDefId, +) -> Result<(), ErrorGuaranteed> { // Every lifetime used in an associated type must be constrained. let impl_self_ty = tcx.type_of(impl_def_id).instantiate_identity(); if impl_self_ty.references_error() { @@ -80,7 +85,10 @@ fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) "potentially unconstrained type parameters weren't evaluated: {impl_self_ty:?}", ), ); - return; + // This is super fishy, but our current `rustc_hir_analysis::check_crate` pipeline depends on + // `type_of` having been called much earlier, and thus this value being read from cache. + // Compilation must continue in order for other important diagnostics to keep showing up. + return Ok(()); } let impl_generics = tcx.generics_of(impl_def_id); let impl_predicates = tcx.predicates_of(impl_def_id); @@ -113,13 +121,19 @@ fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) }) .collect(); + let mut res = Ok(()); for param in &impl_generics.params { match param.kind { // Disallow ANY unconstrained type parameters. ty::GenericParamDefKind::Type { .. } => { let param_ty = ty::ParamTy::for_def(param); if !input_parameters.contains(&cgp::Parameter::from(param_ty)) { - report_unused_parameter(tcx, tcx.def_span(param.def_id), "type", param_ty.name); + res = Err(report_unused_parameter( + tcx, + tcx.def_span(param.def_id), + "type", + param_ty.name, + )); } } ty::GenericParamDefKind::Lifetime => { @@ -127,27 +141,28 @@ fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) if lifetimes_in_associated_types.contains(¶m_lt) && // (*) !input_parameters.contains(¶m_lt) { - report_unused_parameter( + res = Err(report_unused_parameter( tcx, tcx.def_span(param.def_id), "lifetime", param.name, - ); + )); } } ty::GenericParamDefKind::Const { .. } => { let param_ct = ty::ParamConst::for_def(param); if !input_parameters.contains(&cgp::Parameter::from(param_ct)) { - report_unused_parameter( + res = Err(report_unused_parameter( tcx, tcx.def_span(param.def_id), "const", param_ct.name, - ); + )); } } } } + res // (*) This is a horrible concession to reality. I think it'd be // better to just ban unconstrained lifetimes outright, but in @@ -169,7 +184,12 @@ fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) // used elsewhere are not projected back out. } -fn report_unused_parameter(tcx: TyCtxt<'_>, span: Span, kind: &str, name: Symbol) { +fn report_unused_parameter( + tcx: TyCtxt<'_>, + span: Span, + kind: &str, + name: Symbol, +) -> ErrorGuaranteed { let mut err = struct_span_code_err!( tcx.dcx(), span, @@ -188,5 +208,5 @@ fn report_unused_parameter(tcx: TyCtxt<'_>, span: Span, kind: &str, name: Symbol "proving the result of expressions other than the parameter are unique is not supported", ); } - err.emit(); + err.emit() } diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index 93dd2342a4d1..1b6a39d8162e 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -82,10 +82,14 @@ use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _; use rustc_trait_selection::traits::{self, translate_args_with_cause, wf, ObligationCtxt}; -pub(super) fn check_min_specialization(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) { +pub(super) fn check_min_specialization( + tcx: TyCtxt<'_>, + impl_def_id: LocalDefId, +) -> Result<(), ErrorGuaranteed> { if let Some(node) = parent_specialization_node(tcx, impl_def_id) { - check_always_applicable(tcx, impl_def_id, node); + check_always_applicable(tcx, impl_def_id, node)?; } + Ok(()) } fn parent_specialization_node(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId) -> Option { @@ -109,42 +113,58 @@ fn parent_specialization_node(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId) -> Opti /// Check that `impl1` is a sound specialization #[instrument(level = "debug", skip(tcx))] -fn check_always_applicable(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node: Node) { +fn check_always_applicable( + tcx: TyCtxt<'_>, + impl1_def_id: LocalDefId, + impl2_node: Node, +) -> Result<(), ErrorGuaranteed> { let span = tcx.def_span(impl1_def_id); - check_has_items(tcx, impl1_def_id, impl2_node, span); + let mut res = check_has_items(tcx, impl1_def_id, impl2_node, span); - if let Ok((impl1_args, impl2_args)) = get_impl_args(tcx, impl1_def_id, impl2_node) { - let impl2_def_id = impl2_node.def_id(); - debug!(?impl2_def_id, ?impl2_args); + let (impl1_args, impl2_args) = get_impl_args(tcx, impl1_def_id, impl2_node)?; + let impl2_def_id = impl2_node.def_id(); + debug!(?impl2_def_id, ?impl2_args); - let parent_args = if impl2_node.is_from_trait() { - impl2_args.to_vec() - } else { - unconstrained_parent_impl_args(tcx, impl2_def_id, impl2_args) - }; + let parent_args = if impl2_node.is_from_trait() { + impl2_args.to_vec() + } else { + unconstrained_parent_impl_args(tcx, impl2_def_id, impl2_args) + }; - check_constness(tcx, impl1_def_id, impl2_node, span); - check_static_lifetimes(tcx, &parent_args, span); - check_duplicate_params(tcx, impl1_args, &parent_args, span); - check_predicates(tcx, impl1_def_id, impl1_args, impl2_node, impl2_args, span); - } + res = res.and(check_constness(tcx, impl1_def_id, impl2_node, span)); + res = res.and(check_static_lifetimes(tcx, &parent_args, span)); + res = res.and(check_duplicate_params(tcx, impl1_args, &parent_args, span)); + res = res.and(check_predicates(tcx, impl1_def_id, impl1_args, impl2_node, impl2_args, span)); + + res } -fn check_has_items(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node: Node, span: Span) { +fn check_has_items( + tcx: TyCtxt<'_>, + impl1_def_id: LocalDefId, + impl2_node: Node, + span: Span, +) -> Result<(), ErrorGuaranteed> { if let Node::Impl(impl2_id) = impl2_node && tcx.associated_item_def_ids(impl1_def_id).is_empty() { let base_impl_span = tcx.def_span(impl2_id); - tcx.dcx().emit_err(errors::EmptySpecialization { span, base_impl_span }); + return Err(tcx.dcx().emit_err(errors::EmptySpecialization { span, base_impl_span })); } + Ok(()) } /// Check that the specializing impl `impl1` is at least as const as the base /// impl `impl2` -fn check_constness(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node: Node, span: Span) { +fn check_constness( + tcx: TyCtxt<'_>, + impl1_def_id: LocalDefId, + impl2_node: Node, + span: Span, +) -> Result<(), ErrorGuaranteed> { if impl2_node.is_from_trait() { // This isn't a specialization - return; + return Ok(()); } let impl1_constness = tcx.constness(impl1_def_id.to_def_id()); @@ -152,9 +172,10 @@ fn check_constness(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node: Node, if let hir::Constness::Const = impl2_constness { if let hir::Constness::NotConst = impl1_constness { - tcx.dcx().emit_err(errors::ConstSpecialize { span }); + return Err(tcx.dcx().emit_err(errors::ConstSpecialize { span })); } } + Ok(()) } /// Given a specializing impl `impl1`, and the base impl `impl2`, returns two @@ -202,7 +223,7 @@ fn get_impl_args( return Err(guar); } - let implied_bounds = infcx.implied_bounds_tys(param_env, impl1_def_id, assumed_wf_types); + let implied_bounds = infcx.implied_bounds_tys(param_env, impl1_def_id, &assumed_wf_types); let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); let _ = ocx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env); let Ok(impl2_args) = infcx.fully_resolve(impl2_args) else { @@ -290,15 +311,17 @@ fn check_duplicate_params<'tcx>( impl1_args: GenericArgsRef<'tcx>, parent_args: &Vec>, span: Span, -) { +) -> Result<(), ErrorGuaranteed> { let mut base_params = cgp::parameters_for(parent_args, true); base_params.sort_by_key(|param| param.0); if let (_, [duplicate, ..]) = base_params.partition_dedup() { let param = impl1_args[duplicate.0 as usize]; - tcx.dcx() + return Err(tcx + .dcx() .struct_span_err(span, format!("specializing impl repeats parameter `{param}`")) - .emit(); + .emit()); } + Ok(()) } /// Check that `'static` lifetimes are not introduced by the specializing impl. @@ -313,10 +336,11 @@ fn check_static_lifetimes<'tcx>( tcx: TyCtxt<'tcx>, parent_args: &Vec>, span: Span, -) { +) -> Result<(), ErrorGuaranteed> { if tcx.any_free_region_meets(parent_args, |r| r.is_static()) { - tcx.dcx().emit_err(errors::StaticSpecialize { span }); + return Err(tcx.dcx().emit_err(errors::StaticSpecialize { span })); } + Ok(()) } /// Check whether predicates on the specializing impl (`impl1`) are allowed. @@ -337,7 +361,7 @@ fn check_predicates<'tcx>( impl2_node: Node, impl2_args: GenericArgsRef<'tcx>, span: Span, -) { +) -> Result<(), ErrorGuaranteed> { let impl1_predicates: Vec<_> = traits::elaborate( tcx, tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_args).into_iter(), @@ -399,14 +423,16 @@ fn check_predicates<'tcx>( } impl2_predicates.extend(traits::elaborate(tcx, always_applicable_traits)); + let mut res = Ok(()); for (clause, span) in impl1_predicates { if !impl2_predicates .iter() .any(|pred2| trait_predicates_eq(tcx, clause.as_predicate(), *pred2, span)) { - check_specialization_on(tcx, clause, span) + res = res.and(check_specialization_on(tcx, clause, span)) } } + res } /// Checks if some predicate on the specializing impl (`predicate1`) is the same @@ -443,19 +469,26 @@ fn trait_predicates_eq<'tcx>( } #[instrument(level = "debug", skip(tcx))] -fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, clause: ty::Clause<'tcx>, span: Span) { +fn check_specialization_on<'tcx>( + tcx: TyCtxt<'tcx>, + clause: ty::Clause<'tcx>, + span: Span, +) -> Result<(), ErrorGuaranteed> { match clause.kind().skip_binder() { // Global predicates are either always true or always false, so we // are fine to specialize on. - _ if clause.is_global() => (), + _ if clause.is_global() => Ok(()), // We allow specializing on explicitly marked traits with no associated // items. ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => { - if !matches!( + if matches!( trait_specialization_kind(tcx, clause), Some(TraitSpecializationKind::Marker) ) { - tcx.dcx() + Ok(()) + } else { + Err(tcx + .dcx() .struct_span_err( span, format!( @@ -463,17 +496,16 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, clause: ty::Clause<'tcx>, sp tcx.def_path_str(trait_ref.def_id), ), ) - .emit(); + .emit()) } } - ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => { - tcx.dcx() - .struct_span_err( - span, - format!("cannot specialize on associated type `{projection_ty} == {term}`",), - ) - .emit(); - } + ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => Err(tcx + .dcx() + .struct_span_err( + span, + format!("cannot specialize on associated type `{projection_ty} == {term}`",), + ) + .emit()), ty::ClauseKind::ConstArgHasType(..) => { // FIXME(min_specialization), FIXME(const_generics): // It probably isn't right to allow _every_ `ConstArgHasType` but I am somewhat unsure @@ -483,12 +515,12 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, clause: ty::Clause<'tcx>, sp // While we do not support constructs like `` there is probably no risk of // soundness bugs, but when we support generic const parameter types this will need to be // revisited. + Ok(()) } - _ => { - tcx.dcx() - .struct_span_err(span, format!("cannot specialize on predicate `{clause}`")) - .emit(); - } + _ => Err(tcx + .dcx() + .struct_span_err(span, format!("cannot specialize on predicate `{clause}`")) + .emit()), } } diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index f5abb7261c00..0a3a71ba1a28 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -166,33 +166,29 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { tcx.hir().for_each_module(|module| tcx.ensure().collect_mod_item_types(module)) }); - // FIXME(matthewjasper) We shouldn't need to use `track_errors` anywhere in this function - // or the compiler in general. if tcx.features().rustc_attrs { - tcx.sess.track_errors(|| { - tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx)); - })?; + tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx))?; } - tcx.sess.track_errors(|| { - tcx.sess.time("coherence_checking", || { - // Check impls constrain their parameters - tcx.hir().for_each_module(|module| tcx.ensure().check_mod_impl_wf(module)); + tcx.sess.time("coherence_checking", || { + // Check impls constrain their parameters + let res = + tcx.hir().try_par_for_each_module(|module| tcx.ensure().check_mod_impl_wf(module)); + // FIXME(matthewjasper) We shouldn't need to use `track_errors` anywhere in this function + // or the compiler in general. + res.and(tcx.sess.track_errors(|| { for &trait_def_id in tcx.all_local_trait_impls(()).keys() { tcx.ensure().coherent_trait(trait_def_id); } - - // these queries are executed for side-effects (error reporting): - tcx.ensure().crate_inherent_impls(()); - tcx.ensure().crate_inherent_impls_overlap_check(()); - }); + })) + // these queries are executed for side-effects (error reporting): + .and(tcx.ensure().crate_inherent_impls(())) + .and(tcx.ensure().crate_inherent_impls_overlap_check(())) })?; if tcx.features().rustc_attrs { - tcx.sess.track_errors(|| { - tcx.sess.time("variance_testing", || variance::test::test_variance(tcx)); - })?; + tcx.sess.time("variance_testing", || variance::test::test_variance(tcx))?; } tcx.sess.time("wf_checking", || { @@ -200,7 +196,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { })?; if tcx.features().rustc_attrs { - tcx.sess.track_errors(|| collect::test_opaque_hidden_types(tcx))?; + collect::test_opaque_hidden_types(tcx)?; } // Freeze definitions as we don't add new ones at this point. This improves performance by @@ -225,7 +221,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { /// A quasi-deprecated helper used in rustdoc and clippy to get /// the type from a HIR node. -pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> { +pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { // In case there are any projections, etc., find the "environment" // def-ID that will be used to determine the traits/predicates in // scope. This is derived from the enclosing item-like thing. @@ -236,7 +232,7 @@ pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> { pub fn hir_trait_to_predicates<'tcx>( tcx: TyCtxt<'tcx>, - hir_trait: &hir::TraitRef<'_>, + hir_trait: &hir::TraitRef<'tcx>, self_ty: Ty<'tcx>, ) -> Bounds<'tcx> { // In case there are any projections, etc., find the "environment" diff --git a/compiler/rustc_hir_analysis/src/outlives/test.rs b/compiler/rustc_hir_analysis/src/outlives/test.rs index dea3f1a99308..60cd8c39fa02 100644 --- a/compiler/rustc_hir_analysis/src/outlives/test.rs +++ b/compiler/rustc_hir_analysis/src/outlives/test.rs @@ -1,7 +1,8 @@ use rustc_middle::ty::{self, TyCtxt}; -use rustc_span::symbol::sym; +use rustc_span::{symbol::sym, ErrorGuaranteed}; -pub fn test_inferred_outlives(tcx: TyCtxt<'_>) { +pub fn test_inferred_outlives(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { + let mut res = Ok(()); for id in tcx.hir().items() { // For unit testing: check for a special "rustc_outlives" // attribute and report an error with various results if found. @@ -22,7 +23,8 @@ pub fn test_inferred_outlives(tcx: TyCtxt<'_>) { for p in pred { err.note(p); } - err.emit(); + res = Err(err.emit()); } } + res } diff --git a/compiler/rustc_hir_analysis/src/structured_errors.rs b/compiler/rustc_hir_analysis/src/structured_errors.rs index 04d04304e70f..b061d6371388 100644 --- a/compiler/rustc_hir_analysis/src/structured_errors.rs +++ b/compiler/rustc_hir_analysis/src/structured_errors.rs @@ -6,13 +6,13 @@ pub use self::{ missing_cast_for_variadic_arg::*, sized_unsized_cast::*, wrong_number_of_generic_args::*, }; -use rustc_errors::{DiagnosticBuilder, DiagnosticId}; +use rustc_errors::DiagnosticBuilder; use rustc_session::Session; pub trait StructuredDiagnostic<'tcx> { fn session(&self) -> &Session; - fn code(&self) -> DiagnosticId; + fn code(&self) -> String; fn diagnostic(&self) -> DiagnosticBuilder<'tcx> { let err = self.diagnostic_common(); diff --git a/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs b/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs index 634904e32715..6f4435db4114 100644 --- a/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs +++ b/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs @@ -1,5 +1,5 @@ use crate::{errors, structured_errors::StructuredDiagnostic}; -use rustc_errors::{DiagnosticBuilder, DiagnosticId}; +use rustc_errors::DiagnosticBuilder; use rustc_middle::ty::{Ty, TypeVisitableExt}; use rustc_session::Session; use rustc_span::Span; @@ -16,7 +16,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for MissingCastForVariadicArg<'tcx, '_> { self.sess } - fn code(&self) -> DiagnosticId { + fn code(&self) -> String { rustc_errors::error_code!(E0617) } diff --git a/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs b/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs index c68d74969a54..19cac4a38aaa 100644 --- a/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs +++ b/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs @@ -1,5 +1,5 @@ use crate::{errors, structured_errors::StructuredDiagnostic}; -use rustc_errors::{DiagnosticBuilder, DiagnosticId}; +use rustc_errors::DiagnosticBuilder; use rustc_middle::ty::{Ty, TypeVisitableExt}; use rustc_session::Session; use rustc_span::Span; @@ -16,7 +16,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for SizedUnsizedCast<'tcx> { self.sess } - fn code(&self) -> DiagnosticId { + fn code(&self) -> String { rustc_errors::error_code!(E0607) } diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs index 6657e3fd872f..ba81e7f1f816 100644 --- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs +++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs @@ -1,7 +1,5 @@ use crate::structured_errors::StructuredDiagnostic; -use rustc_errors::{ - pluralize, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId, MultiSpan, -}; +use rustc_errors::{pluralize, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan}; use rustc_hir as hir; use rustc_middle::ty::{self as ty, AssocItems, AssocKind, TyCtxt}; use rustc_session::Session; @@ -1107,7 +1105,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for WrongNumberOfGenericArgs<'_, 'tcx> { self.tcx.sess } - fn code(&self) -> DiagnosticId { + fn code(&self) -> String { rustc_errors::error_code!(E0107) } diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index 410706110c96..7d145ea1f23a 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -3,6 +3,7 @@ //! //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/variance.html +use itertools::Itertools; use rustc_arena::DroplessArena; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -91,7 +92,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc fn visit_opaque(&mut self, def_id: DefId, args: GenericArgsRef<'tcx>) -> ControlFlow { if def_id != self.root_def_id && self.tcx.is_descendant_of(def_id, self.root_def_id) { let child_variances = self.tcx.variances_of(def_id); - for (a, v) in args.iter().zip(child_variances) { + for (a, v) in args.iter().zip_eq(child_variances) { if *v != ty::Bivariant { a.visit_with(self)?; } diff --git a/compiler/rustc_hir_analysis/src/variance/test.rs b/compiler/rustc_hir_analysis/src/variance/test.rs index 5264d5aa26f2..c211e1af046a 100644 --- a/compiler/rustc_hir_analysis/src/variance/test.rs +++ b/compiler/rustc_hir_analysis/src/variance/test.rs @@ -2,19 +2,21 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::CRATE_DEF_ID; use rustc_middle::ty::TyCtxt; use rustc_span::symbol::sym; +use rustc_span::ErrorGuaranteed; use crate::errors; -pub fn test_variance(tcx: TyCtxt<'_>) { +pub fn test_variance(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { + let mut res = Ok(()); if tcx.has_attr(CRATE_DEF_ID, sym::rustc_variance_of_opaques) { for id in tcx.hir().items() { if matches!(tcx.def_kind(id.owner_id), DefKind::OpaqueTy) { let variances_of = tcx.variances_of(id.owner_id); - tcx.dcx().emit_err(errors::VariancesOf { + res = Err(tcx.dcx().emit_err(errors::VariancesOf { span: tcx.def_span(id.owner_id), variances_of: format!("{variances_of:?}"), - }); + })); } } } @@ -25,10 +27,11 @@ pub fn test_variance(tcx: TyCtxt<'_>) { if tcx.has_attr(id.owner_id, sym::rustc_variance) { let variances_of = tcx.variances_of(id.owner_id); - tcx.dcx().emit_err(errors::VariancesOf { + res = Err(tcx.dcx().emit_err(errors::VariancesOf { span: tcx.def_span(id.owner_id), variances_of: format!("{variances_of:?}"), - }); + })); } } + res } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index d36e0892d19d..e76303bc6dfa 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1838,6 +1838,11 @@ impl<'a> State<'a> { self.commasep(Inconsistent, after, |s, p| s.print_pat(p)); self.word("]"); } + PatKind::Err(_) => { + self.popen(); + self.word("/*ERROR*/"); + self.pclose(); + } } self.ann.post(self, AnnNode::Pat(pat)) } diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml index b0c60304424a..975f93756427 100644 --- a/compiler/rustc_hir_typeck/Cargo.toml +++ b/compiler/rustc_hir_typeck/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start +itertools = "0.11" rustc_ast = { path = "../rustc_ast" } rustc_attr = { path = "../rustc_attr" } rustc_data_structures = { path = "../rustc_data_structures" } diff --git a/compiler/rustc_hir_typeck/src/autoderef.rs b/compiler/rustc_hir_typeck/src/autoderef.rs index 7873257c4e3d..2bb7caea3c43 100644 --- a/compiler/rustc_hir_typeck/src/autoderef.rs +++ b/compiler/rustc_hir_typeck/src/autoderef.rs @@ -2,6 +2,7 @@ use super::method::MethodCallee; use super::{FnCtxt, PlaceOp}; +use itertools::Itertools; use rustc_hir_analysis::autoderef::{Autoderef, AutoderefKind}; use rustc_infer::infer::InferOk; use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref}; @@ -32,8 +33,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, autoderef: &Autoderef<'a, 'tcx>, ) -> InferOk<'tcx, Vec>> { - let mut obligations = vec![]; let steps = autoderef.steps(); + if steps.is_empty() { + return InferOk { obligations: vec![], value: vec![] }; + } + + let mut obligations = vec![]; let targets = steps.iter().skip(1).map(|&(ty, _)| ty).chain(iter::once(autoderef.final_ty(false))); let steps: Vec<_> = steps @@ -54,7 +59,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None } }) - .zip(targets) + .zip_eq(targets) .map(|(autoderef, target)| Adjustment { kind: Adjust::Deref(autoderef), target }) .collect(); diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 1a4e03d50cae..d486f069989e 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -293,49 +293,59 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { callee_node: &hir::ExprKind<'_>, callee_span: Span, ) { + let hir::ExprKind::Block(..) = callee_node else { + // Only calls on blocks suggested here. + return; + }; + let hir = self.tcx.hir(); - let parent_hir_id = hir.parent_id(hir_id); - let parent_node = self.tcx.hir_node(parent_hir_id); - if let ( - hir::Node::Expr(hir::Expr { - kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, kind, .. }), + let fn_decl_span = if let hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }), + .. + }) = hir.get_parent(hir_id) + { + fn_decl_span + } else if let Some(( + _, + hir::Node::Expr(&hir::Expr { + hir_id: parent_hir_id, + kind: + hir::ExprKind::Closure(&hir::Closure { + kind: + hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Async, + hir::CoroutineSource::Closure, + )), + .. + }), .. }), - hir::ExprKind::Block(..), - ) = (parent_node, callee_node) + )) = hir.parent_iter(hir_id).nth(3) { - let fn_decl_span = if matches!( - kind, - hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( - hir::CoroutineDesugaring::Async, - hir::CoroutineSource::Closure - ),) - ) { - // Actually need to unwrap one more layer of HIR to get to - // the _real_ closure... - let async_closure = hir.parent_id(parent_hir_id); - if let hir::Node::Expr(hir::Expr { - kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }), - .. - }) = self.tcx.hir_node(async_closure) - { - fn_decl_span - } else { - return; - } - } else { + // Actually need to unwrap one more layer of HIR to get to + // the _real_ closure... + let async_closure = hir.parent_id(parent_hir_id); + if let hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }), + .. + }) = self.tcx.hir_node(async_closure) + { fn_decl_span - }; + } else { + return; + } + } else { + return; + }; - let start = fn_decl_span.shrink_to_lo(); - let end = callee_span.shrink_to_hi(); - err.multipart_suggestion( - "if you meant to create this closure and immediately call it, surround the \ + let start = fn_decl_span.shrink_to_lo(); + let end = callee_span.shrink_to_hi(); + err.multipart_suggestion( + "if you meant to create this closure and immediately call it, surround the \ closure with parentheses", - vec![(start, "(".to_string()), (end, ")".to_string())], - Applicability::MaybeIncorrect, - ); - } + vec![(start, "(".to_string()), (end, ")".to_string())], + Applicability::MaybeIncorrect, + ); } /// Give appropriate suggestion when encountering `[("a", 0) ("b", 1)]`, where the diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index b6b332993151..f51cc97b45de 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -14,7 +14,7 @@ use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt}; use rustc_middle::ty::GenericArgs; use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor}; use rustc_span::def_id::LocalDefId; -use rustc_span::{sym, Span}; +use rustc_span::Span; use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits; use rustc_trait_selection::traits::error_reporting::ArgKind; @@ -49,7 +49,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr_span: Span, expected: Expectation<'tcx>, ) -> Ty<'tcx> { - trace!("decl = {:#?}", closure.fn_decl); + let tcx = self.tcx; + let body = tcx.hir().body(closure.body); + let expr_def_id = closure.def_id; // It's always helpful for inference if we know the kind of // closure sooner rather than later, so first examine the expected @@ -61,35 +63,63 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None => (None, None), }; - self.check_closure(closure, expr_span, expected_kind, expected_sig) - } - - #[instrument(skip(self, closure), level = "debug", ret)] - fn check_closure( - &self, - closure: &hir::Closure<'tcx>, - expr_span: Span, - opt_kind: Option, - expected_sig: Option>, - ) -> Ty<'tcx> { - let tcx = self.tcx; - let body = tcx.hir().body(closure.body); - - trace!("decl = {:#?}", closure.fn_decl); - let expr_def_id = closure.def_id; - debug!(?expr_def_id); - let ClosureSignatures { bound_sig, liberated_sig } = self.sig_of_closure(expr_def_id, closure.fn_decl, closure.kind, expected_sig); debug!(?bound_sig, ?liberated_sig); + let parent_args = + GenericArgs::identity_for_item(tcx, tcx.typeck_root_def_id(expr_def_id.to_def_id())); + + let tupled_upvars_ty = self.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::ClosureSynthetic, + span: expr_span, + }); + // FIXME: We could probably actually just unify this further -- // instead of having a `FnSig` and a `Option`, // we can have a `ClosureSignature { Coroutine { .. }, Closure { .. } }`, // similar to how `ty::GenSig` is a distinct data structure. - let coroutine_types = match closure.kind { - hir::ClosureKind::Closure => None, + let (closure_ty, coroutine_types) = match closure.kind { + hir::ClosureKind::Closure => { + // Tuple up the arguments and insert the resulting function type into + // the `closures` table. + let sig = bound_sig.map_bound(|sig| { + tcx.mk_fn_sig( + [Ty::new_tup(tcx, sig.inputs())], + sig.output(), + sig.c_variadic, + sig.unsafety, + sig.abi, + ) + }); + + debug!(?sig, ?expected_kind); + + let closure_kind_ty = match expected_kind { + Some(kind) => Ty::from_closure_kind(tcx, kind), + + // Create a type variable (for now) to represent the closure kind. + // It will be unified during the upvar inference phase (`upvar.rs`) + None => self.next_ty_var(TypeVariableOrigin { + // FIXME(eddyb) distinguish closure kind inference variables from the rest. + kind: TypeVariableOriginKind::ClosureSynthetic, + span: expr_span, + }), + }; + + let closure_args = ty::ClosureArgs::new( + tcx, + ty::ClosureArgsParts { + parent_args, + closure_kind_ty, + closure_sig_as_fn_ptr_ty: Ty::new_fn_ptr(tcx, sig), + tupled_upvars_ty, + }, + ); + + (Ty::new_closure(tcx, expr_def_id.to_def_id(), closure_args.args), None) + } hir::ClosureKind::Coroutine(kind) => { let yield_ty = match kind { hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _) @@ -135,80 +165,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Resume type defaults to `()` if the coroutine has no argument. let resume_ty = liberated_sig.inputs().get(0).copied().unwrap_or(tcx.types.unit); - Some(CoroutineTypes { resume_ty, yield_ty }) - } - }; - - let mut fcx = FnCtxt::new(self, self.param_env, closure.def_id); - check_fn( - &mut fcx, - liberated_sig, - coroutine_types, - closure.fn_decl, - expr_def_id, - body, - // Closure "rust-call" ABI doesn't support unsized params - false, - ); - - let parent_args = - GenericArgs::identity_for_item(tcx, tcx.typeck_root_def_id(expr_def_id.to_def_id())); - - let tupled_upvars_ty = self.next_root_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::ClosureSynthetic, - span: expr_span, - }); - - match closure.kind { - hir::ClosureKind::Closure => { - assert_eq!(coroutine_types, None); - // Tuple up the arguments and insert the resulting function type into - // the `closures` table. - let sig = bound_sig.map_bound(|sig| { - tcx.mk_fn_sig( - [Ty::new_tup(tcx, sig.inputs())], - sig.output(), - sig.c_variadic, - sig.unsafety, - sig.abi, - ) - }); - - debug!(?sig, ?opt_kind); - - let closure_kind_ty = match opt_kind { - Some(kind) => Ty::from_closure_kind(tcx, kind), - - // Create a type variable (for now) to represent the closure kind. - // It will be unified during the upvar inference phase (`upvar.rs`) - None => self.next_root_ty_var(TypeVariableOrigin { - // FIXME(eddyb) distinguish closure kind inference variables from the rest. - kind: TypeVariableOriginKind::ClosureSynthetic, - span: expr_span, - }), - }; - - let closure_args = ty::ClosureArgs::new( - tcx, - ty::ClosureArgsParts { - parent_args, - closure_kind_ty, - closure_sig_as_fn_ptr_ty: Ty::new_fn_ptr(tcx, sig), - tupled_upvars_ty, - }, - ); - - Ty::new_closure(tcx, expr_def_id.to_def_id(), closure_args.args) - } - hir::ClosureKind::Coroutine(_) => { - let Some(CoroutineTypes { resume_ty, yield_ty }) = coroutine_types else { - bug!("expected coroutine to have yield/resume types"); - }; - let interior = fcx.next_ty_var(TypeVariableOrigin { + let interior = self.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::MiscVariable, span: body.value.span, }); - fcx.deferred_coroutine_interiors.borrow_mut().push(( + self.deferred_coroutine_interiors.borrow_mut().push(( expr_def_id, body.id(), interior, @@ -226,9 +187,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }, ); - Ty::new_coroutine(tcx, expr_def_id.to_def_id(), coroutine_args.args) + ( + Ty::new_coroutine(tcx, expr_def_id.to_def_id(), coroutine_args.args), + Some(CoroutineTypes { resume_ty, yield_ty }), + ) } - } + }; + + check_fn( + &mut FnCtxt::new(self, self.param_env, closure.def_id), + liberated_sig, + coroutine_types, + closure.fn_decl, + expr_def_id, + body, + // Closure "rust-call" ABI doesn't support unsized params + false, + ); + + closure_ty } /// Given the expected type, figures out what it can about this closure we @@ -364,36 +341,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let tcx = self.tcx; let trait_def_id = projection.trait_def_id(tcx); - - let is_fn = tcx.is_fn_trait(trait_def_id); - - let coroutine_trait = tcx.lang_items().coroutine_trait(); - let is_gen = coroutine_trait == Some(trait_def_id); - - if !is_fn && !is_gen { - debug!("not fn or coroutine"); + // For now, we only do signature deduction based off of the `Fn` traits. + if !tcx.is_fn_trait(trait_def_id) { return None; } - // Check that we deduce the signature from the `<_ as std::ops::Coroutine>::Return` - // associated item and not yield. - if is_gen && self.tcx.associated_item(projection.projection_def_id()).name != sym::Return { - debug!("not `Return` assoc item of `Coroutine`"); - return None; - } + let arg_param_ty = projection.skip_binder().projection_ty.args.type_at(1); + let arg_param_ty = self.resolve_vars_if_possible(arg_param_ty); + debug!(?arg_param_ty); - let input_tys = if is_fn { - let arg_param_ty = projection.skip_binder().projection_ty.args.type_at(1); - let arg_param_ty = self.resolve_vars_if_possible(arg_param_ty); - debug!(?arg_param_ty); - - match arg_param_ty.kind() { - &ty::Tuple(tys) => tys, - _ => return None, - } - } else { - // Coroutines with a `()` resume type may be defined with 0 or 1 explicit arguments, - // else they must have exactly 1 argument. For now though, just give up in this case. + let ty::Tuple(input_tys) = *arg_param_ty.kind() else { return None; }; @@ -416,7 +373,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn sig_of_closure( &self, expr_def_id: LocalDefId, - decl: &hir::FnDecl<'_>, + decl: &hir::FnDecl<'tcx>, closure_kind: hir::ClosureKind, expected_sig: Option>, ) -> ClosureSignatures<'tcx> { @@ -433,7 +390,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn sig_of_closure_no_expectation( &self, expr_def_id: LocalDefId, - decl: &hir::FnDecl<'_>, + decl: &hir::FnDecl<'tcx>, closure_kind: hir::ClosureKind, ) -> ClosureSignatures<'tcx> { let bound_sig = self.supplied_sig_of_closure(expr_def_id, decl, closure_kind); @@ -492,7 +449,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn sig_of_closure_with_expectation( &self, expr_def_id: LocalDefId, - decl: &hir::FnDecl<'_>, + decl: &hir::FnDecl<'tcx>, closure_kind: hir::ClosureKind, expected_sig: ExpectedSig<'tcx>, ) -> ClosureSignatures<'tcx> { @@ -549,7 +506,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn sig_of_closure_with_mismatched_number_of_arguments( &self, expr_def_id: LocalDefId, - decl: &hir::FnDecl<'_>, + decl: &hir::FnDecl<'tcx>, expected_sig: ExpectedSig<'tcx>, ) -> ClosureSignatures<'tcx> { let expr_map_node = self.tcx.hir_node_by_def_id(expr_def_id); @@ -590,7 +547,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn merge_supplied_sig_with_expectation( &self, expr_def_id: LocalDefId, - decl: &hir::FnDecl<'_>, + decl: &hir::FnDecl<'tcx>, closure_kind: hir::ClosureKind, mut expected_sigs: ClosureSignatures<'tcx>, ) -> InferResult<'tcx, ClosureSignatures<'tcx>> { @@ -684,7 +641,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn supplied_sig_of_closure( &self, expr_def_id: LocalDefId, - decl: &hir::FnDecl<'_>, + decl: &hir::FnDecl<'tcx>, closure_kind: hir::ClosureKind, ) -> ty::PolyFnSig<'tcx> { let astconv: &dyn AstConv<'_> = self; @@ -720,10 +677,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }) } // All `gen {}` and `async gen {}` must return unit. - hir::ClosureKind::Coroutine( - hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _) - | hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _), - ) => self.tcx.types.unit, + hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Gen | hir::CoroutineDesugaring::AsyncGen, + _, + )) => self.tcx.types.unit, // For async blocks, we just fall back to `_` here. // For closures/coroutines, we know nothing about the return @@ -797,16 +754,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { get_future_output(obligation.predicate, obligation.cause.span) })? } + ty::Alias(ty::Projection, _) => { + return Some(Ty::new_error_with_message( + self.tcx, + closure_span, + "this projection should have been projected to an opaque type", + )); + } ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => self .tcx .explicit_item_bounds(def_id) .iter_instantiated_copied(self.tcx, args) .find_map(|(p, s)| get_future_output(p.as_predicate(), s))?, ty::Error(_) => return Some(ret_ty), - _ => span_bug!( - closure_span, - "async fn coroutine return type not an inference variable: {ret_ty}" - ), + _ => { + span_bug!(closure_span, "invalid async fn coroutine return type: {ret_ty:?}") + } }; let output_ty = self.normalize(closure_span, output_ty); @@ -880,7 +843,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// all parameters are of type `ty::Error`. fn error_sig_of_closure( &self, - decl: &hir::FnDecl<'_>, + decl: &hir::FnDecl<'tcx>, guar: ErrorGuaranteed, ) -> ty::PolyFnSig<'tcx> { let astconv: &dyn AstConv<'_> = self; diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index af47455c16df..aca17ec77a4b 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -26,7 +26,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{ pluralize, struct_span_code_err, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, - DiagnosticId, ErrorGuaranteed, StashKey, + ErrorGuaranteed, StashKey, }; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; @@ -941,7 +941,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let mut err = self.dcx().struct_span_err(op_span, "invalid left-hand side of assignment"); - err.code(DiagnosticId::Error(err_code.into())); + err.code(err_code.into()); err.span_label(lhs.span, "cannot assign to this expression"); self.comes_from_while_condition(lhs.hir_id, |expr| { @@ -1315,7 +1315,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_method_call( &self, expr: &'tcx hir::Expr<'tcx>, - segment: &hir::PathSegment<'_>, + segment: &'tcx hir::PathSegment<'tcx>, rcvr: &'tcx hir::Expr<'tcx>, args: &'tcx [hir::Expr<'tcx>], expected: Expectation<'tcx>, @@ -1526,13 +1526,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.check_repeat_element_needs_copy_bound(element, count, element_ty); - self.register_wf_obligation( - Ty::new_array_with_const_len(tcx, t, count).into(), - expr.span, - traits::WellFormed(None), - ); + let ty = Ty::new_array_with_const_len(tcx, t, count); - Ty::new_array_with_const_len(tcx, t, count) + self.register_wf_obligation(ty.into(), expr.span, traits::WellFormed(None)); + + ty } fn check_repeat_element_needs_copy_bound( @@ -1629,7 +1627,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, expr: &hir::Expr<'_>, expected: Expectation<'tcx>, - qpath: &QPath<'_>, + qpath: &QPath<'tcx>, fields: &'tcx [hir::ExprField<'tcx>], base_expr: &'tcx Option<&'tcx hir::Expr<'tcx>>, ) -> Ty<'tcx> { @@ -2104,7 +2102,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut items = self .tcx .inherent_impls(def_id) - .iter() + .into_iter() + .flatten() .flat_map(|i| self.tcx.associated_items(i).in_definition_order()) // Only assoc fn with no receivers. .filter(|item| { @@ -3247,6 +3246,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Ty<'tcx> { let container = self.to_ty(container).normalized; + if let Some(ident_2) = fields.get(1) + && !self.tcx.features().offset_of_nested + { + rustc_session::parse::feature_err( + &self.tcx.sess, + sym::offset_of_nested, + ident_2.span, + "only a single ident or integer is stable as the field in offset_of", + ) + .emit(); + } + let mut field_indices = Vec::with_capacity(fields.len()); let mut current_container = container; let mut fields = fields.into_iter(); diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index ed3dd1e39dfc..3ecf6c5e428b 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -458,11 +458,15 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { needs_to_be_read = true; } } - PatKind::Or(_) | PatKind::Box(_) | PatKind::Ref(..) | PatKind::Wild => { + PatKind::Or(_) + | PatKind::Box(_) + | PatKind::Ref(..) + | PatKind::Wild + | PatKind::Err(_) => { // If the PatKind is Or, Box, or Ref, the decision is made later // as these patterns contains subpatterns - // If the PatKind is Wild, the decision is made based on the other patterns being - // examined + // If the PatKind is Wild or Err, the decision is made based on the other patterns + // being examined } } })? diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index a4cd9ccc984e..3ea409827b4b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -377,13 +377,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { RawTy { raw: ty, normalized: self.normalize(span, ty) } } - pub fn to_ty(&self, ast_t: &hir::Ty<'_>) -> RawTy<'tcx> { + pub fn to_ty(&self, ast_t: &hir::Ty<'tcx>) -> RawTy<'tcx> { let t = self.astconv().ast_ty_to_ty(ast_t); self.register_wf_obligation(t.into(), ast_t.span, traits::WellFormed(None)); self.handle_raw_ty(ast_t.span, t) } - pub fn to_ty_saving_user_provided_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> { + pub fn to_ty_saving_user_provided_ty(&self, ast_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { let ty = self.to_ty(ast_ty); debug!("to_ty_saving_user_provided_ty: ty={:?}", ty); @@ -1073,7 +1073,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { #[instrument(skip(self, span), level = "debug")] pub fn instantiate_value_path( &self, - segments: &[hir::PathSegment<'_>], + segments: &'tcx [hir::PathSegment<'tcx>], self_ty: Option>, res: Res, span: Span, @@ -1260,13 +1260,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, path_segs: &'a [PathSeg], infer_args_for_err: &'a FxHashSet, - segments: &'a [hir::PathSegment<'a>], + segments: &'tcx [hir::PathSegment<'tcx>], } impl<'tcx, 'a> CreateSubstsForGenericArgsCtxt<'a, 'tcx> for CreateCtorSubstsContext<'a, 'tcx> { fn args_for_def_id( &mut self, def_id: DefId, - ) -> (Option<&'a hir::GenericArgs<'a>>, bool) { + ) -> (Option<&'a hir::GenericArgs<'tcx>>, bool) { if let Some(&PathSeg(_, index)) = self.path_segs.iter().find(|&PathSeg(did, _)| *did == def_id) { @@ -1287,7 +1287,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn provided_kind( &mut self, param: &ty::GenericParamDef, - arg: &GenericArg<'_>, + arg: &GenericArg<'tcx>, ) -> ty::GenericArg<'tcx> { match (¶m.kind, arg) { (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index 76360239c454..1ad79cb78c4b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -86,7 +86,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Finally, for ambiguity-related errors, we actually want to look // for a parameter that is the source of the inference type left // over in this predicate. - if let traits::FulfillmentErrorCode::CodeAmbiguity { .. } = error.code { + if let traits::FulfillmentErrorCode::Ambiguity { .. } = error.code { fallback_param_to_point_at = None; self_param_to_point_at = None; param_to_point_at = @@ -361,10 +361,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { error: &traits::FulfillmentError<'tcx>, span: Span, ) -> bool { - if let traits::FulfillmentErrorCode::CodeSelectionError( - traits::SelectionError::OutputTypeParameterMismatch( - box traits::SelectionOutputTypeParameterMismatch { expected_trait_ref, .. }, - ), + if let traits::FulfillmentErrorCode::SelectionError( + traits::SelectionError::SignatureMismatch(box traits::SignatureMismatchData { + expected_trait_ref, + .. + }), ) = error.code && let ty::Closure(def_id, _) | ty::Coroutine(def_id, ..) = expected_trait_ref.skip_binder().self_ty().kind() diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 8cd5ed3494b1..ddb4224b60db 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -9,11 +9,10 @@ use crate::{ struct_span_code_err, BreakableCtxt, Diverges, Expectation, FnCtxt, Needs, RawTy, TupleArgumentsFlag, }; +use itertools::Itertools; use rustc_ast as ast; use rustc_data_structures::fx::FxIndexSet; -use rustc_errors::{ - pluralize, Applicability, Diagnostic, DiagnosticId, ErrorGuaranteed, MultiSpan, StashKey, -}; +use rustc_errors::{pluralize, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan, StashKey}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; @@ -421,7 +420,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { formal_input_tys .iter() .copied() - .zip(expected_input_tys.iter().copied()) + .zip_eq(expected_input_tys.iter().copied()) .map(|vars| self.resolve_vars_if_possible(vars)), ); @@ -678,7 +677,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pluralize!("was", provided_args.len()) ), ); - err.code(DiagnosticId::Error(err_code.to_owned())); + err.code(err_code.to_owned()); err.multipart_suggestion_verbose( "wrap these arguments in parentheses to construct a tuple", vec![ @@ -828,7 +827,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pluralize!("was", provided_args.len()) ), ) - .with_code(DiagnosticId::Error(err_code.to_owned())) + .with_code(err_code.to_owned()) }; // As we encounter issues, keep track of what we want to provide for the suggestion @@ -1328,7 +1327,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn check_struct_path( &self, - qpath: &QPath<'_>, + qpath: &QPath<'tcx>, hir_id: hir::HirId, ) -> Result<(&'tcx ty::VariantDef, Ty<'tcx>), ErrorGuaranteed> { let path_span = qpath.span(); @@ -1784,7 +1783,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // The newly resolved definition is written into `type_dependent_defs`. fn finish_resolving_struct_path( &self, - qpath: &QPath<'_>, + qpath: &QPath<'tcx>, path_span: Span, hir_id: hir::HirId, ) -> (Res, RawTy<'tcx>) { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index fde3d41faecf..e6c2091d85ad 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -190,10 +190,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn errors_reported_since_creation(&self) -> bool { self.dcx().err_count() > self.err_count_on_creation } - - pub fn next_root_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> { - Ty::new_var(self.tcx, self.next_ty_var_id_in_universe(origin, ty::UniverseIndex::ROOT)) - } } impl<'a, 'tcx> Deref for FnCtxt<'a, 'tcx> { @@ -287,7 +283,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { &self, span: Span, item_def_id: DefId, - item_segment: &hir::PathSegment<'_>, + item_segment: &hir::PathSegment<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Ty<'tcx> { let trait_ref = self.instantiate_binder_with_fresh_vars( diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index b542132d71ce..2778ada655e3 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -784,7 +784,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(in super::super) fn suggest_missing_return_type( &self, err: &mut Diagnostic, - fn_decl: &hir::FnDecl<'_>, + fn_decl: &hir::FnDecl<'tcx>, expected: Ty<'tcx>, found: Ty<'tcx>, can_suggest: bool, @@ -995,7 +995,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, err: &mut Diagnostic, expr: &'tcx hir::Expr<'tcx>, - fn_decl: &hir::FnDecl<'_>, + fn_decl: &hir::FnDecl<'tcx>, expected: Ty<'tcx>, found: Ty<'tcx>, id: hir::HirId, @@ -1468,7 +1468,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(crate) fn suggest_associated_const( &self, err: &mut Diagnostic, - expr: &hir::Expr<'_>, + expr: &hir::Expr<'tcx>, expected_ty: Ty<'tcx>, ) -> bool { let Some((DefKind::AssocFn, old_def_id)) = @@ -1623,7 +1623,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } else { if let Some(errors) = - self.could_impl_trait(clone_trait_did, expected_ty, self.param_env) + self.type_implements_trait_shallow(clone_trait_did, expected_ty, self.param_env) { match &errors[..] { [] => {} @@ -1648,7 +1648,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } for error in errors { - if let traits::FulfillmentErrorCode::CodeSelectionError( + if let traits::FulfillmentErrorCode::SelectionError( traits::SelectionError::Unimplemented, ) = error.code && let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) = diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 36dd06d944c4..80467ca9381e 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -52,7 +52,7 @@ use crate::expectation::Expectation; use crate::fn_ctxt::RawTy; use crate::gather_locals::GatherLocalsVisitor; use rustc_data_structures::unord::UnordSet; -use rustc_errors::{struct_span_code_err, DiagnosticId, ErrorGuaranteed}; +use rustc_errors::{struct_span_code_err, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::Visitor; @@ -60,6 +60,7 @@ use rustc_hir::{HirIdMap, Node}; use rustc_hir_analysis::astconv::AstConv; use rustc_hir_analysis::check::check_abi; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc_infer::traits::ObligationInspector; use rustc_middle::query::Providers; use rustc_middle::traits; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -139,7 +140,7 @@ fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &UnordSet(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> { let fallback = move || tcx.type_of(def_id.to_def_id()).instantiate_identity(); - typeck_with_fallback(tcx, def_id, fallback) + typeck_with_fallback(tcx, def_id, fallback, None) } /// Used only to get `TypeckResults` for type inference during error recovery. @@ -149,14 +150,28 @@ fn diagnostic_only_typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::T let span = tcx.hir().span(tcx.local_def_id_to_hir_id(def_id)); Ty::new_error_with_message(tcx, span, "diagnostic only typeck table used") }; - typeck_with_fallback(tcx, def_id, fallback) + typeck_with_fallback(tcx, def_id, fallback, None) } -#[instrument(level = "debug", skip(tcx, fallback), ret)] +/// Same as `typeck` but `inspect` is invoked on evaluation of each root obligation. +/// Inspecting obligations only works with the new trait solver. +/// This function is *only to be used* by external tools, it should not be +/// called from within rustc. Note, this is not a query, and thus is not cached. +pub fn inspect_typeck<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, + inspect: ObligationInspector<'tcx>, +) -> &'tcx ty::TypeckResults<'tcx> { + let fallback = move || tcx.type_of(def_id.to_def_id()).instantiate_identity(); + typeck_with_fallback(tcx, def_id, fallback, Some(inspect)) +} + +#[instrument(level = "debug", skip(tcx, fallback, inspector), ret)] fn typeck_with_fallback<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, fallback: impl Fn() -> Ty<'tcx> + 'tcx, + inspector: Option>, ) -> &'tcx ty::TypeckResults<'tcx> { // Closures' typeck results come from their outermost function, // as they are part of the same "inference environment". @@ -178,6 +193,9 @@ fn typeck_with_fallback<'tcx>( let param_env = tcx.param_env(def_id); let inh = Inherited::new(tcx, def_id); + if let Some(inspector) = inspector { + inh.infcx.attach_obligation_inspector(inspector); + } let mut fcx = FnCtxt::new(&inh, param_env, def_id); if let Some(hir::FnSig { header, decl, .. }) = fn_sig { @@ -369,7 +387,7 @@ fn report_unexpected_variant_res( let err = tcx .dcx() .struct_span_err(span, format!("expected {expected}, found {res_descr} `{path_str}`")) - .with_code(DiagnosticId::Error(err_code.into())); + .with_code(err_code.into()); match res { Res::Def(DefKind::Fn | DefKind::AssocFn, _) if err_code == "E0164" => { let patterns_url = "https://doc.rust-lang.org/book/ch18-00-patterns.html"; diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs index ce3a4b4c80ce..1ce0240f7b83 100644 --- a/compiler/rustc_hir_typeck/src/mem_categorization.rs +++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs @@ -767,7 +767,8 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { | PatKind::Lit(..) | PatKind::Range(..) | PatKind::Never - | PatKind::Wild => { + | PatKind::Wild + | PatKind::Err(_) => { // always ok } } diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index b2ead3cd40b7..6f18cc51b11c 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -50,7 +50,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { call_expr: &'tcx hir::Expr<'tcx>, unadjusted_self_ty: Ty<'tcx>, pick: &probe::Pick<'tcx>, - segment: &hir::PathSegment<'_>, + segment: &'tcx hir::PathSegment<'tcx>, ) -> ConfirmResult<'tcx> { debug!( "confirm(unadjusted_self_ty={:?}, pick={:?}, generic_args={:?})", @@ -68,7 +68,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { call_expr: &'tcx hir::Expr<'tcx>, unadjusted_self_ty: Ty<'tcx>, pick: &probe::Pick<'tcx>, - segment: &hir::PathSegment<'_>, + segment: &hir::PathSegment<'tcx>, ) -> ConfirmResult<'tcx> { let mut confirm_cx = ConfirmContext::new(self, span, self_expr, call_expr); confirm_cx.skip_record_for_diagnostics = true; @@ -90,7 +90,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { &mut self, unadjusted_self_ty: Ty<'tcx>, pick: &probe::Pick<'tcx>, - segment: &hir::PathSegment<'_>, + segment: &hir::PathSegment<'tcx>, ) -> ConfirmResult<'tcx> { // Adjust the self expression the user provided and obtain the adjusted type. let self_ty = self.adjust_self_ty(unadjusted_self_ty, pick); @@ -346,7 +346,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { fn instantiate_method_args( &mut self, pick: &probe::Pick<'tcx>, - seg: &hir::PathSegment<'_>, + seg: &hir::PathSegment<'tcx>, parent_args: GenericArgsRef<'tcx>, ) -> GenericArgsRef<'tcx> { // Determine the values for the generic parameters of the method. @@ -370,13 +370,13 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { struct MethodSubstsCtxt<'a, 'tcx> { cfcx: &'a ConfirmContext<'a, 'tcx>, pick: &'a probe::Pick<'tcx>, - seg: &'a hir::PathSegment<'a>, + seg: &'a hir::PathSegment<'tcx>, } impl<'a, 'tcx> CreateSubstsForGenericArgsCtxt<'a, 'tcx> for MethodSubstsCtxt<'a, 'tcx> { fn args_for_def_id( &mut self, def_id: DefId, - ) -> (Option<&'a hir::GenericArgs<'a>>, bool) { + ) -> (Option<&'a hir::GenericArgs<'tcx>>, bool) { if def_id == self.pick.item.def_id { if let Some(data) = self.seg.args { return (Some(data), false); @@ -388,7 +388,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { fn provided_kind( &mut self, param: &ty::GenericParamDef, - arg: &GenericArg<'_>, + arg: &GenericArg<'tcx>, ) -> ty::GenericArg<'tcx> { match (¶m.kind, arg) { (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => { diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index c746fb8af89a..af172b59a146 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -177,7 +177,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn lookup_method( &self, self_ty: Ty<'tcx>, - segment: &hir::PathSegment<'_>, + segment: &'tcx hir::PathSegment<'tcx>, span: Span, call_expr: &'tcx hir::Expr<'tcx>, self_expr: &'tcx hir::Expr<'tcx>, @@ -255,7 +255,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn lookup_method_for_diagnostic( &self, self_ty: Ty<'tcx>, - segment: &hir::PathSegment<'_>, + segment: &hir::PathSegment<'tcx>, span: Span, call_expr: &'tcx hir::Expr<'tcx>, self_expr: &'tcx hir::Expr<'tcx>, diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 10c31d8c641c..4dc802008d03 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -711,14 +711,14 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsCandidateKey) else { bug!("unexpected incoherent type: {:?}", self_ty) }; - for &impl_def_id in self.tcx.incoherent_impls(simp) { + for &impl_def_id in self.tcx.incoherent_impls(simp).into_iter().flatten() { self.assemble_inherent_impl_probe(impl_def_id); } } fn assemble_inherent_impl_candidates_for_type(&mut self, def_id: DefId) { - let impl_def_ids = self.tcx.at(self.span).inherent_impls(def_id); - for &impl_def_id in impl_def_ids.iter() { + let impl_def_ids = self.tcx.at(self.span).inherent_impls(def_id).into_iter().flatten(); + for &impl_def_id in impl_def_ids { self.assemble_inherent_impl_probe(impl_def_id); } } diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 1f01c6b7406b..0b8a25eedafa 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -359,7 +359,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let ty::Adt(adt_def, _) = ty.kind() { self.tcx .inherent_impls(adt_def.did()) - .iter() + .into_iter() + .flatten() .any(|def_id| self.associated_value(*def_id, item_name).is_some()) } else { false @@ -825,11 +826,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "auto trait is invoked with no method error, but no error reported?", ); } - Some(Node::Item(hir::Item { - ident, - kind: hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..), - .. - })) => { + Some( + Node::Item(hir::Item { + ident, + kind: hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..), + .. + }) + // We may also encounter unsatisfied GAT or method bounds + | Node::TraitItem(hir::TraitItem { ident, .. }) + | Node::ImplItem(hir::ImplItem { ident, .. }), + ) => { skip_list.insert(p); let entry = spanned_predicates.entry(ident.span); let entry = entry.or_insert_with(|| { @@ -840,7 +846,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { entry.1.insert((cause_span, "unsatisfied trait bound introduced here")); entry.2.push(p); } - Some(node) => unreachable!("encountered `{node:?}`"), + Some(node) => unreachable!("encountered `{node:?}` due to `{cause:#?}`"), None => (), } } @@ -1043,7 +1049,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut inherent_impls_candidate = self .tcx .inherent_impls(adt.did()) - .iter() + .into_iter() + .flatten() .copied() .filter(|def_id| { if let Some(assoc) = self.associated_value(*def_id, item_name) { @@ -1098,7 +1105,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "the {item_kind} was found for\n{type_candidates}{additional_types}" )); } else { - 'outer: for inherent_impl_did in self.tcx.inherent_impls(adt.did()) { + 'outer: for inherent_impl_did in + self.tcx.inherent_impls(adt.did()).into_iter().flatten() + { for inherent_method in self.tcx.associated_items(inherent_impl_did).in_definition_order() { @@ -1452,9 +1461,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty::Adt(adt_def, _) = rcvr_ty.kind() else { return; }; - let mut items = self - .tcx - .inherent_impls(adt_def.did()) + // FIXME(oli-obk): try out bubbling this error up one level and cancelling the other error in that case. + let Ok(impls) = self.tcx.inherent_impls(adt_def.did()) else { return }; + let mut items = impls .iter() .flat_map(|i| self.tcx.associated_items(i).in_definition_order()) // Only assoc fn with no receivers. @@ -1818,7 +1827,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { simplify_type(tcx, ty, TreatParams::AsCandidateKey) .and_then(|simp| { tcx.incoherent_impls(simp) - .iter() + .into_iter() + .flatten() .find_map(|&id| self.associated_value(id, item_name)) }) .is_some() diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 95813cb68a66..371068672770 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -177,9 +177,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { PatInfo { binding_mode: def_bm, top_info: ti, decl_origin: pat_info.decl_origin }; let ty = match pat.kind { - PatKind::Wild => expected, - // FIXME(never_patterns): check the type is uninhabited. If that is not possible within - // typeck, do that in a later phase. + PatKind::Wild | PatKind::Err(_) => expected, + // We allow any type here; we ensure that the type is uninhabited during match checking. PatKind::Never => expected, PatKind::Lit(lt) => self.check_pat_lit(pat.span, lt, expected, ti), PatKind::Range(lhs, rhs, _) => self.check_pat_range(pat.span, lhs, rhs, expected, ti), @@ -325,6 +324,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { PatKind::Ref(..) => AdjustMode::Reset, // A `_` pattern works with any expected type, so there's no need to do anything. PatKind::Wild + // A malformed pattern doesn't have an expected type, so let's just accept any type. + | PatKind::Err(_) // Bindings also work with whatever the expected type is, // and moreover if we peel references off, that will give us the wrong binding type. // Also, we can have a subpattern `binding @ pat`. @@ -754,7 +755,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | PatKind::Box(..) | PatKind::Ref(..) | PatKind::Lit(..) - | PatKind::Range(..) => break 'block None, + | PatKind::Range(..) + | PatKind::Err(_) => break 'block None, }, // Don't provide suggestions in other cases @@ -856,7 +858,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_pat_struct( &self, pat: &'tcx Pat<'tcx>, - qpath: &hir::QPath<'_>, + qpath: &hir::QPath<'tcx>, fields: &'tcx [hir::PatField<'tcx>], has_rest_pat: bool, expected: Ty<'tcx>, diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs index 7b8d91702b39..6f909a0cc9db 100644 --- a/compiler/rustc_incremental/src/assert_dep_graph.rs +++ b/compiler/rustc_incremental/src/assert_dep_graph.rs @@ -128,9 +128,11 @@ impl<'tcx> IfThisChanged<'tcx> { if attr.has_name(sym::rustc_if_this_changed) { let dep_node_interned = self.argument(attr); let dep_node = match dep_node_interned { - None => { - DepNode::from_def_path_hash(self.tcx, def_path_hash, dep_kinds::hir_owner) - } + None => DepNode::from_def_path_hash( + self.tcx, + def_path_hash, + dep_kinds::hir_owner_nodes, + ), Some(n) => { match DepNode::from_label_string(self.tcx, n.as_str(), def_path_hash) { Ok(n) => n, diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs index f6acc60190a8..842cc9fae9b4 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs @@ -57,8 +57,7 @@ const BASE_FN: &[&str] = &[ /// DepNodes for Hir, which is pretty much everything const BASE_HIR: &[&str] = &[ - // hir_owner and hir_owner_nodes should be computed for all nodes - label_strs::hir_owner, + // hir_owner_nodes should be computed for all nodes label_strs::hir_owner_nodes, ]; diff --git a/compiler/rustc_index_macros/src/lib.rs b/compiler/rustc_index_macros/src/lib.rs index ac374a41eb6f..72567b43a5f8 100644 --- a/compiler/rustc_index_macros/src/lib.rs +++ b/compiler/rustc_index_macros/src/lib.rs @@ -31,11 +31,17 @@ mod newtype; /// - `#[max = 0xFFFF_FFFD]`: specifies the max value, which allows niche /// optimizations. The default max value is 0xFFFF_FF00. /// - `#[gate_rustc_only]`: makes parts of the generated code nightly-only. +/// +/// `SpecOptionPartialEq` is specialized by this macro, so using it requires enabling +/// `#![feature(min_specialization)]` for the crate. #[proc_macro] #[cfg_attr( feature = "nightly", allow_internal_unstable(step_trait, rustc_attrs, trusted_step, spec_option_partial_eq) )] +// FIXME: Remove the above comment about `min_specialization` once bootstrap is bumped, +// and the corresponding one on SpecOptionPartialEq +#[cfg_attr(all(feature = "nightly", not(bootstrap)), allow_internal_unstable(min_specialization))] pub fn newtype_index(input: TokenStream) -> TokenStream { newtype::newtype(input) } diff --git a/compiler/rustc_index_macros/src/newtype.rs b/compiler/rustc_index_macros/src/newtype.rs index df1318c835e2..0b25628b9e19 100644 --- a/compiler/rustc_index_macros/src/newtype.rs +++ b/compiler/rustc_index_macros/src/newtype.rs @@ -104,7 +104,7 @@ impl Parse for Newtype { #gate_rustc_only impl ::rustc_serialize::Encodable for #name { fn encode(&self, e: &mut E) { - e.emit_u32(self.private); + e.emit_u32(self.as_u32()); } } } @@ -164,7 +164,7 @@ impl Parse for Newtype { #[inline] fn eq(l: &Option, r: &Option) -> bool { if #max_val < u32::MAX { - l.map(|i| i.private).unwrap_or(#max_val+1) == r.map(|i| i.private).unwrap_or(#max_val+1) + l.map(|i| i.as_u32()).unwrap_or(#max_val+1) == r.map(|i| i.as_u32()).unwrap_or(#max_val+1) } else { match (l, r) { (Some(l), Some(r)) => r == l, @@ -188,7 +188,7 @@ impl Parse for Newtype { #[cfg_attr(#gate_rustc_only_cfg, rustc_layout_scalar_valid_range_end(#max))] #[cfg_attr(#gate_rustc_only_cfg, rustc_pass_by_value)] #vis struct #name { - private: u32, + private_use_as_methods_instead: u32, } #(#consts)* @@ -238,7 +238,7 @@ impl Parse for Newtype { /// Prefer using `from_u32`. #[inline] #vis const unsafe fn from_u32_unchecked(value: u32) -> Self { - Self { private: value } + Self { private_use_as_methods_instead: value } } /// Extracts the value of this index as a `usize`. @@ -250,7 +250,7 @@ impl Parse for Newtype { /// Extracts the value of this index as a `u32`. #[inline] #vis const fn as_u32(self) -> u32 { - self.private + self.private_use_as_methods_instead } /// Extracts the value of this index as a `usize`. @@ -263,6 +263,7 @@ impl Parse for Newtype { impl std::ops::Add for #name { type Output = Self; + #[inline] fn add(self, other: usize) -> Self { Self::from_usize(self.index() + other) } diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index e60e3ffeaa72..0f1af81d9f04 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -90,6 +90,7 @@ impl<'tcx> InferCtxt<'tcx> { universe: self.universe.clone(), intercrate, next_trait_solver: self.next_trait_solver, + obligation_inspector: self.obligation_inspector.clone(), } } } diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 8cca4c6231fc..1f071a9ff0bc 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -483,7 +483,13 @@ impl<'tcx> InferCtxt<'tcx> { let result_subst = CanonicalVarValues { var_values: self.tcx.mk_args_from_iter( query_response.variables.iter().enumerate().map(|(index, info)| { - if info.is_existential() { + if info.universe() != ty::UniverseIndex::ROOT { + // A variable from inside a binder of the query. While ideally these shouldn't + // exist at all, we have to deal with them for now. + self.instantiate_canonical_var(cause.span, info, |u| { + universe_map[u.as_usize()] + }) + } else if info.is_existential() { match opt_values[BoundVar::new(index)] { Some(k) => k, None => self.instantiate_canonical_var(cause.span, info, |u| { @@ -491,9 +497,11 @@ impl<'tcx> InferCtxt<'tcx> { }), } } else { - self.instantiate_canonical_var(cause.span, info, |u| { - universe_map[u.as_usize()] - }) + // For placeholders which were already part of the input, we simply map this + // universal bound variable back the placeholder of the input. + opt_values[BoundVar::new(index)].expect( + "expected placeholder to be unified with itself during response", + ) } }), ), diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 4aefadf590dd..03c8e08aa01a 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -13,7 +13,9 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{Body, Closure, Expr, ExprKind, FnRetTy, HirId, Local, LocalSource}; use rustc_middle::hir::nested_filter; -use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; +use rustc_middle::infer::unify_key::{ + ConstVariableOrigin, ConstVariableOriginKind, ConstVariableValue, +}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow}; use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer}; use rustc_middle::ty::{self, InferConst}; @@ -41,8 +43,8 @@ pub enum TypeAnnotationNeeded { E0284, } -impl Into for TypeAnnotationNeeded { - fn into(self) -> rustc_errors::DiagnosticId { +impl Into for TypeAnnotationNeeded { + fn into(self) -> String { match self { Self::E0282 => rustc_errors::error_code!(E0282), Self::E0283 => rustc_errors::error_code!(E0283), @@ -178,17 +180,23 @@ fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinte } }; printer.ty_infer_name_resolver = Some(Box::new(ty_getter)); - let const_getter = move |ct_vid| { - if infcx.probe_const_var(ct_vid).is_ok() { + let const_getter = move |ct_vid| match infcx + .inner + .borrow_mut() + .const_unification_table() + .probe_value(ct_vid) + { + ConstVariableValue::Known { value: _ } => { warn!("resolved const var in error message"); - } - if let ConstVariableOriginKind::ConstParameterDefinition(name, _) = - infcx.inner.borrow_mut().const_unification_table().probe_value(ct_vid).origin.kind - { - return Some(name); - } else { None } + ConstVariableValue::Unknown { origin, universe: _ } => { + if let ConstVariableOriginKind::ConstParameterDefinition(name, _) = origin.kind { + return Some(name); + } else { + None + } + } }; printer.const_infer_name_resolver = Some(Box::new(const_getter)); printer @@ -303,7 +311,12 @@ impl<'tcx> InferCtxt<'tcx> { GenericArgKind::Const(ct) => { if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.kind() { let origin = - self.inner.borrow_mut().const_unification_table().probe_value(vid).origin; + match self.inner.borrow_mut().const_unification_table().probe_value(vid) { + ConstVariableValue::Known { value } => { + bug!("resolved infer var: {vid:?} {value}") + } + ConstVariableValue::Unknown { origin, universe: _ } => origin, + }; if let ConstVariableOriginKind::ConstParameterDefinition(name, def_id) = origin.kind { diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index c7cab048db1b..d256994d8d1f 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -146,14 +146,8 @@ impl<'a, 'tcx> TypeFolder> for TypeFreshener<'a, 'tcx> { fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { match ct.kind() { ty::ConstKind::Infer(ty::InferConst::Var(v)) => { - let opt_ct = self - .infcx - .inner - .borrow_mut() - .const_unification_table() - .probe_value(v) - .val - .known(); + let opt_ct = + self.infcx.inner.borrow_mut().const_unification_table().probe_value(v).known(); self.freshen_const(opt_ct, ty::InferConst::Var(v), ty::InferConst::Fresh, ct.ty()) } ty::ConstKind::Infer(ty::InferConst::EffectVar(v)) => { diff --git a/compiler/rustc_infer/src/infer/fudge.rs b/compiler/rustc_infer/src/infer/fudge.rs index 8ca97ae1b8e5..99033922bdf7 100644 --- a/compiler/rustc_infer/src/infer/fudge.rs +++ b/compiler/rustc_infer/src/infer/fudge.rs @@ -1,4 +1,4 @@ -use rustc_middle::infer::unify_key::ConstVidKey; +use rustc_middle::infer::unify_key::{ConstVariableOriginKind, ConstVariableValue, ConstVidKey}; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::{self, ConstVid, FloatVid, IntVid, RegionVid, Ty, TyCtxt, TyVid}; @@ -28,10 +28,17 @@ fn const_vars_since_snapshot<'tcx>( snapshot_var_len: usize, ) -> (Range, Vec) { let range = vars_since_snapshot(table, snapshot_var_len); + ( range.start.vid..range.end.vid, (range.start.index()..range.end.index()) - .map(|index| table.probe_value(ConstVid::from_u32(index)).origin) + .map(|index| match table.probe_value(ConstVid::from_u32(index)) { + ConstVariableValue::Known { value: _ } => ConstVariableOrigin { + kind: ConstVariableOriginKind::MiscVariable, + span: rustc_span::DUMMY_SP, + }, + ConstVariableValue::Unknown { origin, universe: _ } => origin, + }) .collect(), ) } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index e164041c5991..1eab8575fc0c 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -13,7 +13,9 @@ use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey}; use self::opaque_types::OpaqueTypeStorage; pub(crate) use self::undo_log::{InferCtxtUndoLogs, Snapshot, UndoLog}; -use crate::traits::{self, ObligationCause, PredicateObligations, TraitEngine, TraitEngineExt}; +use crate::traits::{ + self, ObligationCause, ObligationInspector, PredicateObligations, TraitEngine, TraitEngineExt, +}; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -23,8 +25,8 @@ use rustc_data_structures::unify as ut; use rustc_errors::{DiagCtxt, DiagnosticBuilder, ErrorGuaranteed}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues}; -use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue, EffectVarValue}; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType}; +use rustc_middle::infer::unify_key::{ConstVariableValue, EffectVarValue}; use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult}; use rustc_middle::mir::ConstraintCategory; use rustc_middle::traits::{select, DefiningAnchor}; @@ -334,6 +336,8 @@ pub struct InferCtxt<'tcx> { pub intercrate: bool, next_trait_solver: bool, + + pub obligation_inspector: Cell>>, } impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> { @@ -708,6 +712,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> { universe: Cell::new(ty::UniverseIndex::ROOT), intercrate, next_trait_solver, + obligation_inspector: Cell::new(None), } } } @@ -1086,7 +1091,7 @@ impl<'tcx> InferCtxt<'tcx> { .inner .borrow_mut() .const_unification_table() - .new_key(ConstVarValue { origin, val: ConstVariableValue::Unknown { universe } }) + .new_key(ConstVariableValue::Unknown { origin, universe }) .vid; ty::Const::new_var(self.tcx, vid, ty) } @@ -1095,10 +1100,7 @@ impl<'tcx> InferCtxt<'tcx> { self.inner .borrow_mut() .const_unification_table() - .new_key(ConstVarValue { - origin, - val: ConstVariableValue::Unknown { universe: self.universe() }, - }) + .new_key(ConstVariableValue::Unknown { origin, universe: self.universe() }) .vid } @@ -1217,10 +1219,7 @@ impl<'tcx> InferCtxt<'tcx> { .inner .borrow_mut() .const_unification_table() - .new_key(ConstVarValue { - origin, - val: ConstVariableValue::Unknown { universe: self.universe() }, - }) + .new_key(ConstVariableValue::Unknown { origin, universe: self.universe() }) .vid; ty::Const::new_var( self.tcx, @@ -1410,9 +1409,9 @@ impl<'tcx> InferCtxt<'tcx> { } pub fn probe_const_var(&self, vid: ty::ConstVid) -> Result, ty::UniverseIndex> { - match self.inner.borrow_mut().const_unification_table().probe_value(vid).val { + match self.inner.borrow_mut().const_unification_table().probe_value(vid) { ConstVariableValue::Known { value } => Ok(value), - ConstVariableValue::Unknown { universe } => Err(universe), + ConstVariableValue::Unknown { origin: _, universe } => Err(universe), } } @@ -1709,7 +1708,7 @@ impl<'tcx> InferCtxt<'tcx> { // `ty::ConstKind::Infer(ty::InferConst::Var(v))`. // // Not `inlined_probe_value(v)` because this call site is colder. - match self.inner.borrow_mut().const_unification_table().probe_value(v).val { + match self.inner.borrow_mut().const_unification_table().probe_value(v) { ConstVariableValue::Unknown { .. } => false, ConstVariableValue::Known { .. } => true, } @@ -1724,6 +1723,15 @@ impl<'tcx> InferCtxt<'tcx> { } } } + + /// Attach a callback to be invoked on each root obligation evaluated in the new trait solver. + pub fn attach_obligation_inspector(&self, inspector: ObligationInspector<'tcx>) { + debug_assert!( + self.obligation_inspector.get().is_none(), + "shouldn't override a set obligation inspector" + ); + self.obligation_inspector.set(Some(inspector)); + } } impl<'tcx> TypeErrCtxt<'_, 'tcx> { @@ -1876,7 +1884,6 @@ impl<'a, 'tcx> TypeFolder> for ShallowResolver<'a, 'tcx> { .borrow_mut() .const_unification_table() .probe_value(vid) - .val .known() .unwrap_or(ct), ty::ConstKind::Infer(InferConst::EffectVar(vid)) => self diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 11b5b437eff9..db46b39ce25f 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -631,13 +631,6 @@ impl<'tcx> InferCtxt<'tcx> { ct_op: |ct| ct, }); - if let ty::ClauseKind::Projection(projection) = predicate.kind().skip_binder() { - if projection.term.references_error() { - // No point on adding any obligations since there's a type error involved. - obligations.clear(); - return; - } - } // Require that the predicate holds for the concrete type. debug!(?predicate); obligations.push(traits::Obligation::new( diff --git a/compiler/rustc_infer/src/infer/relate/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs index 4b254fc7df51..9e1dab12b4d4 100644 --- a/compiler/rustc_infer/src/infer/relate/combine.rs +++ b/compiler/rustc_infer/src/infer/relate/combine.rs @@ -30,14 +30,12 @@ use super::sub::Sub; use crate::infer::{DefineOpaqueTypes, InferCtxt, TypeTrace}; use crate::traits::{Obligation, PredicateObligations}; use rustc_middle::infer::canonical::OriginalQueryValues; -use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue, EffectVarValue}; -use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; +use rustc_middle::infer::unify_key::{ConstVariableValue, EffectVarValue}; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::relate::{RelateResult, TypeRelation}; use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{AliasRelationDirection, TyVar}; use rustc_middle::ty::{IntType, UintType}; -use rustc_span::DUMMY_SP; #[derive(Clone)] pub struct CombineFields<'infcx, 'tcx> { @@ -328,8 +326,12 @@ impl<'tcx> InferCtxt<'tcx> { ct: ty::Const<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> RelateResult<'tcx, ty::Const<'tcx>> { - let span = - self.inner.borrow_mut().const_unification_table().probe_value(target_vid).origin.span; + let span = match self.inner.borrow_mut().const_unification_table().probe_value(target_vid) { + ConstVariableValue::Known { value } => { + bug!("instantiating a known const var: {target_vid:?} {value} {ct}") + } + ConstVariableValue::Unknown { origin, universe: _ } => origin.span, + }; // FIXME(generic_const_exprs): Occurs check failures for unevaluated // constants and generic expressions are not yet handled correctly. let Generalization { value_may_be_infer: value, needs_wf: _ } = generalize::generalize( @@ -340,16 +342,10 @@ impl<'tcx> InferCtxt<'tcx> { ty::Variance::Invariant, )?; - self.inner.borrow_mut().const_unification_table().union_value( - target_vid, - ConstVarValue { - origin: ConstVariableOrigin { - kind: ConstVariableOriginKind::ConstInference, - span: DUMMY_SP, - }, - val: ConstVariableValue::Known { value }, - }, - ); + self.inner + .borrow_mut() + .const_unification_table() + .union_value(target_vid, ConstVariableValue::Known { value }); Ok(value) } diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index 27d37fd93697..417c8695e248 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -3,7 +3,7 @@ use std::mem; use rustc_data_structures::sso::SsoHashMap; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::def_id::DefId; -use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue}; +use rustc_middle::infer::unify_key::ConstVariableValue; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::visit::MaxUniverse; @@ -431,22 +431,19 @@ where let mut inner = self.infcx.inner.borrow_mut(); let variable_table = &mut inner.const_unification_table(); - let var_value = variable_table.probe_value(vid); - match var_value.val { + match variable_table.probe_value(vid) { ConstVariableValue::Known { value: u } => { drop(inner); self.relate(u, u) } - ConstVariableValue::Unknown { universe } => { + ConstVariableValue::Unknown { origin, universe } => { if self.for_universe.can_name(universe) { Ok(c) } else { let new_var_id = variable_table - .new_key(ConstVarValue { - origin: var_value.origin, - val: ConstVariableValue::Unknown { - universe: self.for_universe, - }, + .new_key(ConstVariableValue::Unknown { + origin, + universe: self.for_universe, }) .vid; Ok(ty::Const::new_var(self.tcx(), new_var_id, c.ty())) diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index f317ccee6918..959b09031277 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -1,12 +1,8 @@ -use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use super::{FixupError, FixupResult, InferCtxt, Span}; -use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; +use super::{FixupError, FixupResult, InferCtxt}; use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFolder, TypeSuperFoldable}; -use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitableExt, TypeVisitor}; +use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{self, Const, InferConst, Ty, TyCtxt, TypeFoldable}; -use std::ops::ControlFlow; - /////////////////////////////////////////////////////////////////////////// // OPPORTUNISTIC VAR RESOLVER @@ -104,88 +100,6 @@ impl<'a, 'tcx> TypeFolder> for OpportunisticRegionResolver<'a, 'tcx } } -/////////////////////////////////////////////////////////////////////////// -// UNRESOLVED TYPE FINDER - -/// The unresolved type **finder** walks a type searching for -/// type variables that don't yet have a value. The first unresolved type is stored. -/// It does not construct the fully resolved type (which might -/// involve some hashing and so forth). -pub struct UnresolvedTypeOrConstFinder<'a, 'tcx> { - infcx: &'a InferCtxt<'tcx>, -} - -impl<'a, 'tcx> UnresolvedTypeOrConstFinder<'a, 'tcx> { - pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self { - UnresolvedTypeOrConstFinder { infcx } - } -} - -impl<'a, 'tcx> TypeVisitor> for UnresolvedTypeOrConstFinder<'a, 'tcx> { - type BreakTy = (ty::Term<'tcx>, Option); - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { - let t = self.infcx.shallow_resolve(t); - if let ty::Infer(infer_ty) = *t.kind() { - // Since we called `shallow_resolve` above, this must - // be an (as yet...) unresolved inference variable. - let ty_var_span = if let ty::TyVar(ty_vid) = infer_ty { - let mut inner = self.infcx.inner.borrow_mut(); - let ty_vars = &inner.type_variables(); - if let TypeVariableOrigin { - kind: TypeVariableOriginKind::TypeParameterDefinition(_, _), - span, - } = ty_vars.var_origin(ty_vid) - { - Some(span) - } else { - None - } - } else { - None - }; - ControlFlow::Break((t.into(), ty_var_span)) - } else if !t.has_non_region_infer() { - // All const/type variables in inference types must already be resolved, - // no need to visit the contents. - ControlFlow::Continue(()) - } else { - // Otherwise, keep visiting. - t.super_visit_with(self) - } - } - - fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow { - let ct = self.infcx.shallow_resolve(ct); - if let ty::ConstKind::Infer(i) = ct.kind() { - // Since we called `shallow_resolve` above, this must - // be an (as yet...) unresolved inference variable. - let ct_var_span = if let ty::InferConst::Var(vid) = i { - let mut inner = self.infcx.inner.borrow_mut(); - let ct_vars = &mut inner.const_unification_table(); - if let ConstVariableOrigin { - span, - kind: ConstVariableOriginKind::ConstParameterDefinition(_, _), - } = ct_vars.probe_value(vid).origin - { - Some(span) - } else { - None - } - } else { - None - }; - ControlFlow::Break((ct.into(), ct_var_span)) - } else if !ct.has_non_region_infer() { - // All const/type variables in inference types must already be resolved, - // no need to visit the contents. - ControlFlow::Continue(()) - } else { - // Otherwise, keep visiting. - ct.super_visit_with(self) - } - } -} - /////////////////////////////////////////////////////////////////////////// // FULL TYPE RESOLUTION diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index b9be178916cf..72ec07375ac0 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -13,13 +13,15 @@ use std::hash::{Hash, Hasher}; use hir::def_id::LocalDefId; use rustc_hir as hir; +use rustc_middle::traits::query::NoSolution; +use rustc_middle::traits::solve::Certainty; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{self, Const, ToPredicate, Ty, TyCtxt}; use rustc_span::Span; -pub use self::FulfillmentErrorCode::*; pub use self::ImplSource::*; pub use self::SelectionError::*; +use crate::infer::InferCtxt; pub use self::engine::{TraitEngine, TraitEngineExt}; pub use self::project::MismatchedProjectionTypes; @@ -117,6 +119,11 @@ pub type PredicateObligations<'tcx> = Vec>; pub type Selection<'tcx> = ImplSource<'tcx, PredicateObligation<'tcx>>; +/// A callback that can be provided to `inspect_typeck`. Invoked on evaluation +/// of root obligations. +pub type ObligationInspector<'tcx> = + fn(&InferCtxt<'tcx>, &PredicateObligation<'tcx>, Result); + pub struct FulfillmentError<'tcx> { pub obligation: PredicateObligation<'tcx>, pub code: FulfillmentErrorCode<'tcx>, @@ -129,12 +136,12 @@ pub struct FulfillmentError<'tcx> { #[derive(Clone)] pub enum FulfillmentErrorCode<'tcx> { /// Inherently impossible to fulfill; this trait is implemented if and only if it is already implemented. - CodeCycle(Vec>), - CodeSelectionError(SelectionError<'tcx>), - CodeProjectionError(MismatchedProjectionTypes<'tcx>), - CodeSubtypeError(ExpectedFound>, TypeError<'tcx>), // always comes from a SubtypePredicate - CodeConstEquateError(ExpectedFound>, TypeError<'tcx>), - CodeAmbiguity { + Cycle(Vec>), + SelectionError(SelectionError<'tcx>), + ProjectionError(MismatchedProjectionTypes<'tcx>), + SubtypeError(ExpectedFound>, TypeError<'tcx>), // always comes from a SubtypePredicate + ConstEquateError(ExpectedFound>, TypeError<'tcx>), + Ambiguity { /// Overflow reported from the new solver `-Znext-solver`, which will /// be reported as an regular error as opposed to a fatal error. overflow: bool, diff --git a/compiler/rustc_infer/src/traits/structural_impls.rs b/compiler/rustc_infer/src/traits/structural_impls.rs index 51c06c8970b1..3b4050fcd27e 100644 --- a/compiler/rustc_infer/src/traits/structural_impls.rs +++ b/compiler/rustc_infer/src/traits/structural_impls.rs @@ -37,18 +37,19 @@ impl<'tcx> fmt::Debug for traits::FulfillmentError<'tcx> { impl<'tcx> fmt::Debug for traits::FulfillmentErrorCode<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use traits::FulfillmentErrorCode::*; match *self { - super::CodeSelectionError(ref e) => write!(f, "{e:?}"), - super::CodeProjectionError(ref e) => write!(f, "{e:?}"), - super::CodeSubtypeError(ref a, ref b) => { + SelectionError(ref e) => write!(f, "{e:?}"), + ProjectionError(ref e) => write!(f, "{e:?}"), + SubtypeError(ref a, ref b) => { write!(f, "CodeSubtypeError({a:?}, {b:?})") } - super::CodeConstEquateError(ref a, ref b) => { + ConstEquateError(ref a, ref b) => { write!(f, "CodeConstEquateError({a:?}, {b:?})") } - super::CodeAmbiguity { overflow: false } => write!(f, "Ambiguity"), - super::CodeAmbiguity { overflow: true } => write!(f, "Overflow"), - super::CodeCycle(ref cycle) => write!(f, "Cycle({cycle:?})"), + Ambiguity { overflow: false } => write!(f, "Ambiguity"), + Ambiguity { overflow: true } => write!(f, "Overflow"), + Cycle(ref cycle) => write!(f, "Cycle({cycle:?})"), } } } diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index 319e81758094..a238eacda44b 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start -libloading = "0.7.1" +libloading = "0.8.0" rustc-rayon = { version = "0.5.0", optional = true } rustc-rayon-core = { version = "0.5.0", optional = true } rustc_ast = { path = "../rustc_ast" } diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 32fba6ade88d..5ca880909967 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -218,7 +218,9 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec) -> CheckCfg { } } - if values.is_empty() && !values_any_specified && !any_specified { + if !values_specified && !any_specified { + // `cfg(name)` is equivalent to `cfg(name, values(none()))` so add + // an implicit `none()` values.insert(None); } else if !values.is_empty() && values_any_specified { error!( diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs index cfa46447845a..764306ce6ec6 100644 --- a/compiler/rustc_interface/src/lib.rs +++ b/compiler/rustc_interface/src/lib.rs @@ -1,9 +1,10 @@ #![feature(box_patterns)] #![feature(decl_macro)] +#![feature(error_iter)] #![feature(internal_output_capture)] -#![feature(thread_spawn_unchecked)] #![feature(lazy_cell)] #![feature(let_chains)] +#![feature(thread_spawn_unchecked)] #![feature(try_blocks)] #![recursion_limit = "256"] #![deny(rustc::untranslatable_diagnostic)] diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 588139a303c5..555c822ad6d6 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -4,10 +4,10 @@ use rustc_data_structures::profiling::TimePassesFormat; use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig}; use rustc_session::config::{ build_configuration, build_session_options, rustc_optgroups, BranchProtection, CFGuard, Cfg, - DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation, Externs, - FunctionReturn, InliningThreshold, Input, InstrumentCoverage, InstrumentXRay, - LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli, NextSolverConfig, OomStrategy, - Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, Passes, Polonius, + CollapseMacroDebuginfo, DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, + ExternLocation, Externs, FunctionReturn, InliningThreshold, Input, InstrumentCoverage, + InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli, NextSolverConfig, + OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, Passes, Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion, WasiExecModel, }; use rustc_session::lint::Level; @@ -742,6 +742,7 @@ fn test_unstable_options_tracking_hash() { }) ); tracked!(codegen_backend, Some("abc".to_string())); + tracked!(collapse_macro_debuginfo, CollapseMacroDebuginfo::Yes); tracked!(crate_attr, vec!["abc".to_string()]); tracked!(cross_crate_inline_threshold, InliningThreshold::Always); tracked!(debug_info_for_profiling, true); diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 9fd44e46b316..76b9e8de75fb 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -162,15 +162,21 @@ pub(crate) fn run_in_thread_pool_with_globals R + Send, R: Send>( } fn load_backend_from_dylib(early_dcx: &EarlyDiagCtxt, path: &Path) -> MakeBackendFn { + fn format_err(e: &(dyn std::error::Error + 'static)) -> String { + e.sources().map(|e| format!(": {e}")).collect() + } let lib = unsafe { Library::new(path) }.unwrap_or_else(|err| { - let err = format!("couldn't load codegen backend {path:?}: {err}"); + let err = format!("couldn't load codegen backend {path:?}{}", format_err(&err)); early_dcx.early_fatal(err); }); let backend_sym = unsafe { lib.get::(b"__rustc_codegen_backend") } .unwrap_or_else(|e| { - let err = format!("couldn't load codegen backend: {e}"); - early_dcx.early_fatal(err); + let e = format!( + "`__rustc_codegen_backend` symbol lookup in the codegen backend failed{}", + format_err(&e) + ); + early_dcx.early_fatal(e); }); // Intentionally leak the dynamic library. We can't ever unload it diff --git a/compiler/rustc_lexer/src/unescape.rs b/compiler/rustc_lexer/src/unescape.rs index abec12f52a6e..0a632c4d12ad 100644 --- a/compiler/rustc_lexer/src/unescape.rs +++ b/compiler/rustc_lexer/src/unescape.rs @@ -59,6 +59,9 @@ pub enum EscapeError { /// Non-ascii character in byte literal, byte string literal, or raw byte string literal. NonAsciiCharInByte, + // `\0` in a C string literal. + NulInCStr, + /// After a line ending with '\', the next line contains whitespace /// characters that are not skipped. UnskippedWhitespaceWarning, @@ -122,10 +125,20 @@ where { match mode { CStr => { - unescape_non_raw_common(src, mode, callback); + unescape_non_raw_common(src, mode, &mut |r, mut result| { + if let Ok(CStrUnit::Byte(0) | CStrUnit::Char('\0')) = result { + result = Err(EscapeError::NulInCStr); + } + callback(r, result) + }); } RawCStr => { - check_raw_common(src, mode, &mut |r, result| callback(r, result.map(CStrUnit::Char))); + check_raw_common(src, mode, &mut |r, mut result| { + if let Ok('\0') = result { + result = Err(EscapeError::NulInCStr); + } + callback(r, result.map(CStrUnit::Char)) + }); } Char | Byte | Str | RawStr | ByteStr | RawByteStr => unreachable!(), } diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index 9e6a6f70eac0..312874db3f54 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -354,6 +354,15 @@ pub(super) fn builtin( Applicability::MaybeIncorrect, ); } + } else { + db.note(format!("no expected values for `{name}`")); + + let sp = if let Some((_value, value_span)) = value { + name_span.to(value_span) + } else { + name_span + }; + db.span_suggestion(sp, "remove the condition", "", Applicability::MaybeIncorrect); } // We don't want to suggest adding values to well known names @@ -373,6 +382,8 @@ pub(super) fn builtin( if name == sym::feature { if let Some((value, _value_span)) = value { db.help(format!("consider adding `{value}` as a feature in `Cargo.toml`")); + } else { + db.help("consider defining some features in `Cargo.toml`"); } } else if !is_cfg_a_well_know_name { db.help(format!("consider using a Cargo feature instead or adding `println!(\"cargo:rustc-check-cfg={inst}\");` to the top of a `build.rs`")); diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 0f4528d1d5c2..39decf1faabf 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -1166,7 +1166,7 @@ impl EarlyLintPass for UnusedParens { // Do not lint on `(..)` as that will result in the other arms being useless. Paren(_) // The other cases do not contain sub-patterns. - | Wild | Never | Rest | Lit(..) | MacCall(..) | Range(..) | Ident(.., None) | Path(..) => {}, + | Wild | Never | Rest | Lit(..) | MacCall(..) | Range(..) | Ident(.., None) | Path(..) | Err(_) => {}, // These are list-like patterns; parens can always be removed. TupleStruct(_, _, ps) | Tuple(ps) | Slice(ps) | Or(ps) => for p in ps { self.check_unused_parens_pat(cx, p, false, false, keep_space); diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index fb908fe2db15..0b7ecff8148b 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -211,7 +211,7 @@ impl DiagnosticDeriveVariantBuilder { let code = nested.parse::()?; tokens.extend(quote! { - diag.code(rustc_errors::DiagnosticId::Error(#code.to_string())); + diag.code(#code.to_string()); }); } else { span_err(path.span().unwrap(), "unknown argument") diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml index 08cc8173eb04..79d3482472a8 100644 --- a/compiler/rustc_metadata/Cargo.toml +++ b/compiler/rustc_metadata/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start bitflags = "2.4.1" -libloading = "0.7.1" +libloading = "0.8.0" odht = { version = "0.3.1", features = ["nightly"] } rustc_ast = { path = "../rustc_ast" } rustc_attr = { path = "../rustc_attr" } diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 49e849964be4..20e3ae3ba949 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1027,6 +1027,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { self.root.edition, Symbol::intern(name), &attrs, + false, ) } diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 912c2f36eb3c..c3d6c21c4027 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -283,7 +283,7 @@ provide! { tcx, def_id, other, cdata, tcx.arena.alloc_from_iter(cdata.get_associated_item_or_field_def_ids(def_id.index)) } associated_item => { cdata.get_associated_item(def_id.index, tcx.sess) } - inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) } + inherent_impls => { Ok(cdata.get_inherent_implementations_for_type(tcx, def_id.index)) } item_attrs => { tcx.arena.alloc_from_iter(cdata.get_item_attrs(def_id.index, tcx.sess)) } is_mir_available => { cdata.is_item_mir_available(def_id.index) } is_ctfe_mir_available => { cdata.is_ctfe_mir_available(def_id.index) } @@ -328,7 +328,7 @@ provide! { tcx, def_id, other, cdata, traits => { tcx.arena.alloc_from_iter(cdata.get_traits()) } trait_impls_in_crate => { tcx.arena.alloc_from_iter(cdata.get_trait_impls()) } implementations_of_trait => { cdata.get_implementations_of_trait(tcx, other) } - crate_incoherent_impls => { cdata.get_incoherent_impls(tcx, other) } + crate_incoherent_impls => { Ok(cdata.get_incoherent_impls(tcx, other)) } dep_kind => { cdata.dep_kind } module_children => { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index a458b528a97c..2d4e49e27d9b 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1485,7 +1485,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } let inherent_impls = tcx.with_stable_hashing_context(|hcx| { - tcx.crate_inherent_impls(()).inherent_impls.to_sorted(&hcx, true) + tcx.crate_inherent_impls(()).unwrap().inherent_impls.to_sorted(&hcx, true) }); for (def_id, impls) in inherent_impls { record_defaulted_array!(self.tables.inherent_impls[def_id.to_def_id()] <- impls.iter().map(|def_id| { @@ -2028,7 +2028,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { empty_proc_macro!(self); let tcx = self.tcx; let all_impls = tcx.with_stable_hashing_context(|hcx| { - tcx.crate_inherent_impls(()).incoherent_impls.to_sorted(&hcx, true) + tcx.crate_inherent_impls(()).unwrap().incoherent_impls.to_sorted(&hcx, true) }); let all_impls: Vec<_> = all_impls diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml index 8e6ca645f80c..82e56c9cbe20 100644 --- a/compiler/rustc_middle/Cargo.toml +++ b/compiler/rustc_middle/Cargo.toml @@ -10,7 +10,7 @@ derive_more = "0.99.17" either = "1.5.0" field-offset = "0.3.5" gsgdt = "0.1.2" -measureme = "10.0.0" +measureme = "11" polonius-engine = "0.13.0" rustc-rayon = { version = "0.5.0", optional = true } rustc-rayon-core = { version = "0.5.0", optional = true } diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 8a4fd01437f9..e745913fabc3 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -114,6 +114,7 @@ macro_rules! arena_types { [] mod_child: rustc_middle::metadata::ModChild, [] features: rustc_feature::Features, [decode] specialization_graph: rustc_middle::traits::specialization_graph::Graph, + [] crate_inherent_impls: rustc_middle::ty::CrateInherentImpls, ]); ) } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 1574f0f1b31f..949b786e3a7d 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -1,4 +1,4 @@ -use crate::hir::{ModuleItems, Owner}; +use crate::hir::ModuleItems; use crate::middle::debugger_visualizer::DebuggerVisualizerFile; use crate::query::LocalCrate; use crate::ty::TyCtxt; @@ -108,7 +108,7 @@ impl<'hir> Iterator for ParentOwnerIterator<'hir> { if self.current_id.local_id.index() != 0 { self.current_id.local_id = ItemLocalId::new(0); if let Some(node) = self.map.tcx.hir_owner(self.current_id.owner) { - return Some((self.current_id.owner, node.node)); + return Some((self.current_id.owner, node)); } } if self.current_id == CRATE_HIR_ID { @@ -126,23 +126,23 @@ impl<'hir> Iterator for ParentOwnerIterator<'hir> { // If this `HirId` doesn't have an entry, skip it and look for its `parent_id`. if let Some(node) = self.map.tcx.hir_owner(self.current_id.owner) { - return Some((self.current_id.owner, node.node)); + return Some((self.current_id.owner, node)); } } } } impl<'tcx> TyCtxt<'tcx> { + #[inline] + fn hir_owner(self, owner: OwnerId) -> Option> { + Some(self.hir_owner_nodes(owner).as_owner()?.node()) + } + /// Retrieves the `hir::Node` corresponding to `id`, returning `None` if cannot be found. pub fn opt_hir_node(self, id: HirId) -> Option> { - if id.local_id == ItemLocalId::from_u32(0) { - let owner = self.hir_owner(id.owner)?; - Some(owner.node.into()) - } else { - let owner = self.hir_owner_nodes(id.owner).as_owner()?; - let node = owner.nodes[id.local_id].as_ref()?; - Some(node.node) - } + let owner = self.hir_owner_nodes(id.owner).as_owner()?; + let node = owner.nodes[id.local_id].as_ref()?; + Some(node.node) } /// Retrieves the `hir::Node` corresponding to `id`, returning `None` if cannot be found. @@ -174,7 +174,7 @@ impl<'hir> Map<'hir> { #[inline] pub fn root_module(self) -> &'hir Mod<'hir> { - match self.tcx.hir_owner(CRATE_OWNER_ID).map(|o| o.node) { + match self.tcx.hir_owner(CRATE_OWNER_ID) { Some(OwnerNode::Crate(item)) => item, _ => bug!(), } @@ -242,27 +242,27 @@ impl<'hir> Map<'hir> { pub fn get_generics(self, id: LocalDefId) -> Option<&'hir Generics<'hir>> { let node = self.tcx.hir_owner(OwnerId { def_id: id })?; - node.node.generics() + node.generics() } pub fn owner(self, id: OwnerId) -> OwnerNode<'hir> { - self.tcx.hir_owner(id).unwrap_or_else(|| bug!("expected owner for {:?}", id)).node + self.tcx.hir_owner(id).unwrap_or_else(|| bug!("expected owner for {:?}", id)) } pub fn item(self, id: ItemId) -> &'hir Item<'hir> { - self.tcx.hir_owner(id.owner_id).unwrap().node.expect_item() + self.tcx.hir_owner(id.owner_id).unwrap().expect_item() } pub fn trait_item(self, id: TraitItemId) -> &'hir TraitItem<'hir> { - self.tcx.hir_owner(id.owner_id).unwrap().node.expect_trait_item() + self.tcx.hir_owner(id.owner_id).unwrap().expect_trait_item() } pub fn impl_item(self, id: ImplItemId) -> &'hir ImplItem<'hir> { - self.tcx.hir_owner(id.owner_id).unwrap().node.expect_impl_item() + self.tcx.hir_owner(id.owner_id).unwrap().expect_impl_item() } pub fn foreign_item(self, id: ForeignItemId) -> &'hir ForeignItem<'hir> { - self.tcx.hir_owner(id.owner_id).unwrap().node.expect_foreign_item() + self.tcx.hir_owner(id.owner_id).unwrap().expect_foreign_item() } pub fn body(self, id: BodyId) -> &'hir Body<'hir> { @@ -436,7 +436,7 @@ impl<'hir> Map<'hir> { pub fn get_module(self, module: LocalModDefId) -> (&'hir Mod<'hir>, Span, HirId) { let hir_id = HirId::make_owner(module.to_local_def_id()); - match self.tcx.hir_owner(hir_id.owner).map(|o| o.node) { + match self.tcx.hir_owner(hir_id.owner) { Some(OwnerNode::Item(&Item { span, kind: ItemKind::Mod(m), .. })) => (m, span, hir_id), Some(OwnerNode::Crate(item)) => (item, item.spans.inner_span, hir_id), node => panic!("not a module: {node:?}"), @@ -726,11 +726,10 @@ impl<'hir> Map<'hir> { pub fn get_foreign_abi(self, hir_id: HirId) -> Abi { let parent = self.get_parent_item(hir_id); - if let Some(node) = self.tcx.hir_owner(parent) { - if let OwnerNode::Item(Item { kind: ItemKind::ForeignMod { abi, .. }, .. }) = node.node - { - return *abi; - } + if let Some(node) = self.tcx.hir_owner(parent) + && let OwnerNode::Item(Item { kind: ItemKind::ForeignMod { abi, .. }, .. }) = node + { + return *abi; } bug!( "expected foreign mod or inlined parent, found {}", @@ -742,33 +741,32 @@ impl<'hir> Map<'hir> { self.tcx .hir_owner(OwnerId { def_id }) .unwrap_or_else(|| bug!("expected owner for {:?}", def_id)) - .node } pub fn expect_item(self, id: LocalDefId) -> &'hir Item<'hir> { match self.tcx.hir_owner(OwnerId { def_id: id }) { - Some(Owner { node: OwnerNode::Item(item), .. }) => item, + Some(OwnerNode::Item(item)) => item, _ => bug!("expected item, found {}", self.node_to_string(HirId::make_owner(id))), } } pub fn expect_impl_item(self, id: LocalDefId) -> &'hir ImplItem<'hir> { match self.tcx.hir_owner(OwnerId { def_id: id }) { - Some(Owner { node: OwnerNode::ImplItem(item), .. }) => item, + Some(OwnerNode::ImplItem(item)) => item, _ => bug!("expected impl item, found {}", self.node_to_string(HirId::make_owner(id))), } } pub fn expect_trait_item(self, id: LocalDefId) -> &'hir TraitItem<'hir> { match self.tcx.hir_owner(OwnerId { def_id: id }) { - Some(Owner { node: OwnerNode::TraitItem(item), .. }) => item, + Some(OwnerNode::TraitItem(item)) => item, _ => bug!("expected trait item, found {}", self.node_to_string(HirId::make_owner(id))), } } pub fn get_fn_output(self, def_id: LocalDefId) -> Option<&'hir FnRetTy<'hir>> { match self.tcx.hir_owner(OwnerId { def_id }) { - Some(Owner { node, .. }) => node.fn_decl().map(|fn_decl| &fn_decl.output), + Some(node) => node.fn_decl().map(|fn_decl| &fn_decl.output), _ => None, } } @@ -782,7 +780,7 @@ impl<'hir> Map<'hir> { pub fn expect_foreign_item(self, id: OwnerId) -> &'hir ForeignItem<'hir> { match self.tcx.hir_owner(id) { - Some(Owner { node: OwnerNode::ForeignItem(item), .. }) => item, + Some(OwnerNode::ForeignItem(item)) => item, _ => { bug!( "expected foreign item, found {}", diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index af99c7d55c37..2d4d5deaefa9 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -8,34 +8,12 @@ pub mod place; use crate::query::Providers; use crate::ty::{EarlyBinder, ImplSubject, TyCtxt}; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{try_par_for_each_in, DynSend, DynSync}; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; use rustc_hir::*; -use rustc_query_system::ich::StableHashingContext; use rustc_span::{ErrorGuaranteed, ExpnId, DUMMY_SP}; -/// Top-level HIR node for current owner. This only contains the node for which -/// `HirId::local_id == 0`, and excludes bodies. -/// -/// This struct exists to encapsulate all access to the hir_owner query in this module, and to -/// implement HashStable without hashing bodies. -#[derive(Copy, Clone, Debug)] -pub struct Owner<'tcx> { - node: OwnerNode<'tcx>, -} - -impl<'a, 'tcx> HashStable> for Owner<'tcx> { - #[inline] - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - // Perform a shallow hash instead using the deep hash saved in `OwnerNodes`. This lets us - // differentiate queries that depend on the full HIR tree from those that only depend on - // the item signature. - hcx.without_hir_bodies(|hcx| self.node.hash_stable(hcx, hasher)); - } -} - /// Gather the LocalDefId for each item-like within a module, including items contained within /// bodies. The Ids are in visitor order. This is used to partition a pass between modules. #[derive(Debug, HashStable, Encodable, Decodable)] @@ -149,11 +127,6 @@ pub fn provide(providers: &mut Providers) { providers.hir_crate_items = map::hir_crate_items; providers.crate_hash = map::crate_hash; providers.hir_module_items = map::hir_module_items; - providers.hir_owner = |tcx, id| { - let owner = tcx.hir_crate(()).owners.get(id.def_id)?.as_owner()?; - let node = owner.node(); - Some(Owner { node }) - }; providers.opt_local_def_id_to_hir_id = |tcx, id| { let owner = tcx.hir_crate(()).owners[id].map(|_| ()); Some(match owner { @@ -162,7 +135,13 @@ pub fn provide(providers: &mut Providers) { MaybeOwner::NonOwner(hir_id) => hir_id, }) }; - providers.hir_owner_nodes = |tcx, id| tcx.hir_crate(()).owners[id.def_id].map(|i| &i.nodes); + providers.hir_owner_nodes = |tcx, id| { + if let Some(i) = tcx.hir_crate(()).owners.get(id.def_id) { + i.map(|i| &i.nodes) + } else { + MaybeOwner::Phantom + } + }; providers.hir_owner_parent = |tcx, id| { // Accessing the local_parent is ok since its value is hashed as part of `id`'s DefPathHash. tcx.opt_local_parent(id.def_id).map_or(CRATE_HIR_ID, |parent| { diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs index 6e50e8940464..c35799ef47f2 100644 --- a/compiler/rustc_middle/src/infer/unify_key.rs +++ b/compiler/rustc_middle/src/infer/unify_key.rs @@ -120,7 +120,7 @@ pub enum ConstVariableOriginKind { #[derive(Copy, Clone, Debug)] pub enum ConstVariableValue<'tcx> { Known { value: ty::Const<'tcx> }, - Unknown { universe: ty::UniverseIndex }, + Unknown { origin: ConstVariableOrigin, universe: ty::UniverseIndex }, } impl<'tcx> ConstVariableValue<'tcx> { @@ -134,12 +134,6 @@ impl<'tcx> ConstVariableValue<'tcx> { } } -#[derive(Copy, Clone, Debug)] -pub struct ConstVarValue<'tcx> { - pub origin: ConstVariableOrigin, - pub val: ConstVariableValue<'tcx>, -} - #[derive(PartialEq, Copy, Clone, Debug)] pub struct ConstVidKey<'tcx> { pub vid: ty::ConstVid, @@ -153,7 +147,7 @@ impl<'tcx> From for ConstVidKey<'tcx> { } impl<'tcx> UnifyKey for ConstVidKey<'tcx> { - type Value = ConstVarValue<'tcx>; + type Value = ConstVariableValue<'tcx>; #[inline] fn index(&self) -> u32 { self.vid.as_u32() @@ -167,23 +161,23 @@ impl<'tcx> UnifyKey for ConstVidKey<'tcx> { } } -impl<'tcx> UnifyValue for ConstVarValue<'tcx> { +impl<'tcx> UnifyValue for ConstVariableValue<'tcx> { type Error = NoError; fn unify_values(&value1: &Self, &value2: &Self) -> Result { - Ok(match (value1.val, value2.val) { + match (value1, value2) { (ConstVariableValue::Known { .. }, ConstVariableValue::Known { .. }) => { bug!("equating two const variables, both of which have known values") } // If one side is known, prefer that one. - (ConstVariableValue::Known { .. }, ConstVariableValue::Unknown { .. }) => value1, - (ConstVariableValue::Unknown { .. }, ConstVariableValue::Known { .. }) => value2, + (ConstVariableValue::Known { .. }, ConstVariableValue::Unknown { .. }) => Ok(value1), + (ConstVariableValue::Unknown { .. }, ConstVariableValue::Known { .. }) => Ok(value2), // If both sides are *unknown*, it hardly matters, does it? ( - ConstVariableValue::Unknown { universe: universe1 }, - ConstVariableValue::Unknown { universe: universe2 }, + ConstVariableValue::Unknown { origin, universe: universe1 }, + ConstVariableValue::Unknown { origin: _, universe: universe2 }, ) => { // If we unify two unbound variables, ?T and ?U, then whatever // value they wind up taking (which must be the same value) must @@ -191,12 +185,9 @@ impl<'tcx> UnifyValue for ConstVarValue<'tcx> { // universe is the minimum of the two universes, because that is // the one which contains the fewest names in scope. let universe = cmp::min(universe1, universe2); - ConstVarValue { - val: ConstVariableValue::Unknown { universe }, - origin: value1.origin, - } + Ok(ConstVariableValue::Unknown { origin, universe }) } - }) + } } } diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index c5e4dfaf19ee..4ab16cf19ba9 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -2,7 +2,7 @@ use std::cmp; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sorted_map::SortedMap; -use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, MultiSpan}; +use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticMessage, MultiSpan}; use rustc_hir::{HirId, ItemLocalId}; use rustc_session::lint::{ builtin::{self, FORBIDDEN_LINT_GROUPS}, @@ -322,8 +322,6 @@ pub fn struct_lint_level( err.span(span); } - err.is_lint(); - // If this code originates in a foreign macro, aka something that this crate // did not itself author, then it's likely that there's nothing this crate // can do about it. We probably want to skip the lint entirely. @@ -351,8 +349,7 @@ pub fn struct_lint_level( // suppressed the lint due to macros. err.primary_message(msg); - let name = lint.name_lower(); - err.code(DiagnosticId::Lint { name, has_future_breakage }); + err.is_lint(lint.name_lower(), has_future_breakage); // Lint diagnostics that are covered by the expect level will not be emitted outside // the compiler. It is therefore not necessary to add any information for the user. diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index 092b59deeff3..b20df1b23434 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -145,7 +145,7 @@ impl<'tcx> TyCtxt<'tcx> { ) -> EvalToConstValueResult<'tcx> { // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should // improve caching of queries. - let inputs = self.erase_regions(param_env.and(cid)); + let inputs = self.erase_regions(param_env.with_reveal_all_normalized(self).and(cid)); if let Some(span) = span { // The query doesn't know where it is being invoked, so we need to fix the span. self.at(span).eval_to_const_value_raw(inputs).map_err(|e| e.with_span(span)) @@ -164,7 +164,7 @@ impl<'tcx> TyCtxt<'tcx> { ) -> EvalToValTreeResult<'tcx> { // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should // improve caching of queries. - let inputs = self.erase_regions(param_env.and(cid)); + let inputs = self.erase_regions(param_env.with_reveal_all_normalized(self).and(cid)); debug!(?inputs); if let Some(span) = span { // The query doesn't know where it is being invoked, so we need to fix the span. diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 36f5ba161d5f..624ae8c22f9d 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1672,13 +1672,19 @@ mod size_asserts { use super::*; use rustc_data_structures::static_assert_size; // tidy-alphabetical-start - static_assert_size!(BasicBlockData<'_>, 136); + // This can be removed after i128:128 is in the bootstrap compiler's target. + #[cfg(not(bootstrap))] + static_assert_size!(BasicBlockData<'_>, 144); static_assert_size!(LocalDecl<'_>, 40); static_assert_size!(SourceScopeData<'_>, 72); static_assert_size!(Statement<'_>, 32); static_assert_size!(StatementKind<'_>, 16); - static_assert_size!(Terminator<'_>, 104); - static_assert_size!(TerminatorKind<'_>, 88); + // This can be removed after i128:128 is in the bootstrap compiler's target. + #[cfg(not(bootstrap))] + static_assert_size!(Terminator<'_>, 112); + // This can be removed after i128:128 is in the bootstrap compiler's target. + #[cfg(not(bootstrap))] + static_assert_size!(TerminatorKind<'_>, 96); static_assert_size!(VarDebugInfo<'_>, 88); // tidy-alphabetical-end } diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 1a6b0f4031d3..3b60eba2dfe0 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -142,15 +142,17 @@ fn dump_matched_mir_node<'tcx, F>( } } -/// Returns the file basename portion (without extension) of a filename path -/// where we should dump a MIR representation output files. -fn dump_file_basename<'tcx>( +/// Returns the path to the filename where we should dump a given MIR. +/// Also used by other bits of code (e.g., NLL inference) that dump +/// graphviz data or other things. +fn dump_path<'tcx>( tcx: TyCtxt<'tcx>, + extension: &str, pass_num: bool, pass_name: &str, disambiguator: &dyn Display, body: &Body<'tcx>, -) -> String { +) -> PathBuf { let source = body.source; let promotion_id = match source.promoted { Some(id) => format!("-{id:?}"), @@ -186,45 +188,18 @@ fn dump_file_basename<'tcx>( _ => String::new(), }; - format!( - "{crate_name}.{item_name}{shim_disambiguator}{promotion_id}{pass_num}.{pass_name}.{disambiguator}", - ) -} - -/// Returns the path to the filename where we should dump a given MIR. -/// Also used by other bits of code (e.g., NLL inference) that dump -/// graphviz data or other things. -fn dump_path(tcx: TyCtxt<'_>, basename: &str, extension: &str) -> PathBuf { let mut file_path = PathBuf::new(); file_path.push(Path::new(&tcx.sess.opts.unstable_opts.dump_mir_dir)); - let file_name = format!("{basename}.{extension}",); + let file_name = format!( + "{crate_name}.{item_name}{shim_disambiguator}{promotion_id}{pass_num}.{pass_name}.{disambiguator}.{extension}", + ); file_path.push(&file_name); file_path } -/// Attempts to open the MIR dump file with the given name and extension. -fn create_dump_file_with_basename( - tcx: TyCtxt<'_>, - file_basename: &str, - extension: &str, -) -> io::Result> { - let file_path = dump_path(tcx, file_basename, extension); - if let Some(parent) = file_path.parent() { - fs::create_dir_all(parent).map_err(|e| { - io::Error::new( - e.kind(), - format!("IO error creating MIR dump directory: {parent:?}; {e}"), - ) - })?; - } - Ok(io::BufWriter::new(fs::File::create(&file_path).map_err(|e| { - io::Error::new(e.kind(), format!("IO error creating MIR dump file: {file_path:?}; {e}")) - })?)) -} - /// Attempts to open a file where we should dump a given MIR or other /// bit of MIR-related data. Used by `mir-dump`, but also by other /// bits of code (e.g., NLL inference) that dump graphviz data or @@ -237,11 +212,18 @@ pub fn create_dump_file<'tcx>( disambiguator: &dyn Display, body: &Body<'tcx>, ) -> io::Result> { - create_dump_file_with_basename( - tcx, - &dump_file_basename(tcx, pass_num, pass_name, disambiguator, body), - extension, - ) + let file_path = dump_path(tcx, extension, pass_num, pass_name, disambiguator, body); + if let Some(parent) = file_path.parent() { + fs::create_dir_all(parent).map_err(|e| { + io::Error::new( + e.kind(), + format!("IO error creating MIR dump directory: {parent:?}; {e}"), + ) + })?; + } + Ok(io::BufWriter::new(fs::File::create(&file_path).map_err(|e| { + io::Error::new(e.kind(), format!("IO error creating MIR dump file: {file_path:?}; {e}")) + })?)) } /////////////////////////////////////////////////////////////////////////// @@ -785,7 +767,7 @@ impl<'tcx> TerminatorKind<'tcx> { Call { func, args, destination, .. } => { write!(fmt, "{destination:?} = ")?; write!(fmt, "{func:?}(")?; - for (index, arg) in args.iter().enumerate() { + for (index, arg) in args.iter().map(|a| &a.node).enumerate() { if index > 0 { write!(fmt, ", ")?; } @@ -1116,10 +1098,10 @@ fn pre_fmt_projection(projection: &[PlaceElem<'_>], fmt: &mut Formatter<'_>) -> | ProjectionElem::Subtype(_) | ProjectionElem::Downcast(_, _) | ProjectionElem::Field(_, _) => { - write!(fmt, "(").unwrap(); + write!(fmt, "(")?; } ProjectionElem::Deref => { - write!(fmt, "(*").unwrap(); + write!(fmt, "(*")?; } ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 462076d750f2..6ebe57e29da2 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -16,6 +16,7 @@ use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_hir::def_id::DefId; use rustc_hir::{self, CoroutineKind}; use rustc_index::IndexVec; +use rustc_span::source_map::Spanned; use rustc_target::abi::{FieldIdx, VariantIdx}; use rustc_ast::Mutability; @@ -673,7 +674,9 @@ pub enum TerminatorKind<'tcx> { /// 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>, + /// The span for each arg is also included + /// (e.g. `a` and `b` in `x.foo(a, b)`). + args: Vec>>, /// Where the returned value will be written destination: Place<'tcx>, /// Where to go after this call returns. If none, the call necessarily diverges. diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index 234ccee55468..5597609c7d79 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -229,6 +229,18 @@ impl<'tcx> Operand<'tcx> { Operand::Constant(c) => c.const_.ty(), } } + + pub fn span(&self, local_decls: &D) -> Span + where + D: HasLocalDecls<'tcx>, + { + match self { + &Operand::Copy(ref l) | &Operand::Move(ref l) => { + local_decls.local_decls()[l.local].source_info.span + } + Operand::Constant(c) => c.span, + } + } } impl<'tcx> BinOp { diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 2ccf5a9f6f7a..4696f54c8978 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -524,7 +524,7 @@ macro_rules! make_mir_visitor { } => { self.visit_operand(func, location); for arg in args { - self.visit_operand(arg, location); + self.visit_operand(&$($mutability)? arg.node, location); } self.visit_place( destination, diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index b9200f1abf16..778b4308d2ee 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -74,10 +74,18 @@ impl EraseType for Result<&'_ T, traits::query::NoSolution> { type Result = [u8; size_of::>()]; } +impl EraseType for Result<&'_ [T], traits::query::NoSolution> { + type Result = [u8; size_of::>()]; +} + impl EraseType for Result<&'_ T, rustc_errors::ErrorGuaranteed> { type Result = [u8; size_of::>()]; } +impl EraseType for Result<&'_ [T], rustc_errors::ErrorGuaranteed> { + type Result = [u8; size_of::>()]; +} + impl EraseType for Result<&'_ T, traits::CodegenObligationError> { type Result = [u8; size_of::>()]; } @@ -160,10 +168,6 @@ impl EraseType for Option<&'_ [T]> { type Result = [u8; size_of::>()]; } -impl EraseType for Option> { - type Result = [u8; size_of::>>()]; -} - impl EraseType for Option> { type Result = [u8; size_of::>>()]; } @@ -320,7 +324,6 @@ macro_rules! tcx_lifetime { } tcx_lifetime! { - rustc_middle::hir::Owner, rustc_middle::middle::exported_symbols::ExportedSymbol, rustc_middle::mir::Const, rustc_middle::mir::DestructuredConstant, diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index 945f17d5df2a..69d3974184db 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -9,6 +9,7 @@ use crate::ty::{self, Ty, TyCtxt}; use crate::ty::{GenericArg, GenericArgsRef}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalModDefId, ModDefId, LOCAL_CRATE}; use rustc_hir::hir_id::{HirId, OwnerId}; +use rustc_query_system::query::DefIdCacheSelector; use rustc_query_system::query::{DefaultCacheSelector, SingleCacheSelector, VecCacheSelector}; use rustc_span::symbol::{Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; @@ -152,7 +153,7 @@ impl Key for LocalDefId { } impl Key for DefId { - type CacheSelector = DefaultCacheSelector; + type CacheSelector = DefIdCacheSelector; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { tcx.def_span(*self) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 1dc772208810..a9dc7f5d11a2 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -174,14 +174,6 @@ rustc_queries! { cache_on_disk_if { true } } - /// Gives access to the HIR node for the HIR owner `key`. - /// - /// This can be conveniently accessed by methods on `tcx.hir()`. - /// Avoid calling this query directly. - query hir_owner(key: hir::OwnerId) -> Option> { - desc { |tcx| "getting HIR owner of `{}`", tcx.def_path_str(key) } - } - /// Gives access to the HIR ID for the given `LocalDefId` owner `key` if any. /// /// Definitions that were generated with no HIR, would be fed to return `None`. @@ -859,13 +851,13 @@ rustc_queries! { /// Maps a `DefId` of a type to a list of its inherent impls. /// Contains implementations of methods that are inherent to a type. /// Methods in these implementations don't need to be exported. - query inherent_impls(key: DefId) -> &'tcx [DefId] { + query inherent_impls(key: DefId) -> Result<&'tcx [DefId], ErrorGuaranteed> { desc { |tcx| "collecting inherent impls for `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } separate_provide_extern } - query incoherent_impls(key: SimplifiedType) -> &'tcx [DefId] { + query incoherent_impls(key: SimplifiedType) -> Result<&'tcx [DefId], ErrorGuaranteed> { desc { |tcx| "collecting all inherent impls for `{:?}`", key } } @@ -961,8 +953,9 @@ rustc_queries! { desc { |tcx| "checking deathness of variables in {}", describe_as_module(key, tcx) } } - query check_mod_impl_wf(key: LocalModDefId) -> () { + query check_mod_impl_wf(key: LocalModDefId) -> Result<(), ErrorGuaranteed> { desc { |tcx| "checking that impls are well-formed in {}", describe_as_module(key, tcx) } + ensure_forwards_result_if_red } query check_mod_type_wf(key: LocalModDefId) -> Result<(), ErrorGuaranteed> { @@ -1011,15 +1004,16 @@ rustc_queries! { /// Gets a complete map from all types to their inherent impls. /// Not meant to be used directly outside of coherence. - query crate_inherent_impls(k: ()) -> &'tcx CrateInherentImpls { - arena_cache + query crate_inherent_impls(k: ()) -> Result<&'tcx CrateInherentImpls, ErrorGuaranteed> { desc { "finding all inherent impls defined in crate" } + ensure_forwards_result_if_red } /// Checks all types in the crate for overlap in their inherent impls. Reports errors. /// Not meant to be used directly outside of coherence. - query crate_inherent_impls_overlap_check(_: ()) -> () { + query crate_inherent_impls_overlap_check(_: ()) -> Result<(), ErrorGuaranteed> { desc { "check for overlap between inherent impls defined in this crate" } + ensure_forwards_result_if_red } /// Checks whether all impls in the crate pass the overlap check, returning @@ -1645,7 +1639,7 @@ rustc_queries! { /// /// Do not call this directly, but instead use the `incoherent_impls` query. /// This query is only used to get the data necessary for that query. - query crate_incoherent_impls(key: (CrateNum, SimplifiedType)) -> &'tcx [DefId] { + query crate_incoherent_impls(key: (CrateNum, SimplifiedType)) -> Result<&'tcx [DefId], ErrorGuaranteed> { desc { |tcx| "collecting all impls for a type in a crate" } separate_provide_extern } @@ -1949,7 +1943,7 @@ rustc_queries! { desc { "normalizing `{}`", goal.value } } - query implied_outlives_bounds( + query implied_outlives_bounds_compat( goal: CanonicalTyGoal<'tcx> ) -> Result< &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec>>>, @@ -1958,6 +1952,15 @@ rustc_queries! { desc { "computing implied outlives bounds for `{}`", goal.value.value } } + query implied_outlives_bounds( + goal: CanonicalTyGoal<'tcx> + ) -> Result< + &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec>>>, + NoSolution, + > { + desc { "computing implied outlives bounds v2 for `{}`", goal.value.value } + } + /// Do not call this query directly: /// invoke `DropckOutlives::new(dropped_ty)).fully_perform(typeck.infcx)` instead. query dropck_outlives( diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index a41d4f1ad589..8d88488e1675 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -174,7 +174,7 @@ pub fn query_ensure<'tcx, Cache>( } #[inline] -pub fn query_ensure_error_guaranteed<'tcx, Cache>( +pub fn query_ensure_error_guaranteed<'tcx, Cache, T>( tcx: TyCtxt<'tcx>, execute_query: fn(TyCtxt<'tcx>, Span, Cache::Key, QueryMode) -> Option, query_cache: &Cache, @@ -182,14 +182,16 @@ pub fn query_ensure_error_guaranteed<'tcx, Cache>( check_cache: bool, ) -> Result<(), ErrorGuaranteed> where - Cache: QueryCache>>, + Cache: QueryCache>>, + Result: EraseType, { let key = key.into_query_param(); if let Some(res) = try_get_cached(tcx, query_cache, &key) { - super::erase::restore(res) + super::erase::restore(res).map(drop) } else { execute_query(tcx, DUMMY_SP, key, QueryMode::Ensure { check_cache }) .map(super::erase::restore) + .map(|res| res.map(drop)) // Either we actually executed the query, which means we got a full `Result`, // or we can just assume the query succeeded, because it was green in the // incremental cache. If it is green, that means that the previous compilation @@ -205,7 +207,7 @@ macro_rules! query_ensure { query_ensure($($args)*) }; ([(ensure_forwards_result_if_red) $($rest:tt)*]$($args:tt)*) => { - query_ensure_error_guaranteed($($args)*) + query_ensure_error_guaranteed($($args)*).map(|_| ()) }; ([$other:tt $($modifiers:tt)*]$($args:tt)*) => { query_ensure!([$($modifiers)*]$($args)*) @@ -667,5 +669,7 @@ mod sealed { pub use sealed::IntoQueryParam; +use super::erase::EraseType; + #[derive(Copy, Clone, Debug, HashStable)] pub struct CyclePlaceholder(pub ErrorGuaranteed); diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index bebee8df10e8..135680b93493 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -604,7 +604,7 @@ pub enum SelectionError<'tcx> { /// After a closure impl has selected, its "outputs" were evaluated /// (which for closures includes the "input" type params) and they /// didn't resolve. See `confirm_poly_trait_refs` for more. - OutputTypeParameterMismatch(Box>), + SignatureMismatch(Box>), /// The trait pointed by `DefId` is not object safe. TraitNotObjectSafe(DefId), /// A given constant couldn't be evaluated. @@ -618,7 +618,7 @@ pub enum SelectionError<'tcx> { } #[derive(Clone, Debug, TypeVisitable)] -pub struct SelectionOutputTypeParameterMismatch<'tcx> { +pub struct SignatureMismatchData<'tcx> { pub found_trait_ref: ty::PolyTraitRef<'tcx>, pub expected_trait_ref: ty::PolyTraitRef<'tcx>, pub terr: ty::error::TypeError<'tcx>, diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs index 5f02dd22961c..61d96cad57d7 100644 --- a/compiler/rustc_middle/src/traits/query.rs +++ b/compiler/rustc_middle/src/traits/query.rs @@ -191,7 +191,7 @@ pub struct NormalizationResult<'tcx> { /// case they are called implied bounds). They are fed to the /// `OutlivesEnv` which in turn is supplied to the region checker and /// other parts of the inference system. -#[derive(Clone, Debug, TypeFoldable, TypeVisitable, HashStable)] +#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, HashStable)] pub enum OutlivesBound<'tcx> { RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>), RegionSubParam(ty::Region<'tcx>, ty::ParamTy), diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index ad9296a4cc88..a5d9e0fcf44c 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2535,8 +2535,7 @@ impl<'tcx> TyCtxt<'tcx> { if self.sess.opts.unstable_opts.debug_macros || !span.from_expansion() { return span; } - let collapse_debuginfo_enabled = self.features().collapse_debuginfo; - hygiene::walk_chain_collapsed(span, upto, collapse_debuginfo_enabled) + hygiene::walk_chain_collapsed(span, upto, self.features().collapse_debuginfo) } #[inline] diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index a10bdc6012c0..4028de27cae1 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -15,7 +15,6 @@ use rustc_hir::def::{self, CtorKind, DefKind, Namespace}; use rustc_hir::def_id::{DefIdMap, DefIdSet, ModDefId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::definitions::{DefKey, DefPathDataName}; use rustc_hir::LangItem; -use rustc_session::config::TrimmedDefPaths; use rustc_session::cstore::{ExternCrate, ExternCrateSource}; use rustc_session::Limit; use rustc_span::symbol::{kw, Ident, Symbol}; @@ -365,26 +364,19 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { /// Try to see if this path can be trimmed to a unique symbol name. fn try_print_trimmed_def_path(&mut self, def_id: DefId) -> Result { - if with_forced_trimmed_paths() { - let trimmed = self.force_print_trimmed_def_path(def_id)?; - if trimmed { - return Ok(true); - } + if with_forced_trimmed_paths() && self.force_print_trimmed_def_path(def_id)? { + return Ok(true); } - if !self.tcx().sess.opts.unstable_opts.trim_diagnostic_paths - || matches!(self.tcx().sess.opts.trimmed_def_paths, TrimmedDefPaths::Never) - || with_no_trimmed_paths() - || with_crate_prefix() + if self.tcx().sess.opts.unstable_opts.trim_diagnostic_paths + && self.tcx().sess.opts.trimmed_def_paths + && !with_no_trimmed_paths() + && !with_crate_prefix() + && let Some(symbol) = self.tcx().trimmed_def_paths(()).get(&def_id) { - return Ok(false); - } - - match self.tcx().trimmed_def_paths(()).get(&def_id) { - None => Ok(false), - Some(symbol) => { - write!(self, "{}", Ident::with_dummy_span(*symbol))?; - Ok(true) - } + write!(self, "{}", Ident::with_dummy_span(*symbol))?; + Ok(true) + } else { + Ok(false) } } @@ -1021,7 +1013,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { .extend( // Group the return ty with its def id, if we had one. entry.return_ty.map(|ty| { - (tcx.require_lang_item(LangItem::FnOnce, None), ty) + (tcx.require_lang_item(LangItem::FnOnceOutput, None), ty) }), ); } @@ -3080,18 +3072,19 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N /// See also [`DelayDm`](rustc_error_messages::DelayDm) and [`with_no_trimmed_paths!`]. // this is pub to be able to intra-doc-link it pub fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> DefIdMap { - let mut map: DefIdMap = Default::default(); + assert!(tcx.sess.opts.trimmed_def_paths); - if let TrimmedDefPaths::GoodPath = tcx.sess.opts.trimmed_def_paths { - // Trimming paths is expensive and not optimized, since we expect it to only be used for error reporting. - // - // For good paths causing this bug, the `rustc_middle::ty::print::with_no_trimmed_paths` - // wrapper can be used to suppress this query, in exchange for full paths being formatted. - tcx.sess.good_path_delayed_bug( - "trimmed_def_paths constructed but no error emitted; use `DelayDm` for lints or `with_no_trimmed_paths` for debugging", - ); - } + // Trimming paths is expensive and not optimized, since we expect it to only be used for error + // reporting. + // + // For good paths causing this bug, the `rustc_middle::ty::print::with_no_trimmed_paths` + // wrapper can be used to suppress this query, in exchange for full paths being formatted. + tcx.sess.good_path_delayed_bug( + "trimmed_def_paths constructed but no error emitted; use `DelayDm` for lints or `with_no_trimmed_paths` for debugging", + ); + // Once constructed, unique namespace+symbol pairs will have a `Some(_)` entry, while + // non-unique pairs will have a `None` entry. let unique_symbols_rev: &mut FxHashMap<(Namespace, Symbol), Option> = &mut FxHashMap::default(); @@ -3121,6 +3114,8 @@ pub fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> DefIdMap { } }); + // Put the symbol from all the unique namespace+symbol pairs into `map`. + let mut map: DefIdMap = Default::default(); for ((_, symbol), opt_def_id) in unique_symbols_rev.drain() { use std::collections::hash_map::Entry::{Occupied, Vacant}; diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 7c869adbd832..11b579a1f85b 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -9,6 +9,7 @@ use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer}; use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; use crate::ty::{self, AliasTy, InferConst, Lift, Term, TermKind, Ty, TyCtxt}; use rustc_hir::def::Namespace; +use rustc_span::source_map::Spanned; use rustc_target::abi::TyAndLayout; use rustc_type_ir::{ConstKind, DebugWithInfcx, InferCtxtLike, WithInfcx}; @@ -819,3 +820,27 @@ impl<'tcx> TypeVisitable> for TyAndLayout<'tcx, Ty<'tcx>> { visitor.visit_ty(self.ty) } } + +impl<'tcx, T: TypeVisitable> + Debug + Clone> TypeVisitable> + for Spanned +{ + fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { + self.node.visit_with(visitor)?; + self.span.visit_with(visitor)?; + ControlFlow::Continue(()) + } +} + +impl<'tcx, T: TypeFoldable> + Debug + Clone> TypeFoldable> + for Spanned +{ + fn try_fold_with>>( + self, + folder: &mut F, + ) -> Result { + Ok(Spanned { + node: self.node.try_fold_with(folder)?, + span: self.span.try_fold_with(folder)?, + }) + } +} diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index 227a0753d042..d85b541d3638 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -254,16 +254,28 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait } /// Query provider for `incoherent_impls`. -pub(super) fn incoherent_impls_provider(tcx: TyCtxt<'_>, simp: SimplifiedType) -> &[DefId] { +pub(super) fn incoherent_impls_provider( + tcx: TyCtxt<'_>, + simp: SimplifiedType, +) -> Result<&[DefId], ErrorGuaranteed> { let mut impls = Vec::new(); + let mut res = Ok(()); for cnum in iter::once(LOCAL_CRATE).chain(tcx.crates(()).iter().copied()) { - for &impl_def_id in tcx.crate_incoherent_impls((cnum, simp)) { + let incoherent_impls = match tcx.crate_incoherent_impls((cnum, simp)) { + Ok(impls) => impls, + Err(e) => { + res = Err(e); + continue; + } + }; + for &impl_def_id in incoherent_impls { impls.push(impl_def_id) } } debug!(?impls); + res?; - tcx.arena.alloc_slice(&impls) + Ok(tcx.arena.alloc_slice(&impls)) } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 372f11a5accf..ef621f29bfd7 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -604,19 +604,15 @@ impl<'tcx> TyCtxt<'tcx> { /// wrapped in a binder. pub fn closure_env_ty( self, - closure_def_id: DefId, - closure_args: GenericArgsRef<'tcx>, + closure_ty: Ty<'tcx>, + closure_kind: ty::ClosureKind, env_region: ty::Region<'tcx>, - ) -> Option> { - let closure_ty = Ty::new_closure(self, closure_def_id, closure_args); - let closure_kind_ty = closure_args.as_closure().kind_ty(); - let closure_kind = closure_kind_ty.to_opt_closure_kind()?; - let env_ty = match closure_kind { + ) -> Ty<'tcx> { + match closure_kind { ty::ClosureKind::Fn => Ty::new_imm_ref(self, env_region, closure_ty), ty::ClosureKind::FnMut => Ty::new_mut_ref(self, env_region, closure_ty), ty::ClosureKind::FnOnce => closure_ty, - }; - Some(env_ty) + } } /// Returns `true` if the node pointed to by `def_id` is a `static` item. diff --git a/compiler/rustc_middle/src/util/find_self_call.rs b/compiler/rustc_middle/src/util/find_self_call.rs index 9f1e4ac11c23..0ca4fce5da9b 100644 --- a/compiler/rustc_middle/src/util/find_self_call.rs +++ b/compiler/rustc_middle/src/util/find_self_call.rs @@ -2,6 +2,7 @@ use crate::mir::*; use crate::ty::GenericArgsRef; use crate::ty::{self, TyCtxt}; use rustc_span::def_id::DefId; +use rustc_span::source_map::Spanned; /// Checks if the specified `local` is used as the `self` parameter of a method call /// in the provided `BasicBlock`. If it is, then the `DefId` of the called method is @@ -23,7 +24,13 @@ pub fn find_self_call<'tcx>( tcx.opt_associated_item(def_id) { debug!("find_self_call: args={:?}", fn_args); - if let [Operand::Move(self_place) | Operand::Copy(self_place), ..] = **args { + if let [ + Spanned { + node: Operand::Move(self_place) | Operand::Copy(self_place), .. + }, + .., + ] = **args + { if self_place.as_local() == Some(local) { return Some((def_id, fn_args)); } diff --git a/compiler/rustc_mir_build/Cargo.toml b/compiler/rustc_mir_build/Cargo.toml index 6d681dc295ef..d71f71213220 100644 --- a/compiler/rustc_mir_build/Cargo.toml +++ b/compiler/rustc_mir_build/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start either = "1" +itertools = "0.11" rustc_apfloat = "0.2.0" rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 615b553434fe..2f11cb123ee1 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -234,6 +234,11 @@ mir_build_mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsa mir_build_non_const_path = runtime values cannot be referenced in patterns +mir_build_non_empty_never_pattern = + mismatched types + .label = a never pattern must be used on an uninhabited type + .note = the matched value is of type `{$ty}` + mir_build_non_exhaustive_match_all_arms_guarded = match arms with guards don't count towards exhaustivity diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs index e3dea2212df0..5428333a1161 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs @@ -2,6 +2,7 @@ use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::ty::cast::mir_cast_kind; use rustc_middle::{mir::*, thir::*, ty}; +use rustc_span::source_map::Spanned; use rustc_span::Span; use rustc_target::abi::{FieldIdx, VariantIdx}; @@ -162,7 +163,9 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { let fun = self.parse_operand(*fun)?; let args = args .iter() - .map(|arg| self.parse_operand(*arg)) + .map(|arg| + Ok(Spanned { node: self.parse_operand(*arg)?, span: self.thir.exprs[*arg].span } ) + ) .collect::>>()?; Ok(TerminatorKind::Call { func: fun, diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index f799be165ecd..6e8af7bb6df6 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -2,6 +2,7 @@ use rustc_index::{Idx, IndexVec}; use rustc_middle::ty::util::IntTypeExt; +use rustc_span::source_map::Spanned; use rustc_target::abi::{Abi, FieldIdx, Primitive}; use crate::build::expr::as_place::PlaceBase; @@ -15,7 +16,7 @@ use rustc_middle::thir::*; use rustc_middle::ty::cast::{mir_cast_kind, CastTy}; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{self, Ty, UpvarArgs}; -use rustc_span::Span; +use rustc_span::{Span, DUMMY_SP}; impl<'a, 'tcx> Builder<'a, 'tcx> { /// Returns an rvalue suitable for use until the end of the current @@ -156,7 +157,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { synth_info, TerminatorKind::Call { func: exchange_malloc, - args: vec![Operand::Move(size), Operand::Move(align)], + args: vec![ + Spanned { node: Operand::Move(size), span: DUMMY_SP }, + Spanned { node: Operand::Move(align), span: DUMMY_SP }, + ], destination: storage, target: Some(success), unwind: UnwindAction::Continue, @@ -733,7 +737,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.diverge_from(block); block = success; } - this.record_operands_moved(&[value_operand]); + this.record_operands_moved(&[Spanned { node: value_operand, span: DUMMY_SP }]); } block.and(Rvalue::Aggregate(Box::new(AggregateKind::Array(elem_ty)), IndexVec::new())) } diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 060a3b521a4f..2978491d646e 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -9,6 +9,7 @@ use rustc_hir as hir; use rustc_middle::mir::*; use rustc_middle::thir::*; use rustc_middle::ty::CanonicalUserTypeAnnotation; +use rustc_span::source_map::Spanned; use std::iter; impl<'a, 'tcx> Builder<'a, 'tcx> { @@ -248,7 +249,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let args: Vec<_> = args .into_iter() .copied() - .map(|arg| unpack!(block = this.as_local_call_operand(block, arg))) + .map(|arg| Spanned { + node: unpack!(block = this.as_local_call_operand(block, arg)), + span: this.thir.exprs[arg].span, + }) .collect(); let success = this.cfg.start_new_block(); diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index 53e5d70f946e..990be30b2d68 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -17,8 +17,9 @@ use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::GenericArg; use rustc_middle::ty::{self, adjustment::PointerCoercion, Ty, TyCtxt}; use rustc_span::def_id::DefId; +use rustc_span::source_map::Spanned; use rustc_span::symbol::{sym, Symbol}; -use rustc_span::Span; +use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::VariantIdx; use std::cmp::Ordering; @@ -271,7 +272,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { user_ty: None, const_: method, })), - args: vec![Operand::Move(ref_string)], + args: vec![Spanned { node: Operand::Move(ref_string), span: DUMMY_SP }], destination: ref_str, target: Some(eq_block), unwind: UnwindAction::Continue, @@ -526,7 +527,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { const_: method, })), - args: vec![Operand::Copy(val), expect], + args: vec![ + Spanned { node: Operand::Copy(val), span: DUMMY_SP }, + Spanned { node: expect, span: DUMMY_SP }, + ], destination: eq_result, target: Some(eq_block), unwind: UnwindAction::Continue, diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index b8d08319422d..714c5f2686eb 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -1,5 +1,6 @@ use crate::build::expr::as_place::PlaceBuilder; use crate::build::scope::DropKind; +use itertools::Itertools; use rustc_apfloat::ieee::{Double, Single}; use rustc_apfloat::Float; use rustc_ast::attr; @@ -654,7 +655,7 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) - ty::ClosureKind::FnOnce => closure_ty, }; ( - [self_ty].into_iter().chain(sig.inputs().to_vec()).collect(), + [self_ty].into_iter().chain(sig.inputs()[0].tuple_fields()).collect(), sig.output(), None, ) @@ -835,7 +836,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.upvars = tcx .closure_captures(self.def_id) .iter() - .zip(capture_tys) + .zip_eq(capture_tys) .enumerate() .map(|(i, (captured_place, ty))| { let name = captured_place.to_symbol(); diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index 48b237f3ae62..6827797df372 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -91,6 +91,7 @@ use rustc_middle::middle::region; use rustc_middle::mir::*; use rustc_middle::thir::{ExprId, LintLevel}; use rustc_session::lint::Level; +use rustc_span::source_map::Spanned; use rustc_span::{Span, DUMMY_SP}; #[derive(Debug)] @@ -1020,14 +1021,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// spurious borrow-check errors -- the problem, ironically, is /// not the `DROP(_X)` itself, but the (spurious) unwind pathways /// that it creates. See #64391 for an example. - pub(crate) fn record_operands_moved(&mut self, operands: &[Operand<'tcx>]) { + pub(crate) fn record_operands_moved(&mut self, operands: &[Spanned>]) { let local_scope = self.local_scope(); let scope = self.scopes.scopes.last_mut().unwrap(); assert_eq!(scope.region_scope, local_scope, "local scope is not the topmost scope!",); // look for moves of a local variable, like `MOVE(_X)` - let locals_moved = operands.iter().flat_map(|operand| match operand { + let locals_moved = operands.iter().flat_map(|operand| match operand.node { Operand::Copy(_) | Operand::Constant(_) => None, Operand::Move(place) => place.as_local(), }); diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 61ad99acf38a..e3cc21cef11c 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -788,6 +788,16 @@ pub struct FloatPattern; #[diag(mir_build_pointer_pattern)] pub struct PointerPattern; +#[derive(Diagnostic)] +#[diag(mir_build_non_empty_never_pattern)] +#[note] +pub struct NonEmptyNeverPattern<'tcx> { + #[primary_span] + #[label] + pub span: Span, + pub ty: Ty<'tcx>, +} + #[derive(LintDiagnostic)] #[diag(mir_build_indirect_structural_match)] #[note(mir_build_type_not_structural_tip)] diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 78d72b302841..22094c112fc1 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -2,6 +2,7 @@ use crate::errors; use crate::thir::cx::region::Scope; use crate::thir::cx::Cx; use crate::thir::util::UserAnnotatedTyHelpers; +use itertools::Itertools; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; @@ -565,7 +566,7 @@ impl<'tcx> Cx<'tcx> { .tcx .closure_captures(def_id) .iter() - .zip(args.upvar_tys()) + .zip_eq(args.upvar_tys()) .map(|(captured_place, ty)| { let upvars = self.capture_upvar(expr, captured_place, ty); self.thir.exprs.push(upvars) diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index fa3dd2afa85d..5d0bb3954ccc 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -117,50 +117,32 @@ impl<'tcx> Cx<'tcx> { pat_from_hir(self.tcx, self.param_env, self.typeck_results(), p) } - fn closure_env_param(&self, owner_def: LocalDefId, owner_id: HirId) -> Option> { - match self.tcx.def_kind(owner_def) { - DefKind::Closure if self.tcx.is_coroutine(owner_def.to_def_id()) => { - let coroutine_ty = self.typeck_results.node_type(owner_id); - let coroutine_param = Param { - ty: coroutine_ty, - pat: None, - ty_span: None, - self_kind: None, - hir_id: None, - }; - Some(coroutine_param) - } - DefKind::Closure => { - let closure_ty = self.typeck_results.node_type(owner_id); - - let ty::Closure(closure_def_id, closure_args) = *closure_ty.kind() else { - bug!("closure expr does not have closure type: {:?}", closure_ty); - }; - - let bound_vars = - self.tcx.mk_bound_variable_kinds(&[ty::BoundVariableKind::Region(ty::BrEnv)]); - let br = ty::BoundRegion { - var: ty::BoundVar::from_usize(bound_vars.len() - 1), - kind: ty::BrEnv, - }; - let env_region = ty::Region::new_bound(self.tcx, ty::INNERMOST, br); - let closure_env_ty = - self.tcx.closure_env_ty(closure_def_id, closure_args, env_region).unwrap(); - let liberated_closure_env_ty = self.tcx.instantiate_bound_regions_with_erased( - ty::Binder::bind_with_vars(closure_env_ty, bound_vars), - ); - let env_param = Param { - ty: liberated_closure_env_ty, - pat: None, - ty_span: None, - self_kind: None, - hir_id: None, - }; - - Some(env_param) - } - _ => None, + fn closure_env_param(&self, owner_def: LocalDefId, expr_id: HirId) -> Option> { + if self.tcx.def_kind(owner_def) != DefKind::Closure { + return None; } + + let closure_ty = self.typeck_results.node_type(expr_id); + Some(match *closure_ty.kind() { + ty::Coroutine(..) => { + Param { ty: closure_ty, pat: None, ty_span: None, self_kind: None, hir_id: None } + } + ty::Closure(_, closure_args) => { + let closure_env_ty = self.tcx.closure_env_ty( + closure_ty, + closure_args.as_closure().kind(), + self.tcx.lifetimes.re_erased, + ); + Param { + ty: closure_env_ty, + pat: None, + ty_span: None, + self_kind: None, + hir_id: None, + } + } + _ => bug!("unexpected closure type: {closure_ty}"), + }) } fn explicit_params<'a>( diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index f6c5e4a5cd6e..693dc49c6e8f 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -276,10 +276,13 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { } else { // Check the pattern for some things unrelated to exhaustiveness. let refutable = if cx.refutable { Refutable } else { Irrefutable }; + let mut err = Ok(()); pat.walk_always(|pat| { check_borrow_conflicts_in_at_patterns(self, pat); check_for_bindings_named_same_as_variants(self, pat, refutable); + err = err.and(check_never_pattern(cx, pat)); }); + err?; Ok(cx.pattern_arena.alloc(cx.lower_pat(pat))) } } @@ -289,7 +292,8 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { fn is_known_valid_scrutinee(&self, scrutinee: &Expr<'tcx>) -> bool { use ExprKind::*; match &scrutinee.kind { - // Both pointers and references can validly point to a place with invalid data. + // Pointers can validly point to a place with invalid data. It is undecided whether + // references can too, so we conservatively assume they can. Deref { .. } => false, // Inherit validity of the parent place, unless the parent is an union. Field { lhs, .. } => { @@ -811,6 +815,19 @@ fn check_for_bindings_named_same_as_variants( } } +/// Check that never patterns are only used on inhabited types. +fn check_never_pattern<'tcx>( + cx: &MatchCheckCtxt<'_, 'tcx>, + pat: &Pat<'tcx>, +) -> Result<(), ErrorGuaranteed> { + if let PatKind::Never = pat.kind { + if !cx.is_uninhabited(pat.ty) { + return Err(cx.tcx.dcx().emit_err(NonEmptyNeverPattern { span: pat.span, ty: pat.ty })); + } + } + Ok(()) +} + fn report_irrefutable_let_patterns( tcx: TyCtxt<'_>, id: HirId, @@ -1113,7 +1130,7 @@ fn collect_non_exhaustive_tys<'tcx>( non_exhaustive_tys.insert(pat.ty().inner()); } if let Constructor::IntRange(range) = pat.ctor() { - if cx.is_range_beyond_boundaries(range, pat.ty()) { + if cx.is_range_beyond_boundaries(range, *pat.ty()) { // The range denotes the values before `isize::MIN` or the values after `usize::MAX`/`isize::MAX`. non_exhaustive_tys.insert(pat.ty().inner()); } diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index c4987634b78b..ff7e985bdfdc 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -345,6 +345,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { } hir::PatKind::Or(pats) => PatKind::Or { pats: self.lower_patterns(pats) }, + + hir::PatKind::Err(guar) => PatKind::Error(guar), }; Box::new(Pat { span, ty, kind }) diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index c9930565186f..862876f53c76 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -7,6 +7,8 @@ use rustc_middle::traits::Reveal; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::GenericArgsRef; use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_span::source_map::Spanned; +use rustc_span::DUMMY_SP; use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT}; use std::{fmt, iter}; @@ -652,7 +654,10 @@ where [ty.into()], self.source_info.span, ), - args: vec![Operand::Move(Place::from(ref_place))], + args: vec![Spanned { + node: Operand::Move(Place::from(ref_place)), + span: DUMMY_SP, + }], destination: unit_temp, target: Some(succ), unwind: unwind.into_action(), diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index f0b21fd41847..b805f8ca23eb 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -34,6 +34,7 @@ mod errors; mod framework; pub mod impls; pub mod move_paths; +pub mod points; pub mod rustc_peek; pub mod storage; pub mod un_derefer; diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index cae357653087..38ee26c5a876 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -469,7 +469,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { } => { self.gather_operand(func); for arg in args { - self.gather_operand(arg); + self.gather_operand(&arg.node); } if let Some(_bb) = target { self.create_move_path(destination); diff --git a/compiler/rustc_mir_dataflow/src/points.rs b/compiler/rustc_mir_dataflow/src/points.rs new file mode 100644 index 000000000000..ff17ce1fe079 --- /dev/null +++ b/compiler/rustc_mir_dataflow/src/points.rs @@ -0,0 +1,156 @@ +use crate::framework::{visit_results, ResultsVisitable, ResultsVisitor}; +use rustc_index::bit_set::ChunkedBitSet; +use rustc_index::interval::SparseIntervalMatrix; +use rustc_index::Idx; +use rustc_index::IndexVec; +use rustc_middle::mir::{self, BasicBlock, Body, Location}; + +/// Maps between a `Location` and a `PointIndex` (and vice versa). +pub struct DenseLocationMap { + /// For each basic block, how many points are contained within? + statements_before_block: IndexVec, + + /// Map backward from each point to the basic block that it + /// belongs to. + basic_blocks: IndexVec, + + num_points: usize, +} + +impl DenseLocationMap { + #[inline] + pub fn new(body: &Body<'_>) -> Self { + let mut num_points = 0; + let statements_before_block: IndexVec = body + .basic_blocks + .iter() + .map(|block_data| { + let v = num_points; + num_points += block_data.statements.len() + 1; + v + }) + .collect(); + + let mut basic_blocks = IndexVec::with_capacity(num_points); + for (bb, bb_data) in body.basic_blocks.iter_enumerated() { + basic_blocks.extend((0..=bb_data.statements.len()).map(|_| bb)); + } + + Self { statements_before_block, basic_blocks, num_points } + } + + /// Total number of point indices + #[inline] + pub fn num_points(&self) -> usize { + self.num_points + } + + /// Converts a `Location` into a `PointIndex`. O(1). + #[inline] + pub fn point_from_location(&self, location: Location) -> PointIndex { + let Location { block, statement_index } = location; + let start_index = self.statements_before_block[block]; + PointIndex::new(start_index + statement_index) + } + + /// Returns the `PointIndex` for the first statement in the given `BasicBlock`. O(1). + #[inline] + pub fn entry_point(&self, block: BasicBlock) -> PointIndex { + let start_index = self.statements_before_block[block]; + PointIndex::new(start_index) + } + + /// Return the PointIndex for the block start of this index. + #[inline] + pub fn to_block_start(&self, index: PointIndex) -> PointIndex { + PointIndex::new(self.statements_before_block[self.basic_blocks[index]]) + } + + /// Converts a `PointIndex` back to a location. O(1). + #[inline] + pub fn to_location(&self, index: PointIndex) -> Location { + assert!(index.index() < self.num_points); + let block = self.basic_blocks[index]; + let start_index = self.statements_before_block[block]; + let statement_index = index.index() - start_index; + Location { block, statement_index } + } + + /// Sometimes we get point-indices back from bitsets that may be + /// out of range (because they round up to the nearest 2^N number + /// of bits). Use this function to filter such points out if you + /// like. + #[inline] + pub fn point_in_range(&self, index: PointIndex) -> bool { + index.index() < self.num_points + } +} + +rustc_index::newtype_index! { + /// A single integer representing a `Location` in the MIR control-flow + /// graph. Constructed efficiently from `DenseLocationMap`. + #[orderable] + #[debug_format = "PointIndex({})"] + pub struct PointIndex {} +} + +/// Add points depending on the result of the given dataflow analysis. +pub fn save_as_intervals<'tcx, N, R>( + elements: &DenseLocationMap, + body: &mir::Body<'tcx>, + mut results: R, +) -> SparseIntervalMatrix +where + N: Idx, + R: ResultsVisitable<'tcx, FlowState = ChunkedBitSet>, +{ + let values = SparseIntervalMatrix::new(elements.num_points()); + let mut visitor = Visitor { elements, values }; + visit_results( + body, + body.basic_blocks.reverse_postorder().iter().copied(), + &mut results, + &mut visitor, + ); + visitor.values +} + +struct Visitor<'a, N: Idx> { + elements: &'a DenseLocationMap, + values: SparseIntervalMatrix, +} + +impl<'mir, 'tcx, R, N> ResultsVisitor<'mir, 'tcx, R> for Visitor<'_, N> +where + N: Idx, +{ + type FlowState = ChunkedBitSet; + + fn visit_statement_after_primary_effect( + &mut self, + _results: &mut R, + state: &Self::FlowState, + _statement: &'mir mir::Statement<'tcx>, + location: Location, + ) { + let point = self.elements.point_from_location(location); + // Use internal iterator manually as it is much more efficient. + state.iter().for_each(|node| { + self.values.insert(node, point); + }); + } + + fn visit_terminator_after_primary_effect( + &mut self, + _results: &mut R, + state: &Self::FlowState, + _terminator: &'mir mir::Terminator<'tcx>, + location: Location, + ) { + let point = self.elements.point_from_location(location); + // Use internal iterator manually as it is much more efficient. + state.iter().for_each(|node| { + self.values.insert(node, point); + }); + } +} diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs index 5373876d1c2c..08a5d70fb6fc 100644 --- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs +++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs @@ -209,7 +209,7 @@ impl PeekCall { assert_eq!(fn_args.len(), 1); let kind = PeekCallKind::from_arg_ty(fn_args.type_at(0)); - let arg = match &args[0] { + let arg = match &args[0].node { Operand::Copy(place) | Operand::Move(place) => { if let Some(local) = place.as_local() { local diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 379e96e263c2..eaa36e0cc91e 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -675,9 +675,9 @@ fn eliminate_get_context_call<'tcx>(bb_data: &mut BasicBlockData<'tcx>) -> Local let terminator = bb_data.terminator.take().unwrap(); if let TerminatorKind::Call { mut args, destination, target, .. } = terminator.kind { let arg = args.pop().unwrap(); - let local = arg.place().unwrap().local; + let local = arg.node.place().unwrap().local; - let arg = Rvalue::Use(arg); + let arg = Rvalue::Use(arg.node); let assign = Statement { source_info: terminator.source_info, kind: StatementKind::Assign(Box::new((destination, arg))), @@ -1865,7 +1865,7 @@ impl<'tcx> Visitor<'tcx> for EnsureCoroutineFieldAssignmentsNeverAlias<'_> { self.check_assigned_place(*destination, |this| { this.visit_operand(func, location); for arg in args { - this.visit_operand(arg, location); + this.visit_operand(&arg.node, location); } }); } diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs index 263bfdaaabab..c6badbe78a49 100644 --- a/compiler/rustc_mir_transform/src/coverage/graph.rs +++ b/compiler/rustc_mir_transform/src/coverage/graph.rs @@ -1,9 +1,10 @@ use rustc_data_structures::captures::Captures; +use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::graph::dominators::{self, Dominators}; use rustc_data_structures::graph::{self, GraphSuccessors, WithNumNodes, WithStartNode}; use rustc_index::bit_set::BitSet; -use rustc_index::{IndexSlice, IndexVec}; -use rustc_middle::mir::{self, BasicBlock, TerminatorKind}; +use rustc_index::IndexVec; +use rustc_middle::mir::{self, BasicBlock, Terminator, TerminatorKind}; use std::cmp::Ordering; use std::collections::VecDeque; @@ -30,23 +31,16 @@ impl CoverageGraph { // `SwitchInt` to have multiple targets to the same destination `BasicBlock`, so // de-duplication is required. This is done without reordering the successors. - let mut seen = IndexVec::from_elem(false, &bcbs); let successors = IndexVec::from_fn_n( |bcb| { - for b in seen.iter_mut() { - *b = false; - } - let bcb_data = &bcbs[bcb]; - let mut bcb_successors = Vec::new(); - for successor in bcb_filtered_successors(mir_body, bcb_data.last_bb()) + let mut seen_bcbs = FxHashSet::default(); + let terminator = mir_body[bcbs[bcb].last_bb()].terminator(); + bcb_filtered_successors(terminator) + .into_iter() .filter_map(|successor_bb| bb_to_bcb[successor_bb]) - { - if !seen[successor] { - seen[successor] = true; - bcb_successors.push(successor); - } - } - bcb_successors + // Remove duplicate successor BCBs, keeping only the first. + .filter(|&successor_bcb| seen_bcbs.insert(successor_bcb)) + .collect::>() }, bcbs.len(), ); @@ -80,9 +74,23 @@ impl CoverageGraph { IndexVec>, ) { let num_basic_blocks = mir_body.basic_blocks.len(); - let mut bcbs = IndexVec::with_capacity(num_basic_blocks); + let mut bcbs = IndexVec::::with_capacity(num_basic_blocks); let mut bb_to_bcb = IndexVec::from_elem_n(None, num_basic_blocks); + let mut add_basic_coverage_block = |basic_blocks: &mut Vec| { + // Take the accumulated list of blocks, leaving the vector empty + // to be used by subsequent BCBs. + let basic_blocks = std::mem::take(basic_blocks); + + let bcb = bcbs.next_index(); + for &bb in basic_blocks.iter() { + bb_to_bcb[bb] = Some(bcb); + } + let bcb_data = BasicCoverageBlockData::from(basic_blocks); + debug!("adding bcb{}: {:?}", bcb.index(), bcb_data); + bcbs.push(bcb_data); + }; + // Walk the MIR CFG using a Preorder traversal, which starts from `START_BLOCK` and follows // each block terminator's `successors()`. Coverage spans must map to actual source code, // so compiler generated blocks and paths can be ignored. To that end, the CFG traversal @@ -90,102 +98,42 @@ impl CoverageGraph { // FIXME(#78544): MIR InstrumentCoverage: Improve coverage of `#[should_panic]` tests and // `catch_unwind()` handlers. + // Accumulates a chain of blocks that will be combined into one BCB. let mut basic_blocks = Vec::new(); - for bb in short_circuit_preorder(mir_body, bcb_filtered_successors) { - if let Some(last) = basic_blocks.last() { - let predecessors = &mir_body.basic_blocks.predecessors()[bb]; - if predecessors.len() > 1 || !predecessors.contains(last) { - // The `bb` has more than one _incoming_ edge, and should start its own - // `BasicCoverageBlockData`. (Note, the `basic_blocks` vector does not yet - // include `bb`; it contains a sequence of one or more sequential basic_blocks - // with no intermediate branches in or out. Save these as a new - // `BasicCoverageBlockData` before starting the new one.) - Self::add_basic_coverage_block( - &mut bcbs, - &mut bb_to_bcb, - basic_blocks.split_off(0), - ); - debug!( - " because {}", - if predecessors.len() > 1 { - "predecessors.len() > 1".to_owned() - } else { - format!("bb {} is not in predecessors: {:?}", bb.index(), predecessors) - } - ); - } + + let filtered_successors = |bb| bcb_filtered_successors(mir_body[bb].terminator()); + for bb in short_circuit_preorder(mir_body, filtered_successors) + .filter(|&bb| mir_body[bb].terminator().kind != TerminatorKind::Unreachable) + { + // If the previous block can't be chained into `bb`, flush the accumulated + // blocks into a new BCB, then start building the next chain. + if let Some(&prev) = basic_blocks.last() + && (!filtered_successors(prev).is_chainable() || { + // If `bb` has multiple predecessor blocks, or `prev` isn't + // one of its predecessors, we can't chain and must flush. + let predecessors = &mir_body.basic_blocks.predecessors()[bb]; + predecessors.len() > 1 || !predecessors.contains(&prev) + }) + { + debug!( + terminator_kind = ?mir_body[prev].terminator().kind, + predecessors = ?&mir_body.basic_blocks.predecessors()[bb], + "can't chain from {prev:?} to {bb:?}" + ); + add_basic_coverage_block(&mut basic_blocks); } + basic_blocks.push(bb); - - let term = mir_body[bb].terminator(); - - match term.kind { - TerminatorKind::Return { .. } - | TerminatorKind::UnwindTerminate(_) - | TerminatorKind::Yield { .. } - | TerminatorKind::SwitchInt { .. } => { - // The `bb` has more than one _outgoing_ edge, or exits the function. Save the - // current sequence of `basic_blocks` gathered to this point, as a new - // `BasicCoverageBlockData`. - Self::add_basic_coverage_block( - &mut bcbs, - &mut bb_to_bcb, - basic_blocks.split_off(0), - ); - debug!(" because term.kind = {:?}", term.kind); - // Note that this condition is based on `TerminatorKind`, even though it - // theoretically boils down to `successors().len() != 1`; that is, either zero - // (e.g., `Return`, `Terminate`) or multiple successors (e.g., `SwitchInt`), but - // since the BCB CFG ignores things like unwind branches (which exist in the - // `Terminator`s `successors()` list) checking the number of successors won't - // work. - } - - // The following `TerminatorKind`s are either not expected outside an unwind branch, - // or they should not (under normal circumstances) branch. Coverage graphs are - // simplified by assuring coverage results are accurate for program executions that - // don't panic. - // - // Programs that panic and unwind may record slightly inaccurate coverage results - // for a coverage region containing the `Terminator` that began the panic. This - // is as intended. (See Issue #78544 for a possible future option to support - // coverage in test programs that panic.) - TerminatorKind::Goto { .. } - | TerminatorKind::UnwindResume - | TerminatorKind::Unreachable - | TerminatorKind::Drop { .. } - | TerminatorKind::Call { .. } - | TerminatorKind::CoroutineDrop - | TerminatorKind::Assert { .. } - | TerminatorKind::FalseEdge { .. } - | TerminatorKind::FalseUnwind { .. } - | TerminatorKind::InlineAsm { .. } => {} - } } if !basic_blocks.is_empty() { - // process any remaining basic_blocks into a final `BasicCoverageBlockData` - Self::add_basic_coverage_block(&mut bcbs, &mut bb_to_bcb, basic_blocks.split_off(0)); - debug!(" because the end of the MIR CFG was reached while traversing"); + debug!("flushing accumulated blocks into one last BCB"); + add_basic_coverage_block(&mut basic_blocks); } (bcbs, bb_to_bcb) } - fn add_basic_coverage_block( - bcbs: &mut IndexVec, - bb_to_bcb: &mut IndexSlice>, - basic_blocks: Vec, - ) { - let bcb = bcbs.next_index(); - for &bb in basic_blocks.iter() { - bb_to_bcb[bb] = Some(bcb); - } - let bcb_data = BasicCoverageBlockData::from(basic_blocks); - debug!("adding bcb{}: {:?}", bcb.index(), bcb_data); - bcbs.push(bcb_data); - } - #[inline(always)] pub fn iter_enumerated( &self, @@ -346,28 +294,76 @@ impl BasicCoverageBlockData { } } +/// Holds the coverage-relevant successors of a basic block's terminator, and +/// indicates whether that block can potentially be combined into the same BCB +/// as its sole successor. +#[derive(Clone, Copy, Debug)] +enum CoverageSuccessors<'a> { + /// The terminator has exactly one straight-line successor, so its block can + /// potentially be combined into the same BCB as that successor. + Chainable(BasicBlock), + /// The block cannot be combined into the same BCB as its successor(s). + NotChainable(&'a [BasicBlock]), +} + +impl CoverageSuccessors<'_> { + fn is_chainable(&self) -> bool { + match self { + Self::Chainable(_) => true, + Self::NotChainable(_) => false, + } + } +} + +impl IntoIterator for CoverageSuccessors<'_> { + type Item = BasicBlock; + type IntoIter = impl DoubleEndedIterator; + + fn into_iter(self) -> Self::IntoIter { + match self { + Self::Chainable(bb) => Some(bb).into_iter().chain((&[]).iter().copied()), + Self::NotChainable(bbs) => None.into_iter().chain(bbs.iter().copied()), + } + } +} + // Returns the subset of a block's successors that are relevant to the coverage -// graph, i.e. those that do not represent unwinds or unreachable branches. +// graph, i.e. those that do not represent unwinds or false edges. // FIXME(#78544): MIR InstrumentCoverage: Improve coverage of `#[should_panic]` tests and // `catch_unwind()` handlers. -fn bcb_filtered_successors<'a, 'tcx>( - body: &'a mir::Body<'tcx>, - bb: BasicBlock, -) -> impl Iterator + Captures<'a> + Captures<'tcx> { - let terminator = body[bb].terminator(); +fn bcb_filtered_successors<'a, 'tcx>(terminator: &'a Terminator<'tcx>) -> CoverageSuccessors<'a> { + use TerminatorKind::*; + match terminator.kind { + // A switch terminator can have many coverage-relevant successors. + // (If there is exactly one successor, we still treat it as not chainable.) + SwitchInt { ref targets, .. } => CoverageSuccessors::NotChainable(targets.all_targets()), - let take_n_successors = match terminator.kind { - // SwitchInt successors are never unwinds, so all of them should be traversed. - TerminatorKind::SwitchInt { .. } => usize::MAX, - // For all other kinds, return only the first successor (if any), ignoring any - // unwind successors. - _ => 1, - }; + // A yield terminator has exactly 1 successor, but should not be chained, + // because its resume edge has a different execution count. + Yield { ref resume, .. } => CoverageSuccessors::NotChainable(std::slice::from_ref(resume)), - terminator - .successors() - .take(take_n_successors) - .filter(move |&successor| body[successor].terminator().kind != TerminatorKind::Unreachable) + // These terminators have exactly one coverage-relevant successor, + // and can be chained into it. + Assert { target, .. } + | Drop { target, .. } + | FalseEdge { real_target: target, .. } + | FalseUnwind { real_target: target, .. } + | Goto { target } => CoverageSuccessors::Chainable(target), + + // These terminators can normally be chained, except when they have no + // successor because they are known to diverge. + Call { target: maybe_target, .. } | InlineAsm { destination: maybe_target, .. } => { + match maybe_target { + Some(target) => CoverageSuccessors::Chainable(target), + None => CoverageSuccessors::NotChainable(&[]), + } + } + + // These terminators have no coverage-relevant successors. + CoroutineDrop | Return | Unreachable | UnwindResume | UnwindTerminate(_) => { + CoverageSuccessors::NotChainable(&[]) + } + } } /// Maintains separate worklists for each loop in the BasicCoverageBlock CFG, plus one for the @@ -544,8 +540,8 @@ fn short_circuit_preorder<'a, 'tcx, F, Iter>( filtered_successors: F, ) -> impl Iterator + Captures<'a> + Captures<'tcx> where - F: Fn(&'a mir::Body<'tcx>, BasicBlock) -> Iter, - Iter: Iterator, + F: Fn(BasicBlock) -> Iter, + Iter: IntoIterator, { let mut visited = BitSet::new_empty(body.basic_blocks.len()); let mut worklist = vec![mir::START_BLOCK]; @@ -556,7 +552,7 @@ where continue; } - worklist.extend(filtered_successors(body, bb)); + worklist.extend(filtered_successors(bb)); return Some(bb); } diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs index 3d74ef7e3278..e6317e5469ce 100644 --- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs +++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs @@ -52,7 +52,7 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { live.seek_to_block_end(bb); let mut state = live.get().clone(); - for (index, arg) in args.iter().enumerate().rev() { + for (index, arg) in args.iter().map(|a| &a.node).enumerate().rev() { if let Operand::Copy(place) = *arg && !place.is_indirect() // Do not skip the transformation if the local is in debuginfo, as we do @@ -119,17 +119,25 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let TerminatorKind::Call { ref mut args, .. } = bbs[block].terminator_mut().kind else { bug!() }; - let arg = &mut args[argument_index]; + let arg = &mut args[argument_index].node; let Operand::Copy(place) = *arg else { bug!() }; *arg = Operand::Move(place); } - - crate::simplify::simplify_locals(body, tcx) } -pub struct DeadStoreElimination; +pub enum DeadStoreElimination { + Initial, + Final, +} impl<'tcx> MirPass<'tcx> for DeadStoreElimination { + fn name(&self) -> &'static str { + match self { + DeadStoreElimination::Initial => "DeadStoreElimination-initial", + DeadStoreElimination::Final => "DeadStoreElimination-final", + } + } + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() >= 2 } diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs index 990cfb05e607..a6750911394b 100644 --- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs +++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs @@ -111,7 +111,7 @@ impl<'tcx> Visitor<'tcx> for DeduceReadOnly { if let TerminatorKind::Call { ref args, .. } = terminator.kind { for arg in args { - if let Operand::Move(place) = *arg { + if let Operand::Move(place) = arg.node { let local = place.local; if place.is_indirect() || local == RETURN_PLACE diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index 49b0edc0db88..0ac4ab61d409 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -134,6 +134,7 @@ use crate::MirPass; use rustc_data_structures::fx::{FxIndexMap, IndexEntry, IndexOccupiedEntry}; use rustc_index::bit_set::BitSet; +use rustc_index::interval::SparseIntervalMatrix; use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor}; use rustc_middle::mir::HasLocalDecls; use rustc_middle::mir::{dump_mir, PassWhere}; @@ -143,7 +144,8 @@ use rustc_middle::mir::{ }; use rustc_middle::ty::TyCtxt; use rustc_mir_dataflow::impls::MaybeLiveLocals; -use rustc_mir_dataflow::{Analysis, ResultsCursor}; +use rustc_mir_dataflow::points::{save_as_intervals, DenseLocationMap, PointIndex}; +use rustc_mir_dataflow::Analysis; pub struct DestinationPropagation; @@ -167,6 +169,13 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation { let borrowed = rustc_mir_dataflow::impls::borrowed_locals(body); + let live = MaybeLiveLocals + .into_engine(tcx, body) + .pass_name("MaybeLiveLocals-DestinationPropagation") + .iterate_to_fixpoint(); + let points = DenseLocationMap::new(body); + let mut live = save_as_intervals(&points, body, live); + // In order to avoid having to collect data for every single pair of locals in the body, we // do not allow doing more than one merge for places that are derived from the same local at // once. To avoid missed opportunities, we instead iterate to a fixed point - we'll refer to @@ -190,22 +199,19 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation { &mut allocations.candidates_reverse, ); trace!(?candidates); - let mut live = MaybeLiveLocals - .into_engine(tcx, body) - .iterate_to_fixpoint() - .into_results_cursor(body); - dest_prop_mir_dump(tcx, body, &mut live, round_count); + dest_prop_mir_dump(tcx, body, &points, &live, round_count); FilterInformation::filter_liveness( &mut candidates, - &mut live, + &points, + &live, &mut allocations.write_info, body, ); - // Because we do not update liveness information, it is unsound to use a local for more - // than one merge operation within a single round of optimizations. We store here which - // ones we have already used. + // Because we only filter once per round, it is unsound to use a local for more than + // one merge operation within a single round of optimizations. We store here which ones + // we have already used. let mut merged_locals: BitSet = BitSet::new_empty(body.local_decls.len()); // This is the set of merges we will apply this round. It is a subset of the candidates. @@ -224,9 +230,15 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation { }) { break; } + + // Replace `src` by `dest` everywhere. merges.insert(*src, *dest); merged_locals.insert(*src); merged_locals.insert(*dest); + + // Update liveness information based on the merge we just performed. + // Every location where `src` was live, `dest` will be live. + live.union_rows(*src, *dest); } trace!(merging = ?merges); @@ -349,7 +361,8 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Merger<'a, 'tcx> { struct FilterInformation<'a, 'body, 'alloc, 'tcx> { body: &'body Body<'tcx>, - live: &'a mut ResultsCursor<'body, 'tcx, MaybeLiveLocals>, + points: &'a DenseLocationMap, + live: &'a SparseIntervalMatrix, candidates: &'a mut Candidates<'alloc>, write_info: &'alloc mut WriteInfo, at: Location, @@ -452,12 +465,14 @@ impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> { /// locals as also being read from. fn filter_liveness<'b>( candidates: &mut Candidates<'alloc>, - live: &mut ResultsCursor<'b, 'tcx, MaybeLiveLocals>, + points: &DenseLocationMap, + live: &SparseIntervalMatrix, write_info_alloc: &'alloc mut WriteInfo, body: &'b Body<'tcx>, ) { let mut this = FilterInformation { body, + points, live, candidates, // We don't actually store anything at this scope, we just keep things here to be able @@ -472,13 +487,11 @@ impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> { fn internal_filter_liveness(&mut self) { for (block, data) in traversal::preorder(self.body) { self.at = Location { block, statement_index: data.statements.len() }; - self.live.seek_after_primary_effect(self.at); self.write_info.for_terminator(&data.terminator().kind); self.apply_conflicts(); for (i, statement) in data.statements.iter().enumerate().rev() { self.at = Location { block, statement_index: i }; - self.live.seek_after_primary_effect(self.at); self.write_info.for_statement(&statement.kind, self.body); self.apply_conflicts(); } @@ -497,6 +510,7 @@ impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> { None } }); + let at = self.points.point_from_location(self.at); self.candidates.filter_candidates_by( *p, |q| { @@ -508,7 +522,7 @@ impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> { // calls or inline asm. Because of this, we also mark locals as // conflicting when both of them are written to in the same // statement. - if self.live.contains(q) || writes.contains(&q) { + if self.live.contains(q, at) || writes.contains(&q) { CandidateFilter::Remove } else { CandidateFilter::Keep @@ -609,7 +623,7 @@ impl WriteInfo { self.add_place(*destination); self.add_operand(func); for arg in args { - self.add_operand(arg); + self.add_operand(&arg.node); } } TerminatorKind::InlineAsm { operands, .. } => { @@ -801,38 +815,17 @@ fn is_local_required(local: Local, body: &Body<'_>) -> bool { fn dest_prop_mir_dump<'body, 'tcx>( tcx: TyCtxt<'tcx>, body: &'body Body<'tcx>, - live: &mut ResultsCursor<'body, 'tcx, MaybeLiveLocals>, + points: &DenseLocationMap, + live: &SparseIntervalMatrix, round: usize, ) { - let mut reachable = None; + let locals_live_at = |location| { + let location = points.point_from_location(location); + live.rows().filter(|&r| live.contains(r, location)).collect::>() + }; dump_mir(tcx, false, "DestinationPropagation-dataflow", &round, body, |pass_where, w| { - let reachable = reachable.get_or_insert_with(|| traversal::reachable_as_bitset(body)); - - match pass_where { - PassWhere::BeforeLocation(loc) if reachable.contains(loc.block) => { - live.seek_after_primary_effect(loc); - writeln!(w, " // live: {:?}", live.get())?; - } - PassWhere::AfterTerminator(bb) if reachable.contains(bb) => { - let loc = body.terminator_loc(bb); - live.seek_before_primary_effect(loc); - writeln!(w, " // live: {:?}", live.get())?; - } - - PassWhere::BeforeBlock(bb) if reachable.contains(bb) => { - live.seek_to_block_start(bb); - writeln!(w, " // live: {:?}", live.get())?; - } - - PassWhere::BeforeCFG | PassWhere::AfterCFG | PassWhere::AfterLocation(_) => {} - - PassWhere::BeforeLocation(_) | PassWhere::AfterTerminator(_) => { - writeln!(w, " // live: ")?; - } - - PassWhere::BeforeBlock(_) => { - writeln!(w, " // live: ")?; - } + if let PassWhere::BeforeLocation(loc) = pass_where { + writeln!(w, " // live: {:?}", locals_live_at(loc))?; } Ok(()) diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index 446f13feff08..2ee660ddc9be 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -66,7 +66,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for RequiresUnsafe { #[track_caller] fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { let mut diag = DiagnosticBuilder::new(dcx, level, fluent::mir_transform_requires_unsafe); - diag.code(rustc_errors::DiagnosticId::Error("E0133".to_string())); + diag.code("E0133".to_string()); diag.span(self.span); diag.span_label(self.span, self.details.label()); let desc = dcx.eagerly_translate_to_string(self.details.label(), [].into_iter()); diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs index 340bb1948ebf..61d99f1f018b 100644 --- a/compiler/rustc_mir_transform/src/function_item_references.rs +++ b/compiler/rustc_mir_transform/src/function_item_references.rs @@ -4,6 +4,7 @@ use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; use rustc_middle::ty::{self, EarlyBinder, GenericArgsRef, Ty, TyCtxt}; use rustc_session::lint::builtin::FUNCTION_ITEM_REFERENCES; +use rustc_span::source_map::Spanned; use rustc_span::{symbol::sym, Span}; use rustc_target::spec::abi::Abi; @@ -43,7 +44,7 @@ impl<'tcx> Visitor<'tcx> for FunctionItemRefChecker<'_, 'tcx> { if let ty::FnDef(def_id, args_ref) = *func_ty.kind() { // Handle calls to `transmute` if self.tcx.is_diagnostic_item(sym::transmute, def_id) { - let arg_ty = args[0].ty(self.body, self.tcx); + let arg_ty = args[0].node.ty(self.body, self.tcx); for inner_ty in arg_ty.walk().filter_map(|arg| arg.as_type()) { if let Some((fn_id, fn_args)) = FunctionItemRefChecker::is_fn_ref(inner_ty) { @@ -67,7 +68,7 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> { &self, def_id: DefId, args_ref: GenericArgsRef<'tcx>, - args: &[Operand<'tcx>], + args: &[Spanned>], source_info: SourceInfo, ) { let param_env = self.tcx.param_env(def_id); @@ -134,8 +135,8 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> { .unwrap_or(None) } - fn nth_arg_span(&self, args: &[Operand<'tcx>], n: usize) -> Span { - match &args[n] { + fn nth_arg_span(&self, args: &[Spanned>], n: usize) -> Span { + match &args[n].node { Operand::Copy(place) | Operand::Move(place) => { self.body.local_decls[place.local].source_info.span } diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 2551c8aca883..390ec3e1a36a 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -84,7 +84,7 @@ use rustc_const_eval::interpret::{intern_const_alloc_for_constprop, MemoryKind}; use rustc_const_eval::interpret::{ImmTy, InterpCx, OpTy, Projectable, Scalar}; -use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; +use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::graph::dominators::Dominators; use rustc_hir::def::DefKind; use rustc_index::bit_set::BitSet; @@ -99,6 +99,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt, TypeAndMut}; use rustc_span::def_id::DefId; use rustc_span::DUMMY_SP; use rustc_target::abi::{self, Abi, Size, VariantIdx, FIRST_VARIANT}; +use smallvec::SmallVec; use std::borrow::Cow; use crate::dataflow_const_prop::DummyMachine; @@ -238,14 +239,18 @@ struct VnState<'body, 'tcx> { local_decls: &'body LocalDecls<'tcx>, /// Value stored in each local. locals: IndexVec>, - /// First local to be assigned that value. - rev_locals: FxHashMap>, + /// Locals that are assigned that value. + // This vector does not hold all the values of `VnIndex` that we create. + // It stops at the largest value created in the first phase of collecting assignments. + rev_locals: IndexVec>, values: FxIndexSet>, /// Values evaluated as constants if possible. evaluated: IndexVec>>, /// Counter to generate different values. /// This is an option to stop creating opaques during replacement. next_opaque: Option, + /// Cache the value of the `unsized_locals` features, to avoid fetching it repeatedly in a loop. + feature_unsized_locals: bool, ssa: &'body SsaLocals, dominators: &'body Dominators, reused_locals: BitSet, @@ -265,10 +270,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { param_env, local_decls, locals: IndexVec::from_elem(None, local_decls), - rev_locals: FxHashMap::default(), + rev_locals: IndexVec::default(), values: FxIndexSet::default(), evaluated: IndexVec::new(), next_opaque: Some(0), + feature_unsized_locals: tcx.features().unsized_locals, ssa, dominators, reused_locals: BitSet::new_empty(local_decls.len()), @@ -316,10 +322,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { self.locals[local] = Some(value); // Only register the value if its type is `Sized`, as we will emit copies of it. - let is_sized = !self.tcx.features().unsized_locals + let is_sized = !self.feature_unsized_locals || self.local_decls[local].ty.is_sized(self.tcx, self.param_env); if is_sized { - self.rev_locals.entry(value).or_default().push(local); + self.rev_locals.ensure_contains_elem(value, SmallVec::new); + self.rev_locals[value].push(local); } } @@ -338,11 +345,20 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { Some(self.insert(Value::Constant { value, disambiguator })) } + fn insert_bool(&mut self, flag: bool) -> VnIndex { + // Booleans are deterministic. + self.insert(Value::Constant { value: Const::from_bool(self.tcx, flag), disambiguator: 0 }) + } + fn insert_scalar(&mut self, scalar: Scalar, ty: Ty<'tcx>) -> VnIndex { self.insert_constant(Const::from_scalar(self.tcx, scalar, ty)) .expect("scalars are deterministic") } + fn insert_tuple(&mut self, values: Vec) -> VnIndex { + self.insert(Value::Aggregate(AggregateTy::Tuple, VariantIdx::from_u32(0), values)) + } + #[instrument(level = "trace", skip(self), ret)] fn eval_to_const(&mut self, value: VnIndex) -> Option> { use Value::*; @@ -630,6 +646,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { if place.is_indirect() && let Some(base) = self.locals[place.local] && let Some(new_local) = self.try_as_local(base, location) + && place.local != new_local { place.local = new_local; self.reused_locals.insert(new_local); @@ -639,8 +656,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { for i in 0..projection.len() { let elem = projection[i]; - if let ProjectionElem::Index(idx) = elem - && let Some(idx) = self.locals[idx] + if let ProjectionElem::Index(idx_local) = elem + && let Some(idx) = self.locals[idx_local] { if let Some(offset) = self.evaluated[idx].as_ref() && let Ok(offset) = self.ecx.read_target_usize(offset) @@ -648,9 +665,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { { projection.to_mut()[i] = ProjectionElem::ConstantIndex { offset, min_length, from_end: false }; - } else if let Some(new_idx) = self.try_as_local(idx, location) { - projection.to_mut()[i] = ProjectionElem::Index(new_idx); - self.reused_locals.insert(new_idx); + } else if let Some(new_idx_local) = self.try_as_local(idx, location) + && idx_local != new_idx_local + { + projection.to_mut()[i] = ProjectionElem::Index(new_idx_local); + self.reused_locals.insert(new_idx_local); } } } @@ -757,10 +776,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } // Operations. - Rvalue::Len(ref mut place) => { - let place = self.simplify_place_value(place, location)?; - Value::Len(place) - } + Rvalue::Len(ref mut place) => return self.simplify_len(place, location), Rvalue::Cast(kind, ref mut value, to) => { let from = value.ty(self.local_decls, self.tcx); let value = self.simplify_operand(value, location)?; @@ -775,17 +791,36 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { Value::Cast { kind, value, from, to } } Rvalue::BinaryOp(op, box (ref mut lhs, ref mut rhs)) => { + let ty = lhs.ty(self.local_decls, self.tcx); let lhs = self.simplify_operand(lhs, location); let rhs = self.simplify_operand(rhs, location); - Value::BinaryOp(op, lhs?, rhs?) + // Only short-circuit options after we called `simplify_operand` + // on both operands for side effect. + let lhs = lhs?; + let rhs = rhs?; + if let Some(value) = self.simplify_binary(op, false, ty, lhs, rhs) { + return Some(value); + } + Value::BinaryOp(op, lhs, rhs) } Rvalue::CheckedBinaryOp(op, box (ref mut lhs, ref mut rhs)) => { + let ty = lhs.ty(self.local_decls, self.tcx); let lhs = self.simplify_operand(lhs, location); let rhs = self.simplify_operand(rhs, location); - Value::CheckedBinaryOp(op, lhs?, rhs?) + // Only short-circuit options after we called `simplify_operand` + // on both operands for side effect. + let lhs = lhs?; + let rhs = rhs?; + if let Some(value) = self.simplify_binary(op, true, ty, lhs, rhs) { + return Some(value); + } + Value::CheckedBinaryOp(op, lhs, rhs) } Rvalue::UnaryOp(op, ref mut arg) => { let arg = self.simplify_operand(arg, location)?; + if let Some(value) = self.simplify_unary(op, arg) { + return Some(value); + } Value::UnaryOp(op, arg) } Rvalue::Discriminant(ref mut place) => { @@ -884,6 +919,150 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { Some(self.insert(Value::Aggregate(ty, variant_index, fields))) } + + #[instrument(level = "trace", skip(self), ret)] + fn simplify_unary(&mut self, op: UnOp, value: VnIndex) -> Option { + let value = match (op, self.get(value)) { + (UnOp::Not, Value::UnaryOp(UnOp::Not, inner)) => return Some(*inner), + (UnOp::Neg, Value::UnaryOp(UnOp::Neg, inner)) => return Some(*inner), + (UnOp::Not, Value::BinaryOp(BinOp::Eq, lhs, rhs)) => { + Value::BinaryOp(BinOp::Ne, *lhs, *rhs) + } + (UnOp::Not, Value::BinaryOp(BinOp::Ne, lhs, rhs)) => { + Value::BinaryOp(BinOp::Eq, *lhs, *rhs) + } + _ => return None, + }; + + Some(self.insert(value)) + } + + #[instrument(level = "trace", skip(self), ret)] + fn simplify_binary( + &mut self, + op: BinOp, + checked: bool, + lhs_ty: Ty<'tcx>, + lhs: VnIndex, + rhs: VnIndex, + ) -> Option { + // Floats are weird enough that none of the logic below applies. + let reasonable_ty = + lhs_ty.is_integral() || lhs_ty.is_bool() || lhs_ty.is_char() || lhs_ty.is_any_ptr(); + if !reasonable_ty { + return None; + } + + let layout = self.ecx.layout_of(lhs_ty).ok()?; + + let as_bits = |value| { + let constant = self.evaluated[value].as_ref()?; + if layout.abi.is_scalar() { + let scalar = self.ecx.read_scalar(constant).ok()?; + scalar.to_bits(constant.layout.size).ok() + } else { + // `constant` is a wide pointer. Do not evaluate to bits. + None + } + }; + + // Represent the values as `Left(bits)` or `Right(VnIndex)`. + use Either::{Left, Right}; + let a = as_bits(lhs).map_or(Right(lhs), Left); + let b = as_bits(rhs).map_or(Right(rhs), Left); + let result = match (op, a, b) { + // Neutral elements. + (BinOp::Add | BinOp::BitOr | BinOp::BitXor, Left(0), Right(p)) + | ( + BinOp::Add + | BinOp::BitOr + | BinOp::BitXor + | BinOp::Sub + | BinOp::Offset + | BinOp::Shl + | BinOp::Shr, + Right(p), + Left(0), + ) + | (BinOp::Mul, Left(1), Right(p)) + | (BinOp::Mul | BinOp::Div, Right(p), Left(1)) => p, + // Attempt to simplify `x & ALL_ONES` to `x`, with `ALL_ONES` depending on type size. + (BinOp::BitAnd, Right(p), Left(ones)) | (BinOp::BitAnd, Left(ones), Right(p)) + if ones == layout.size.truncate(u128::MAX) + || (layout.ty.is_bool() && ones == 1) => + { + p + } + // Absorbing elements. + (BinOp::Mul | BinOp::BitAnd, _, Left(0)) + | (BinOp::Rem, _, Left(1)) + | ( + BinOp::Mul | BinOp::Div | BinOp::Rem | BinOp::BitAnd | BinOp::Shl | BinOp::Shr, + Left(0), + _, + ) => self.insert_scalar(Scalar::from_uint(0u128, layout.size), lhs_ty), + // Attempt to simplify `x | ALL_ONES` to `ALL_ONES`. + (BinOp::BitOr, _, Left(ones)) | (BinOp::BitOr, Left(ones), _) + if ones == layout.size.truncate(u128::MAX) + || (layout.ty.is_bool() && ones == 1) => + { + self.insert_scalar(Scalar::from_uint(ones, layout.size), lhs_ty) + } + // Sub/Xor with itself. + (BinOp::Sub | BinOp::BitXor, a, b) if a == b => { + self.insert_scalar(Scalar::from_uint(0u128, layout.size), lhs_ty) + } + // Comparison: + // - if both operands can be computed as bits, just compare the bits; + // - if we proved that both operands have the same value, we can insert true/false; + // - otherwise, do nothing, as we do not try to prove inequality. + (BinOp::Eq, Left(a), Left(b)) => self.insert_bool(a == b), + (BinOp::Eq, a, b) if a == b => self.insert_bool(true), + (BinOp::Ne, Left(a), Left(b)) => self.insert_bool(a != b), + (BinOp::Ne, a, b) if a == b => self.insert_bool(false), + _ => return None, + }; + + if checked { + let false_val = self.insert_bool(false); + Some(self.insert_tuple(vec![result, false_val])) + } else { + Some(result) + } + } + + fn simplify_len(&mut self, place: &mut Place<'tcx>, location: Location) -> Option { + // Trivial case: we are fetching a statically known length. + let place_ty = place.ty(self.local_decls, self.tcx).ty; + if let ty::Array(_, len) = place_ty.kind() { + return self.insert_constant(Const::from_ty_const(*len, self.tcx)); + } + + let mut inner = self.simplify_place_value(place, location)?; + + // The length information is stored in the fat pointer. + // Reborrowing copies length information from one pointer to the other. + while let Value::Address { place: borrowed, .. } = self.get(inner) + && let [PlaceElem::Deref] = borrowed.projection[..] + && let Some(borrowed) = self.locals[borrowed.local] + { + inner = borrowed; + } + + // We have an unsizing cast, which assigns the length to fat pointer metadata. + if let Value::Cast { kind, from, to, .. } = self.get(inner) + && let CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize) = kind + && let Some(from) = from.builtin_deref(true) + && let ty::Array(_, len) = from.ty.kind() + && let Some(to) = to.builtin_deref(true) + && let ty::Slice(..) = to.ty.kind() + { + return self.insert_constant(Const::from_ty_const(*len, self.tcx)); + } + + // Fallback: a symbolic `Len`. + Some(self.insert(Value::Len(inner))) + } } fn op_to_prop_const<'tcx>( @@ -986,11 +1165,11 @@ impl<'tcx> VnState<'_, 'tcx> { /// If there is a local which is assigned `index`, and its assignment strictly dominates `loc`, /// return it. fn try_as_local(&mut self, index: VnIndex, loc: Location) -> Option { - let other = self.rev_locals.get(&index)?; + let other = self.rev_locals.get(index)?; other .iter() + .find(|&&other| self.ssa.assignment_dominates(self.dominators, other, loc)) .copied() - .find(|&other| self.ssa.assignment_dominates(self.dominators, other, loc)) } } @@ -1008,23 +1187,32 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> { } fn visit_statement(&mut self, stmt: &mut Statement<'tcx>, location: Location) { - if let StatementKind::Assign(box (_, ref mut rvalue)) = stmt.kind + if let StatementKind::Assign(box (ref mut lhs, ref mut rvalue)) = stmt.kind { + self.simplify_place_projection(lhs, location); + // Do not try to simplify a constant, it's already in canonical shape. - && !matches!(rvalue, Rvalue::Use(Operand::Constant(_))) - { - if let Some(value) = self.simplify_rvalue(rvalue, location) { - if let Some(const_) = self.try_as_constant(value) { - *rvalue = Rvalue::Use(Operand::Constant(Box::new(const_))); - } else if let Some(local) = self.try_as_local(value, location) - && *rvalue != Rvalue::Use(Operand::Move(local.into())) - { - *rvalue = Rvalue::Use(Operand::Copy(local.into())); - self.reused_locals.insert(local); - } + if matches!(rvalue, Rvalue::Use(Operand::Constant(_))) { + return; } - } else { - self.super_statement(stmt, location); + + let value = lhs + .as_local() + .and_then(|local| self.locals[local]) + .or_else(|| self.simplify_rvalue(rvalue, location)); + let Some(value) = value else { return }; + + if let Some(const_) = self.try_as_constant(value) { + *rvalue = Rvalue::Use(Operand::Constant(Box::new(const_))); + } else if let Some(local) = self.try_as_local(value, location) + && *rvalue != Rvalue::Use(Operand::Move(local.into())) + { + *rvalue = Rvalue::Use(Operand::Copy(local.into())); + self.reused_locals.insert(local); + } + + return; } + self.super_statement(stmt, location); } } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index ebefc3b47cc4..67668a216dee 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -11,6 +11,7 @@ use rustc_middle::mir::*; use rustc_middle::ty::TypeVisitableExt; use rustc_middle::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt}; use rustc_session::config::OptLevel; +use rustc_span::source_map::Spanned; use rustc_target::abi::FieldIdx; use rustc_target::spec::abi::Abi; @@ -172,7 +173,7 @@ impl<'tcx> Inliner<'tcx> { let TerminatorKind::Call { args, destination, .. } = &terminator.kind else { bug!() }; let destination_ty = destination.ty(&caller_body.local_decls, self.tcx).ty; for arg in args { - if !arg.ty(&caller_body.local_decls, self.tcx).is_sized(self.tcx, self.param_env) { + if !arg.node.ty(&caller_body.local_decls, self.tcx).is_sized(self.tcx, self.param_env) { // We do not allow inlining functions with unsized params. Inlining these functions // could create unsized locals, which are unsound and being phased out. return Err("Call has unsized argument"); @@ -238,9 +239,9 @@ impl<'tcx> Inliner<'tcx> { }; let self_arg_ty = - self_arg.map(|self_arg| self_arg.ty(&caller_body.local_decls, self.tcx)); + self_arg.map(|self_arg| self_arg.node.ty(&caller_body.local_decls, self.tcx)); - let arg_tuple_ty = arg_tuple.ty(&caller_body.local_decls, self.tcx); + let arg_tuple_ty = arg_tuple.node.ty(&caller_body.local_decls, self.tcx); let ty::Tuple(arg_tuple_tys) = *arg_tuple_ty.kind() else { bug!("Closure arguments are not passed as a tuple"); }; @@ -263,7 +264,7 @@ impl<'tcx> Inliner<'tcx> { } else { for (arg, input) in args.iter().zip(callee_body.args_iter()) { let input_type = callee_body.local_decls[input].ty; - let arg_ty = arg.ty(&caller_body.local_decls, self.tcx); + let arg_ty = arg.node.ty(&caller_body.local_decls, self.tcx); if !util::relate_types( self.tcx, self.param_env, @@ -694,7 +695,7 @@ impl<'tcx> Inliner<'tcx> { fn make_call_args( &self, - args: Vec>, + args: Vec>>, callsite: &CallSite<'tcx>, caller_body: &mut Body<'tcx>, callee_body: &Body<'tcx>, @@ -728,13 +729,13 @@ impl<'tcx> Inliner<'tcx> { if callsite.fn_sig.abi() == Abi::RustCall && callee_body.spread_arg.is_none() { let mut args = args.into_iter(); let self_ = self.create_temp_if_necessary( - args.next().unwrap(), + args.next().unwrap().node, callsite, caller_body, return_block, ); let tuple = self.create_temp_if_necessary( - args.next().unwrap(), + args.next().unwrap().node, callsite, caller_body, return_block, @@ -761,7 +762,7 @@ impl<'tcx> Inliner<'tcx> { closure_ref_arg.chain(tuple_tmp_args).collect() } else { args.into_iter() - .map(|a| self.create_temp_if_necessary(a, callsite, caller_body, return_block)) + .map(|a| self.create_temp_if_necessary(a.node, callsite, caller_body, return_block)) .collect() } } diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index 4f0f63d22a4d..a28db0defc99 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -215,7 +215,7 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> { // These types are easily available from locals, so check that before // doing DefId lookups to figure out what we're actually calling. - let arg_ty = args[0].ty(self.local_decls, self.tcx); + let arg_ty = args[0].node.ty(self.local_decls, self.tcx); let ty::Ref(_region, inner_ty, Mutability::Not) = *arg_ty.kind() else { return }; @@ -238,7 +238,7 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> { return; } - let Some(arg_place) = args.pop().unwrap().place() else { return }; + let Some(arg_place) = args.pop().unwrap().node.place() else { return }; statements.push(Statement { source_info: terminator.source_info, diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index dcab124505e2..e87f68a09057 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -36,16 +36,21 @@ //! cost by `MAX_COST`. use rustc_arena::DroplessArena; +use rustc_const_eval::interpret::{ImmTy, Immediate, InterpCx, OpTy, Projectable}; use rustc_data_structures::fx::FxHashSet; use rustc_index::bit_set::BitSet; use rustc_index::IndexVec; +use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; -use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt}; +use rustc_middle::ty::layout::LayoutOf; +use rustc_middle::ty::{self, ScalarInt, TyCtxt}; use rustc_mir_dataflow::value_analysis::{Map, PlaceIndex, State, TrackElem}; +use rustc_span::DUMMY_SP; use rustc_target::abi::{TagEncoding, Variants}; use crate::cost_checker::CostChecker; +use crate::dataflow_const_prop::DummyMachine; pub struct JumpThreading; @@ -71,6 +76,7 @@ impl<'tcx> MirPass<'tcx> for JumpThreading { let mut finder = TOFinder { tcx, param_env, + ecx: InterpCx::new(tcx, DUMMY_SP, param_env, DummyMachine), body, arena: &arena, map: &map, @@ -88,7 +94,7 @@ impl<'tcx> MirPass<'tcx> for JumpThreading { debug!(?discr, ?bb); let discr_ty = discr.ty(body, tcx).ty; - let Ok(discr_layout) = tcx.layout_of(param_env.and(discr_ty)) else { continue }; + let Ok(discr_layout) = finder.ecx.layout_of(discr_ty) else { continue }; let Some(discr) = finder.map.find(discr.as_ref()) else { continue }; debug!(?discr); @@ -142,6 +148,7 @@ struct ThreadingOpportunity { struct TOFinder<'tcx, 'a> { tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, + ecx: InterpCx<'tcx, 'tcx, DummyMachine>, body: &'a Body<'tcx>, map: &'a Map, loop_headers: &'a BitSet, @@ -329,11 +336,11 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { } #[instrument(level = "trace", skip(self))] - fn process_operand( + fn process_immediate( &mut self, bb: BasicBlock, lhs: PlaceIndex, - rhs: &Operand<'tcx>, + rhs: ImmTy<'tcx>, state: &mut State>, ) -> Option { let register_opportunity = |c: Condition| { @@ -341,13 +348,70 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { self.opportunities.push(ThreadingOpportunity { chain: vec![bb], target: c.target }) }; + let conditions = state.try_get_idx(lhs, self.map)?; + if let Immediate::Scalar(Scalar::Int(int)) = *rhs { + conditions.iter_matches(int).for_each(register_opportunity); + } + + None + } + + /// If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`. + #[instrument(level = "trace", skip(self))] + fn process_constant( + &mut self, + bb: BasicBlock, + lhs: PlaceIndex, + constant: OpTy<'tcx>, + state: &mut State>, + ) { + self.map.for_each_projection_value( + lhs, + constant, + &mut |elem, op| match elem { + TrackElem::Field(idx) => self.ecx.project_field(op, idx.as_usize()).ok(), + TrackElem::Variant(idx) => self.ecx.project_downcast(op, idx).ok(), + TrackElem::Discriminant => { + let variant = self.ecx.read_discriminant(op).ok()?; + let discr_value = + self.ecx.discriminant_for_variant(op.layout.ty, variant).ok()?; + Some(discr_value.into()) + } + TrackElem::DerefLen => { + let op: OpTy<'_> = self.ecx.deref_pointer(op).ok()?.into(); + let len_usize = op.len(&self.ecx).ok()?; + let layout = self.ecx.layout_of(self.tcx.types.usize).unwrap(); + Some(ImmTy::from_uint(len_usize, layout).into()) + } + }, + &mut |place, op| { + if let Some(conditions) = state.try_get_idx(place, self.map) + && let Ok(imm) = self.ecx.read_immediate_raw(op) + && let Some(imm) = imm.right() + && let Immediate::Scalar(Scalar::Int(int)) = *imm + { + conditions.iter_matches(int).for_each(|c: Condition| { + self.opportunities + .push(ThreadingOpportunity { chain: vec![bb], target: c.target }) + }) + } + }, + ); + } + + #[instrument(level = "trace", skip(self))] + fn process_operand( + &mut self, + bb: BasicBlock, + lhs: PlaceIndex, + rhs: &Operand<'tcx>, + state: &mut State>, + ) -> Option { match rhs { // If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`. Operand::Constant(constant) => { - let conditions = state.try_get_idx(lhs, self.map)?; - let constant = - constant.const_.normalize(self.tcx, self.param_env).try_to_scalar_int()?; - conditions.iter_matches(constant).for_each(register_opportunity); + let constant = self.ecx.eval_mir_constant(&constant.const_, None, None).ok()?; + self.process_constant(bb, lhs, constant, state); } // Transfer the conditions on the copied rhs. Operand::Move(rhs) | Operand::Copy(rhs) => { @@ -359,6 +423,84 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { None } + #[instrument(level = "trace", skip(self))] + fn process_assign( + &mut self, + bb: BasicBlock, + lhs_place: &Place<'tcx>, + rhs: &Rvalue<'tcx>, + state: &mut State>, + ) -> Option { + let lhs = self.map.find(lhs_place.as_ref())?; + match rhs { + Rvalue::Use(operand) => self.process_operand(bb, lhs, operand, state)?, + // Transfer the conditions on the copy rhs. + Rvalue::CopyForDeref(rhs) => { + self.process_operand(bb, lhs, &Operand::Copy(*rhs), state)? + } + Rvalue::Discriminant(rhs) => { + let rhs = self.map.find_discr(rhs.as_ref())?; + state.insert_place_idx(rhs, lhs, self.map); + } + // If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`. + Rvalue::Aggregate(box ref kind, ref operands) => { + let agg_ty = lhs_place.ty(self.body, self.tcx).ty; + let lhs = match kind { + // Do not support unions. + AggregateKind::Adt(.., Some(_)) => return None, + AggregateKind::Adt(_, variant_index, ..) if agg_ty.is_enum() => { + if let Some(discr_target) = self.map.apply(lhs, TrackElem::Discriminant) + && let Ok(discr_value) = + self.ecx.discriminant_for_variant(agg_ty, *variant_index) + { + self.process_immediate(bb, discr_target, discr_value, state); + } + self.map.apply(lhs, TrackElem::Variant(*variant_index))? + } + _ => lhs, + }; + for (field_index, operand) in operands.iter_enumerated() { + if let Some(field) = self.map.apply(lhs, TrackElem::Field(field_index)) { + self.process_operand(bb, field, operand, state); + } + } + } + // Transfer the conditions on the copy rhs, after inversing polarity. + Rvalue::UnaryOp(UnOp::Not, Operand::Move(place) | Operand::Copy(place)) => { + let conditions = state.try_get_idx(lhs, self.map)?; + let place = self.map.find(place.as_ref())?; + let conds = conditions.map(self.arena, Condition::inv); + state.insert_value_idx(place, conds, self.map); + } + // We expect `lhs ?= A`. We found `lhs = Eq(rhs, B)`. + // Create a condition on `rhs ?= B`. + Rvalue::BinaryOp( + op, + box (Operand::Move(place) | Operand::Copy(place), Operand::Constant(value)) + | box (Operand::Constant(value), Operand::Move(place) | Operand::Copy(place)), + ) => { + let conditions = state.try_get_idx(lhs, self.map)?; + let place = self.map.find(place.as_ref())?; + let equals = match op { + BinOp::Eq => ScalarInt::TRUE, + BinOp::Ne => ScalarInt::FALSE, + _ => return None, + }; + let value = value.const_.normalize(self.tcx, self.param_env).try_to_scalar_int()?; + let conds = conditions.map(self.arena, |c| Condition { + value, + polarity: if c.matches(equals) { Polarity::Eq } else { Polarity::Ne }, + ..c + }); + state.insert_value_idx(place, conds, self.map); + } + + _ => {} + } + + None + } + #[instrument(level = "trace", skip(self))] fn process_statement( &mut self, @@ -374,18 +516,6 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { // Below, `lhs` is the return value of `mutated_statement`, // the place to which `conditions` apply. - let discriminant_for_variant = |enum_ty: Ty<'tcx>, variant_index| { - let discr = enum_ty.discriminant_for_variant(self.tcx, variant_index)?; - let discr_layout = self.tcx.layout_of(self.param_env.and(discr.ty)).ok()?; - let scalar = ScalarInt::try_from_uint(discr.val, discr_layout.size)?; - Some(Operand::const_from_scalar( - self.tcx, - discr.ty, - scalar.into(), - rustc_span::DUMMY_SP, - )) - }; - match &stmt.kind { // If we expect `discriminant(place) ?= A`, // we have an opportunity if `variant_index ?= A`. @@ -395,7 +525,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { // `SetDiscriminant` may be a no-op if the assigned variant is the untagged variant // of a niche encoding. If we cannot ensure that we write to the discriminant, do // nothing. - let enum_layout = self.tcx.layout_of(self.param_env.and(enum_ty)).ok()?; + let enum_layout = self.ecx.layout_of(enum_ty).ok()?; let writes_discriminant = match enum_layout.variants { Variants::Single { index } => { assert_eq!(index, *variant_index); @@ -408,8 +538,8 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { } => *variant_index != untagged_variant, }; if writes_discriminant { - let discr = discriminant_for_variant(enum_ty, *variant_index)?; - self.process_operand(bb, discr_target, &discr, state)?; + let discr = self.ecx.discriminant_for_variant(enum_ty, *variant_index).ok()?; + self.process_immediate(bb, discr_target, discr, state)?; } } // If we expect `lhs ?= true`, we have an opportunity if we assume `lhs == true`. @@ -420,89 +550,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { conditions.iter_matches(ScalarInt::TRUE).for_each(register_opportunity); } StatementKind::Assign(box (lhs_place, rhs)) => { - if let Some(lhs) = self.map.find(lhs_place.as_ref()) { - match rhs { - Rvalue::Use(operand) => self.process_operand(bb, lhs, operand, state)?, - // Transfer the conditions on the copy rhs. - Rvalue::CopyForDeref(rhs) => { - self.process_operand(bb, lhs, &Operand::Copy(*rhs), state)? - } - Rvalue::Discriminant(rhs) => { - let rhs = self.map.find_discr(rhs.as_ref())?; - state.insert_place_idx(rhs, lhs, self.map); - } - // If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`. - Rvalue::Aggregate(box ref kind, ref operands) => { - let agg_ty = lhs_place.ty(self.body, self.tcx).ty; - let lhs = match kind { - // Do not support unions. - AggregateKind::Adt(.., Some(_)) => return None, - AggregateKind::Adt(_, variant_index, ..) if agg_ty.is_enum() => { - if let Some(discr_target) = - self.map.apply(lhs, TrackElem::Discriminant) - && let Some(discr_value) = - discriminant_for_variant(agg_ty, *variant_index) - { - self.process_operand(bb, discr_target, &discr_value, state); - } - self.map.apply(lhs, TrackElem::Variant(*variant_index))? - } - _ => lhs, - }; - for (field_index, operand) in operands.iter_enumerated() { - if let Some(field) = - self.map.apply(lhs, TrackElem::Field(field_index)) - { - self.process_operand(bb, field, operand, state); - } - } - } - // Transfer the conditions on the copy rhs, after inversing polarity. - Rvalue::UnaryOp(UnOp::Not, Operand::Move(place) | Operand::Copy(place)) => { - let conditions = state.try_get_idx(lhs, self.map)?; - let place = self.map.find(place.as_ref())?; - let conds = conditions.map(self.arena, Condition::inv); - state.insert_value_idx(place, conds, self.map); - } - // We expect `lhs ?= A`. We found `lhs = Eq(rhs, B)`. - // Create a condition on `rhs ?= B`. - Rvalue::BinaryOp( - op, - box ( - Operand::Move(place) | Operand::Copy(place), - Operand::Constant(value), - ) - | box ( - Operand::Constant(value), - Operand::Move(place) | Operand::Copy(place), - ), - ) => { - let conditions = state.try_get_idx(lhs, self.map)?; - let place = self.map.find(place.as_ref())?; - let equals = match op { - BinOp::Eq => ScalarInt::TRUE, - BinOp::Ne => ScalarInt::FALSE, - _ => return None, - }; - let value = value - .const_ - .normalize(self.tcx, self.param_env) - .try_to_scalar_int()?; - let conds = conditions.map(self.arena, |c| Condition { - value, - polarity: if c.matches(equals) { - Polarity::Eq - } else { - Polarity::Ne - }, - ..c - }); - state.insert_value_idx(place, conds, self.map); - } - - _ => {} - } - } + self.process_assign(bb, lhs_place, rhs, state)?; } _ => {} } @@ -577,7 +625,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { let discr = discr.place()?; let discr_ty = discr.ty(self.body, self.tcx).ty; - let discr_layout = self.tcx.layout_of(self.param_env.and(discr_ty)).ok()?; + let discr_layout = self.ecx.layout_of(discr_ty).ok()?; let conditions = state.try_get(discr.as_ref(), self.map)?; if let Some((value, _)) = targets.iter().find(|&(_, target)| target == target_bb) { diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index ce9043ec2870..19bfed4333c0 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -4,6 +4,7 @@ #![feature(box_patterns)] #![feature(cow_is_borrowed)] #![feature(decl_macro)] +#![feature(impl_trait_in_assoc_type)] #![feature(is_sorted)] #![feature(let_chains)] #![feature(map_try_insert)] @@ -40,7 +41,7 @@ use rustc_middle::mir::{ }; use rustc_middle::query::Providers; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; -use rustc_span::sym; +use rustc_span::{source_map::Spanned, sym, DUMMY_SP}; use rustc_trait_selection::traits; #[macro_use] @@ -169,13 +170,13 @@ fn remap_mir_for_const_eval_select<'tcx>( { let [tupled_args, called_in_const, called_at_rt]: [_; 3] = std::mem::take(args).try_into().unwrap(); - let ty = tupled_args.ty(&body.local_decls, tcx); + let ty = tupled_args.node.ty(&body.local_decls, tcx); let fields = ty.tuple_fields(); let num_args = fields.len(); let func = if context == hir::Constness::Const { called_in_const } else { called_at_rt }; let (method, place): (fn(Place<'tcx>) -> Operand<'tcx>, Place<'tcx>) = - match tupled_args { + match tupled_args.node { Operand::Constant(_) => { // there is no good way of extracting a tuple arg from a constant (const generic stuff) // so we just create a temporary and deconstruct that. @@ -184,7 +185,7 @@ fn remap_mir_for_const_eval_select<'tcx>( source_info: SourceInfo::outermost(fn_span), kind: StatementKind::Assign(Box::new(( local.into(), - Rvalue::Use(tupled_args.clone()), + Rvalue::Use(tupled_args.node.clone()), ))), }); (Operand::Move, local.into()) @@ -199,11 +200,11 @@ fn remap_mir_for_const_eval_select<'tcx>( place_elems.push(ProjectionElem::Field(x.into(), fields[x])); let projection = tcx.mk_place_elems(&place_elems); let place = Place { local: place.local, projection }; - method(place) + Spanned { node: method(place), span: DUMMY_SP } }) .collect(); terminator.kind = TerminatorKind::Call { - func, + func: func.node, args: arguments, destination, target, @@ -595,24 +596,25 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &multiple_return_terminators::MultipleReturnTerminators, &instsimplify::InstSimplify, &simplify::SimplifyLocals::BeforeConstProp, - ©_prop::CopyProp, + &dead_store_elimination::DeadStoreElimination::Initial, + &gvn::GVN, + &simplify::SimplifyLocals::AfterGVN, // Perform `SeparateConstSwitch` after SSA-based analyses, as cloning blocks may // destroy the SSA property. It should still happen before const-propagation, so the // latter pass will leverage the created opportunities. &separate_const_switch::SeparateConstSwitch, - &gvn::GVN, - &simplify::SimplifyLocals::AfterGVN, &dataflow_const_prop::DataflowConstProp, &const_debuginfo::ConstDebugInfo, &o1(simplify_branches::SimplifyConstCondition::AfterConstProp), &jump_threading::JumpThreading, &early_otherwise_branch::EarlyOtherwiseBranch, &simplify_comparison_integral::SimplifyComparisonIntegral, - &dead_store_elimination::DeadStoreElimination, &dest_prop::DestinationPropagation, &o1(simplify_branches::SimplifyConstCondition::Final), &o1(remove_noop_landing_pads::RemoveNoopLandingPads), &o1(simplify::SimplifyCfg::Final), + ©_prop::CopyProp, + &dead_store_elimination::DeadStoreElimination::Final, &nrvo::RenameReturnPlace, &simplify::SimplifyLocals::Final, &multiple_return_terminators::MultipleReturnTerminators, diff --git a/compiler/rustc_mir_transform/src/lint.rs b/compiler/rustc_mir_transform/src/lint.rs index c0c0a3f5ee64..5b269185e87a 100644 --- a/compiler/rustc_mir_transform/src/lint.rs +++ b/compiler/rustc_mir_transform/src/lint.rs @@ -131,7 +131,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Lint<'a, 'tcx> { self.places.insert(destination.as_ref()); let mut has_duplicates = false; for arg in args { - if let Operand::Move(place) = arg { + if let Operand::Move(place) = &arg.node { has_duplicates |= !self.places.insert(place.as_ref()); } } diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index 18f588dccf62..897375e0e164 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -45,9 +45,9 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { kind: StatementKind::Intrinsic(Box::new( NonDivergingIntrinsic::CopyNonOverlapping( rustc_middle::mir::CopyNonOverlapping { - src: args.next().unwrap(), - dst: args.next().unwrap(), - count: args.next().unwrap(), + src: args.next().unwrap().node, + dst: args.next().unwrap().node, + count: args.next().unwrap().node, }, ), )), @@ -66,7 +66,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { block.statements.push(Statement { source_info: terminator.source_info, kind: StatementKind::Intrinsic(Box::new( - NonDivergingIntrinsic::Assume(args.next().unwrap()), + NonDivergingIntrinsic::Assume(args.next().unwrap().node), )), }); assert_eq!( @@ -112,7 +112,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { source_info: terminator.source_info, kind: StatementKind::Assign(Box::new(( *destination, - Rvalue::BinaryOp(bin_op, Box::new((lhs, rhs))), + Rvalue::BinaryOp(bin_op, Box::new((lhs.node, rhs.node))), ))), }); terminator.kind = TerminatorKind::Goto { target }; @@ -136,7 +136,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { source_info: terminator.source_info, kind: StatementKind::Assign(Box::new(( *destination, - Rvalue::CheckedBinaryOp(bin_op, Box::new((lhs, rhs))), + Rvalue::CheckedBinaryOp(bin_op, Box::new((lhs.node, rhs.node))), ))), }); terminator.kind = TerminatorKind::Goto { target }; @@ -164,7 +164,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { let [arg] = args.as_slice() else { span_bug!(terminator.source_info.span, "Wrong number of arguments"); }; - let derefed_place = if let Some(place) = arg.place() + let derefed_place = if let Some(place) = arg.node.place() && let Some(local) = place.as_local() { tcx.mk_place_deref(local.into()) @@ -200,7 +200,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { "Wrong number of arguments for write_via_move intrinsic", ); }; - let derefed_place = if let Some(place) = ptr.place() + let derefed_place = if let Some(place) = ptr.node.place() && let Some(local) = place.as_local() { tcx.mk_place_deref(local.into()) @@ -214,13 +214,13 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { source_info: terminator.source_info, kind: StatementKind::Assign(Box::new(( derefed_place, - Rvalue::Use(val), + Rvalue::Use(val.node), ))), }); terminator.kind = TerminatorKind::Goto { target }; } sym::discriminant_value => { - if let (Some(target), Some(arg)) = (*target, args[0].place()) { + if let (Some(target), Some(arg)) = (*target, args[0].node.place()) { let arg = tcx.mk_place_deref(arg); block.statements.push(Statement { source_info: terminator.source_info, @@ -244,7 +244,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { source_info: terminator.source_info, kind: StatementKind::Assign(Box::new(( *destination, - Rvalue::BinaryOp(BinOp::Offset, Box::new((ptr, delta))), + Rvalue::BinaryOp(BinOp::Offset, Box::new((ptr.node, delta.node))), ))), }); terminator.kind = TerminatorKind::Goto { target }; @@ -265,7 +265,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { source_info: terminator.source_info, kind: StatementKind::Assign(Box::new(( *destination, - Rvalue::Cast(CastKind::Transmute, arg, dst_ty), + Rvalue::Cast(CastKind::Transmute, arg.node, dst_ty), ))), }); diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs index daeb56666f4d..8137525a3324 100644 --- a/compiler/rustc_mir_transform/src/lower_slice_len.rs +++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs @@ -50,7 +50,7 @@ fn lower_slice_len_call<'tcx>( } = &terminator.kind // some heuristics for fast rejection && let [arg] = &args[..] - && let Some(arg) = arg.place() + && let Some(arg) = arg.node.place() && let ty::FnDef(fn_def_id, _) = func.ty(local_decls, tcx).kind() && *fn_def_id == slice_len_fn_item_def_id { diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index 841b86fed454..c00093ea27ed 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -22,6 +22,7 @@ use rustc_middle::ty::{self, List, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::Span; use rustc_index::{Idx, IndexSlice, IndexVec}; +use rustc_span::source_map::Spanned; use std::assert_matches::assert_matches; use std::cell::Cell; @@ -565,7 +566,7 @@ impl<'tcx> Validator<'_, 'tcx> { fn validate_call( &mut self, callee: &Operand<'tcx>, - args: &[Operand<'tcx>], + args: &[Spanned>], ) -> Result<(), Unpromotable> { let fn_ty = callee.ty(self.body, self.tcx); @@ -595,7 +596,7 @@ impl<'tcx> Validator<'_, 'tcx> { self.validate_operand(callee)?; for arg in args { - self.validate_operand(arg)?; + self.validate_operand(&arg.node)?; } Ok(()) @@ -731,7 +732,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { } => { self.visit_operand(&mut func, loc); for arg in &mut args { - self.visit_operand(arg, loc); + self.visit_operand(&mut arg.node, loc); } let last = self.promoted.basic_blocks.last_index().unwrap(); diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index f6b820bfcd01..89414ce940e0 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -9,7 +9,7 @@ use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT}; use rustc_index::{Idx, IndexVec}; -use rustc_span::Span; +use rustc_span::{source_map::Spanned, Span, DUMMY_SP}; use rustc_target::spec::abi::Abi; use std::fmt; @@ -526,7 +526,7 @@ impl<'tcx> CloneShimBuilder<'tcx> { vec![statement], TerminatorKind::Call { func, - args: vec![Operand::Move(ref_loc)], + args: vec![Spanned { node: Operand::Move(ref_loc), span: DUMMY_SP }], destination: dest, target: Some(next), unwind: UnwindAction::Cleanup(cleanup), @@ -811,6 +811,7 @@ fn build_call_shim<'tcx>( }; // BB #0 + let args = args.into_iter().map(|a| Spanned { node: a, span: DUMMY_SP }).collect::>(); block( &mut blocks, statements, diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 92f001cc3212..20e70f87b75e 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -614,8 +614,8 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> { } fn check_operand_move_size(&mut self, operand: &mir::Operand<'tcx>, location: Location) { - let limit = self.tcx.move_size_limit().0; - if limit == 0 { + let limit = self.tcx.move_size_limit(); + if limit.0 == 0 { return; } @@ -627,48 +627,19 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> { return; } - let limit = Size::from_bytes(limit); - let ty = operand.ty(self.body, self.tcx); - let ty = self.monomorphize(ty); - let Ok(layout) = self.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)) else { return }; - if layout.size <= limit { - return; - } - debug!(?layout); let source_info = self.body.source_info(location); debug!(?source_info); - for span in &self.move_size_spans { - if span.overlaps(source_info.span) { - return; - } - } - let lint_root = source_info.scope.lint_root(&self.body.source_scopes); - debug!(?lint_root); - let Some(lint_root) = lint_root else { - // This happens when the issue is in a function from a foreign crate that - // we monomorphized in the current crate. We can't get a `HirId` for things - // in other crates. - // FIXME: Find out where to report the lint on. Maybe simply crate-level lint root - // but correct span? This would make the lint at least accept crate-level lint attributes. - return; + + if let Some(too_large_size) = self.operand_size_if_too_large(limit, operand) { + self.lint_large_assignment(limit.0, too_large_size, location, source_info.span); }; - self.tcx.emit_spanned_lint( - LARGE_ASSIGNMENTS, - lint_root, - source_info.span, - LargeAssignmentsLint { - span: source_info.span, - size: layout.size.bytes(), - limit: limit.bytes(), - }, - ); - self.move_size_spans.push(source_info.span); } fn check_fn_args_move_size( &mut self, callee_ty: Ty<'tcx>, - args: &[mir::Operand<'tcx>], + args: &[Spanned>], + fn_span: Span, location: Location, ) { let limit = self.tcx.move_size_limit(); @@ -692,10 +663,65 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> { return; } + debug!(?def_id, ?fn_span); + for arg in args { - self.check_operand_move_size(arg, location); + if let Some(too_large_size) = self.operand_size_if_too_large(limit, &arg.node) { + self.lint_large_assignment(limit.0, too_large_size, location, arg.span); + }; } } + + fn operand_size_if_too_large( + &mut self, + limit: Limit, + operand: &mir::Operand<'tcx>, + ) -> Option { + let ty = operand.ty(self.body, self.tcx); + let ty = self.monomorphize(ty); + let Ok(layout) = self.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)) else { + return None; + }; + if layout.size.bytes_usize() > limit.0 { + debug!(?layout); + Some(layout.size) + } else { + None + } + } + + fn lint_large_assignment( + &mut self, + limit: usize, + too_large_size: Size, + location: Location, + span: Span, + ) { + let source_info = self.body.source_info(location); + debug!(?source_info); + for reported_span in &self.move_size_spans { + if reported_span.overlaps(span) { + return; + } + } + let lint_root = source_info.scope.lint_root(&self.body.source_scopes); + debug!(?lint_root); + let Some(lint_root) = lint_root else { + // This happens when the issue is in a function from a foreign crate that + // we monomorphized in the current crate. We can't get a `HirId` for things + // in other crates. + // FIXME: Find out where to report the lint on. Maybe simply crate-level lint root + // but correct span? This would make the lint at least accept crate-level lint attributes. + return; + }; + self.tcx.emit_spanned_lint( + LARGE_ASSIGNMENTS, + lint_root, + span, + LargeAssignmentsLint { span, size: too_large_size.bytes(), limit: limit as u64 }, + ); + self.move_size_spans.push(span); + } } impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { @@ -813,11 +839,11 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { }; match terminator.kind { - mir::TerminatorKind::Call { ref func, ref args, .. } => { + mir::TerminatorKind::Call { ref func, ref args, ref fn_span, .. } => { let callee_ty = func.ty(self.body, tcx); let callee_ty = self.monomorphize(callee_ty); - self.check_fn_args_move_size(callee_ty, args, location); - visit_fn_use(self.tcx, callee_ty, true, source, self.output) + self.check_fn_args_move_size(callee_ty, args, *fn_span, location); + visit_fn_use(self.tcx, callee_ty, true, source, &mut self.output) } mir::TerminatorKind::Drop { ref place, .. } => { let ty = place.ty(self.body, self.tcx).ty; @@ -1407,7 +1433,7 @@ fn collect_alloc<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIt } fn assoc_fn_of_type<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, fn_ident: Ident) -> Option { - for impl_def_id in tcx.inherent_impls(def_id) { + for impl_def_id in tcx.inherent_impls(def_id).ok()? { if let Some(new) = tcx.associated_items(impl_def_id).find_by_name_and_kind( tcx, fn_ident, diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 2c40cd4d8f26..7ff182381b83 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -182,7 +182,7 @@ where } // Ensure CGUs are sorted by name, so that we get deterministic results. - if !codegen_units.is_sorted_by(|a, b| Some(a.name().as_str().cmp(b.name().as_str()))) { + if !codegen_units.is_sorted_by(|a, b| a.name().as_str() <= b.name().as_str()) { let mut names = String::new(); for cgu in codegen_units.iter() { names += &format!("- {}\n", cgu.name()); @@ -317,7 +317,7 @@ fn merge_codegen_units<'tcx>( assert!(cx.tcx.sess.codegen_units().as_usize() >= 1); // A sorted order here ensures merging is deterministic. - assert!(codegen_units.is_sorted_by(|a, b| Some(a.name().as_str().cmp(b.name().as_str())))); + assert!(codegen_units.is_sorted_by(|a, b| a.name().as_str() <= b.name().as_str())); // This map keeps track of what got merged into what. let mut cgu_contents: FxHashMap> = diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index c11a6fab7e5d..f904e0c44ea9 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -407,6 +407,9 @@ parse_invalid_logical_operator = `{$incorrect}` is not a logical operator parse_invalid_meta_item = expected unsuffixed literal or identifier, found `{$token}` +parse_invalid_meta_item_unquoted_ident = expected unsuffixed literal, found `{$token}` + .suggestion = surround the identifier with quotation marks to parse it as a string + parse_invalid_offset_of = offset_of expects dot-separated field and variant names parse_invalid_unicode_escape = invalid unicode character escape @@ -613,6 +616,8 @@ parse_note_mut_pattern_usage = `mut` may be followed by `variable` and `variable parse_note_pattern_alternatives_use_single_vert = alternatives in or-patterns are separated with `|`, not `||` +parse_nul_in_c_str = null characters in C string literals are not supported + parse_or_pattern_not_allowed_in_fn_parameters = top-level or-patterns are not allowed in function parameters parse_or_pattern_not_allowed_in_let_binding = top-level or-patterns are not allowed in `let` bindings parse_out_of_range_hex_escape = out of range hex escape @@ -719,6 +724,8 @@ parse_sugg_turbofish_syntax = use `::<...>` instead of `<...>` to specify lifeti parse_sugg_wrap_expression_in_parentheses = wrap the expression in parentheses +parse_sugg_wrap_macro_in_parentheses = use parentheses instead of braces for this macro + parse_sugg_wrap_pattern_in_parens = wrap the pattern in parentheses parse_switch_mut_let_order = diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 0de252707bd3..40852048293a 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -722,19 +722,32 @@ pub(crate) struct LabeledLoopInBreak { #[primary_span] pub span: Span, #[subdiagnostic] - pub sub: WrapExpressionInParentheses, + pub sub: WrapInParentheses, } #[derive(Subdiagnostic)] -#[multipart_suggestion( - parse_sugg_wrap_expression_in_parentheses, - applicability = "machine-applicable" -)] -pub(crate) struct WrapExpressionInParentheses { - #[suggestion_part(code = "(")] - pub left: Span, - #[suggestion_part(code = ")")] - pub right: Span, + +pub(crate) enum WrapInParentheses { + #[multipart_suggestion( + parse_sugg_wrap_expression_in_parentheses, + applicability = "machine-applicable" + )] + Expression { + #[suggestion_part(code = "(")] + left: Span, + #[suggestion_part(code = ")")] + right: Span, + }, + #[multipart_suggestion( + parse_sugg_wrap_macro_in_parentheses, + applicability = "machine-applicable" + )] + MacroArgs { + #[suggestion_part(code = "(")] + left: Span, + #[suggestion_part(code = ")")] + right: Span, + }, } #[derive(Diagnostic)] @@ -936,7 +949,7 @@ pub(crate) struct InvalidExpressionInLetElse { pub span: Span, pub operator: &'static str, #[subdiagnostic] - pub sugg: WrapExpressionInParentheses, + pub sugg: WrapInParentheses, } #[derive(Diagnostic)] @@ -945,7 +958,7 @@ pub(crate) struct InvalidCurlyInLetElse { #[primary_span] pub span: Span, #[subdiagnostic] - pub sugg: WrapExpressionInParentheses, + pub sugg: WrapInParentheses, } #[derive(Diagnostic)] @@ -973,6 +986,25 @@ pub(crate) struct InvalidMetaItem { pub token: Token, } +#[derive(Diagnostic)] +#[diag(parse_invalid_meta_item_unquoted_ident)] +pub(crate) struct InvalidMetaItemUnquotedIdent { + #[primary_span] + pub span: Span, + pub token: Token, + #[subdiagnostic] + pub sugg: InvalidMetaItemSuggQuoteIdent, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +pub(crate) struct InvalidMetaItemSuggQuoteIdent { + #[suggestion_part(code = "\"")] + pub before: Span, + #[suggestion_part(code = "\"")] + pub after: Span, +} + #[derive(Subdiagnostic)] #[suggestion( parse_sugg_escape_identifier, @@ -2144,6 +2176,11 @@ pub enum UnescapeError { #[subdiagnostic] suggestion: MoreThanOneCharSugg, }, + #[diag(parse_nul_in_c_str)] + NulInCStr { + #[primary_span] + span: Span, + }, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs index fbc77f287808..3238f8e23bb0 100644 --- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs +++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs @@ -262,6 +262,9 @@ pub(crate) fn emit_unescape_error( EscapeError::LoneSlash => { dcx.emit_err(UnescapeError::LoneSlash(err_span)); } + EscapeError::NulInCStr => { + dcx.emit_err(UnescapeError::NulInCStr { span: err_span }); + } EscapeError::UnskippedWhitespaceWarning => { let (c, char_span) = last_char(); dcx.emit_warn(UnescapeError::UnskippedWhitespace { diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 02dab95233a3..a92609c2c2f8 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -1,4 +1,7 @@ -use crate::errors::{InvalidMetaItem, SuffixedLiteralInAttribute}; +use crate::errors::{ + InvalidMetaItem, InvalidMetaItemSuggQuoteIdent, InvalidMetaItemUnquotedIdent, + SuffixedLiteralInAttribute, +}; use crate::fluent_generated as fluent; use super::{AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, PathStyle}; @@ -417,9 +420,26 @@ impl<'a> Parser<'a> { Err(err) => err.cancel(), } - Err(self - .dcx() - .create_err(InvalidMetaItem { span: self.token.span, token: self.token.clone() })) + let token = self.token.clone(); + + // Check for unquoted idents in meta items, e.g.: #[cfg(key = foo)] + // `from_expansion()` ensures we don't suggest for cases such as + // `#[cfg(feature = $expr)]` in macros + if self.prev_token == token::Eq && !self.token.span.from_expansion() { + let before = self.token.span.shrink_to_lo(); + while matches!(self.token.kind, token::Ident(..)) { + self.bump(); + } + let after = self.prev_token.span.shrink_to_hi(); + let sugg = InvalidMetaItemSuggQuoteIdent { before, after }; + return Err(self.dcx().create_err(InvalidMetaItemUnquotedIdent { + span: token.span, + token, + sugg, + })); + } + + Err(self.dcx().create_err(InvalidMetaItem { span: token.span, token })) } } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 8ca02452342b..ae3661a530b0 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -33,7 +33,6 @@ use rustc_session::errors::{report_lit_error, ExprParenthesesNeeded}; use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP; use rustc_session::lint::BuiltinLintDiagnostics; use rustc_span::source_map::{self, Spanned}; -use rustc_span::symbol::kw::PathRoot; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{BytePos, Pos, Span}; use thin_vec::{thin_vec, ThinVec}; @@ -642,26 +641,13 @@ impl<'a> Parser<'a> { } /// Parse `box expr` - this syntax has been removed, but we still parse this - /// for now to provide an automated way to fix usages of it - fn parse_expr_box(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> { - let (span, expr) = self.parse_expr_prefix_common(lo)?; - let code = self.sess.source_map().span_to_snippet(span.with_lo(lo.hi())).unwrap(); - self.dcx().emit_err(errors::BoxSyntaxRemoved { span, code: code.trim() }); - // So typechecking works, parse `box ` as `::std::boxed::Box::new(expr)` - let path = Path { - span, - segments: [ - PathSegment::from_ident(Ident::with_dummy_span(PathRoot)), - PathSegment::from_ident(Ident::with_dummy_span(sym::std)), - PathSegment::from_ident(Ident::from_str("boxed")), - PathSegment::from_ident(Ident::from_str("Box")), - PathSegment::from_ident(Ident::with_dummy_span(sym::new)), - ] - .into(), - tokens: None, - }; - let path = self.mk_expr(span, ExprKind::Path(None, path)); - Ok((span, self.mk_call(path, ThinVec::from([expr])))) + /// for now to provide a more useful error + fn parse_expr_box(&mut self, box_kw: Span) -> PResult<'a, (Span, ExprKind)> { + let (span, _) = self.parse_expr_prefix_common(box_kw)?; + let inner_span = span.with_lo(box_kw.hi()); + let code = self.sess.source_map().span_to_snippet(inner_span).unwrap(); + self.dcx().emit_err(errors::BoxSyntaxRemoved { span: span, code: code.trim() }); + Ok((span, ExprKind::Err)) } fn is_mistaken_not_ident_negation(&self) -> bool { @@ -1844,7 +1830,7 @@ impl<'a> Parser<'a> { let lexpr = self.parse_expr_labeled(label, true)?; self.dcx().emit_err(errors::LabeledLoopInBreak { span: lexpr.span, - sub: errors::WrapExpressionInParentheses { + sub: errors::WrapInParentheses::Expression { left: lexpr.span.shrink_to_lo(), right: lexpr.span.shrink_to_hi(), }, diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 1a8bbf0a1572..1bae5b322403 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -389,7 +389,7 @@ impl<'a> Parser<'a> { self.dcx().emit_err(errors::InvalidExpressionInLetElse { span: init.span, operator: op.node.as_str(), - sugg: errors::WrapExpressionInParentheses { + sugg: errors::WrapInParentheses::Expression { left: init.span.shrink_to_lo(), right: init.span.shrink_to_hi(), }, @@ -400,12 +400,19 @@ impl<'a> Parser<'a> { fn check_let_else_init_trailing_brace(&self, init: &ast::Expr) { if let Some(trailing) = classify::expr_trailing_brace(init) { - self.dcx().emit_err(errors::InvalidCurlyInLetElse { - span: trailing.span.with_lo(trailing.span.hi() - BytePos(1)), - sugg: errors::WrapExpressionInParentheses { + let sugg = match &trailing.kind { + ExprKind::MacCall(mac) => errors::WrapInParentheses::MacroArgs { + left: mac.args.dspan.open, + right: mac.args.dspan.close, + }, + _ => errors::WrapInParentheses::Expression { left: trailing.span.shrink_to_lo(), right: trailing.span.shrink_to_hi(), }, + }; + self.dcx().emit_err(errors::InvalidCurlyInLetElse { + span: trailing.span.with_lo(trailing.span.hi() - BytePos(1)), + sugg, }); } } diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index ac2ca23ad417..d7f17ac4547a 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -57,7 +57,7 @@ struct MarkSymbolVisitor<'tcx> { tcx: TyCtxt<'tcx>, maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>, live_symbols: LocalDefIdSet, - repr_has_repr_c: bool, + repr_unconditionally_treats_fields_as_live: bool, repr_has_repr_simd: bool, in_pat: bool, ignore_variant_stack: Vec, @@ -128,7 +128,10 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { if let Some(def_id) = self.typeck_results().type_dependent_def_id(id) { self.check_def_id(def_id); } else { - bug!("no type-dependent def for method"); + assert!( + self.typeck_results().tainted_by_errors.is_some(), + "no type-dependent def for method" + ); } } @@ -362,15 +365,17 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { return; } - let had_repr_c = self.repr_has_repr_c; + let unconditionally_treated_fields_as_live = + self.repr_unconditionally_treats_fields_as_live; let had_repr_simd = self.repr_has_repr_simd; - self.repr_has_repr_c = false; + self.repr_unconditionally_treats_fields_as_live = false; self.repr_has_repr_simd = false; match node { Node::Item(item) => match item.kind { hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => { let def = self.tcx.adt_def(item.owner_id); - self.repr_has_repr_c = def.repr().c(); + self.repr_unconditionally_treats_fields_as_live = + def.repr().c() || def.repr().transparent(); self.repr_has_repr_simd = def.repr().simd(); intravisit::walk_item(self, item) @@ -408,7 +413,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { _ => {} } self.repr_has_repr_simd = had_repr_simd; - self.repr_has_repr_c = had_repr_c; + self.repr_unconditionally_treats_fields_as_live = unconditionally_treated_fields_as_live; } fn mark_as_used_if_union(&mut self, adt: ty::AdtDef<'tcx>, fields: &[hir::ExprField<'_>]) { @@ -432,11 +437,11 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { fn visit_variant_data(&mut self, def: &'tcx hir::VariantData<'tcx>) { let tcx = self.tcx; - let has_repr_c = self.repr_has_repr_c; + let unconditionally_treat_fields_as_live = self.repr_unconditionally_treats_fields_as_live; let has_repr_simd = self.repr_has_repr_simd; let live_fields = def.fields().iter().filter_map(|f| { let def_id = f.def_id; - if has_repr_c || (f.is_positional() && has_repr_simd) { + if unconditionally_treat_fields_as_live || (f.is_positional() && has_repr_simd) { return Some(def_id); } if !tcx.visibility(f.hir_id.owner.def_id).is_public() { @@ -738,7 +743,7 @@ fn live_symbols_and_ignored_derived_traits( tcx, maybe_typeck_results: None, live_symbols: Default::default(), - repr_has_repr_c: false, + repr_unconditionally_treats_fields_as_live: false, repr_has_repr_simd: false, in_pat: false, ignore_variant_stack: vec![], diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index a9d0e0d2dd3e..25ca685cbfad 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -180,8 +180,8 @@ fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) { Default::default() }); let main_def_opt = tcx.resolutions(()).main_def; - let diagnostic_id = error_code!(E0601); - let add_teach_note = tcx.sess.teach(&diagnostic_id); + let code = error_code!(E0601); + let add_teach_note = tcx.sess.teach(&code); // The file may be empty, which leads to the diagnostic machinery not emitting this // note. This is a relatively simple way to detect that case and emit a span-less // note instead. diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index ff29fc5929c7..528a52f42255 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -303,7 +303,8 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { Ref, Lit, Range, - Slice + Slice, + Err ] ); hir_visit::walk_pat(self, p) @@ -576,7 +577,8 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { Rest, Never, Paren, - MacCall + MacCall, + Err ] ); ast_visit::walk_pat(self, p) diff --git a/compiler/rustc_pattern_analysis/Cargo.toml b/compiler/rustc_pattern_analysis/Cargo.toml index 2152f9fda007..1d0e1cb7e6a5 100644 --- a/compiler/rustc_pattern_analysis/Cargo.toml +++ b/compiler/rustc_pattern_analysis/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start derivative = "2.2.0" +rustc-hash = "1.1.0" rustc_apfloat = "0.2.0" rustc_arena = { path = "../rustc_arena", optional = true } rustc_data_structures = { path = "../rustc_data_structures", optional = true } @@ -20,13 +21,10 @@ rustc_span = { path = "../rustc_span", optional = true } rustc_target = { path = "../rustc_target", optional = true } smallvec = { version = "1.8.1", features = ["union"] } tracing = "0.1" -typed-arena = { version = "2.0.2", optional = true } # tidy-alphabetical-end [features] default = ["rustc"] -# It's not possible to only enable the `typed_arena` dependency when the `rustc` feature is off, so -# we use another feature instead. The crate won't compile if one of these isn't enabled. rustc = [ "dep:rustc_arena", "dep:rustc_data_structures", @@ -41,6 +39,3 @@ rustc = [ "smallvec/may_dangle", "rustc_index/nightly", ] -stable = [ - "dep:typed-arena", -] diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs index 15ff4ceb5b3a..eba71a23435a 100644 --- a/compiler/rustc_pattern_analysis/src/constructor.rs +++ b/compiler/rustc_pattern_analysis/src/constructor.rs @@ -155,13 +155,13 @@ use std::iter::once; use smallvec::SmallVec; use rustc_apfloat::ieee::{DoubleS, IeeeFloat, SingleS}; -use rustc_index::bit_set::{BitSet, GrowableBitSet}; -use rustc_index::IndexVec; +use rustc_index::bit_set::GrowableBitSet; use self::Constructor::*; use self::MaybeInfiniteInt::*; use self::SliceKind::*; +use crate::index; use crate::usefulness::PlaceCtxt; use crate::TypeCx; @@ -718,7 +718,7 @@ impl Constructor { /// The number of fields for this constructor. This must be kept in sync with /// `Fields::wildcards`. - pub(crate) fn arity(&self, pcx: &PlaceCtxt<'_, '_, Cx>) -> usize { + pub(crate) fn arity(&self, pcx: &PlaceCtxt<'_, Cx>) -> usize { pcx.ctor_arity(self) } @@ -727,7 +727,7 @@ impl Constructor { /// this checks for inclusion. // We inline because this has a single call site in `Matrix::specialize_constructor`. #[inline] - pub(crate) fn is_covered_by<'p>(&self, pcx: &PlaceCtxt<'_, 'p, Cx>, other: &Self) -> bool { + pub(crate) fn is_covered_by(&self, pcx: &PlaceCtxt<'_, Cx>, other: &Self) -> bool { match (self, other) { (Wildcard, _) => pcx .mcx @@ -804,7 +804,10 @@ pub enum ConstructorSet { Struct { empty: bool }, /// This type has the following list of constructors. If `variants` is empty and /// `non_exhaustive` is false, don't use this; use `NoConstructors` instead. - Variants { variants: IndexVec, non_exhaustive: bool }, + Variants { + variants: index::IdxContainer, + non_exhaustive: bool, + }, /// The type is `&T`. Ref, /// The type is a union. @@ -858,12 +861,14 @@ impl ConstructorSet { /// any) are missing; 2/ split constructors to handle non-trivial intersections e.g. on ranges /// or slices. This can get subtle; see [`SplitConstructorSet`] for details of this operation /// and its invariants. - #[instrument(level = "debug", skip(self, pcx, ctors), ret)] + #[instrument(level = "debug", skip(self, ctors), ret)] pub(crate) fn split<'a>( &self, - pcx: &PlaceCtxt<'a, '_, Cx>, ctors: impl Iterator> + Clone, - ) -> SplitConstructorSet { + ) -> SplitConstructorSet + where + Cx: 'a, + { let mut present: SmallVec<[_; 1]> = SmallVec::new(); // Empty constructors found missing. let mut missing_empty = Vec::new(); @@ -904,7 +909,7 @@ impl ConstructorSet { } } ConstructorSet::Variants { variants, non_exhaustive } => { - let mut seen_set: BitSet<_> = BitSet::new_empty(variants.len()); + let mut seen_set = index::IdxSet::new_empty(variants.len()); for idx in seen.iter().map(|c| c.as_variant().unwrap()) { seen_set.insert(idx); } @@ -1003,17 +1008,6 @@ impl ConstructorSet { } } - // We have now grouped all the constructors into 3 buckets: present, missing, missing_empty. - // In the absence of the `exhaustive_patterns` feature however, we don't count nested empty - // types as empty. Only non-nested `!` or `enum Foo {}` are considered empty. - if !pcx.mcx.tycx.is_exhaustive_patterns_feature_on() - && !(pcx.is_scrutinee && matches!(self, Self::NoConstructors)) - { - // Treat all missing constructors as nonempty. - // This clears `missing_empty`. - missing.append(&mut missing_empty); - } - SplitConstructorSet { present, missing, missing_empty } } } diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index 374914055d8f..4fd01b5e638c 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -21,30 +21,59 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" } use std::fmt; -use rustc_index::Idx; +#[cfg(feature = "rustc")] +pub mod index { + // Faster version when the indices of variants are `0..variants.len()`. + pub use rustc_index::bit_set::BitSet as IdxSet; + pub use rustc_index::Idx; + pub use rustc_index::IndexVec as IdxContainer; +} +#[cfg(not(feature = "rustc"))] +pub mod index { + // Slower version when the indices of variants are something else. + pub trait Idx: Copy + PartialEq + Eq + std::hash::Hash {} + impl Idx for T {} + + #[derive(Debug)] + pub struct IdxContainer(pub rustc_hash::FxHashMap); + impl IdxContainer { + pub fn len(&self) -> usize { + self.0.len() + } + pub fn iter_enumerated(&self) -> impl Iterator { + self.0.iter().map(|(k, v)| (*k, v)) + } + } + + #[derive(Debug)] + pub struct IdxSet(pub rustc_hash::FxHashSet); + impl IdxSet { + pub fn new_empty(_len: usize) -> Self { + Self(Default::default()) + } + pub fn contains(&self, elem: T) -> bool { + self.0.contains(&elem) + } + pub fn insert(&mut self, elem: T) { + self.0.insert(elem); + } + } +} + #[cfg(feature = "rustc")] use rustc_middle::ty::Ty; #[cfg(feature = "rustc")] use rustc_span::ErrorGuaranteed; -use crate::constructor::{Constructor, ConstructorSet}; +use crate::constructor::{Constructor, ConstructorSet, IntRange}; #[cfg(feature = "rustc")] -use crate::lints::{ - lint_nonexhaustive_missing_variants, lint_overlapping_range_endpoints, PatternColumn, -}; +use crate::lints::{lint_nonexhaustive_missing_variants, PatternColumn}; use crate::pat::DeconstructedPat; #[cfg(feature = "rustc")] use crate::rustc::RustcMatchCheckCtxt; #[cfg(feature = "rustc")] use crate::usefulness::{compute_match_usefulness, ValidityConstraint}; -// It's not possible to only enable the `typed_arena` dependency when the `rustc` feature is off, so -// we use another feature instead. The crate won't compile if one of these isn't enabled. -#[cfg(feature = "rustc")] -pub(crate) use rustc_arena::TypedArena; -#[cfg(feature = "stable")] -pub(crate) use typed_arena::Arena as TypedArena; - pub trait Captures<'a> {} impl<'a, T: ?Sized> Captures<'a> for T {} @@ -53,11 +82,11 @@ impl<'a, T: ?Sized> Captures<'a> for T {} /// Most of the crate is parameterized on a type that implements this trait. pub trait TypeCx: Sized + fmt::Debug { /// The type of a pattern. - type Ty: Copy + Clone + fmt::Debug; // FIXME: remove Copy + type Ty: Clone + fmt::Debug; /// Errors that can abort analysis. type Error: fmt::Debug; /// The index of an enum variant. - type VariantIdx: Clone + Idx; + type VariantIdx: Clone + index::Idx + fmt::Debug; /// A string literal type StrLit: Clone + PartialEq + fmt::Debug; /// Extra data to store in a match arm. @@ -68,32 +97,41 @@ pub trait TypeCx: Sized + fmt::Debug { fn is_exhaustive_patterns_feature_on(&self) -> bool; /// The number of fields for this constructor. - fn ctor_arity(&self, ctor: &Constructor, ty: Self::Ty) -> usize; + fn ctor_arity(&self, ctor: &Constructor, ty: &Self::Ty) -> usize; /// The types of the fields for this constructor. The result must have a length of /// `ctor_arity()`. - fn ctor_sub_tys(&self, ctor: &Constructor, ty: Self::Ty) -> &[Self::Ty]; + fn ctor_sub_tys(&self, ctor: &Constructor, ty: &Self::Ty) -> &[Self::Ty]; /// The set of all the constructors for `ty`. /// /// This must follow the invariants of `ConstructorSet` - fn ctors_for_ty(&self, ty: Self::Ty) -> Result, Self::Error>; + fn ctors_for_ty(&self, ty: &Self::Ty) -> Result, Self::Error>; /// Best-effort `Debug` implementation. fn debug_pat(f: &mut fmt::Formatter<'_>, pat: &DeconstructedPat<'_, Self>) -> fmt::Result; /// Raise a bug. fn bug(&self, fmt: fmt::Arguments<'_>) -> !; + + /// Lint that the range `pat` overlapped with all the ranges in `overlaps_with`, where the range + /// they overlapped over is `overlaps_on`. We only detect singleton overlaps. + /// The default implementation does nothing. + fn lint_overlapping_range_endpoints( + &self, + _pat: &DeconstructedPat<'_, Self>, + _overlaps_on: IntRange, + _overlaps_with: &[&DeconstructedPat<'_, Self>], + ) { + } } /// Context that provides information global to a match. #[derive(derivative::Derivative)] #[derivative(Clone(bound = ""), Copy(bound = ""))] -pub struct MatchCtxt<'a, 'p, Cx: TypeCx> { +pub struct MatchCtxt<'a, Cx: TypeCx> { /// The context for type information. pub tycx: &'a Cx, - /// An arena to store the wildcards we produce during analysis. - pub wildcard_arena: &'p TypedArena>, } /// The arm of a match expression. @@ -114,24 +152,16 @@ pub fn analyze_match<'p, 'tcx>( arms: &[rustc::MatchArm<'p, 'tcx>], scrut_ty: Ty<'tcx>, ) -> Result, ErrorGuaranteed> { - // Arena to store the extra wildcards we construct during analysis. - let wildcard_arena = tycx.pattern_arena; let scrut_ty = tycx.reveal_opaque_ty(scrut_ty); let scrut_validity = ValidityConstraint::from_bool(tycx.known_valid_scrutinee); - let cx = MatchCtxt { tycx, wildcard_arena }; + let cx = MatchCtxt { tycx }; let report = compute_match_usefulness(cx, arms, scrut_ty, scrut_validity)?; - let pat_column = PatternColumn::new(arms); - - // Lint ranges that overlap on their endpoints, which is likely a mistake. - if !report.overlapping_range_endpoints.is_empty() { - lint_overlapping_range_endpoints(cx, &report.overlapping_range_endpoints); - } - // Run the non_exhaustive_omitted_patterns lint. Only run on refutable patterns to avoid hitting // `if let`s. Only run if the match is exhaustive otherwise the error is redundant. if tycx.refutable && report.non_exhaustiveness_witnesses.is_empty() { + let pat_column = PatternColumn::new(arms); lint_nonexhaustive_missing_variants(cx, arms, &pat_column, scrut_ty)?; } diff --git a/compiler/rustc_pattern_analysis/src/lints.rs b/compiler/rustc_pattern_analysis/src/lints.rs index cfe4ca3ce93d..f9f065fbe8b1 100644 --- a/compiler/rustc_pattern_analysis/src/lints.rs +++ b/compiler/rustc_pattern_analysis/src/lints.rs @@ -1,14 +1,11 @@ -use rustc_session::lint; use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; use rustc_span::ErrorGuaranteed; -use crate::errors::{ - self, NonExhaustiveOmittedPattern, NonExhaustiveOmittedPatternLintOnArm, Uncovered, -}; +use crate::errors::{NonExhaustiveOmittedPattern, NonExhaustiveOmittedPatternLintOnArm, Uncovered}; use crate::pat::PatOrWild; use crate::rustc::{ - self, Constructor, DeconstructedPat, MatchArm, MatchCtxt, PlaceCtxt, RevealedTy, - RustcMatchCheckCtxt, SplitConstructorSet, WitnessPat, + Constructor, DeconstructedPat, MatchArm, MatchCtxt, PlaceCtxt, RevealedTy, RustcMatchCheckCtxt, + SplitConstructorSet, WitnessPat, }; /// A column of patterns in the matrix, where a column is the intuitive notion of "subpatterns that @@ -49,7 +46,7 @@ impl<'p, 'tcx> PatternColumn<'p, 'tcx> { } fn head_ty(&self) -> Option> { - self.patterns.first().map(|pat| pat.ty()) + self.patterns.first().map(|pat| *pat.ty()) } /// Do constructor splitting on the constructors of the column. @@ -59,7 +56,7 @@ impl<'p, 'tcx> PatternColumn<'p, 'tcx> { ) -> Result, ErrorGuaranteed> { let column_ctors = self.patterns.iter().map(|p| p.ctor()); let ctors_for_ty = &pcx.ctors_for_ty()?; - Ok(ctors_for_ty.split(pcx, column_ctors)) + Ok(ctors_for_ty.split(column_ctors)) } /// Does specialization: given a constructor, this takes the patterns from the column that match @@ -104,7 +101,7 @@ fn collect_nonexhaustive_missing_variants<'a, 'p, 'tcx>( let Some(ty) = column.head_ty() else { return Ok(Vec::new()); }; - let pcx = &PlaceCtxt::new_dummy(cx, ty); + let pcx = &PlaceCtxt::new_dummy(cx, &ty); let set = column.analyze_ctors(pcx)?; if set.present.is_empty() { @@ -196,26 +193,3 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'a, 'p, 'tcx>( } Ok(()) } - -pub(crate) fn lint_overlapping_range_endpoints<'a, 'p, 'tcx>( - cx: MatchCtxt<'a, 'p, 'tcx>, - overlapping_range_endpoints: &[rustc::OverlappingRanges<'p, 'tcx>], -) { - let rcx = cx.tycx; - for overlap in overlapping_range_endpoints { - let overlap_as_pat = rcx.hoist_pat_range(&overlap.overlaps_on, overlap.pat.ty()); - let overlaps: Vec<_> = overlap - .overlaps_with - .iter() - .map(|pat| pat.data().unwrap().span) - .map(|span| errors::Overlap { range: overlap_as_pat.clone(), span }) - .collect(); - let pat_span = overlap.pat.data().unwrap().span; - rcx.tcx.emit_spanned_lint( - lint::builtin::OVERLAPPING_RANGE_ENDPOINTS, - rcx.match_lint_level, - pat_span, - errors::OverlappingRangeEndpoints { overlap: overlaps, range: pat_span }, - ); - } -} diff --git a/compiler/rustc_pattern_analysis/src/pat.rs b/compiler/rustc_pattern_analysis/src/pat.rs index 2f5dc241cb7f..8cd0ecb073c2 100644 --- a/compiler/rustc_pattern_analysis/src/pat.rs +++ b/compiler/rustc_pattern_analysis/src/pat.rs @@ -54,8 +54,8 @@ impl<'p, Cx: TypeCx> DeconstructedPat<'p, Cx> { pub fn ctor(&self) -> &Constructor { &self.ctor } - pub fn ty(&self) -> Cx::Ty { - self.ty + pub fn ty(&self) -> &Cx::Ty { + &self.ty } /// Returns the extra data stored in a pattern. Returns `None` if the pattern is a wildcard that /// does not correspond to a user-supplied pattern. @@ -240,17 +240,17 @@ impl WitnessPat { /// Construct a pattern that matches everything that starts with this constructor. /// For example, if `ctor` is a `Constructor::Variant` for `Option::Some`, we get the pattern /// `Some(_)`. - pub(crate) fn wild_from_ctor(pcx: &PlaceCtxt<'_, '_, Cx>, ctor: Constructor) -> Self { + pub(crate) fn wild_from_ctor(pcx: &PlaceCtxt<'_, Cx>, ctor: Constructor) -> Self { let field_tys = pcx.ctor_sub_tys(&ctor); - let fields = field_tys.iter().map(|ty| Self::wildcard(*ty)).collect(); - Self::new(ctor, fields, pcx.ty) + let fields = field_tys.iter().cloned().map(|ty| Self::wildcard(ty)).collect(); + Self::new(ctor, fields, pcx.ty.clone()) } pub fn ctor(&self) -> &Constructor { &self.ctor } - pub fn ty(&self) -> Cx::Ty { - self.ty + pub fn ty(&self) -> &Cx::Ty { + &self.ty } pub fn iter_fields(&self) -> impl Iterator> { diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index a17cd2c81b94..27b258024271 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -1,3 +1,4 @@ +use smallvec::SmallVec; use std::fmt; use std::iter::once; @@ -5,24 +6,21 @@ use rustc_arena::{DroplessArena, TypedArena}; use rustc_data_structures::captures::Captures; use rustc_hir::def_id::DefId; use rustc_hir::HirId; -use rustc_index::Idx; -use rustc_index::IndexVec; +use rustc_index::{Idx, IndexVec}; use rustc_middle::middle::stability::EvalResult; use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::{self, Const}; use rustc_middle::thir::{FieldPat, Pat, PatKind, PatRange, PatRangeBoundary}; use rustc_middle::ty::layout::IntegerExt; -use rustc_middle::ty::TypeVisitableExt; -use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, VariantDef}; -use rustc_span::ErrorGuaranteed; -use rustc_span::{Span, DUMMY_SP}; +use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeVisitableExt, VariantDef}; +use rustc_session::lint; +use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP}; use rustc_target::abi::{FieldIdx, Integer, VariantIdx, FIRST_VARIANT}; -use smallvec::SmallVec; use crate::constructor::{ IntRange, MaybeInfiniteInt, OpaqueId, RangeEnd, Slice, SliceKind, VariantVisibility, }; -use crate::TypeCx; +use crate::{errors, TypeCx}; use crate::constructor::Constructor::*; @@ -33,11 +31,9 @@ pub type ConstructorSet<'p, 'tcx> = pub type DeconstructedPat<'p, 'tcx> = crate::pat::DeconstructedPat<'p, RustcMatchCheckCtxt<'p, 'tcx>>; pub type MatchArm<'p, 'tcx> = crate::MatchArm<'p, RustcMatchCheckCtxt<'p, 'tcx>>; -pub type MatchCtxt<'a, 'p, 'tcx> = crate::MatchCtxt<'a, 'p, RustcMatchCheckCtxt<'p, 'tcx>>; -pub type OverlappingRanges<'p, 'tcx> = - crate::usefulness::OverlappingRanges<'p, RustcMatchCheckCtxt<'p, 'tcx>>; +pub type MatchCtxt<'a, 'p, 'tcx> = crate::MatchCtxt<'a, RustcMatchCheckCtxt<'p, 'tcx>>; pub(crate) type PlaceCtxt<'a, 'p, 'tcx> = - crate::usefulness::PlaceCtxt<'a, 'p, RustcMatchCheckCtxt<'p, 'tcx>>; + crate::usefulness::PlaceCtxt<'a, RustcMatchCheckCtxt<'p, 'tcx>>; pub(crate) type SplitConstructorSet<'p, 'tcx> = crate::constructor::SplitConstructorSet>; pub type Usefulness<'p, 'tcx> = crate::usefulness::Usefulness<'p, RustcMatchCheckCtxt<'p, 'tcx>>; @@ -80,7 +76,9 @@ pub struct RustcMatchCheckCtxt<'p, 'tcx> { /// outside its module and should not be matchable with an empty match statement. pub module: DefId, pub param_env: ty::ParamEnv<'tcx>, + /// To allocate lowered patterns pub pattern_arena: &'p TypedArena>, + /// To allocate the result of `self.ctor_sub_tys()` pub dropless_arena: &'p DroplessArena, /// Lint level at the match. pub match_lint_level: HirId, @@ -768,7 +766,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { let mut subpatterns = pat.iter_fields().map(|p| Box::new(cx.hoist_witness_pat(p))); let kind = match pat.ctor() { Bool(b) => PatKind::Constant { value: mir::Const::from_bool(cx.tcx, *b) }, - IntRange(range) => return self.hoist_pat_range(range, pat.ty()), + IntRange(range) => return self.hoist_pat_range(range, *pat.ty()), Struct | Variant(_) | UnionField => match pat.ty().kind() { ty::Tuple(..) => PatKind::Leaf { subpatterns: subpatterns @@ -787,7 +785,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { RustcMatchCheckCtxt::variant_index_for_adt(&pat.ctor(), *adt_def); let variant = &adt_def.variant(variant_index); let subpatterns = cx - .list_variant_nonhidden_fields(pat.ty(), variant) + .list_variant_nonhidden_fields(*pat.ty(), variant) .zip(subpatterns) .map(|((field, _ty), pattern)| FieldPat { field, pattern }) .collect(); @@ -798,7 +796,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { PatKind::Leaf { subpatterns } } } - _ => bug!("unexpected ctor for type {:?} {:?}", pat.ctor(), pat.ty()), + _ => bug!("unexpected ctor for type {:?} {:?}", pat.ctor(), *pat.ty()), }, // Note: given the expansion of `&str` patterns done in `expand_pattern`, we should // be careful to reconstruct the correct constant pattern here. However a string @@ -963,21 +961,21 @@ impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> { self.tcx.features().exhaustive_patterns } - fn ctor_arity(&self, ctor: &crate::constructor::Constructor, ty: Self::Ty) -> usize { - self.ctor_arity(ctor, ty) + fn ctor_arity(&self, ctor: &crate::constructor::Constructor, ty: &Self::Ty) -> usize { + self.ctor_arity(ctor, *ty) } fn ctor_sub_tys( &self, ctor: &crate::constructor::Constructor, - ty: Self::Ty, + ty: &Self::Ty, ) -> &[Self::Ty] { - self.ctor_sub_tys(ctor, ty) + self.ctor_sub_tys(ctor, *ty) } fn ctors_for_ty( &self, - ty: Self::Ty, + ty: &Self::Ty, ) -> Result, Self::Error> { - self.ctors_for_ty(ty) + self.ctors_for_ty(*ty) } fn debug_pat( @@ -989,6 +987,27 @@ impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> { fn bug(&self, fmt: fmt::Arguments<'_>) -> ! { span_bug!(self.scrut_span, "{}", fmt) } + + fn lint_overlapping_range_endpoints( + &self, + pat: &crate::pat::DeconstructedPat<'_, Self>, + overlaps_on: IntRange, + overlaps_with: &[&crate::pat::DeconstructedPat<'_, Self>], + ) { + let overlap_as_pat = self.hoist_pat_range(&overlaps_on, *pat.ty()); + let overlaps: Vec<_> = overlaps_with + .iter() + .map(|pat| pat.data().unwrap().span) + .map(|span| errors::Overlap { range: overlap_as_pat.clone(), span }) + .collect(); + let pat_span = pat.data().unwrap().span; + self.tcx.emit_spanned_lint( + lint::builtin::OVERLAPPING_RANGE_ENDPOINTS, + self.match_lint_level, + pat_span, + errors::OverlappingRangeEndpoints { overlap: overlaps, range: pat_span }, + ); + } } /// Recursively expand this pattern into its subpatterns. Only useful for or-patterns. diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index 85b6a6a3b6c7..d7852a2b2cbf 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -732,20 +732,19 @@ pub fn ensure_sufficient_stack(f: impl FnOnce() -> R) -> R { /// Context that provides information local to a place under investigation. #[derive(derivative::Derivative)] #[derivative(Debug(bound = ""), Clone(bound = ""), Copy(bound = ""))] -pub(crate) struct PlaceCtxt<'a, 'p, Cx: TypeCx> { +pub(crate) struct PlaceCtxt<'a, Cx: TypeCx> { #[derivative(Debug = "ignore")] - pub(crate) mcx: MatchCtxt<'a, 'p, Cx>, + pub(crate) mcx: MatchCtxt<'a, Cx>, /// Type of the place under investigation. - pub(crate) ty: Cx::Ty, - /// Whether the place is the original scrutinee place, as opposed to a subplace of it. - pub(crate) is_scrutinee: bool, + #[derivative(Clone(clone_with = "Clone::clone"))] // See rust-derivative#90 + pub(crate) ty: &'a Cx::Ty, } -impl<'a, 'p, Cx: TypeCx> PlaceCtxt<'a, 'p, Cx> { +impl<'a, Cx: TypeCx> PlaceCtxt<'a, Cx> { /// A `PlaceCtxt` when code other than `is_useful` needs one. #[cfg_attr(not(feature = "rustc"), allow(dead_code))] - pub(crate) fn new_dummy(mcx: MatchCtxt<'a, 'p, Cx>, ty: Cx::Ty) -> Self { - PlaceCtxt { mcx, ty, is_scrutinee: false } + pub(crate) fn new_dummy(mcx: MatchCtxt<'a, Cx>, ty: &'a Cx::Ty) -> Self { + PlaceCtxt { mcx, ty } } pub(crate) fn ctor_arity(&self, ctor: &Constructor) -> usize { @@ -768,9 +767,6 @@ impl<'a, 'p, Cx: TypeCx> PlaceCtxt<'a, 'p, Cx> { pub enum ValidityConstraint { ValidOnly, MaybeInvalid, - /// Option for backwards compatibility: the place is not known to be valid but we allow omitting - /// `useful && !reachable` arms anyway. - MaybeInvalidButAllowOmittingArms, } impl ValidityConstraint { @@ -778,20 +774,9 @@ impl ValidityConstraint { if is_valid_only { ValidOnly } else { MaybeInvalid } } - fn allow_omitting_side_effecting_arms(self) -> Self { - match self { - MaybeInvalid | MaybeInvalidButAllowOmittingArms => MaybeInvalidButAllowOmittingArms, - // There are no side-effecting empty arms here, nothing to do. - ValidOnly => ValidOnly, - } - } - fn is_known_valid(self) -> bool { matches!(self, ValidOnly) } - fn allows_omitting_empty_arms(self) -> bool { - matches!(self, ValidOnly | MaybeInvalidButAllowOmittingArms) - } /// If the place has validity given by `self` and we read that the value at the place has /// constructor `ctor`, this computes what we can assume about the validity of the constructor @@ -814,7 +799,7 @@ impl fmt::Display for ValidityConstraint { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let s = match self { ValidOnly => "✓", - MaybeInvalid | MaybeInvalidButAllowOmittingArms => "?", + MaybeInvalid => "?", }; write!(f, "{s}") } @@ -1039,8 +1024,8 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> { matrix } - fn head_ty(&self) -> Option { - self.place_ty.first().copied() + fn head_ty(&self) -> Option<&Cx::Ty> { + self.place_ty.first() } fn column_count(&self) -> usize { self.place_ty.len() @@ -1067,14 +1052,14 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> { /// This computes `specialize(ctor, self)`. See top of the file for explanations. fn specialize_constructor( &self, - pcx: &PlaceCtxt<'_, 'p, Cx>, + pcx: &PlaceCtxt<'_, Cx>, ctor: &Constructor, ctor_is_relevant: bool, ) -> Matrix<'p, Cx> { let ctor_sub_tys = pcx.ctor_sub_tys(ctor); let arity = ctor_sub_tys.len(); let specialized_place_ty = - ctor_sub_tys.iter().chain(self.place_ty[1..].iter()).copied().collect(); + ctor_sub_tys.iter().chain(self.place_ty[1..].iter()).cloned().collect(); let ctor_sub_validity = self.place_validity[0].specialize(ctor); let specialized_place_validity = std::iter::repeat(ctor_sub_validity) .take(arity) @@ -1226,11 +1211,11 @@ impl WitnessStack { /// pats: [(false, "foo"), _, true] /// result: [Enum::Variant { a: (false, "foo"), b: _ }, true] /// ``` - fn apply_constructor(&mut self, pcx: &PlaceCtxt<'_, '_, Cx>, ctor: &Constructor) { + fn apply_constructor(&mut self, pcx: &PlaceCtxt<'_, Cx>, ctor: &Constructor) { let len = self.0.len(); let arity = ctor.arity(pcx); let fields = self.0.drain((len - arity)..).rev().collect(); - let pat = WitnessPat::new(ctor.clone(), fields, pcx.ty); + let pat = WitnessPat::new(ctor.clone(), fields, pcx.ty.clone()); self.0.push(pat); } } @@ -1277,7 +1262,7 @@ impl WitnessMatrix { /// Reverses specialization by `ctor`. See the section on `unspecialize` at the top of the file. fn apply_constructor( &mut self, - pcx: &PlaceCtxt<'_, '_, Cx>, + pcx: &PlaceCtxt<'_, Cx>, missing_ctors: &[Constructor], ctor: &Constructor, report_individual_missing_ctors: bool, @@ -1340,10 +1325,10 @@ impl WitnessMatrix { /// We can however get false negatives because exhaustiveness does not explore all cases. See the /// section on relevancy at the top of the file. fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>( + mcx: MatchCtxt<'_, Cx>, overlap_range: IntRange, matrix: &Matrix<'p, Cx>, specialized_matrix: &Matrix<'p, Cx>, - overlapping_range_endpoints: &mut Vec>, ) { let overlap = overlap_range.lo; // Ranges that look like `lo..=overlap`. @@ -1373,11 +1358,7 @@ fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>( .map(|&(_, pat)| pat) .collect(); if !overlaps_with.is_empty() { - overlapping_range_endpoints.push(OverlappingRanges { - pat, - overlaps_on: overlap_range, - overlaps_with, - }); + mcx.tycx.lint_overlapping_range_endpoints(pat, overlap_range, &overlaps_with); } } suffixes.push((child_row_id, pat)) @@ -1393,11 +1374,7 @@ fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>( .map(|&(_, pat)| pat) .collect(); if !overlaps_with.is_empty() { - overlapping_range_endpoints.push(OverlappingRanges { - pat, - overlaps_on: overlap_range, - overlaps_with, - }); + mcx.tycx.lint_overlapping_range_endpoints(pat, overlap_range, &overlaps_with); } } prefixes.push((child_row_id, pat)) @@ -1421,9 +1398,8 @@ fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>( /// This is all explained at the top of the file. #[instrument(level = "debug", skip(mcx, is_top_level), ret)] fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( - mcx: MatchCtxt<'a, 'p, Cx>, + mcx: MatchCtxt<'a, Cx>, matrix: &mut Matrix<'p, Cx>, - overlapping_range_endpoints: &mut Vec>, is_top_level: bool, ) -> Result, Cx::Error> { debug_assert!(matrix.rows().all(|r| r.len() == matrix.column_count())); @@ -1435,7 +1411,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( return Ok(WitnessMatrix::empty()); } - let Some(ty) = matrix.head_ty() else { + let Some(ty) = matrix.head_ty().cloned() else { // The base case: there are no columns in the matrix. We are morally pattern-matching on (). // A row is useful iff it has no (unguarded) rows above it. let mut useful = true; // Whether the next row is useful. @@ -1456,41 +1432,44 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( }; debug!("ty: {ty:?}"); - let pcx = &PlaceCtxt { mcx, ty, is_scrutinee: is_top_level }; + let pcx = &PlaceCtxt { mcx, ty: &ty }; + let ctors_for_ty = pcx.ctors_for_ty()?; // Whether the place/column we are inspecting is known to contain valid data. let place_validity = matrix.place_validity[0]; - // For backwards compability we allow omitting some empty arms that we ideally shouldn't. - let place_validity = place_validity.allow_omitting_side_effecting_arms(); + // We treat match scrutinees of type `!` or `EmptyEnum` differently. + let is_toplevel_exception = + is_top_level && matches!(ctors_for_ty, ConstructorSet::NoConstructors); + // Whether empty patterns can be omitted for exhaustiveness. + let can_omit_empty_arms = is_toplevel_exception || mcx.tycx.is_exhaustive_patterns_feature_on(); + // Whether empty patterns are counted as useful or not. + let empty_arms_are_unreachable = place_validity.is_known_valid() && can_omit_empty_arms; // Analyze the constructors present in this column. let ctors = matrix.heads().map(|p| p.ctor()); - let ctors_for_ty = pcx.ctors_for_ty()?; - let is_integers = matches!(ctors_for_ty, ConstructorSet::Integers { .. }); // For diagnostics. - let split_set = ctors_for_ty.split(pcx, ctors); + let mut split_set = ctors_for_ty.split(ctors); let all_missing = split_set.present.is_empty(); - // Build the set of constructors we will specialize with. It must cover the whole type. + // We need to iterate over a full set of constructors, so we add `Missing` to represent the + // missing ones. This is explained under "Constructor Splitting" at the top of this file. let mut split_ctors = split_set.present; - if !split_set.missing.is_empty() { - // We need to iterate over a full set of constructors, so we add `Missing` to represent the - // missing ones. This is explained under "Constructor Splitting" at the top of this file. - split_ctors.push(Constructor::Missing); - } else if !split_set.missing_empty.is_empty() && !place_validity.is_known_valid() { - // The missing empty constructors are reachable if the place can contain invalid data. + if !(split_set.missing.is_empty() + && (split_set.missing_empty.is_empty() || empty_arms_are_unreachable)) + { split_ctors.push(Constructor::Missing); } // Decide what constructors to report. + let is_integers = matches!(ctors_for_ty, ConstructorSet::Integers { .. }); let always_report_all = is_top_level && !is_integers; // Whether we should report "Enum::A and Enum::C are missing" or "_ is missing". let report_individual_missing_ctors = always_report_all || !all_missing; // Which constructors are considered missing. We ensure that `!missing_ctors.is_empty() => - // split_ctors.contains(Missing)`. The converse usually holds except in the - // `MaybeInvalidButAllowOmittingArms` backwards-compatibility case. + // split_ctors.contains(Missing)`. The converse usually holds except when + // `!place_validity.is_known_valid()`. let mut missing_ctors = split_set.missing; - if !place_validity.allows_omitting_empty_arms() { - missing_ctors.extend(split_set.missing_empty); + if !can_omit_empty_arms { + missing_ctors.append(&mut split_set.missing_empty); } let mut ret = WitnessMatrix::empty(); @@ -1503,12 +1482,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( let ctor_is_relevant = matches!(ctor, Constructor::Missing) || missing_ctors.is_empty(); let mut spec_matrix = matrix.specialize_constructor(pcx, &ctor, ctor_is_relevant); let mut witnesses = ensure_sufficient_stack(|| { - compute_exhaustiveness_and_usefulness( - mcx, - &mut spec_matrix, - overlapping_range_endpoints, - false, - ) + compute_exhaustiveness_and_usefulness(mcx, &mut spec_matrix, false) })?; // Transform witnesses for `spec_matrix` into witnesses for `matrix`. @@ -1537,12 +1511,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( && spec_matrix.rows.len() >= 2 && spec_matrix.rows.iter().any(|row| !row.intersects.is_empty()) { - collect_overlapping_range_endpoints( - overlap_range, - matrix, - &spec_matrix, - overlapping_range_endpoints, - ); + collect_overlapping_range_endpoints(mcx, overlap_range, matrix, &spec_matrix); } } } @@ -1569,15 +1538,6 @@ pub enum Usefulness<'p, Cx: TypeCx> { Redundant, } -/// Indicates that the range `pat` overlapped with all the ranges in `overlaps_with`, where the -/// range they overlapped over is `overlaps_on`. We only detect singleton overlaps. -#[derive(Clone, Debug)] -pub struct OverlappingRanges<'p, Cx: TypeCx> { - pub pat: &'p DeconstructedPat<'p, Cx>, - pub overlaps_on: IntRange, - pub overlaps_with: Vec<&'p DeconstructedPat<'p, Cx>>, -} - /// The output of checking a match for exhaustiveness and arm usefulness. pub struct UsefulnessReport<'p, Cx: TypeCx> { /// For each arm of the input, whether that arm is useful after the arms above it. @@ -1585,25 +1545,19 @@ pub struct UsefulnessReport<'p, Cx: TypeCx> { /// If the match is exhaustive, this is empty. If not, this contains witnesses for the lack of /// exhaustiveness. pub non_exhaustiveness_witnesses: Vec>, - pub overlapping_range_endpoints: Vec>, } /// Computes whether a match is exhaustive and which of its arms are useful. #[instrument(skip(cx, arms), level = "debug")] pub fn compute_match_usefulness<'p, Cx: TypeCx>( - cx: MatchCtxt<'_, 'p, Cx>, + cx: MatchCtxt<'_, Cx>, arms: &[MatchArm<'p, Cx>], scrut_ty: Cx::Ty, scrut_validity: ValidityConstraint, ) -> Result, Cx::Error> { - let mut overlapping_range_endpoints = Vec::new(); let mut matrix = Matrix::new(arms, scrut_ty, scrut_validity); - let non_exhaustiveness_witnesses = compute_exhaustiveness_and_usefulness( - cx, - &mut matrix, - &mut overlapping_range_endpoints, - true, - )?; + let non_exhaustiveness_witnesses = + compute_exhaustiveness_and_usefulness(cx, &mut matrix, true)?; let non_exhaustiveness_witnesses: Vec<_> = non_exhaustiveness_witnesses.single_column(); let arm_usefulness: Vec<_> = arms @@ -1621,9 +1575,5 @@ pub fn compute_match_usefulness<'p, Cx: TypeCx>( }) .collect(); - Ok(UsefulnessReport { - arm_usefulness, - non_exhaustiveness_witnesses, - overlapping_range_endpoints, - }) + Ok(UsefulnessReport { arm_usefulness, non_exhaustiveness_witnesses }) } diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml index 88eb46030697..c57f22a0da2b 100644 --- a/compiler/rustc_query_impl/Cargo.toml +++ b/compiler/rustc_query_impl/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start field-offset = "0.3.5" -measureme = "10.0.0" +measureme = "11" rustc-rayon-core = { version = "0.5.0", optional = true } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 1f09de0ed70c..0f57688063e0 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -891,7 +891,7 @@ impl DepGraphData { insertion for {dep_node:?}" ); - if !side_effects.is_empty() { + if side_effects.maybe_any() { qcx.dep_context().dep_graph().with_query_deserialization(|| { self.emit_side_effects(qcx, dep_node_index, side_effects) }); diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs index 504763f6cdb3..f6f6aa07cb3f 100644 --- a/compiler/rustc_query_system/src/dep_graph/serialized.rs +++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs @@ -169,6 +169,7 @@ impl EdgeHeader { } } +#[inline] fn mask(bits: usize) -> usize { usize::MAX >> ((std::mem::size_of::() * 8) - bits) } diff --git a/compiler/rustc_query_system/src/ich/hcx.rs b/compiler/rustc_query_system/src/ich/hcx.rs index eec0433ae68d..e7eb9694f473 100644 --- a/compiler/rustc_query_system/src/ich/hcx.rs +++ b/compiler/rustc_query_system/src/ich/hcx.rs @@ -1,10 +1,8 @@ use crate::ich; use rustc_ast as ast; -use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::stable_hasher::{HashStable, HashingControls, StableHasher}; use rustc_data_structures::sync::Lrc; -use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::definitions::DefPathHash; use rustc_session::cstore::Untracked; @@ -23,7 +21,6 @@ pub struct StableHashingContext<'a> { // The value of `-Z incremental-ignore-spans`. // This field should only be used by `unstable_opts_incremental_ignore_span` incremental_ignore_spans: bool, - pub(super) body_resolver: BodyResolver<'a>, // Very often, we are hashing something that does not need the // `CachingSourceMapView`, so we initialize it lazily. raw_source_map: &'a SourceMap, @@ -31,26 +28,12 @@ pub struct StableHashingContext<'a> { hashing_controls: HashingControls, } -/// The `BodyResolver` allows mapping a `BodyId` to the corresponding `hir::Body`. -/// We could also just store a plain reference to the `hir::Crate` but we want -/// to avoid that the crate is used to get untracked access to all of the HIR. -#[derive(Clone, Copy)] -pub(super) enum BodyResolver<'tcx> { - Forbidden, - Ignore, - Traverse { - owner: hir::OwnerId, - bodies: &'tcx SortedMap>, - }, -} - impl<'a> StableHashingContext<'a> { #[inline] pub fn new(sess: &'a Session, untracked: &'a Untracked) -> Self { let hash_spans_initial = !sess.opts.unstable_opts.incremental_ignore_spans; StableHashingContext { - body_resolver: BodyResolver::Forbidden, untracked, incremental_ignore_spans: sess.opts.unstable_opts.incremental_ignore_spans, caching_source_map: None, @@ -59,24 +42,6 @@ impl<'a> StableHashingContext<'a> { } } - #[inline] - pub fn without_hir_bodies(&mut self, f: impl FnOnce(&mut StableHashingContext<'_>)) { - f(&mut StableHashingContext { body_resolver: BodyResolver::Ignore, ..self.clone() }); - } - - #[inline] - pub fn with_hir_bodies( - &mut self, - owner: hir::OwnerId, - bodies: &SortedMap>, - f: impl FnOnce(&mut StableHashingContext<'_>), - ) { - f(&mut StableHashingContext { - body_resolver: BodyResolver::Traverse { owner, bodies }, - ..self.clone() - }); - } - #[inline] pub fn while_hashing_spans(&mut self, hash_spans: bool, f: F) { let prev_hash_spans = self.hashing_controls.hash_spans; diff --git a/compiler/rustc_query_system/src/ich/impls_hir.rs b/compiler/rustc_query_system/src/ich/impls_hir.rs deleted file mode 100644 index aa008d404c3e..000000000000 --- a/compiler/rustc_query_system/src/ich/impls_hir.rs +++ /dev/null @@ -1,22 +0,0 @@ -//! This module contains `HashStable` implementations for various HIR data -//! types in no particular order. - -use crate::ich::hcx::BodyResolver; -use crate::ich::StableHashingContext; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_hir as hir; - -impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> { - #[inline] - fn hash_body_id(&mut self, id: hir::BodyId, hasher: &mut StableHasher) { - let hcx = self; - match hcx.body_resolver { - BodyResolver::Forbidden => panic!("Hashing HIR bodies is forbidden."), - BodyResolver::Ignore => {} - BodyResolver::Traverse { owner, bodies } => { - assert_eq!(id.hir_id.owner, owner); - bodies[&id.hir_id.local_id].hash_stable(hcx, hasher); - } - } - } -} diff --git a/compiler/rustc_query_system/src/ich/impls_syntax.rs b/compiler/rustc_query_system/src/ich/impls_syntax.rs index d170cd36ca6a..5bd4fe04848f 100644 --- a/compiler/rustc_query_system/src/ich/impls_syntax.rs +++ b/compiler/rustc_query_system/src/ich/impls_syntax.rs @@ -57,6 +57,8 @@ impl<'ctx> rustc_ast::HashStableContext for StableHashingContext<'ctx> { } } +impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> {} + impl<'a> HashStable> for SourceFile { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { let SourceFile { diff --git a/compiler/rustc_query_system/src/ich/mod.rs b/compiler/rustc_query_system/src/ich/mod.rs index 0a1c350b2db1..86e3ecb1eddb 100644 --- a/compiler/rustc_query_system/src/ich/mod.rs +++ b/compiler/rustc_query_system/src/ich/mod.rs @@ -4,7 +4,6 @@ pub use self::hcx::StableHashingContext; use rustc_span::symbol::{sym, Symbol}; mod hcx; -mod impls_hir; mod impls_syntax; pub const IGNORED_ATTRIBUTES: &[Symbol] = &[ diff --git a/compiler/rustc_query_system/src/query/caches.rs b/compiler/rustc_query_system/src/query/caches.rs index 0240f012da05..674a0984ae98 100644 --- a/compiler/rustc_query_system/src/query/caches.rs +++ b/compiler/rustc_query_system/src/query/caches.rs @@ -2,8 +2,11 @@ use crate::dep_graph::DepNodeIndex; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sharded::{self, Sharded}; -use rustc_data_structures::sync::OnceLock; +use rustc_data_structures::sync::{Lock, OnceLock}; +use rustc_hir::def_id::LOCAL_CRATE; use rustc_index::{Idx, IndexVec}; +use rustc_span::def_id::DefId; +use rustc_span::def_id::DefIndex; use std::fmt::Debug; use std::hash::Hash; use std::marker::PhantomData; @@ -148,6 +151,8 @@ where #[inline(always)] fn lookup(&self, key: &K) -> Option<(V, DepNodeIndex)> { + // FIXME: lock_shard_by_hash will use high bits which are usually zero in the index() passed + // here. This makes sharding essentially useless, always selecting the zero'th shard. let lock = self.cache.lock_shard_by_hash(key.index() as u64); if let Some(Some(value)) = lock.get(*key) { Some(*value) } else { None } } @@ -168,3 +173,75 @@ where } } } + +pub struct DefIdCacheSelector; + +impl<'tcx, V: 'tcx> CacheSelector<'tcx, V> for DefIdCacheSelector { + type Cache = DefIdCache + where + V: Copy; +} + +pub struct DefIdCache { + /// Stores the local DefIds in a dense map. Local queries are much more often dense, so this is + /// a win over hashing query keys at marginal memory cost (~5% at most) compared to FxHashMap. + /// + /// The second element of the tuple is the set of keys actually present in the IndexVec, used + /// for faster iteration in `iter()`. + // FIXME: This may want to be sharded, like VecCache. However *how* to shard an IndexVec isn't + // super clear; VecCache is effectively not sharded today (see FIXME there). For now just omit + // that complexity here. + local: Lock<(IndexVec>, Vec)>, + foreign: DefaultCache, +} + +impl Default for DefIdCache { + fn default() -> Self { + DefIdCache { local: Default::default(), foreign: Default::default() } + } +} + +impl QueryCache for DefIdCache +where + V: Copy, +{ + type Key = DefId; + type Value = V; + + #[inline(always)] + fn lookup(&self, key: &DefId) -> Option<(V, DepNodeIndex)> { + if key.krate == LOCAL_CRATE { + let cache = self.local.lock(); + cache.0.get(key.index).and_then(|v| *v) + } else { + self.foreign.lookup(key) + } + } + + #[inline] + fn complete(&self, key: DefId, value: V, index: DepNodeIndex) { + if key.krate == LOCAL_CRATE { + let mut cache = self.local.lock(); + let (cache, present) = &mut *cache; + let slot = cache.ensure_contains_elem(key.index, Default::default); + if slot.is_none() { + // FIXME: Only store the present set when running in incremental mode. `iter` is not + // used outside of saving caches to disk and self-profile. + present.push(key.index); + } + *slot = Some((value, index)); + } else { + self.foreign.complete(key, value, index) + } + } + + fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) { + let guard = self.local.lock(); + let (cache, present) = &*guard; + for &idx in present.iter() { + let value = cache[idx].unwrap(); + f(&DefId { krate: LOCAL_CRATE, index: idx }, &value.0, value.1); + } + self.foreign.iter(f); + } +} diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index 9ff04c4e910d..02b3c740b631 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -10,7 +10,8 @@ pub use self::job::{ mod caches; pub use self::caches::{ - CacheSelector, DefaultCacheSelector, QueryCache, SingleCacheSelector, VecCacheSelector, + CacheSelector, DefIdCacheSelector, DefaultCacheSelector, QueryCache, SingleCacheSelector, + VecCacheSelector, }; mod config; @@ -92,10 +93,13 @@ pub struct QuerySideEffects { } impl QuerySideEffects { + /// Returns true if there might be side effects. #[inline] - pub fn is_empty(&self) -> bool { + pub fn maybe_any(&self) -> bool { let QuerySideEffects { diagnostics } = self; - diagnostics.is_empty() + // Use `has_capacity` so that the destructor for `self.diagnostics` can be skipped + // if `maybe_any` is known to be false. + diagnostics.has_capacity() } pub fn append(&mut self, other: QuerySideEffects) { let QuerySideEffects { diagnostics } = self; diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 3bb2cc5634fe..9158ba00901c 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -538,10 +538,9 @@ where prof_timer.finish_with_query_invocation_id(dep_node_index.into()); - let diagnostics = diagnostics.into_inner(); - let side_effects = QuerySideEffects { diagnostics }; + let side_effects = QuerySideEffects { diagnostics: diagnostics.into_inner() }; - if std::intrinsics::unlikely(!side_effects.is_empty()) { + if std::intrinsics::unlikely(side_effects.maybe_any()) { if query.anon() { qcx.store_side_effects_for_anon_node(dep_node_index, side_effects); } else { diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index 3f8df16e03f7..c8ec10cad17c 100644 --- a/compiler/rustc_resolve/messages.ftl +++ b/compiler/rustc_resolve/messages.ftl @@ -36,6 +36,10 @@ resolve_attempt_to_use_non_constant_value_in_constant_with_suggestion = resolve_attempt_to_use_non_constant_value_in_constant_without_suggestion = this would need to be a `{$suggestion}` +resolve_binding_in_never_pattern = + never patterns cannot contain variable bindings + .suggestion = use a wildcard `_` instead + resolve_binding_shadows_something_unacceptable = {$shadowing_binding}s cannot shadow {$shadowed_binding}s .label = cannot be named the same as {$article} {$shadowed_binding} diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index b57006613850..4a0c522b6ec5 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -959,6 +959,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { .create_err(errs::TraitImplDuplicate { span, name, trait_item_span, old_span }), ResolutionError::InvalidAsmSym => self.dcx().create_err(errs::InvalidAsmSym { span }), ResolutionError::LowercaseSelf => self.dcx().create_err(errs::LowercaseSelf { span }), + ResolutionError::BindingInNeverPattern => { + self.dcx().create_err(errs::BindingInNeverPattern { span }) + } } } diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 1fdb193e571f..821b1e946f31 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -486,6 +486,15 @@ pub(crate) struct LowercaseSelf { pub(crate) span: Span, } +#[derive(Debug)] +#[derive(Diagnostic)] +#[diag(resolve_binding_in_never_pattern)] +pub(crate) struct BindingInNeverPattern { + #[primary_span] + #[suggestion(code = "_", applicability = "machine-applicable", style = "short")] + pub(crate) span: Span, +} + #[derive(Diagnostic)] #[diag(resolve_trait_impl_duplicate, code = "E0201")] pub(crate) struct TraitImplDuplicate { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 82f502279112..abd724a6cc25 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -16,7 +16,7 @@ use rustc_ast::ptr::P; use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; use rustc_ast::*; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; -use rustc_errors::{Applicability, DiagnosticArgValue, DiagnosticId, IntoDiagnosticArg}; +use rustc_errors::{Applicability, DiagnosticArgValue, IntoDiagnosticArg}; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS}; use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; @@ -65,6 +65,8 @@ enum IsRepeatExpr { Yes, } +struct IsNeverPattern; + /// Describes whether an `AnonConst` is a type level const arg or /// some other form of anon const (i.e. inline consts or enum discriminants) #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -531,7 +533,7 @@ impl<'a> PathSource<'a> { } } - fn error_code(self, has_unexpected_resolution: bool) -> DiagnosticId { + fn error_code(self, has_unexpected_resolution: bool) -> String { use rustc_errors::error_code; match (self, has_unexpected_resolution) { (PathSource::Trait(_), true) => error_code!(E0404), @@ -3246,12 +3248,31 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { self.resolve_pattern_top(&local.pat, PatternSource::Let); } - /// build a map from pattern identifiers to binding-info's. - /// this is done hygienically. This could arise for a macro - /// that expands into an or-pattern where one 'x' was from the - /// user and one 'x' came from the macro. - fn binding_mode_map(&mut self, pat: &Pat) -> FxIndexMap { + /// Build a map from pattern identifiers to binding-info's, and check the bindings are + /// consistent when encountering or-patterns and never patterns. + /// This is done hygienically: this could arise for a macro that expands into an or-pattern + /// where one 'x' was from the user and one 'x' came from the macro. + /// + /// A never pattern by definition indicates an unreachable case. For example, matching on + /// `Result` could look like: + /// ```rust + /// # #![feature(never_type)] + /// # #![feature(never_patterns)] + /// # fn bar(_x: u32) {} + /// let foo: Result = Ok(0); + /// match foo { + /// Ok(x) => bar(x), + /// Err(&!), + /// } + /// ``` + /// This extends to product types: `(x, !)` is likewise unreachable. So it doesn't make sense to + /// have a binding here, and we tell the user to use `_` instead. + fn compute_and_check_binding_map( + &mut self, + pat: &Pat, + ) -> Result, IsNeverPattern> { let mut binding_map = FxIndexMap::default(); + let mut is_never_pat = false; pat.walk(&mut |pat| { match pat.kind { @@ -3263,18 +3284,27 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { PatKind::Or(ref ps) => { // Check the consistency of this or-pattern and // then add all bindings to the larger map. - for bm in self.check_consistent_bindings(ps) { - binding_map.extend(bm); + match self.compute_and_check_or_pat_binding_map(ps) { + Ok(bm) => binding_map.extend(bm), + Err(IsNeverPattern) => is_never_pat = true, } return false; } + PatKind::Never => is_never_pat = true, _ => {} } true }); - binding_map + if is_never_pat { + for (_, binding) in binding_map { + self.report_error(binding.span, ResolutionError::BindingInNeverPattern); + } + Err(IsNeverPattern) + } else { + Ok(binding_map) + } } fn is_base_res_local(&self, nid: NodeId) -> bool { @@ -3284,33 +3314,52 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ) } - /// Checks that all of the arms in an or-pattern have exactly the - /// same set of bindings, with the same binding modes for each. - fn check_consistent_bindings( + /// Compute the binding map for an or-pattern. Checks that all of the arms in the or-pattern + /// have exactly the same set of bindings, with the same binding modes for each. + /// Returns the computed binding map and a boolean indicating whether the pattern is a never + /// pattern. + /// + /// A never pattern by definition indicates an unreachable case. For example, destructuring a + /// `Result` could look like: + /// ```rust + /// # #![feature(never_type)] + /// # #![feature(never_patterns)] + /// # fn foo() -> Result { Ok(true) } + /// let (Ok(x) | Err(&!)) = foo(); + /// # let _ = x; + /// ``` + /// Because the `Err(&!)` branch is never reached, it does not need to have the same bindings as + /// the other branches of the or-pattern. So we must ignore never pattern when checking the + /// bindings of an or-pattern. + /// Moreover, if all the subpatterns are never patterns (e.g. `Ok(!) | Err(!)`), then the + /// pattern as a whole counts as a never pattern (since it's definitionallly unreachable). + fn compute_and_check_or_pat_binding_map( &mut self, pats: &[P], - ) -> Vec> { - // pats is consistent. + ) -> Result, IsNeverPattern> { let mut missing_vars = FxIndexMap::default(); let mut inconsistent_vars = FxIndexMap::default(); - // 1) Compute the binding maps of all arms. - let maps = pats.iter().map(|pat| self.binding_mode_map(pat)).collect::>(); + // 1) Compute the binding maps of all arms; we must ignore never patterns here. + let not_never_pats = pats + .iter() + .filter_map(|pat| { + let binding_map = self.compute_and_check_binding_map(pat).ok()?; + Some((binding_map, pat)) + }) + .collect::>(); // 2) Record any missing bindings or binding mode inconsistencies. - for (map_outer, pat_outer) in maps.iter().zip(pats.iter()) { + for (map_outer, pat_outer) in not_never_pats.iter() { // Check against all arms except for the same pattern which is always self-consistent. - let inners = maps + let inners = not_never_pats .iter() - .zip(pats.iter()) .filter(|(_, pat)| pat.id != pat_outer.id) - .flat_map(|(map, _)| map) - .map(|(key, binding)| (key.name, map_outer.get(key), binding)); + .flat_map(|(map, _)| map); - let inners = inners.collect::>(); - - for (name, info, &binding_inner) in inners { - match info { + for (key, binding_inner) in inners { + let name = key.name; + match map_outer.get(key) { None => { // The inner binding is missing in the outer. let binding_error = @@ -3351,19 +3400,32 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { self.report_error(v.0, ResolutionError::VariableBoundWithDifferentMode(name, v.1)); } - // 5) Finally bubble up all the binding maps. - maps + // 5) Bubble up the final binding map. + if not_never_pats.is_empty() { + // All the patterns are never patterns, so the whole or-pattern is one too. + Err(IsNeverPattern) + } else { + let mut binding_map = FxIndexMap::default(); + for (bm, _) in not_never_pats { + binding_map.extend(bm); + } + Ok(binding_map) + } } - /// Check the consistency of the outermost or-patterns. - fn check_consistent_bindings_top(&mut self, pat: &'ast Pat) { + /// Check the consistency of bindings wrt or-patterns and never patterns. + fn check_consistent_bindings(&mut self, pat: &'ast Pat) { + let mut is_or_or_never = false; pat.walk(&mut |pat| match pat.kind { - PatKind::Or(ref ps) => { - self.check_consistent_bindings(ps); + PatKind::Or(..) | PatKind::Never => { + is_or_or_never = true; false } _ => true, - }) + }); + if is_or_or_never { + let _ = self.compute_and_check_binding_map(pat); + } } fn resolve_arm(&mut self, arm: &'ast Arm) { @@ -3392,7 +3454,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { visit::walk_pat(self, pat); self.resolve_pattern_inner(pat, pat_src, bindings); // This has to happen *after* we determine which pat_idents are variants: - self.check_consistent_bindings_top(pat); + self.check_consistent_bindings(pat); } /// Resolve bindings in a pattern. This is a helper to `resolve_pattern`. @@ -3759,7 +3821,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { swap(&mut err.span, &mut parent_err.span); err.children = take(&mut parent_err.children); err.sort_span = parent_err.sort_span; - err.is_lint = parent_err.is_lint; + err.is_lint = parent_err.is_lint.clone(); // merge the parent's suggestions with the typo suggestions fn append_result(res1: &mut Result, E>, res2: Result, E>) { diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 58ff4d8c7934..abb0a7a465aa 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1745,12 +1745,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { // Doing analysis on local `DefId`s would cause infinite recursion. return; } + let Ok(impls) = self.r.tcx.inherent_impls(def_id) else { return }; // Look at all the associated functions without receivers in the type's // inherent impls to look for builders that return `Self` - let mut items = self - .r - .tcx - .inherent_impls(def_id) + let mut items = impls .iter() .flat_map(|i| self.r.tcx.associated_items(i).in_definition_order()) // Only assoc fn with no receivers. @@ -2569,8 +2567,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { debug!(?param.ident, ?param.ident.span, ?use_span); let elidable = matches!(use_ctxt, LifetimeCtxt::Ref); + let deletion_span = + if param.bounds.is_empty() { deletion_span() } else { None }; - let deletion_span = deletion_span(); self.r.lint_buffer.buffer_lint_with_diagnostic( lint::builtin::SINGLE_USE_LIFETIMES, param.id, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 90aa7d79bf04..341c566d97fc 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -257,7 +257,7 @@ enum ResolutionError<'a> { kind: &'static str, trait_path: String, trait_item_span: Span, - code: rustc_errors::DiagnosticId, + code: String, }, /// Error E0201: multiple impl items for the same trait item. TraitImplDuplicate { name: Symbol, trait_item_span: Span, old_span: Span }, @@ -265,6 +265,8 @@ enum ResolutionError<'a> { InvalidAsmSym, /// `self` used instead of `Self` in a generic parameter LowercaseSelf, + /// A never pattern has a binding. + BindingInNeverPattern, } enum VisResolutionError<'a> { diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs index 352758214530..48bee4cd2f0e 100644 --- a/compiler/rustc_serialize/src/lib.rs +++ b/compiler/rustc_serialize/src/lib.rs @@ -16,7 +16,6 @@ #![feature(min_specialization)] #![feature(never_type)] #![feature(ptr_sub_ptr)] -#![feature(slice_first_last_chunk)] #![cfg_attr(test, feature(test))] #![allow(rustc::internal)] #![deny(rustc::untranslatable_diagnostic)] diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl index 53bdef6dfa0f..af8c962a2ed6 100644 --- a/compiler/rustc_session/messages.ftl +++ b/compiler/rustc_session/messages.ftl @@ -75,8 +75,6 @@ session_not_circumvent_feature = `-Zunleash-the-miri-inside-of-you` may not be u session_not_supported = not supported -session_nul_in_c_str = null characters in C string literals are not supported - session_octal_float_literal_not_supported = octal float literal is not supported session_optimization_fuel_exhausted = optimization-fuel-exhausted: {$msg} diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index fe1166457bae..e751ff13a34c 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -533,21 +533,6 @@ impl Default for ErrorOutputType { } } -/// Parameter to control path trimming. -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] -pub enum TrimmedDefPaths { - /// `try_print_trimmed_def_path` never prints a trimmed path and never calls the expensive - /// query. - #[default] - Never, - /// `try_print_trimmed_def_path` calls the expensive query, the query doesn't call - /// `good_path_delayed_bug`. - Always, - /// `try_print_trimmed_def_path` calls the expensive query, the query calls - /// `good_path_delayed_bug`. - GoodPath, -} - #[derive(Clone, Hash, Debug)] pub enum ResolveDocLinks { /// Do not resolve doc links. @@ -1089,7 +1074,7 @@ impl Default for Options { debug_assertions: true, actually_rustdoc: false, resolve_doc_links: ResolveDocLinks::None, - trimmed_def_paths: TrimmedDefPaths::default(), + trimmed_def_paths: false, cli_forced_codegen_units: None, cli_forced_local_thinlto_off: false, remap_path_prefix: Vec::new(), @@ -2926,7 +2911,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M debug_assertions, actually_rustdoc: false, resolve_doc_links: ResolveDocLinks::ExportedMetadata, - trimmed_def_paths: TrimmedDefPaths::default(), + trimmed_def_paths: false, cli_forced_codegen_units: codegen_units, cli_forced_local_thinlto_off: disable_local_thinlto, remap_path_prefix, @@ -3205,12 +3190,12 @@ pub enum WasiExecModel { /// how the hash should be calculated when adding a new command-line argument. pub(crate) mod dep_tracking { use super::{ - BranchProtection, CFGuard, CFProtection, CrateType, DebugInfo, DebugInfoCompression, - ErrorOutputType, FunctionReturn, InliningThreshold, InstrumentCoverage, InstrumentXRay, - LinkerPluginLto, LocationDetail, LtoCli, NextSolverConfig, OomStrategy, OptLevel, - OutFileName, OutputType, OutputTypes, Polonius, RemapPathScopeComponents, ResolveDocLinks, - SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion, - TrimmedDefPaths, WasiExecModel, + BranchProtection, CFGuard, CFProtection, CollapseMacroDebuginfo, CrateType, DebugInfo, + DebugInfoCompression, ErrorOutputType, FunctionReturn, InliningThreshold, + InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail, LtoCli, + NextSolverConfig, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes, Polonius, + RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind, + SwitchWithOptPath, SymbolManglingVersion, WasiExecModel, }; use crate::lint; use crate::utils::NativeLib; @@ -3289,6 +3274,7 @@ pub(crate) mod dep_tracking { LtoCli, DebugInfo, DebugInfoCompression, + CollapseMacroDebuginfo, UnstableFeatures, NativeLib, SanitizerSet, @@ -3305,7 +3291,6 @@ pub(crate) mod dep_tracking { SymbolManglingVersion, RemapPathScopeComponents, SourceFileHashAlgorithm, - TrimmedDefPaths, OutFileName, OutputType, RealFileName, @@ -3453,6 +3438,25 @@ pub enum ProcMacroExecutionStrategy { CrossThread, } +/// How to perform collapse macros debug info +/// if-ext - if macro from different crate (related to callsite code) +/// | cmd \ attr | no | (unspecified) | external | yes | +/// | no | no | no | no | no | +/// | (unspecified) | no | no | if-ext | yes | +/// | external | no | if-ext | if-ext | yes | +/// | yes | yes | yes | yes | yes | +#[derive(Clone, Copy, PartialEq, Hash, Debug)] +pub enum CollapseMacroDebuginfo { + /// Don't collapse debuginfo for the macro + No = 0, + /// Unspecified value + Unspecified = 1, + /// Collapse debuginfo if the macro comes from a different crate + External = 2, + /// Collapse debuginfo for the macro + Yes = 3, +} + /// Which format to use for `-Z dump-mono-stats` #[derive(Clone, Copy, PartialEq, Hash, Debug)] pub enum DumpMonoStatsFormat { diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 21a206798af1..e19f0fd84de5 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -6,7 +6,7 @@ use rustc_errors::{ error_code, DiagCtxt, DiagnosticBuilder, DiagnosticMessage, IntoDiagnostic, Level, MultiSpan, }; use rustc_macros::Diagnostic; -use rustc_span::{BytePos, Span, Symbol}; +use rustc_span::{Span, Symbol}; use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple}; use crate::parse::ParseSess; @@ -346,13 +346,6 @@ pub(crate) struct BinaryFloatLiteralNotSupported { pub span: Span, } -#[derive(Diagnostic)] -#[diag(session_nul_in_c_str)] -pub(crate) struct NulInCStr { - #[primary_span] - pub span: Span, -} - pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span: Span) { // Checks if `s` looks like i32 or u1234 etc. fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool { @@ -432,12 +425,6 @@ pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span: }; dcx.emit_err(IntLiteralTooLarge { span, limit }); } - LitError::NulInCStr(range) => { - let lo = BytePos(span.lo().0 + range.start as u32 + 2); - let hi = BytePos(span.lo().0 + range.end as u32 + 2); - let span = span.with_lo(lo).with_hi(hi); - dcx.emit_err(NulInCStr { span }); - } } } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 2d91a3fbd911..1337ade62c01 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -183,7 +183,7 @@ top_level_options!( resolve_doc_links: ResolveDocLinks [TRACKED], /// Control path trimming. - trimmed_def_paths: TrimmedDefPaths [TRACKED], + trimmed_def_paths: bool [TRACKED], /// Specifications of codegen units / ThinLTO which are forced as a /// result of parsing command line options. These are not necessarily @@ -388,6 +388,7 @@ mod desc { pub const parse_cfprotection: &str = "`none`|`no`|`n` (default), `branch`, `return`, or `full`|`yes`|`y` (equivalent to `branch` and `return`)"; pub const parse_debuginfo: &str = "either an integer (0, 1, 2), `none`, `line-directives-only`, `line-tables-only`, `limited`, or `full`"; pub const parse_debuginfo_compression: &str = "one of `none`, `zlib`, or `zstd`"; + pub const parse_collapse_macro_debuginfo: &str = "one of `no`, `external`, or `yes`"; pub const parse_strip: &str = "either `none`, `debuginfo`, or `symbols`"; pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavorCli::one_of(); pub const parse_optimization_fuel: &str = "crate=integer"; @@ -1302,6 +1303,19 @@ mod parse { true } + pub(crate) fn parse_collapse_macro_debuginfo( + slot: &mut CollapseMacroDebuginfo, + v: Option<&str>, + ) -> bool { + *slot = match v { + Some("no") => CollapseMacroDebuginfo::No, + Some("external") => CollapseMacroDebuginfo::External, + Some("yes") => CollapseMacroDebuginfo::Yes, + _ => return false, + }; + true + } + pub(crate) fn parse_proc_macro_execution_strategy( slot: &mut ProcMacroExecutionStrategy, v: Option<&str>, @@ -1534,6 +1548,9 @@ options! { "instrument control-flow architecture protection"), codegen_backend: Option = (None, parse_opt_string, [TRACKED], "the backend to use"), + collapse_macro_debuginfo: CollapseMacroDebuginfo = (CollapseMacroDebuginfo::Unspecified, + parse_collapse_macro_debuginfo, [TRACKED], + "set option to collapse debuginfo for macros"), combine_cgu: bool = (false, parse_bool, [TRACKED], "combine CGUs into a single one"), crate_attr: Vec = (Vec::new(), parse_string_push, [TRACKED], @@ -1724,6 +1741,8 @@ options! { "run all passes except codegen; no output"), no_generate_arange_section: bool = (false, parse_no_flag, [TRACKED], "omit DWARF address ranges that give faster lookups"), + no_implied_bounds_compat: bool = (false, parse_bool, [TRACKED], + "disable the compatibility version of the `implied_bounds_ty` query"), no_jump_tables: bool = (false, parse_no_flag, [TRACKED], "disable the jump tables and lookup tables that can be generated from a switch case lowering"), no_leak_check: bool = (false, parse_no_flag, [UNTRACKED], diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index c629c9884c8e..16036e5be38c 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -15,8 +15,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::{AppendOnlyVec, Lock, Lrc}; use rustc_errors::{emitter::SilentEmitter, DiagCtxt}; use rustc_errors::{ - fallback_fluent_bundle, Diagnostic, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, - MultiSpan, StashKey, + fallback_fluent_bundle, Diagnostic, DiagnosticBuilder, DiagnosticMessage, MultiSpan, StashKey, }; use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures}; use rustc_span::edition::Edition; @@ -148,7 +147,7 @@ pub fn feature_warn_issue( // Decorate this as a future-incompatibility lint as in rustc_middle::lint::struct_lint_level let lint = UNSTABLE_SYNTAX_PRE_EXPANSION; let future_incompatible = lint.future_incompatible.as_ref().unwrap(); - err.code(DiagnosticId::Lint { name: lint.name_lower(), has_future_breakage: false }); + err.is_lint(lint.name_lower(), /* has_future_breakage */ false); err.warn(lint.desc); err.note(format!("for more information, see {}", future_incompatible.reference)); diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 1c3d5a3cb881..cba6ce0d235e 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -14,15 +14,16 @@ use rustc_data_structures::flock; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_data_structures::jobserver::{self, Client}; use rustc_data_structures::profiling::{SelfProfiler, SelfProfilerRef}; -use rustc_data_structures::sync::{AtomicU64, DynSend, DynSync, Lock, Lrc, OneThread}; +use rustc_data_structures::sync::{ + AtomicU64, DynSend, DynSync, Lock, Lrc, MappedReadGuard, ReadGuard, RwLock, +}; use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitter; use rustc_errors::emitter::{DynEmitter, HumanEmitter, HumanReadableErrorType}; use rustc_errors::json::JsonEmitter; use rustc_errors::registry::Registry; use rustc_errors::{ - error_code, fallback_fluent_bundle, DiagCtxt, DiagnosticBuilder, DiagnosticId, - DiagnosticMessage, ErrorGuaranteed, FatalAbort, FluentBundle, IntoDiagnostic, - LazyFallbackBundle, TerminalUrl, + error_code, fallback_fluent_bundle, DiagCtxt, DiagnosticBuilder, DiagnosticMessage, + ErrorGuaranteed, FatalAbort, FluentBundle, IntoDiagnostic, LazyFallbackBundle, TerminalUrl, }; use rustc_macros::HashStable_Generic; pub use rustc_span::def_id::StableCrateId; @@ -36,7 +37,6 @@ use rustc_target::spec::{ }; use std::any::Any; -use std::cell::{self, RefCell}; use std::env; use std::fmt; use std::ops::{Div, Mul}; @@ -150,7 +150,7 @@ pub struct Session { /// Input, input file path and output file path to this compilation process. pub io: CompilerIO, - incr_comp_session: OneThread>, + incr_comp_session: RwLock, /// Used by `-Z self-profile`. pub prof: SelfProfilerRef, @@ -534,9 +534,9 @@ impl Session { *incr_comp_session = IncrCompSession::InvalidBecauseOfErrors { session_directory }; } - pub fn incr_comp_session_dir(&self) -> cell::Ref<'_, PathBuf> { + pub fn incr_comp_session_dir(&self) -> MappedReadGuard<'_, PathBuf> { let incr_comp_session = self.incr_comp_session.borrow(); - cell::Ref::map(incr_comp_session, |incr_comp_session| match *incr_comp_session { + ReadGuard::map(incr_comp_session, |incr_comp_session| match *incr_comp_session { IncrCompSession::NotInitialized => panic!( "trying to get session directory from `IncrCompSession`: {:?}", *incr_comp_session, @@ -549,7 +549,7 @@ impl Session { }) } - pub fn incr_comp_session_dir_opt(&self) -> Option> { + pub fn incr_comp_session_dir_opt(&self) -> Option> { self.opts.incremental.as_ref().map(|_| self.incr_comp_session_dir()) } @@ -906,7 +906,7 @@ impl Session { CodegenUnits::Default(16) } - pub fn teach(&self, code: &DiagnosticId) -> bool { + pub fn teach(&self, code: &str) -> bool { self.opts.unstable_opts.teach && self.dcx().must_teach(code) } @@ -1177,7 +1177,7 @@ pub fn build_session( parse_sess, sysroot, io, - incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)), + incr_comp_session: RwLock::new(IncrCompSession::NotInitialized), prof, code_stats: Default::default(), optimization_fuel, diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index 4bac98909add..b99640d2f2d6 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -190,35 +190,120 @@ where stable_mir::compiler_interface::run(&tables, || init(&tables, f)) } +/// Instantiate and run the compiler with the provided arguments and callback. +/// +/// The callback will be invoked after the compiler ran all its analyses, but before code generation. +/// Note that this macro accepts two different formats for the callback: +/// 1. An ident that resolves to a function that accepts no argument and returns `ControlFlow` +/// ```ignore(needs-extern-crate) +/// # extern crate rustc_driver; +/// # extern crate rustc_interface; +/// # #[macro_use] +/// # extern crate rustc_smir; +/// # extern crate stable_mir; +/// # +/// # fn main() { +/// # use std::ops::ControlFlow; +/// # use stable_mir::CompilerError; +/// fn analyze_code() -> ControlFlow<(), ()> { +/// // Your code goes in here. +/// # ControlFlow::Continue(()) +/// } +/// # let args = vec!["--verbose".to_string()]; +/// let result = run!(args, analyze_code); +/// # assert_eq!(result, Err(CompilerError::Skipped)) +/// # } +/// ``` +/// 2. A closure expression: +/// ```ignore(needs-extern-crate) +/// # extern crate rustc_driver; +/// # extern crate rustc_interface; +/// # #[macro_use] +/// # extern crate rustc_smir; +/// # extern crate stable_mir; +/// # +/// # fn main() { +/// # use std::ops::ControlFlow; +/// # use stable_mir::CompilerError; +/// fn analyze_code(extra_args: Vec) -> ControlFlow<(), ()> { +/// # let _ = extra_args; +/// // Your code goes in here. +/// # ControlFlow::Continue(()) +/// } +/// # let args = vec!["--verbose".to_string()]; +/// # let extra_args = vec![]; +/// let result = run!(args, || analyze_code(extra_args)); +/// # assert_eq!(result, Err(CompilerError::Skipped)) +/// # } +/// ``` #[macro_export] macro_rules! run { - ($args:expr, $callback:expr) => { - run!($args, tcx, $callback) + ($args:expr, $callback_fn:ident) => { + run_driver!($args, || $callback_fn()) }; - ($args:expr, $tcx:ident, $callback:expr) => {{ + ($args:expr, $callback:expr) => { + run_driver!($args, $callback) + }; +} + +/// Instantiate and run the compiler with the provided arguments and callback. +/// +/// This is similar to `run` but it invokes the callback with the compiler's `TyCtxt`, +/// which can be used to invoke internal APIs. +#[macro_export] +macro_rules! run_with_tcx { + ($args:expr, $callback_fn:ident) => { + run_driver!($args, |tcx| $callback_fn(tcx), with_tcx) + }; + ($args:expr, $callback:expr) => { + run_driver!($args, $callback, with_tcx) + }; +} + +/// Optionally include an ident. This is needed due to macro hygiene. +#[macro_export] +#[doc(hidden)] +macro_rules! optional { + (with_tcx $ident:ident) => { + $ident + }; +} + +/// Prefer using [run!] and [run_with_tcx] instead. +/// +/// This macro implements the instantiation of a StableMIR driver, and it will invoke +/// the given callback after the compiler analyses. +/// +/// The third argument determines whether the callback requires `tcx` as an argument. +#[macro_export] +#[doc(hidden)] +macro_rules! run_driver { + ($args:expr, $callback:expr $(, $with_tcx:ident)?) => {{ use rustc_driver::{Callbacks, Compilation, RunCompiler}; use rustc_interface::{interface, Queries}; use stable_mir::CompilerError; use std::ops::ControlFlow; - pub struct StableMir + pub struct StableMir ControlFlow> where B: Send, C: Send, + F: FnOnce($(optional!($with_tcx TyCtxt))?) -> ControlFlow + Send, { args: Vec, - callback: fn(TyCtxt<'_>) -> ControlFlow, + callback: Option, result: Option>, } - impl StableMir + impl StableMir where B: Send, C: Send, + F: FnOnce($(optional!($with_tcx TyCtxt))?) -> ControlFlow + Send, { /// Creates a new `StableMir` instance, with given test_function and arguments. - pub fn new(args: Vec, callback: fn(TyCtxt<'_>) -> ControlFlow) -> Self { - StableMir { args, callback, result: None } + pub fn new(args: Vec, callback: F) -> Self { + StableMir { args, callback: Some(callback), result: None } } /// Runs the compiler against given target and tests it with `test_function` @@ -238,10 +323,11 @@ macro_rules! run { } } - impl Callbacks for StableMir + impl Callbacks for StableMir where B: Send, C: Send, + F: FnOnce($(optional!($with_tcx TyCtxt))?) -> ControlFlow + Send, { /// Called after analysis. Return value instructs the compiler whether to /// continue the compilation afterwards (defaults to `Compilation::Continue`) @@ -251,20 +337,24 @@ macro_rules! run { queries: &'tcx Queries<'tcx>, ) -> Compilation { queries.global_ctxt().unwrap().enter(|tcx| { - rustc_internal::run(tcx, || { - self.result = Some((self.callback)(tcx)); - }) - .unwrap(); - if self.result.as_ref().is_some_and(|val| val.is_continue()) { - Compilation::Continue + if let Some(callback) = self.callback.take() { + rustc_internal::run(tcx, || { + self.result = Some(callback($(optional!($with_tcx tcx))?)); + }) + .unwrap(); + if self.result.as_ref().is_some_and(|val| val.is_continue()) { + Compilation::Continue + } else { + Compilation::Stop + } } else { - Compilation::Stop + Compilation::Continue } }) } } - StableMir::new($args, |$tcx| $callback).run() + StableMir::new($args, $callback).run() }}; } diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs index c5fb6f7a26f1..2f3d9d69b858 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs @@ -609,7 +609,7 @@ impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> { fn_span: _, } => TerminatorKind::Call { func: func.stable(tables), - args: args.iter().map(|arg| arg.stable(tables)).collect(), + args: args.iter().map(|arg| arg.node.stable(tables)).collect(), destination: destination.stable(tables), target: target.map(|t| t.as_usize()), unwind: unwind.stable(tables), diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index d03965b539c8..3d26efec5a65 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -330,7 +330,7 @@ pub(crate) struct HygieneData { /// would have collisions without a disambiguator. /// The keys of this map are always computed with `ExpnData.disambiguator` /// set to 0. - expn_data_disambiguators: FxHashMap, + expn_data_disambiguators: UnhashMap, } impl HygieneData { @@ -359,7 +359,7 @@ impl HygieneData { dollar_crate_name: kw::DollarCrate, }], syntax_context_map: FxHashMap::default(), - expn_data_disambiguators: FxHashMap::default(), + expn_data_disambiguators: UnhashMap::default(), } } @@ -464,12 +464,15 @@ impl HygieneData { &self, mut span: Span, to: Span, - collapse_debuginfo_enabled: bool, + collapse_debuginfo_feature_enabled: bool, ) -> Span { let orig_span = span; let mut ret_span = span; - debug!("walk_chain_collapsed({:?}, {:?})", span, to); + debug!( + "walk_chain_collapsed({:?}, {:?}), feature_enable={}", + span, to, collapse_debuginfo_feature_enabled, + ); debug!("walk_chain_collapsed: span ctxt = {:?}", span.ctxt()); while !span.eq_ctxt(to) && span.from_expansion() { let outer_expn = self.outer_expn(span.ctxt()); @@ -477,7 +480,7 @@ impl HygieneData { let expn_data = self.expn_data(outer_expn); debug!("walk_chain_collapsed({:?}): expn_data={:?}", span, expn_data); span = expn_data.call_site; - if !collapse_debuginfo_enabled || expn_data.collapse_debuginfo { + if !collapse_debuginfo_feature_enabled || expn_data.collapse_debuginfo { ret_span = span; } } @@ -601,8 +604,14 @@ pub fn walk_chain(span: Span, to: SyntaxContext) -> Span { HygieneData::with(|data| data.walk_chain(span, to)) } -pub fn walk_chain_collapsed(span: Span, to: Span, collapse_debuginfo_enabled: bool) -> Span { - HygieneData::with(|hdata| hdata.walk_chain_collapsed(span, to, collapse_debuginfo_enabled)) +pub fn walk_chain_collapsed( + span: Span, + to: Span, + collapse_debuginfo_feature_enabled: bool, +) -> Span { + HygieneData::with(|hdata| { + hdata.walk_chain_collapsed(span, to, collapse_debuginfo_feature_enabled) + }) } pub fn update_dollar_crate_names(mut get_name: impl FnMut(SyntaxContext) -> Symbol) { diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index 8253ffefcaa7..df7635e447da 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -10,8 +10,8 @@ //! information, source code snippets, etc. use crate::*; -use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::{IntoDynSyncSend, MappedReadGuard, ReadGuard, RwLock}; +use rustc_data_structures::unhash::UnhashMap; use std::fs; use std::io::{self, BorrowedBuf, Read}; use std::path::{self}; @@ -70,7 +70,7 @@ mod monotonic { impl !DerefMut for MonotonicVec {} } -#[derive(Clone, Encodable, Decodable, Debug, Copy, HashStable_Generic)] +#[derive(Clone, Encodable, Decodable, Debug, Copy, PartialEq, Hash, HashStable_Generic)] pub struct Spanned { pub node: T, pub span: Span, @@ -164,7 +164,7 @@ impl FileLoader for RealFileLoader { #[derive(Default)] struct SourceMapFiles { source_files: monotonic::MonotonicVec>, - stable_id_to_source_file: FxHashMap>, + stable_id_to_source_file: UnhashMap>, } pub struct SourceMap { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 72b62a795fc5..7b0138d50bae 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -749,6 +749,7 @@ symbols! { extern_in_paths, extern_prelude, extern_types, + external, external_doc, f, f16c_target_feature, @@ -1152,6 +1153,7 @@ symbols! { offset, offset_of, offset_of_enum, + offset_of_nested, ok_or_else, omit_gdb_pretty_printer_section, on, @@ -1811,6 +1813,7 @@ symbols! { xmm_reg, yeet_desugar_details, yeet_expr, + yes, yield_expr, ymm_reg, zmm_reg, diff --git a/compiler/rustc_target/src/spec/base/freebsd.rs b/compiler/rustc_target/src/spec/base/freebsd.rs index 8c141aaaec34..80b3da8a752d 100644 --- a/compiler/rustc_target/src/spec/base/freebsd.rs +++ b/compiler/rustc_target/src/spec/base/freebsd.rs @@ -6,6 +6,7 @@ pub fn opts() -> TargetOptions { dynamic_linking: true, families: cvs!["unix"], has_rpath: true, + crt_static_respected: true, position_independent_executables: true, relro_level: RelroLevel::Full, abi_return_struct_as_int: true, diff --git a/compiler/rustc_target/src/spec/targets/asmjs_unknown_emscripten.rs b/compiler/rustc_target/src/spec/targets/asmjs_unknown_emscripten.rs deleted file mode 100644 index e4768c67af55..000000000000 --- a/compiler/rustc_target/src/spec/targets/asmjs_unknown_emscripten.rs +++ /dev/null @@ -1,7 +0,0 @@ -use crate::spec::{targets::wasm32_unknown_emscripten, LinkerFlavor, Target}; - -pub fn target() -> Target { - let mut target = wasm32_unknown_emscripten::target(); - target.add_post_link_args(LinkerFlavor::EmCc, &["-sWASM=0", "--memory-init-file", "0"]); - target -} diff --git a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs index 13f8b6b5a0a0..a221538b9022 100644 --- a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs @@ -11,7 +11,7 @@ pub fn target() -> Target { llvm_target: ios_sim_llvm_target(arch).into(), pointer_width: 32, data_layout: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - f64:32:64-f80:128-n8:16:32-S128" + i128:128-f64:32:64-f80:128-n8:16:32-S128" .into(), arch: arch.target_arch(), options: TargetOptions { max_atomic_width: Some(64), ..opts("ios", arch) }, diff --git a/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs b/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs index 3ebf4bcf5231..ea8b919e7480 100644 --- a/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs +++ b/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs @@ -5,7 +5,7 @@ pub fn target() -> Target { llvm_target: "i586-pc-unknown".into(), pointer_width: 32, data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - f64:32:64-f80:32-n8:16:32-S128" + i128:128-f64:32:64-f80:32-n8:16:32-S128" .into(), arch: "x86".into(), options: TargetOptions { diff --git a/compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs index 8375fa4c0c0f..574dc658b78c 100644 --- a/compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs @@ -10,7 +10,7 @@ pub fn target() -> Target { llvm_target: "i586-unknown-netbsdelf".into(), pointer_width: 32, data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - f64:32:64-f80:32-n8:16:32-S128" + i128:128-f64:32:64-f80:32-n8:16:32-S128" .into(), arch: "x86".into(), options: TargetOptions { mcount: "__mcount".into(), ..base }, diff --git a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs index 59069fe4e3a9..25617b4436cb 100644 --- a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs @@ -18,7 +18,7 @@ pub fn target() -> Target { llvm_target: macos_llvm_target(Arch::I686).into(), pointer_width: 32, data_layout: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - f64:32:64-f80:128-n8:16:32-S128" + i128:128-f64:32:64-f80:128-n8:16:32-S128" .into(), arch: arch.target_arch(), options: TargetOptions { mcount: "\u{1}mcount".into(), ..base }, diff --git a/compiler/rustc_target/src/spec/targets/i686_linux_android.rs b/compiler/rustc_target/src/spec/targets/i686_linux_android.rs index 79471040f0da..12ebf0c72f83 100644 --- a/compiler/rustc_target/src/spec/targets/i686_linux_android.rs +++ b/compiler/rustc_target/src/spec/targets/i686_linux_android.rs @@ -17,7 +17,7 @@ pub fn target() -> Target { llvm_target: "i686-linux-android".into(), pointer_width: 32, data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - f64:32:64-f80:32-n8:16:32-S128" + i128:128-f64:32:64-f80:32-n8:16:32-S128" .into(), arch: "x86".into(), options: TargetOptions { supported_sanitizers: SanitizerSet::ADDRESS, ..base }, diff --git a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs index 8d4a39b58114..118180344143 100644 --- a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs @@ -19,7 +19,7 @@ pub fn target() -> Target { llvm_target: "i686-pc-windows-gnu".into(), pointer_width: 32, data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - i64:64-f80:32-n8:16:32-a:0:32-S32" + i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32" .into(), arch: "x86".into(), options: base, diff --git a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs index bb410cd8caf2..f4e33b881788 100644 --- a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs +++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs @@ -18,7 +18,7 @@ pub fn target() -> Target { llvm_target: "i686-pc-windows-gnu".into(), pointer_width: 32, data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - i64:64-f80:32-n8:16:32-a:0:32-S32" + i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32" .into(), arch: "x86".into(), options: base, diff --git a/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs index 5abc3017bf80..9f1c8f4676cb 100644 --- a/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs @@ -25,7 +25,7 @@ pub fn target() -> Target { llvm_target: "i686-pc-windows-msvc".into(), pointer_width: 32, data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - i64:64-f80:128-n8:16:32-a:0:32-S32" + i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32" .into(), arch: "x86".into(), options: base, diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs index 927b2ab877dd..d90f481c68cf 100644 --- a/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs @@ -11,7 +11,7 @@ pub fn target() -> Target { llvm_target: "i686-unknown-freebsd".into(), pointer_width: 32, data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - f64:32:64-f80:32-n8:16:32-S128" + i128:128-f64:32:64-f80:32-n8:16:32-S128" .into(), arch: "x86".into(), options: base, diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs index bc7fd6fbc68c..330a390c9817 100644 --- a/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs @@ -11,7 +11,7 @@ pub fn target() -> Target { llvm_target: "i686-unknown-haiku".into(), pointer_width: 32, data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - f64:32:64-f80:32-n8:16:32-S128" + i128:128-f64:32:64-f80:32-n8:16:32-S128" .into(), arch: "x86".into(), options: base, diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs index 6884e078c27e..c32f7177c1a0 100644 --- a/compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs @@ -11,7 +11,7 @@ pub fn target() -> Target { llvm_target: "i686-unknown-hurd-gnu".into(), pointer_width: 32, data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - f64:32:64-f80:32-n8:16:32-S128" + i128:128-f64:32:64-f80:32-n8:16:32-S128" .into(), arch: "x86".into(), options: base, diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs index 3b7be48dbbc5..9bc38a72f4d3 100644 --- a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs @@ -12,7 +12,7 @@ pub fn target() -> Target { llvm_target: "i686-unknown-linux-gnu".into(), pointer_width: 32, data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - f64:32:64-f80:32-n8:16:32-S128" + i128:128-f64:32:64-f80:32-n8:16:32-S128" .into(), arch: "x86".into(), options: base, diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs index ef58b4fb4588..4a82e0986c72 100644 --- a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs @@ -25,7 +25,7 @@ pub fn target() -> Target { llvm_target: "i686-unknown-linux-musl".into(), pointer_width: 32, data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - f64:32:64-f80:32-n8:16:32-S128" + i128:128-f64:32:64-f80:32-n8:16:32-S128" .into(), arch: "x86".into(), options: base, diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs index 5f3afbe5afdc..ea72656607e4 100644 --- a/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs @@ -11,7 +11,7 @@ pub fn target() -> Target { llvm_target: "i686-unknown-netbsdelf".into(), pointer_width: 32, data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - f64:32:64-f80:32-n8:16:32-S128" + i128:128-f64:32:64-f80:32-n8:16:32-S128" .into(), arch: "x86".into(), options: TargetOptions { mcount: "__mcount".into(), ..base }, diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs index f44584a10be5..945dc0f89670 100644 --- a/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs @@ -11,7 +11,7 @@ pub fn target() -> Target { llvm_target: "i686-unknown-openbsd".into(), pointer_width: 32, data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - f64:32:64-f80:32-n8:16:32-S128" + i128:128-f64:32:64-f80:32-n8:16:32-S128" .into(), arch: "x86".into(), options: base, diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs index 25315e19cddb..37d57c1cdf30 100644 --- a/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs @@ -80,7 +80,7 @@ pub fn target() -> Target { llvm_target: "i686-unknown-windows-gnu".into(), pointer_width: 32, data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - i64:64-f80:32-n8:16:32-a:0:32-S32" + i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32" .into(), arch: "x86".into(), diff --git a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs index ec211a710eb0..0830033dc23d 100644 --- a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs @@ -18,7 +18,7 @@ pub fn target() -> Target { llvm_target: "i686-pc-windows-gnu".into(), pointer_width: 32, data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - i64:64-f80:32-n8:16:32-a:0:32-S32" + i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32" .into(), arch: "x86".into(), options: base, diff --git a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs index 7cca2fc6b9f7..534dd6ee54fb 100644 --- a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs @@ -9,7 +9,7 @@ pub fn target() -> Target { llvm_target: "i686-pc-windows-msvc".into(), pointer_width: 32, data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - i64:64-f80:128-n8:16:32-a:0:32-S32" + i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32" .into(), arch: "x86".into(), options: base, diff --git a/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs index 5b91682e168a..35ad81dc052b 100644 --- a/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs @@ -25,7 +25,7 @@ pub fn target() -> Target { llvm_target: "i686-pc-windows-msvc".into(), pointer_width: 32, data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - i64:64-f80:128-n8:16:32-a:0:32-S32" + i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32" .into(), arch: "x86".into(), options: base, diff --git a/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs index ee501c5165e0..30c2295e4021 100644 --- a/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs @@ -11,7 +11,7 @@ pub fn target() -> Target { llvm_target: "i686-unknown-linux-gnu".into(), pointer_width: 32, data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - f64:32:64-f80:32-n8:16:32-S128" + i128:128-f64:32:64-f80:32-n8:16:32-S128" .into(), arch: "x86".into(), options: base, diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs index e2e707f4a1ac..90df3c696846 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs @@ -11,7 +11,7 @@ pub fn target() -> Target { Target { llvm_target: "powerpc64-unknown-linux-musl".into(), pointer_width: 64, - data_layout: "E-m:e-Fi64-i64:64-n32:64-S128-v256:256:256-v512:512:512".into(), + data_layout: "E-m:e-Fn32-i64:64-n32:64-S128-v256:256:256-v512:512:512".into(), arch: "powerpc64".into(), options: TargetOptions { endian: Endian::Big, mcount: "_mcount".into(), ..base }, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs index 59df3937ea6f..356c67218681 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs @@ -17,8 +17,8 @@ pub fn target() -> Target { // correctly, we do too. llvm_target: macos_llvm_target(arch).into(), pointer_width: 64, - data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: arch.target_arch(), options: TargetOptions { mcount: "\u{1}mcount".into(), ..base }, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs index d0e2ac44a2a2..55165ea4ec68 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs @@ -9,8 +9,8 @@ pub fn target() -> Target { Target { llvm_target: ios_sim_llvm_target(arch).into(), pointer_width: 64, - data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: arch.target_arch(), options: TargetOptions { max_atomic_width: Some(128), ..base }, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs index 8ef4b88b8b1c..ff21e4893332 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs @@ -12,8 +12,8 @@ pub fn target() -> Target { Target { llvm_target: llvm_target.into(), pointer_width: 64, - data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: arch.target_arch(), options: TargetOptions { max_atomic_width: Some(128), ..base }, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs index 17efd437f2fc..20b016125531 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs @@ -6,8 +6,8 @@ pub fn target() -> Target { Target { llvm_target: tvos_sim_llvm_target(arch).into(), pointer_width: 64, - data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: arch.target_arch(), options: TargetOptions { max_atomic_width: Some(128), ..opts("tvos", arch) }, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs index b1f72ee2f212..806a58e980be 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs @@ -6,8 +6,8 @@ pub fn target() -> Target { Target { llvm_target: watchos_sim_llvm_target(arch).into(), pointer_width: 64, - data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: arch.target_arch(), options: TargetOptions { max_atomic_width: Some(128), ..opts("watchos", arch) }, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs b/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs index f4117edc3ff5..c38a1a08536b 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs @@ -75,8 +75,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-elf".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: opts, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs b/compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs index 0e6d41abc9b4..30b1ee73630e 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs @@ -16,8 +16,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-linux-android".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: TargetOptions { supported_sanitizers: SanitizerSet::ADDRESS, ..base }, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs index 93aec4c425a2..0ef015973998 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs @@ -4,8 +4,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-pc-unknown".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: TargetOptions { cpu: "x86-64".into(), diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs index f15ad8dda63b..ade4dd6d4319 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs @@ -13,8 +13,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-pc-solaris".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs index 6d3e07270517..9e964d248bf8 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs @@ -16,8 +16,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-pc-windows-gnu".into(), pointer_width: 64, - data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs index a56ebfa585e2..1facf9450cd2 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs @@ -11,8 +11,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-pc-windows-gnu".into(), pointer_width: 64, - data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs index 3a4da91c2443..357261073a8f 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs @@ -10,8 +10,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-pc-windows-msvc".into(), pointer_width: 64, - data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs b/compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs index e6159fca3aea..6c9d11475487 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs @@ -5,8 +5,8 @@ pub fn target() -> Target { llvm_target: "x86_64-unknown-linux-musl".into(), pointer_width: 64, arch: "x86_64".into(), - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), options: TargetOptions { cpu: "x86-64".into(), plt_by_default: false, diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs index 80adb8fa2d95..ce682bb80056 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs @@ -11,8 +11,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-unknown-dragonfly".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs index fa3210353670..6d6940e7891c 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs @@ -14,8 +14,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-unknown-freebsd".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs index 5b19ed1b5ff1..50139e5c1d83 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs @@ -12,8 +12,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-unknown-fuchsia".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs index 0f927be962bf..c00c689f7ef7 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs @@ -13,8 +13,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-unknown-haiku".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs index df191f515bd6..fb46848ba8c0 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs @@ -5,8 +5,8 @@ pub fn target() -> Target { llvm_target: "x86_64-unknown-hermit".into(), pointer_width: 64, arch: "x86_64".into(), - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), options: TargetOptions { cpu: "x86-64".into(), features: "+rdrnd,+rdseed".into(), diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs index eb2b13cb5c26..3e3f4921322c 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs @@ -13,8 +13,8 @@ pub fn target() -> Target { // so we still pass Solaris to it llvm_target: "x86_64-pc-solaris".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs index 7b86fe738b1e..646623668c6c 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs @@ -10,8 +10,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-unknown-l4re-uclibc".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs index bf10f7e5d2de..2296b58f45dc 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs @@ -19,8 +19,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-unknown-linux-gnu".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs index 1856c6afd52b..d4b6519262e9 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs @@ -16,7 +16,7 @@ pub fn target() -> Target { llvm_target: "x86_64-unknown-linux-gnux32".into(), pointer_width: 32, data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ - i64:64-f80:128-n8:16:32:64-S128" + i64:64-i128:128-f80:128-n8:16:32:64-S128" .into(), arch: "x86_64".into(), options: base, diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs index 8dc5503e336a..c71dc65670c2 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs @@ -18,8 +18,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-unknown-linux-musl".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs index 35862656aa2f..c25105f6e35c 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs @@ -18,8 +18,8 @@ pub fn target() -> Target { // LLVM 15 doesn't support OpenHarmony yet, use a linux target instead. llvm_target: "x86_64-unknown-linux-musl".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs index e2cee0513bab..466498acb0b7 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs @@ -19,8 +19,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-unknown-netbsd".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: TargetOptions { mcount: "__mcount".into(), ..base }, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs index 8f7655d8ccd3..ceded7790a64 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs @@ -30,8 +30,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-unknown-none-elf".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: opts, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs index 1133b50f3d22..b542a569bbd2 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs @@ -12,8 +12,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-unknown-openbsd".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs index c1f573112920..550b7a3d2823 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs @@ -11,8 +11,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-unknown-redox".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs index 5abfb8162f70..95847e57a0fb 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs @@ -32,8 +32,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-unknown-windows".into(), pointer_width: 64, - data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, diff --git a/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs index a46d3a0e27bc..c2981ddbad69 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs @@ -15,8 +15,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-pc-windows-gnu".into(), pointer_width: 64, - data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs index a3bc27aa0650..3f0702c7ad60 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs @@ -9,8 +9,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-pc-windows-msvc".into(), pointer_width: 64, - data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs index 5a59839ebc68..fd26b6e8caea 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs @@ -10,8 +10,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-win7-windows-msvc".into(), pointer_width: 64, - data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs index 765239bdd39c..f7a78b48f95d 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs @@ -12,8 +12,8 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-unknown-linux-gnu".into(), pointer_width: 64, - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs index 0c731e369ebc..e0e4cb93e31e 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs @@ -35,8 +35,8 @@ pub fn target() -> Target { // correctly, we do too. llvm_target: macos_llvm_target(arch).into(), pointer_width: 64, - data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - .into(), + data_layout: + "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), arch: arch.target_arch(), options: TargetOptions { mcount: "\u{1}mcount".into(), ..base }, } diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index 251f0628a713..ef4a0f52f9ea 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -1,13 +1,14 @@ -use crate::solve::FulfillmentCtxt; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; -use crate::traits::{self, DefiningAnchor, ObligationCtxt}; +use crate::traits::{self, DefiningAnchor, ObligationCtxt, SelectionContext}; +use crate::traits::TraitEngineExt as _; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; -use rustc_infer::traits::{TraitEngine, TraitEngineExt}; +use rustc_infer::traits::{Obligation, TraitEngine, TraitEngineExt as _}; use rustc_middle::arena::ArenaAllocatable; use rustc_middle::infer::canonical::{Canonical, CanonicalQueryResponse, QueryResponse}; use rustc_middle::traits::query::NoSolution; +use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_middle::ty::{GenericArg, ToPredicate}; use rustc_span::DUMMY_SP; @@ -21,7 +22,8 @@ pub trait InferCtxtExt<'tcx> { fn type_is_sized_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool; - /// Check whether a `ty` implements given trait(trait_def_id). + /// Check whether a `ty` implements given trait(trait_def_id) without side-effects. + /// /// The inputs are: /// /// - the def-id of the trait @@ -29,8 +31,8 @@ pub trait InferCtxtExt<'tcx> { /// - the parameter environment /// /// Invokes `evaluate_obligation`, so in the event that evaluating - /// `Ty: Trait` causes overflow, EvaluatedToErrStackDependent (or EvaluatedToAmbigStackDependent) - /// will be returned. + /// `Ty: Trait` causes overflow, EvaluatedToErrStackDependent + /// (or EvaluatedToAmbigStackDependent) will be returned. fn type_implements_trait( &self, trait_def_id: DefId, @@ -38,7 +40,18 @@ pub trait InferCtxtExt<'tcx> { param_env: ty::ParamEnv<'tcx>, ) -> traits::EvaluationResult; - fn could_impl_trait( + /// Returns `Some` if a type implements a trait shallowly, without side-effects, + /// along with any errors that would have been reported upon further obligation + /// processing. + /// + /// - If this returns `Some([])`, then the trait holds modulo regions. + /// - If this returns `Some([errors..])`, then the trait has an impl for + /// the self type, but some nested obligations do not hold. + /// - If this returns `None`, no implementation that applies could be found. + /// + /// FIXME(-Znext-solver): Due to the recursive nature of the new solver, + /// this will probably only ever return `Some([])` or `None`. + fn type_implements_trait_shallow( &self, trait_def_id: DefId, ty: Ty<'tcx>, @@ -86,64 +99,26 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { self.evaluate_obligation(&obligation).unwrap_or(traits::EvaluationResult::EvaluatedToErr) } - fn could_impl_trait( + fn type_implements_trait_shallow( &self, trait_def_id: DefId, ty: Ty<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> Option>> { self.probe(|_snapshot| { - if let ty::Adt(def, args) = ty.kind() - && let Some((impl_def_id, _)) = self - .tcx - .all_impls(trait_def_id) - .filter_map(|impl_def_id| { - self.tcx.impl_trait_ref(impl_def_id).map(|r| (impl_def_id, r)) - }) - .map(|(impl_def_id, imp)| (impl_def_id, imp.skip_binder())) - .find(|(_, imp)| match imp.self_ty().peel_refs().kind() { - ty::Adt(i_def, _) if i_def.did() == def.did() => true, - _ => false, - }) - { - let mut fulfill_cx = FulfillmentCtxt::new(self); - // We get all obligations from the impl to talk about specific - // trait bounds. - let obligations = self - .tcx - .predicates_of(impl_def_id) - .instantiate(self.tcx, args) - .into_iter() - .map(|(clause, span)| { - traits::Obligation::new( - self.tcx, - traits::ObligationCause::dummy_with_span(span), - param_env, - clause, - ) - }) - .collect::>(); - fulfill_cx.register_predicate_obligations(self, obligations); - let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, [ty]); - let obligation = traits::Obligation::new( - self.tcx, - traits::ObligationCause::dummy(), - param_env, - trait_ref, - ); - fulfill_cx.register_predicate_obligation(self, obligation); - let mut errors = fulfill_cx.select_all_or_error(self); - // We remove the last predicate failure, which corresponds to - // the top-level obligation, because most of the type we only - // care about the other ones, *except* when it is the only one. - // This seems to only be relevant for arbitrary self-types. - // Look at `tests/ui/moves/move-fn-self-receiver.rs`. - if errors.len() > 1 { - errors.truncate(errors.len() - 1); + let mut selcx = SelectionContext::new(self); + match selcx.select(&Obligation::new( + self.tcx, + ObligationCause::dummy(), + param_env, + ty::TraitRef::new(self.tcx, trait_def_id, [ty]), + )) { + Ok(Some(selection)) => { + let mut fulfill_cx = >::new(self); + fulfill_cx.register_predicate_obligations(self, selection.nested_obligations()); + Some(fulfill_cx.select_all_or_error(self)) } - Some(errors) - } else { - None + Ok(None) | Err(_) => None, } }) } diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 2139210b8736..f08622816ec2 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -11,7 +11,7 @@ use rustc_middle::ty; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use super::eval_ctxt::GenerateProofTree; -use super::{Certainty, InferCtxtEvalExt}; +use super::{Certainty, Goal, InferCtxtEvalExt}; /// A trait engine using the new trait solver. /// @@ -36,8 +36,28 @@ pub struct FulfillmentCtxt<'tcx> { impl<'tcx> FulfillmentCtxt<'tcx> { pub fn new(infcx: &InferCtxt<'tcx>) -> FulfillmentCtxt<'tcx> { + assert!( + infcx.next_trait_solver(), + "new trait solver fulfillment context created when \ + infcx is set up for old trait solver" + ); FulfillmentCtxt { obligations: Vec::new(), usable_in_snapshot: infcx.num_open_snapshots() } } + + fn inspect_evaluated_obligation( + &self, + infcx: &InferCtxt<'tcx>, + obligation: &PredicateObligation<'tcx>, + result: &Result<(bool, Certainty, Vec>>), NoSolution>, + ) { + if let Some(inspector) = infcx.obligation_inspector.get() { + let result = match result { + Ok((_, c, _)) => Ok(*c), + Err(NoSolution) => Err(NoSolution), + }; + (inspector)(infcx, &obligation, result); + } + } } impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { @@ -61,10 +81,10 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { .0 { Ok((_, Certainty::Maybe(MaybeCause::Ambiguity), _)) => { - FulfillmentErrorCode::CodeAmbiguity { overflow: false } + FulfillmentErrorCode::Ambiguity { overflow: false } } Ok((_, Certainty::Maybe(MaybeCause::Overflow), _)) => { - FulfillmentErrorCode::CodeAmbiguity { overflow: true } + FulfillmentErrorCode::Ambiguity { overflow: true } } Ok((_, Certainty::Yes, _)) => { bug!("did not expect successful goal when collecting ambiguity errors") @@ -95,65 +115,66 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { let mut has_changed = false; for obligation in mem::take(&mut self.obligations) { let goal = obligation.clone().into(); - let (changed, certainty, nested_goals) = - match infcx.evaluate_root_goal(goal, GenerateProofTree::IfEnabled).0 { - Ok(result) => result, - Err(NoSolution) => { - errors.push(FulfillmentError { - obligation: obligation.clone(), - code: match goal.predicate.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) => { - FulfillmentErrorCode::CodeProjectionError( - // FIXME: This could be a `Sorts` if the term is a type - MismatchedProjectionTypes { err: TypeError::Mismatch }, - ) - } - ty::PredicateKind::NormalizesTo(..) => { - FulfillmentErrorCode::CodeProjectionError( - MismatchedProjectionTypes { err: TypeError::Mismatch }, - ) - } - ty::PredicateKind::AliasRelate(_, _, _) => { - FulfillmentErrorCode::CodeProjectionError( - MismatchedProjectionTypes { err: TypeError::Mismatch }, - ) - } - ty::PredicateKind::Subtype(pred) => { - let (a, b) = infcx.instantiate_binder_with_placeholders( - goal.predicate.kind().rebind((pred.a, pred.b)), - ); - let expected_found = ExpectedFound::new(true, a, b); - FulfillmentErrorCode::CodeSubtypeError( - expected_found, - TypeError::Sorts(expected_found), - ) - } - ty::PredicateKind::Coerce(pred) => { - let (a, b) = infcx.instantiate_binder_with_placeholders( - goal.predicate.kind().rebind((pred.a, pred.b)), - ); - let expected_found = ExpectedFound::new(false, a, b); - FulfillmentErrorCode::CodeSubtypeError( - expected_found, - TypeError::Sorts(expected_found), - ) - } - ty::PredicateKind::Clause(_) - | ty::PredicateKind::ObjectSafe(_) - | ty::PredicateKind::Ambiguous => { - FulfillmentErrorCode::CodeSelectionError( - SelectionError::Unimplemented, - ) - } - ty::PredicateKind::ConstEquate(..) => { - bug!("unexpected goal: {goal:?}") - } - }, - root_obligation: obligation, - }); - continue; - } - }; + let result = infcx.evaluate_root_goal(goal, GenerateProofTree::IfEnabled).0; + self.inspect_evaluated_obligation(infcx, &obligation, &result); + let (changed, certainty, nested_goals) = match result { + Ok(result) => result, + Err(NoSolution) => { + errors.push(FulfillmentError { + obligation: obligation.clone(), + code: match goal.predicate.kind().skip_binder() { + ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) => { + FulfillmentErrorCode::ProjectionError( + // FIXME: This could be a `Sorts` if the term is a type + MismatchedProjectionTypes { err: TypeError::Mismatch }, + ) + } + ty::PredicateKind::NormalizesTo(..) => { + FulfillmentErrorCode::ProjectionError( + MismatchedProjectionTypes { err: TypeError::Mismatch }, + ) + } + ty::PredicateKind::AliasRelate(_, _, _) => { + FulfillmentErrorCode::ProjectionError( + MismatchedProjectionTypes { err: TypeError::Mismatch }, + ) + } + ty::PredicateKind::Subtype(pred) => { + let (a, b) = infcx.instantiate_binder_with_placeholders( + goal.predicate.kind().rebind((pred.a, pred.b)), + ); + let expected_found = ExpectedFound::new(true, a, b); + FulfillmentErrorCode::SubtypeError( + expected_found, + TypeError::Sorts(expected_found), + ) + } + ty::PredicateKind::Coerce(pred) => { + let (a, b) = infcx.instantiate_binder_with_placeholders( + goal.predicate.kind().rebind((pred.a, pred.b)), + ); + let expected_found = ExpectedFound::new(false, a, b); + FulfillmentErrorCode::SubtypeError( + expected_found, + TypeError::Sorts(expected_found), + ) + } + ty::PredicateKind::Clause(_) + | ty::PredicateKind::ObjectSafe(_) + | ty::PredicateKind::Ambiguous => { + FulfillmentErrorCode::SelectionError( + SelectionError::Unimplemented, + ) + } + ty::PredicateKind::ConstEquate(..) => { + bug!("unexpected goal: {goal:?}") + } + }, + root_obligation: obligation, + }); + continue; + } + }; // Push any nested goals that we get from unifying our canonical response // with our obligation onto the fulfillment context. self.obligations.extend(nested_goals.into_iter().map(|goal| { diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 6c0909d28539..0e33e9cd790d 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -859,6 +859,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { && let hir::Node::Expr(lhs) = self.tcx.hir_node(*lhs_hir_id) && let hir::Node::Expr(rhs) = self.tcx.hir_node(*rhs_hir_id) && let Some(rhs_ty) = typeck_results.expr_ty_opt(rhs) + && let trait_pred = predicate.unwrap_or(trait_pred) + // Only run this code on binary operators + && hir::lang_items::BINARY_OPERATORS + .iter() + .filter_map(|&op| self.tcx.lang_items().get(op)) + .any(|op| { + op == trait_pred.skip_binder().trait_ref.def_id + }) { // Suggest dereferencing the LHS, RHS, or both terms of a binop if possible diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index b970ec7f726e..149dcffe333d 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -14,8 +14,8 @@ use crate::traits::specialize::to_pretty_impl_header; use crate::traits::NormalizeExt; use crate::traits::{ elaborate, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, Obligation, - ObligationCause, ObligationCauseCode, ObligationCtxt, OutputTypeParameterMismatch, Overflow, - PredicateObligation, SelectionError, TraitNotObjectSafe, + ObligationCause, ObligationCauseCode, ObligationCtxt, Overflow, PredicateObligation, + SelectionError, SignatureMismatch, TraitNotObjectSafe, }; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_errors::{ @@ -30,7 +30,7 @@ use rustc_hir::{GenericParam, Item, Node}; use rustc_infer::infer::error_reporting::TypeErrCtxt; use rustc_infer::infer::{InferOk, TypeTrace}; use rustc_middle::traits::select::OverflowError; -use rustc_middle::traits::{DefiningAnchor, SelectionOutputTypeParameterMismatch}; +use rustc_middle::traits::{DefiningAnchor, SignatureMismatchData}; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::{BottomUpFolder, TypeFolder, TypeSuperFoldable}; @@ -785,14 +785,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ty::PredicateKind::Subtype(predicate) => { // Errors for Subtype predicates show up as - // `FulfillmentErrorCode::CodeSubtypeError`, + // `FulfillmentErrorCode::SubtypeError`, // not selection error. span_bug!(span, "subtype requirement gave wrong error: `{:?}`", predicate) } ty::PredicateKind::Coerce(predicate) => { // Errors for Coerce predicates show up as - // `FulfillmentErrorCode::CodeSubtypeError`, + // `FulfillmentErrorCode::SubtypeError`, // not selection error. span_bug!(span, "coerce requirement gave wrong error: `{:?}`", predicate) } @@ -891,22 +891,22 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } - OutputTypeParameterMismatch(box SelectionOutputTypeParameterMismatch { + SignatureMismatch(box SignatureMismatchData { found_trait_ref, expected_trait_ref, terr: terr @ TypeError::CyclicTy(_), - }) => self.report_type_parameter_mismatch_cyclic_type_error( + }) => self.report_cyclic_signature_error( &obligation, found_trait_ref, expected_trait_ref, terr, ), - OutputTypeParameterMismatch(box SelectionOutputTypeParameterMismatch { + SignatureMismatch(box SignatureMismatchData { found_trait_ref, expected_trait_ref, terr: _, }) => { - match self.report_type_parameter_mismatch_error( + match self.report_signature_mismatch_error( &obligation, span, found_trait_ref, @@ -1492,7 +1492,7 @@ pub(super) trait InferCtxtPrivExt<'tcx> { kind: ty::ClosureKind, ) -> DiagnosticBuilder<'tcx>; - fn report_type_parameter_mismatch_cyclic_type_error( + fn report_cyclic_signature_error( &self, obligation: &PredicateObligation<'tcx>, found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, @@ -1506,7 +1506,7 @@ pub(super) trait InferCtxtPrivExt<'tcx> { def_id: DefId, ) -> DiagnosticBuilder<'tcx>; - fn report_type_parameter_mismatch_error( + fn report_signature_mismatch_error( &self, obligation: &PredicateObligation<'tcx>, span: Span, @@ -1572,23 +1572,23 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } match error.code { - FulfillmentErrorCode::CodeSelectionError(ref selection_error) => { + FulfillmentErrorCode::SelectionError(ref selection_error) => { self.report_selection_error( error.obligation.clone(), &error.root_obligation, selection_error, ); } - FulfillmentErrorCode::CodeProjectionError(ref e) => { + FulfillmentErrorCode::ProjectionError(ref e) => { self.report_projection_error(&error.obligation, e); } - FulfillmentErrorCode::CodeAmbiguity { overflow: false } => { + FulfillmentErrorCode::Ambiguity { overflow: false } => { self.maybe_report_ambiguity(&error.obligation); } - FulfillmentErrorCode::CodeAmbiguity { overflow: true } => { + FulfillmentErrorCode::Ambiguity { overflow: true } => { self.report_overflow_no_abort(error.obligation.clone()); } - FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => { + FulfillmentErrorCode::SubtypeError(ref expected_found, ref err) => { self.report_mismatched_types( &error.obligation.cause, expected_found.expected, @@ -1597,7 +1597,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ) .emit(); } - FulfillmentErrorCode::CodeConstEquateError(ref expected_found, ref err) => { + FulfillmentErrorCode::ConstEquateError(ref expected_found, ref err) => { let mut diag = self.report_mismatched_consts( &error.obligation.cause, expected_found.expected, @@ -1622,7 +1622,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } diag.emit(); } - FulfillmentErrorCode::CodeCycle(ref cycle) => { + FulfillmentErrorCode::Cycle(ref cycle) => { self.report_overflow_obligation_cycle(cycle); } } @@ -3366,7 +3366,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { self.dcx().create_err(err) } - fn report_type_parameter_mismatch_cyclic_type_error( + fn report_cyclic_signature_error( &self, obligation: &PredicateObligation<'tcx>, found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, @@ -3427,7 +3427,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { err } - fn report_type_parameter_mismatch_error( + fn report_signature_mismatch_error( &self, obligation: &PredicateObligation<'tcx>, span: Span, @@ -3446,10 +3446,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { }; let found_did = match *found_trait_ty.kind() { - ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) | ty::Coroutine(did, ..) => { - Some(did) - } - ty::Adt(def, _) => Some(def.did()), + ty::Closure(did, _) | ty::FnDef(did, _) | ty::Coroutine(did, ..) => Some(did), _ => None, }; diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 045d7e444b6e..0337672b3027 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -18,9 +18,6 @@ use super::const_evaluatable; use super::project::{self, ProjectAndUnifyResult}; use super::select::SelectionContext; use super::wf; -use super::CodeAmbiguity; -use super::CodeProjectionError; -use super::CodeSelectionError; use super::EvaluationResult; use super::PredicateObligation; use super::Unimplemented; @@ -80,6 +77,11 @@ static_assert_size!(PendingPredicateObligation<'_>, 72); impl<'tcx> FulfillmentContext<'tcx> { /// Creates a new fulfillment context. pub(super) fn new(infcx: &InferCtxt<'tcx>) -> FulfillmentContext<'tcx> { + assert!( + !infcx.next_trait_solver(), + "old trait solver fulfillment context created when \ + infcx is set up for new trait solver" + ); FulfillmentContext { predicates: ObligationForest::new(), usable_in_snapshot: infcx.num_open_snapshots(), @@ -135,7 +137,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { _infcx: &InferCtxt<'tcx>, ) -> Vec> { self.predicates - .to_errors(CodeAmbiguity { overflow: false }) + .to_errors(FulfillmentErrorCode::Ambiguity { overflow: false }) .into_iter() .map(to_fulfillment_error) .collect() @@ -409,7 +411,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { ty::PredicateKind::ObjectSafe(trait_def_id) => { if !self.selcx.tcx().check_is_object_safe(trait_def_id) { - ProcessResult::Error(CodeSelectionError(Unimplemented)) + ProcessResult::Error(FulfillmentErrorCode::SelectionError(Unimplemented)) } else { ProcessResult::Changed(vec![]) } @@ -480,7 +482,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { Ok(Err(err)) => { let expected_found = ExpectedFound::new(subtype.a_is_expected, subtype.a, subtype.b); - ProcessResult::Error(FulfillmentErrorCode::CodeSubtypeError( + ProcessResult::Error(FulfillmentErrorCode::SubtypeError( expected_found, err, )) @@ -503,7 +505,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { Ok(Ok(ok)) => ProcessResult::Changed(mk_pending(ok.obligations)), Ok(Err(err)) => { let expected_found = ExpectedFound::new(false, coerce.a, coerce.b); - ProcessResult::Error(FulfillmentErrorCode::CodeSubtypeError( + ProcessResult::Error(FulfillmentErrorCode::SubtypeError( expected_found, err, )) @@ -529,7 +531,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { Err( e @ NotConstEvaluatable::MentionsParam | e @ NotConstEvaluatable::Error(_), - ) => ProcessResult::Error(CodeSelectionError( + ) => ProcessResult::Error(FulfillmentErrorCode::SelectionError( SelectionError::NotConstEvaluatable(e), )), } @@ -618,20 +620,22 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { Ok(inf_ok) => { ProcessResult::Changed(mk_pending(inf_ok.into_obligations())) } - Err(err) => ProcessResult::Error( - FulfillmentErrorCode::CodeConstEquateError( + Err(err) => { + ProcessResult::Error(FulfillmentErrorCode::ConstEquateError( ExpectedFound::new(true, c1, c2), err, - ), - ), + )) + } } } (Err(ErrorHandled::Reported(reported, _)), _) - | (_, Err(ErrorHandled::Reported(reported, _))) => ProcessResult::Error( - CodeSelectionError(SelectionError::NotConstEvaluatable( - NotConstEvaluatable::Error(reported.into()), - )), - ), + | (_, Err(ErrorHandled::Reported(reported, _))) => { + ProcessResult::Error(FulfillmentErrorCode::SelectionError( + SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error( + reported.into(), + )), + )) + } (Err(ErrorHandled::TooGeneric(_)), _) | (_, Err(ErrorHandled::TooGeneric(_))) => { if c1.has_non_region_infer() || c2.has_non_region_infer() { @@ -639,7 +643,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { } else { // Two different constants using generic parameters ~> error. let expected_found = ExpectedFound::new(true, c1, c2); - ProcessResult::Error(FulfillmentErrorCode::CodeConstEquateError( + ProcessResult::Error(FulfillmentErrorCode::ConstEquateError( expected_found, TypeError::ConstMismatch(expected_found), )) @@ -654,7 +658,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { ty, ) { Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())), - Err(_) => ProcessResult::Error(FulfillmentErrorCode::CodeSelectionError( + Err(_) => ProcessResult::Error(FulfillmentErrorCode::SelectionError( SelectionError::Unimplemented, )), } @@ -677,7 +681,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { Ok(()) } else { let cycle: Vec<_> = cycle.map(|c| c.obligation.clone()).collect(); - Err(FulfillmentErrorCode::CodeCycle(cycle)) + Err(FulfillmentErrorCode::Cycle(cycle)) } } } @@ -732,7 +736,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { Err(selection_err) => { debug!("selecting trait at depth {} yielded Err", obligation.recursion_depth); - ProcessResult::Error(CodeSelectionError(selection_err)) + ProcessResult::Error(FulfillmentErrorCode::SelectionError(selection_err)) } } } @@ -784,7 +788,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { project_obligation.with(tcx, project_obligation.predicate), ])), ProjectAndUnifyResult::MismatchedProjectionTypes(e) => { - ProcessResult::Error(CodeProjectionError(e)) + ProcessResult::Error(FulfillmentErrorCode::ProjectionError(e)) } } } diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs index 073174127d6a..0cd376fcbbdc 100644 --- a/compiler/rustc_trait_selection/src/traits/misc.rs +++ b/compiler/rustc_trait_selection/src/traits/misc.rs @@ -194,7 +194,7 @@ pub fn all_fields_implement_trait<'tcx>( infcx.implied_bounds_tys( param_env, parent_cause.body_id, - FxIndexSet::from_iter([self_type]), + &FxIndexSet::from_iter([self_type]), ), ); let errors = infcx.resolve_regions(&outlives_env); diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs index 5b349d576b6a..52631d4353bf 100644 --- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs @@ -9,123 +9,153 @@ use rustc_span::def_id::LocalDefId; pub use rustc_middle::traits::query::OutlivesBound; +pub type BoundsCompat<'a, 'tcx: 'a> = impl Iterator> + 'a; pub type Bounds<'a, 'tcx: 'a> = impl Iterator> + 'a; pub trait InferCtxtExt<'a, 'tcx> { - fn implied_outlives_bounds( - &self, + /// Do *NOT* call this directly. + fn implied_bounds_tys_compat( + &'a self, param_env: ty::ParamEnv<'tcx>, body_id: LocalDefId, - ty: Ty<'tcx>, - ) -> Vec>; + tys: &'a FxIndexSet>, + compat: bool, + ) -> BoundsCompat<'a, 'tcx>; + /// If `-Z no-implied-bounds-compat` is set, calls `implied_bounds_tys_compat` + /// with `compat` set to `true`, otherwise `false`. fn implied_bounds_tys( &'a self, param_env: ty::ParamEnv<'tcx>, body_id: LocalDefId, - tys: FxIndexSet>, + tys: &'a FxIndexSet>, ) -> Bounds<'a, 'tcx>; } -impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> { - /// Implied bounds are region relationships that we deduce - /// automatically. The idea is that (e.g.) a caller must check that a - /// function's argument types are well-formed immediately before - /// calling that fn, and hence the *callee* can assume that its - /// argument types are well-formed. This may imply certain relationships - /// between generic parameters. For example: - /// ``` - /// fn foo(x: &T) {} - /// ``` - /// can only be called with a `'a` and `T` such that `&'a T` is WF. - /// For `&'a T` to be WF, `T: 'a` must hold. So we can assume `T: 'a`. - /// - /// # Parameters - /// - /// - `param_env`, the where-clauses in scope - /// - `body_id`, the body-id to use when normalizing assoc types. - /// Note that this may cause outlives obligations to be injected - /// into the inference context with this body-id. - /// - `ty`, the type that we are supposed to assume is WF. - #[instrument(level = "debug", skip(self, param_env, body_id), ret)] - fn implied_outlives_bounds( - &self, - param_env: ty::ParamEnv<'tcx>, - body_id: LocalDefId, - ty: Ty<'tcx>, - ) -> Vec> { - let ty = self.resolve_vars_if_possible(ty); - let ty = OpportunisticRegionResolver::new(self).fold_ty(ty); +/// Implied bounds are region relationships that we deduce +/// automatically. The idea is that (e.g.) a caller must check that a +/// function's argument types are well-formed immediately before +/// calling that fn, and hence the *callee* can assume that its +/// argument types are well-formed. This may imply certain relationships +/// between generic parameters. For example: +/// ``` +/// fn foo(x: &T) {} +/// ``` +/// can only be called with a `'a` and `T` such that `&'a T` is WF. +/// For `&'a T` to be WF, `T: 'a` must hold. So we can assume `T: 'a`. +/// +/// # Parameters +/// +/// - `param_env`, the where-clauses in scope +/// - `body_id`, the body-id to use when normalizing assoc types. +/// Note that this may cause outlives obligations to be injected +/// into the inference context with this body-id. +/// - `ty`, the type that we are supposed to assume is WF. +#[instrument(level = "debug", skip(infcx, param_env, body_id), ret)] +fn implied_outlives_bounds<'a, 'tcx>( + infcx: &'a InferCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + body_id: LocalDefId, + ty: Ty<'tcx>, + compat: bool, +) -> Vec> { + let ty = infcx.resolve_vars_if_possible(ty); + let ty = OpportunisticRegionResolver::new(infcx).fold_ty(ty); - // We do not expect existential variables in implied bounds. - // We may however encounter unconstrained lifetime variables - // in very rare cases. - // - // See `ui/implied-bounds/implied-bounds-unconstrained-2.rs` for - // an example. - assert!(!ty.has_non_region_infer()); + // We do not expect existential variables in implied bounds. + // We may however encounter unconstrained lifetime variables + // in very rare cases. + // + // See `ui/implied-bounds/implied-bounds-unconstrained-2.rs` for + // an example. + assert!(!ty.has_non_region_infer()); - let mut canonical_var_values = OriginalQueryValues::default(); - let canonical_ty = self.canonicalize_query(param_env.and(ty), &mut canonical_var_values); - let Ok(canonical_result) = self.tcx.implied_outlives_bounds(canonical_ty) else { - return vec![]; - }; + let mut canonical_var_values = OriginalQueryValues::default(); + let canonical_ty = infcx.canonicalize_query(param_env.and(ty), &mut canonical_var_values); + let implied_bounds_result = if compat { + infcx.tcx.implied_outlives_bounds_compat(canonical_ty) + } else { + infcx.tcx.implied_outlives_bounds(canonical_ty) + }; + let Ok(canonical_result) = implied_bounds_result else { + return vec![]; + }; - let mut constraints = QueryRegionConstraints::default(); - let Ok(InferOk { value: mut bounds, obligations }) = self - .instantiate_nll_query_response_and_region_obligations( - &ObligationCause::dummy(), + let mut constraints = QueryRegionConstraints::default(); + let Ok(InferOk { value: mut bounds, obligations }) = infcx + .instantiate_nll_query_response_and_region_obligations( + &ObligationCause::dummy(), + param_env, + &canonical_var_values, + canonical_result, + &mut constraints, + ) + else { + return vec![]; + }; + assert_eq!(&obligations, &[]); + + // Because of #109628, we may have unexpected placeholders. Ignore them! + // FIXME(#109628): panic in this case once the issue is fixed. + bounds.retain(|bound| !bound.has_placeholders()); + + if !constraints.is_empty() { + let span = infcx.tcx.def_span(body_id); + + debug!(?constraints); + if !constraints.member_constraints.is_empty() { + span_bug!(span, "{:#?}", constraints.member_constraints); + } + + // Instantiation may have produced new inference variables and constraints on those + // variables. Process these constraints. + let ocx = ObligationCtxt::new(infcx); + let cause = ObligationCause::misc(span, body_id); + for &constraint in &constraints.outlives { + ocx.register_obligation(infcx.query_outlives_constraint_to_obligation( + constraint, + cause.clone(), param_env, - &canonical_var_values, - canonical_result, - &mut constraints, - ) - else { - return vec![]; - }; - assert_eq!(&obligations, &[]); + )); + } - // Because of #109628, we may have unexpected placeholders. Ignore them! - // FIXME(#109628): panic in this case once the issue is fixed. - bounds.retain(|bound| !bound.has_placeholders()); + let errors = ocx.select_all_or_error(); + if !errors.is_empty() { + infcx.dcx().span_delayed_bug( + span, + "implied_outlives_bounds failed to solve obligations from instantiation", + ); + } + }; - if !constraints.is_empty() { - let span = self.tcx.def_span(body_id); + bounds +} - debug!(?constraints); - if !constraints.member_constraints.is_empty() { - span_bug!(span, "{:#?}", constraints.member_constraints); - } - - // Instantiation may have produced new inference variables and constraints on those - // variables. Process these constraints. - let ocx = ObligationCtxt::new(self); - let cause = ObligationCause::misc(span, body_id); - for &constraint in &constraints.outlives { - ocx.register_obligation(self.query_outlives_constraint_to_obligation( - constraint, - cause.clone(), - param_env, - )); - } - - let errors = ocx.select_all_or_error(); - if !errors.is_empty() { - self.dcx().span_delayed_bug( - span, - "implied_outlives_bounds failed to solve obligations from instantiation", - ); - } - }; - - bounds +impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> { + fn implied_bounds_tys_compat( + &'a self, + param_env: ParamEnv<'tcx>, + body_id: LocalDefId, + tys: &'a FxIndexSet>, + compat: bool, + ) -> BoundsCompat<'a, 'tcx> { + tys.iter() + .flat_map(move |ty| implied_outlives_bounds(self, param_env, body_id, *ty, compat)) } fn implied_bounds_tys( &'a self, param_env: ParamEnv<'tcx>, body_id: LocalDefId, - tys: FxIndexSet>, + tys: &'a FxIndexSet>, ) -> Bounds<'a, 'tcx> { - tys.into_iter().flat_map(move |ty| self.implied_outlives_bounds(param_env, body_id, ty)) + tys.iter().flat_map(move |ty| { + implied_outlives_bounds( + self, + param_env, + body_id, + *ty, + !self.tcx.sess.opts.unstable_opts.no_implied_bounds_compat, + ) + }) } } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index dd4e69efe379..abbc2066eac1 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -2466,7 +2466,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>( debug!(?cache_projection, ?obligation_projection); match infcx.at(cause, param_env).eq( - DefineOpaqueTypes::No, + DefineOpaqueTypes::Yes, cache_projection, obligation_projection, ) { diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs index 152ceeee8699..0aaeacb6a239 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs @@ -63,13 +63,16 @@ fn relate_mir_and_user_ty<'tcx>( user_ty: Ty<'tcx>, ) -> Result<(), NoSolution> { let cause = ObligationCause::dummy_with_span(span); + ocx.register_obligation(Obligation::new( + ocx.infcx.tcx, + cause.clone(), + param_env, + ty::ClauseKind::WellFormed(user_ty.into()), + )); + let user_ty = ocx.normalize(&cause, param_env, user_ty); ocx.eq(&cause, param_env, mir_ty, user_ty)?; - // FIXME(#104764): We should check well-formedness before normalization. - let predicate = - ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(user_ty.into()))); - ocx.register_obligation(Obligation::new(ocx.infcx.tcx, cause, param_env, predicate)); Ok(()) } @@ -113,31 +116,38 @@ fn relate_mir_and_user_args<'tcx>( ocx.register_obligation(Obligation::new(tcx, cause, param_env, instantiated_predicate)); } + // Now prove the well-formedness of `def_id` with `substs`. + // Note for some items, proving the WF of `ty` is not sufficient because the + // well-formedness of an item may depend on the WF of gneneric args not present in the + // item's type. Currently this is true for associated consts, e.g.: + // ```rust + // impl MyTy { + // const CONST: () = { /* arbitrary code that depends on T being WF */ }; + // } + // ``` + for arg in args { + ocx.register_obligation(Obligation::new( + tcx, + cause.clone(), + param_env, + ty::ClauseKind::WellFormed(arg), + )); + } + if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty { + ocx.register_obligation(Obligation::new( + tcx, + cause.clone(), + param_env, + ty::ClauseKind::WellFormed(self_ty.into()), + )); + let self_ty = ocx.normalize(&cause, param_env, self_ty); let impl_self_ty = tcx.type_of(impl_def_id).instantiate(tcx, args); let impl_self_ty = ocx.normalize(&cause, param_env, impl_self_ty); ocx.eq(&cause, param_env, self_ty, impl_self_ty)?; - let predicate = ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed( - impl_self_ty.into(), - ))); - ocx.register_obligation(Obligation::new(tcx, cause.clone(), param_env, predicate)); } - // In addition to proving the predicates, we have to - // prove that `ty` is well-formed -- this is because - // the WF of `ty` is predicated on the args being - // well-formed, and we haven't proven *that*. We don't - // want to prove the WF of types from `args` directly because they - // haven't been normalized. - // - // FIXME(nmatsakis): Well, perhaps we should normalize - // them? This would only be relevant if some input - // type were ill-formed but did not appear in `ty`, - // which...could happen with normalization... - let predicate = - ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(ty.into()))); - ocx.register_obligation(Obligation::new(tcx, cause, param_env, predicate)); Ok(()) } diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs index ba6ed2987740..83d23597c0cd 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs @@ -5,10 +5,11 @@ use crate::traits::ObligationCtxt; use rustc_infer::infer::canonical::Canonical; use rustc_infer::infer::outlives::components::{push_outlives_components, Component}; +use rustc_infer::infer::resolve::OpportunisticRegionResolver; use rustc_infer::traits::query::OutlivesBound; use rustc_middle::infer::canonical::CanonicalQueryResponse; use rustc_middle::traits::ObligationCause; -use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeFolder, TypeVisitableExt}; use rustc_span::def_id::CRATE_DEF_ID; use rustc_span::DUMMY_SP; use smallvec::{smallvec, SmallVec}; @@ -47,14 +48,22 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ImpliedOutlivesBounds<'tcx> { param_env.and(ty) }); - tcx.implied_outlives_bounds(canonicalized) + if tcx.sess.opts.unstable_opts.no_implied_bounds_compat { + tcx.implied_outlives_bounds(canonicalized) + } else { + tcx.implied_outlives_bounds_compat(canonicalized) + } } fn perform_locally_with_next_solver( ocx: &ObligationCtxt<'_, 'tcx>, key: ParamEnvAnd<'tcx, Self>, ) -> Result { - compute_implied_outlives_bounds_inner(ocx, key.param_env, key.value.ty) + if ocx.infcx.tcx.sess.opts.unstable_opts.no_implied_bounds_compat { + compute_implied_outlives_bounds_inner(ocx, key.param_env, key.value.ty) + } else { + compute_implied_outlives_bounds_compat_inner(ocx, key.param_env, key.value.ty) + } } } @@ -62,6 +71,85 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>( ocx: &ObligationCtxt<'_, 'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>, +) -> Result>, NoSolution> { + let normalize_op = |ty| { + let ty = ocx.normalize(&ObligationCause::dummy(), param_env, ty); + if !ocx.select_all_or_error().is_empty() { + return Err(NoSolution); + } + let ty = ocx.infcx.resolve_vars_if_possible(ty); + let ty = OpportunisticRegionResolver::new(&ocx.infcx).fold_ty(ty); + Ok(ty) + }; + + // Sometimes when we ask what it takes for T: WF, we get back that + // U: WF is required; in that case, we push U onto this stack and + // process it next. Because the resulting predicates aren't always + // guaranteed to be a subset of the original type, so we need to store the + // WF args we've computed in a set. + let mut checked_wf_args = rustc_data_structures::fx::FxHashSet::default(); + let mut wf_args = vec![ty.into(), normalize_op(ty)?.into()]; + + let mut outlives_bounds: Vec> = vec![]; + + while let Some(arg) = wf_args.pop() { + if !checked_wf_args.insert(arg) { + continue; + } + + // From the full set of obligations, just filter down to the region relationships. + for obligation in + wf::unnormalized_obligations(ocx.infcx, param_env, arg).into_iter().flatten() + { + assert!(!obligation.has_escaping_bound_vars()); + let Some(pred) = obligation.predicate.kind().no_bound_vars() else { + continue; + }; + match pred { + // FIXME(const_generics): Make sure that `<'a, 'b, const N: &'a &'b u32>` is sound + // if we ever support that + ty::PredicateKind::Clause(ty::ClauseKind::Trait(..)) + | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) + | ty::PredicateKind::Subtype(..) + | ty::PredicateKind::Coerce(..) + | ty::PredicateKind::Clause(ty::ClauseKind::Projection(..)) + | ty::PredicateKind::ObjectSafe(..) + | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) + | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::Ambiguous + | ty::PredicateKind::NormalizesTo(..) + | ty::PredicateKind::AliasRelate(..) => {} + + // We need to search through *all* WellFormed predicates + ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => { + wf_args.push(arg); + } + + // We need to register region relationships + ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives( + ty::OutlivesPredicate(r_a, r_b), + )) => outlives_bounds.push(OutlivesBound::RegionSubRegion(r_b, r_a)), + + ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate( + ty_a, + r_b, + ))) => { + let ty_a = normalize_op(ty_a)?; + let mut components = smallvec![]; + push_outlives_components(ocx.infcx.tcx, ty_a, &mut components); + outlives_bounds.extend(implied_bounds_from_components(r_b, components)) + } + } + } + } + + Ok(outlives_bounds) +} + +pub fn compute_implied_outlives_bounds_compat_inner<'tcx>( + ocx: &ObligationCtxt<'_, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + ty: Ty<'tcx>, ) -> Result>, NoSolution> { let tcx = ocx.infcx.tcx; diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs index e21ede47f6d6..14f14ae6e2e0 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs @@ -30,6 +30,23 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> { } } + if let ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) = + key.value.predicate.kind().skip_binder() + { + match arg.as_type()?.kind() { + ty::Param(_) + | ty::Bool + | ty::Char + | ty::Int(_) + | ty::Float(_) + | ty::Str + | ty::Uint(_) => { + return Some(()); + } + _ => {} + } + } + None } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index e20bb06d7770..74f388e53a3c 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -11,7 +11,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::lang_items::LangItem; use rustc_infer::infer::BoundRegionConversionTime::HigherRankedType; use rustc_infer::infer::{DefineOpaqueTypes, InferOk}; -use rustc_middle::traits::{BuiltinImplSource, SelectionOutputTypeParameterMismatch}; +use rustc_middle::traits::{BuiltinImplSource, SignatureMismatchData}; use rustc_middle::ty::{ self, GenericArgs, GenericArgsRef, GenericParamDefKind, ToPolyTraitRef, ToPredicate, TraitPredicate, Ty, TyCtxt, TypeVisitableExt, @@ -26,9 +26,9 @@ use crate::traits::vtable::{ }; use crate::traits::{ BuiltinDerivedObligation, ImplDerivedObligation, ImplDerivedObligationCause, ImplSource, - ImplSourceUserDefinedData, Normalized, Obligation, ObligationCause, - OutputTypeParameterMismatch, PolyTraitObligation, PredicateObligation, Selection, - SelectionError, TraitNotObjectSafe, Unimplemented, + ImplSourceUserDefinedData, Normalized, Obligation, ObligationCause, PolyTraitObligation, + PredicateObligation, Selection, SelectionError, SignatureMismatch, TraitNotObjectSafe, + Unimplemented, }; use super::BuiltinImplConditions; @@ -922,7 +922,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligations }) .map_err(|terr| { - OutputTypeParameterMismatch(Box::new(SelectionOutputTypeParameterMismatch { + SignatureMismatch(Box::new(SignatureMismatchData { expected_trait_ref: obligation_trait_ref, found_trait_ref: expected_trait_ref, terr, diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 200d022c80c6..b37d9714ddd8 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -26,7 +26,7 @@ use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{GenericArgs, GenericArgsRef}; use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK; use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS; -use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP}; +use rustc_span::{sym, ErrorGuaranteed, Span, DUMMY_SP}; use super::util; use super::SelectionContext; @@ -142,10 +142,30 @@ pub fn translate_args_with_cause<'tcx>( pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, DefId)) -> bool { // The feature gate should prevent introducing new specializations, but not // taking advantage of upstream ones. + // If specialization is enabled for this crate then no extra checks are needed. + // If it's not, and either of the `impl`s is local to this crate, then this definitely + // isn't specializing - unless specialization is enabled for the `impl` span, + // e.g. if it comes from an `allow_internal_unstable` macro let features = tcx.features(); let specialization_enabled = features.specialization || features.min_specialization; - if !specialization_enabled && (impl1_def_id.is_local() || impl2_def_id.is_local()) { - return false; + if !specialization_enabled { + if impl1_def_id.is_local() { + let span = tcx.def_span(impl1_def_id); + if !span.allows_unstable(sym::specialization) + && !span.allows_unstable(sym::min_specialization) + { + return false; + } + } + + if impl2_def_id.is_local() { + let span = tcx.def_span(impl2_def_id); + if !span.allows_unstable(sym::specialization) + && !span.allows_unstable(sym::min_specialization) + { + return false; + } + } } // We determine whether there's a subset relationship by: diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs index 2cd1c3b502ae..f3fae63ecc7b 100644 --- a/compiler/rustc_traits/src/codegen.rs +++ b/compiler/rustc_traits/src/codegen.rs @@ -63,7 +63,7 @@ pub fn codegen_select_candidate<'tcx>( // Cycle errors are the only post-monomorphization errors possible; emit them now so // `rustc_ty_utils::resolve_associated_item` doesn't return `None` post-monomorphization. for err in errors { - if let FulfillmentErrorCode::CodeCycle(cycle) = err.code { + if let FulfillmentErrorCode::Cycle(cycle) = err.code { infcx.err_ctxt().report_overflow_obligation_cycle(&cycle); } } diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs index 959838ab348f..24e91c263e34 100644 --- a/compiler/rustc_traits/src/implied_outlives_bounds.rs +++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs @@ -8,13 +8,29 @@ use rustc_infer::traits::query::OutlivesBound; use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_trait_selection::infer::InferCtxtBuilderExt; -use rustc_trait_selection::traits::query::type_op::implied_outlives_bounds::compute_implied_outlives_bounds_inner; +use rustc_trait_selection::traits::query::type_op::implied_outlives_bounds::{ + compute_implied_outlives_bounds_compat_inner, compute_implied_outlives_bounds_inner, +}; use rustc_trait_selection::traits::query::{CanonicalTyGoal, NoSolution}; pub(crate) fn provide(p: &mut Providers) { + *p = Providers { implied_outlives_bounds_compat, ..*p }; *p = Providers { implied_outlives_bounds, ..*p }; } +fn implied_outlives_bounds_compat<'tcx>( + tcx: TyCtxt<'tcx>, + goal: CanonicalTyGoal<'tcx>, +) -> Result< + &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec>>>, + NoSolution, +> { + tcx.infer_ctxt().enter_canonical_trait_query(&goal, |ocx, key| { + let (param_env, ty) = key.into_parts(); + compute_implied_outlives_bounds_compat_inner(ocx, param_env, ty) + }) +} + fn implied_outlives_bounds<'tcx>( tcx: TyCtxt<'tcx>, goal: CanonicalTyGoal<'tcx>, diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs index b8c71bc96f88..21a016e29d69 100644 --- a/compiler/rustc_traits/src/normalize_projection_ty.rs +++ b/compiler/rustc_traits/src/normalize_projection_ty.rs @@ -54,7 +54,7 @@ fn normalize_projection_ty<'tcx>( // that impl vars are constrained by the signature, for example). if !tcx.sess.opts.actually_rustdoc { for error in &errors { - if let FulfillmentErrorCode::CodeCycle(cycle) = &error.code { + if let FulfillmentErrorCode::Cycle(cycle) = &error.code { ocx.infcx.err_ctxt().report_overflow_obligation_cycle(cycle); } } diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 6e8293dac312..333aec1d38d7 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -83,7 +83,11 @@ fn fn_sig_for_fn_abi<'tcx>( kind: ty::BoundRegionKind::BrEnv, }; let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br); - let env_ty = tcx.closure_env_ty(def_id, args, env_region).unwrap(); + let env_ty = tcx.closure_env_ty( + Ty::new_closure(tcx, def_id, args), + args.as_closure().kind(), + env_region, + ); let sig = sig.skip_binder(); ty::Binder::bind_with_vars( diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index b8351463c55c..2fc4bfd4aa31 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -1052,6 +1052,8 @@ fn variant_info_for_coroutine<'tcx>( def_id: DefId, args: ty::GenericArgsRef<'tcx>, ) -> (Vec, Option) { + use itertools::Itertools; + let Variants::Multiple { tag, ref tag_encoding, tag_field, .. } = layout.variants else { return (vec![], None); }; @@ -1064,7 +1066,7 @@ fn variant_info_for_coroutine<'tcx>( .as_coroutine() .upvar_tys() .iter() - .zip(upvar_names) + .zip_eq(upvar_names) .enumerate() .map(|(field_idx, (_, name))| { let field_layout = layout.field(cx, field_idx); diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index bff938596458..83efbfb855f9 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -327,21 +327,21 @@ impl UniverseIndex { /// name the region `'a`, but that region was not nameable from /// `U` because it was not in scope there. pub fn next_universe(self) -> UniverseIndex { - UniverseIndex::from_u32(self.private.checked_add(1).unwrap()) + UniverseIndex::from_u32(self.as_u32().checked_add(1).unwrap()) } /// Returns `true` if `self` can name a name from `other` -- in other words, /// if the set of names in `self` is a superset of those in /// `other` (`self >= other`). pub fn can_name(self, other: UniverseIndex) -> bool { - self.private >= other.private + self >= other } /// Returns `true` if `self` cannot name some names from `other` -- in other /// words, if the set of names in `self` is a strict subset of /// those in `other` (`self < other`). pub fn cannot_name(self, other: UniverseIndex) -> bool { - self.private < other.private + self < other } } diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index eba2ac57012b..b0a08cd9b792 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -12,7 +12,7 @@ use std::fmt::{self, Debug, Display, Formatter}; use std::ops::Range; #[derive(Copy, Clone, Eq, PartialEq, Hash)] -pub struct Ty(pub usize); +pub struct Ty(usize); impl Debug for Ty { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { @@ -138,7 +138,7 @@ impl Const { } #[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub struct ConstId(pub usize); +pub struct ConstId(usize); type Ident = Opaque; diff --git a/library/alloc/src/boxed/thin.rs b/library/alloc/src/boxed/thin.rs index 9463b73b574f..f83c8f83cc98 100644 --- a/library/alloc/src/boxed/thin.rs +++ b/library/alloc/src/boxed/thin.rs @@ -171,7 +171,6 @@ struct WithHeader(NonNull, PhantomData); /// An opaque representation of `WithHeader` to avoid the /// projection invariance of `::Metadata`. #[repr(transparent)] -#[allow(dead_code)] // Field only used through `WithHeader` type above. struct WithOpaqueHeader(NonNull); impl WithOpaqueHeader { diff --git a/library/alloc/src/vec/in_place_collect.rs b/library/alloc/src/vec/in_place_collect.rs index 0a2280545dac..5a783e667521 100644 --- a/library/alloc/src/vec/in_place_collect.rs +++ b/library/alloc/src/vec/in_place_collect.rs @@ -9,7 +9,7 @@ //! or [`BinaryHeap`], the adapters guarantee to consume enough items per step to make room //! for the results (represented by [`InPlaceIterable`]), provide transitive access to `source` //! (via [`SourceIter`]) and thus the underlying allocation. -//! And finally there are alignment and size constriants to consider, this is currently ensured via +//! And finally there are alignment and size constraints to consider, this is currently ensured via //! const eval instead of trait bounds in the specialized [`SpecFromIter`] implementation. //! //! [`BinaryHeap`]: crate::collections::BinaryHeap @@ -168,7 +168,9 @@ const fn in_place_collectible( step_merge: Option, step_expand: Option, ) -> bool { - if const { SRC::IS_ZST || DEST::IS_ZST || mem::align_of::() < mem::align_of::() } { + // Require matching alignments because an alignment-changing realloc is inefficient on many + // system allocators and better implementations would require the unstable Allocator trait. + if const { SRC::IS_ZST || DEST::IS_ZST || mem::align_of::() != mem::align_of::() } { return false; } @@ -188,7 +190,8 @@ const fn in_place_collectible( const fn needs_realloc(src_cap: usize, dst_cap: usize) -> bool { if const { mem::align_of::() != mem::align_of::() } { - return src_cap > 0; + // FIXME: use unreachable! once that works in const + panic!("in_place_collectible() prevents this"); } // If src type size is an integer multiple of the destination type size then @@ -276,8 +279,8 @@ where let dst_guard = InPlaceDstBufDrop { ptr: dst_buf, len, cap: dst_cap }; src.forget_allocation_drop_remaining(); - // Adjust the allocation if the alignment didn't match or the source had a capacity in bytes - // that wasn't a multiple of the destination type size. + // Adjust the allocation if the source had a capacity in bytes that wasn't a multiple + // of the destination type size. // Since the discrepancy should generally be small this should only result in some // bookkeeping updates and no memmove. if needs_realloc::(src_cap, dst_cap) { @@ -290,7 +293,7 @@ where let src_size = mem::size_of::().unchecked_mul(src_cap); let old_layout = Layout::from_size_align_unchecked(src_size, src_align); - // The must be equal or smaller for in-place iteration to be possible + // The allocation must be equal or smaller for in-place iteration to be possible // therefore the new layout must be ≤ the old one and therefore valid. let dst_align = mem::align_of::(); let dst_size = mem::size_of::().unchecked_mul(dst_cap); diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 8aa0c6e7ed62..35ea97bfe609 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -358,7 +358,7 @@ mod spec_extend; /// /// `vec![x; n]`, `vec![a, b, c, d]`, and /// [`Vec::with_capacity(n)`][`Vec::with_capacity`], will all produce a `Vec` -/// with exactly the requested capacity. If [len] == [capacity], +/// with at least the requested capacity. If [len] == [capacity], /// (as is the case for the [`vec!`] macro), then a `Vec` can be converted to /// and from a [`Box<[T]>`][owned slice] without reallocating or moving the elements. /// @@ -1023,8 +1023,11 @@ impl Vec { /// Shrinks the capacity of the vector as much as possible. /// - /// It will drop down as close as possible to the length but the allocator - /// may still inform the vector that there is space for a few more elements. + /// The behavior of this method depends on the allocator, which may either shrink the vector + /// in-place or reallocate. The resulting vector might still have some excess capacity, just as + /// is the case for [`with_capacity`]. See [`Allocator::shrink`] for more details. + /// + /// [`with_capacity`]: Vec::with_capacity /// /// # Examples /// @@ -1074,10 +1077,10 @@ impl Vec { /// Converts the vector into [`Box<[T]>`][owned slice]. /// - /// If the vector has excess capacity, its items will be moved into a - /// newly-allocated buffer with exactly the right capacity. + /// Before doing the conversion, this method discards excess capacity like [`shrink_to_fit`]. /// /// [owned slice]: Box + /// [`shrink_to_fit`]: Vec::shrink_to_fit /// /// # Examples /// @@ -3290,8 +3293,10 @@ impl From> for Vec { impl From> for Box<[T], A> { /// Convert a vector into a boxed slice. /// - /// If `v` has excess capacity, its items will be moved into a - /// newly-allocated buffer with exactly the right capacity. + /// Before doing the conversion, this method discards excess capacity like [`Vec::shrink_to_fit`]. + /// + /// [owned slice]: Box + /// [`Vec::shrink_to_fit`]: Vec::shrink_to_fit /// /// # Examples /// diff --git a/library/alloc/src/vec/spec_from_iter.rs b/library/alloc/src/vec/spec_from_iter.rs index e976552cf2b9..33dd4139bc08 100644 --- a/library/alloc/src/vec/spec_from_iter.rs +++ b/library/alloc/src/vec/spec_from_iter.rs @@ -13,13 +13,13 @@ use super::{IntoIter, SpecExtend, SpecFromIterNested, Vec}; /// +-+-----------+ /// | /// v -/// +-+-------------------------------+ +---------------------+ -/// |SpecFromIter +---->+SpecFromIterNested | -/// |where I: | | |where I: | -/// | Iterator (default)----------+ | | Iterator (default) | -/// | vec::IntoIter | | | TrustedLen | -/// | SourceIterMarker---fallback-+ | +---------------------+ -/// +---------------------------------+ +/// +-+---------------------------------+ +---------------------+ +/// |SpecFromIter +---->+SpecFromIterNested | +/// |where I: | | |where I: | +/// | Iterator (default)------------+ | | Iterator (default) | +/// | vec::IntoIter | | | TrustedLen | +/// | InPlaceCollect--(fallback to)-+ | +---------------------+ +/// +-----------------------------------+ /// ``` pub(super) trait SpecFromIter { fn from_iter(iter: I) -> Self; diff --git a/library/core/benches/ascii.rs b/library/core/benches/ascii.rs index 64938745a4a1..71ec9fed2fe7 100644 --- a/library/core/benches/ascii.rs +++ b/library/core/benches/ascii.rs @@ -63,6 +63,7 @@ macro_rules! benches { } } +use std::fmt::Write; use test::black_box; use test::Bencher; @@ -351,3 +352,30 @@ static ASCII_CHARACTER_CLASS: [AsciiCharacterClass; 256] = [ N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, ]; + +const ASCII_PATH: &[u8] = b"home/kyubey/rust/build/x86_64-unknown-linux-gnu/stage0/lib:/home/kyubey/workspace/rust/build/x86_64-unknown-linux-gnu/stage0-tools/release/deps"; +const RUST_INCANTATION: &[u8] = br#"AR_x86_64_unknown_linux_gnu="ar" CARGO_INCREMENTAL="0" CARGO_PROFILE_RELEASE_DEBUG="1" CARGO_PROFILE_RELEASE_DEBUG_ASSERTIONS="false" CARGO_PROFILE_RELEASE_OVERFLOW_CHECKS="false" CARGO_TARGET_DIR="/home/kyubey/workspace/rust/build/x86_64-unknown-linux-gnu/stage0-std" CC_x86_64_unknown_linux_gnu="cc" CFG_COMPILER_HOST_TRIPLE="x86_64-unknown-linux-gnu" CFG_RELEASE_CHANNEL="dev" CFLAGS_x86_64_unknown_linux_gnu="-ffunction-sections -fdata-sections -fPIC -m64" CXXFLAGS_x86_64_unknown_linux_gnu="-ffunction-sections -fdata-sections -fPIC -m64" CXX_x86_64_unknown_linux_gnu="c++" LD_LIBRARY_PATH="/home/kyubey/workspace/rust/build/x86_64-unknown-linux-gnu/stage0-sysroot/lib/rustlib/x86_64-unknown-linux-gnu/lib" LIBC_CHECK_CFG="1" RANLIB_x86_64_unknown_linux_gnu="ar s" REAL_LIBRARY_PATH_VAR="LD_LIBRARY_PATH" RUSTBUILD_NATIVE_DIR="/home/kyubey/workspace/rust/build/x86_64-unknown-linux-gnu/native" RUSTC="/home/kyubey/workspace/rust/build/bootstrap/debug/rustc" RUSTC_BOOTSTRAP="1" RUSTC_BREAK_ON_ICE="1" RUSTC_ERROR_METADATA_DST="/home/kyubey/workspace/rust/build/tmp/extended-error-metadata" RUSTC_FORCE_UNSTABLE="1" RUSTC_HOST_FUSE_LD_LLD="1" RUSTC_INSTALL_BINDIR="bin" RUSTC_LIBDIR="/home/kyubey/workspace/rust/build/x86_64-unknown-linux-gnu/stage0/lib" RUSTC_LINT_FLAGS="-Wrust_2018_idioms -Wunused_lifetimes -Wsemicolon_in_expressions_from_macros" RUSTC_REAL="/home/kyubey/workspace/rust/build/x86_64-unknown-linux-gnu/stage0/bin/rustc" RUSTC_SNAPSHOT="/home/kyubey/workspace/rust/build/x86_64-unknown-linux-gnu/stage0/bin/rustc" RUSTC_SNAPSHOT_LIBDIR="/home/kyubey/workspace/rust/build/x86_64-unknown-linux-gnu/stage0/lib" RUSTC_STAGE="0" RUSTC_SYSROOT="/home/kyubey/workspace/rust/build/x86_64-unknown-linux-gnu/stage0-sysroot" RUSTC_VERBOSE="0" RUSTDOC="/home/kyubey/workspace/rust/build/bootstrap/debug/rustdoc" RUSTDOCFLAGS="-C target-cpu=native --cfg=bootstrap -Csymbol-mangling-version=legacy -Zunstable-options -Zunstable-options --check-cfg=values(bootstrap) --check-cfg=values(stdarch_intel_sde) --check-cfg=values(no_fp_fmt_parse) --check-cfg=values(no_global_oom_handling) --check-cfg=values(no_rc) --check-cfg=values(no_sync) --check-cfg=values(freebsd12) --check-cfg=values(freebsd13) --check-cfg=values(backtrace_in_libstd) --check-cfg=values(target_env,\"libnx\") --check-cfg=values(target_arch,\"asmjs\",\"spirv\",\"nvptx\",\"xtensa\") -Clink-arg=-fuse-ld=lld -Clink-arg=-Wl,--threads=1 -Wrustdoc::invalid_codeblock_attributes --crate-version 1.72.0-dev -Zcrate-attr=doc(html_root_url=\"https://doc.rust-lang.org/nightly/\") -Zcrate-attr=warn(rust_2018_idioms)" RUSTDOC_FUSE_LD_LLD="1" RUSTDOC_LIBDIR="/home/kyubey/workspace/rust/build/x86_64-unknown-linux-gnu/stage0/lib" RUSTDOC_REAL="/path/to/nowhere/rustdoc/not/required" RUSTFLAGS="-C target-cpu=native --cfg=bootstrap -Csymbol-mangling-version=legacy -Zunstable-options -Zunstable-options --check-cfg=values(bootstrap) --check-cfg=values(stdarch_intel_sde) --check-cfg=values(no_fp_fmt_parse) --check-cfg=values(no_global_oom_handling) --check-cfg=values(no_rc) --check-cfg=values(no_sync) --check-cfg=values(freebsd12) --check-cfg=values(freebsd13) --check-cfg=values(backtrace_in_libstd) --check-cfg=values(target_env,\"libnx\") --check-cfg=values(target_arch,\"asmjs\",\"spirv\",\"nvptx\",\"xtensa\") -Zmacro-backtrace -Clink-args=-Wl,-z,origin -Clink-args=-Wl,-rpath,$ORIGIN/../lib -Clink-args=-fuse-ld=lld -Csplit-debuginfo=off -Cprefer-dynamic -Zinline-mir -Clto=off -Zcrate-attr=doc(html_root_url=\"https://doc.rust-lang.org/nightly/\")" RUST_COMPILER_RT_ROOT="/home/kyubey/workspace/rust/src/llvm-project/compiler-rt" RUST_TEST_THREADS="48" WINAPI_NO_BUNDLED_LIBRARIES="1" __CARGO_DEFAULT_LIB_METADATA="bootstrapstd" "/home/kyubey/workspace/rust/build/x86_64-unknown-linux-gnu/stage0/bin/cargo" "bench" "--target" "x86_64-unknown-linux-gnu" "-Zcheck-cfg=names,values,output" "-Zbinary-dep-depinfo" "-j" "48" "--features" " panic-unwind backtrace compiler-builtins-c" "--manifest-path" "/home/kyubey/workspace/rust/library/sysroot/Cargo.toml" "-p" "core" "--" "bench_ascii_escape_display" "--quiet" "-Z" "unstable-options" "--format" "json""#; + +#[bench] +fn bench_ascii_escape_display_no_escape(b: &mut Bencher) { + let mut writer = String::with_capacity(8 * 1024); + + b.iter(move || { + writer.clear(); + let iter = ASCII_PATH.escape_ascii(); + write!(writer, "{}", iter).unwrap(); + writer.len() + }) +} + +#[bench] +fn bench_ascii_escape_display_mixed(b: &mut Bencher) { + let mut writer = String::with_capacity(8 * 1024); + + b.iter(move || { + writer.clear(); + let iter = RUST_INCANTATION.escape_ascii(); + write!(writer, "{}", iter).unwrap(); + writer.len() + }) +} diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 34213637a32f..9d95b32409c9 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -647,7 +647,7 @@ impl [T; N] { )] #[inline] pub fn split_array_ref(&self) -> (&[T; M], &[T]) { - (&self[..]).split_array_ref::() + (&self[..]).split_first_chunk::().unwrap() } /// Divides one mutable array reference into two at an index. @@ -680,7 +680,7 @@ impl [T; N] { )] #[inline] pub fn split_array_mut(&mut self) -> (&mut [T; M], &mut [T]) { - (&mut self[..]).split_array_mut::() + (&mut self[..]).split_first_chunk_mut::().unwrap() } /// Divides one array reference into two at an index from the end. @@ -725,7 +725,7 @@ impl [T; N] { )] #[inline] pub fn rsplit_array_ref(&self) -> (&[T], &[T; M]) { - (&self[..]).rsplit_array_ref::() + (&self[..]).split_last_chunk::().unwrap() } /// Divides one mutable array reference into two at an index from the end. @@ -758,7 +758,7 @@ impl [T; N] { )] #[inline] pub fn rsplit_array_mut(&mut self) -> (&mut [T], &mut [T; M]) { - (&mut self[..]).rsplit_array_mut::() + (&mut self[..]).split_last_chunk_mut::().unwrap() } } diff --git a/library/core/src/ascii.rs b/library/core/src/ascii.rs index ef8e4d098ed9..02867789b79d 100644 --- a/library/core/src/ascii.rs +++ b/library/core/src/ascii.rs @@ -96,6 +96,17 @@ pub fn escape_default(c: u8) -> EscapeDefault { EscapeDefault(escape::EscapeIterInner::new(data, range)) } +impl EscapeDefault { + pub(crate) fn empty() -> Self { + let data = [Char::Null; 4]; + EscapeDefault(escape::EscapeIterInner::new(data, 0..0)) + } + + pub(crate) fn as_str(&self) -> &str { + self.0.as_str() + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for EscapeDefault { type Item = u8; diff --git a/library/core/src/error.rs b/library/core/src/error.rs index f1a7ad935480..ded17e69bd9c 100644 --- a/library/core/src/error.rs +++ b/library/core/src/error.rs @@ -415,7 +415,7 @@ where // Request and its methods /////////////////////////////////////////////////////////////////////////////// -/// `Request` supports generic, type-driven access to data. It's use is currently restricted to the +/// `Request` supports generic, type-driven access to data. Its use is currently restricted to the /// standard library in cases where trait authors wish to allow trait implementors to share generic /// information across trait boundaries. The motivating and prototypical use case is /// `core::error::Error` which would otherwise require a method per concrete type (eg. diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs index 6122332da0d2..7d6f746845e3 100644 --- a/library/core/src/iter/adapters/flatten.rs +++ b/library/core/src/iter/adapters/flatten.rs @@ -24,6 +24,14 @@ impl U> FlatMap { pub(in crate::iter) fn new(iter: I, f: F) -> FlatMap { FlatMap { inner: FlattenCompat::new(iter.map(f)) } } + + pub(crate) fn into_parts(self) -> (Option, Option, Option) { + ( + self.inner.frontiter, + self.inner.iter.into_inner().map(Map::into_inner), + self.inner.backiter, + ) + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/iter/adapters/fuse.rs b/library/core/src/iter/adapters/fuse.rs index 462a7e877332..7781ed088b76 100644 --- a/library/core/src/iter/adapters/fuse.rs +++ b/library/core/src/iter/adapters/fuse.rs @@ -24,6 +24,10 @@ impl Fuse { pub(in crate::iter) fn new(iter: I) -> Fuse { Fuse { iter: Some(iter) } } + + pub(crate) fn into_inner(self) -> Option { + self.iter + } } #[stable(feature = "fused", since = "1.26.0")] diff --git a/library/core/src/iter/adapters/map.rs b/library/core/src/iter/adapters/map.rs index e27fc7257f6c..c882c9e7f3f5 100644 --- a/library/core/src/iter/adapters/map.rs +++ b/library/core/src/iter/adapters/map.rs @@ -69,6 +69,10 @@ impl Map { pub(in crate::iter) fn new(iter: I, f: F) -> Map { Map { iter, f } } + + pub(crate) fn into_inner(self) -> I { + self.iter + } } #[stable(feature = "core_impl_debug", since = "1.9.0")] diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index d94a508b5b28..83f8fd25b50b 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -4033,42 +4033,42 @@ pub trait Iterator { Self: Sized, Self::Item: PartialOrd, { - self.is_sorted_by(PartialOrd::partial_cmp) + self.is_sorted_by(|a, b| a <= b) } /// Checks if the elements of this iterator are sorted using the given comparator function. /// /// Instead of using `PartialOrd::partial_cmp`, this function uses the given `compare` - /// function to determine the ordering of two elements. Apart from that, it's equivalent to - /// [`is_sorted`]; see its documentation for more information. + /// function to determine whether two elements are to be considered in sorted order. /// /// # Examples /// /// ``` /// #![feature(is_sorted)] /// - /// assert!([1, 2, 2, 9].iter().is_sorted_by(|a, b| a.partial_cmp(b))); - /// assert!(![1, 3, 2, 4].iter().is_sorted_by(|a, b| a.partial_cmp(b))); - /// assert!([0].iter().is_sorted_by(|a, b| a.partial_cmp(b))); - /// assert!(std::iter::empty::().is_sorted_by(|a, b| a.partial_cmp(b))); - /// assert!(![0.0, 1.0, f32::NAN].iter().is_sorted_by(|a, b| a.partial_cmp(b))); - /// ``` + /// assert!([1, 2, 2, 9].iter().is_sorted_by(|a, b| a <= b)); + /// assert!(![1, 2, 2, 9].iter().is_sorted_by(|a, b| a < b)); /// - /// [`is_sorted`]: Iterator::is_sorted + /// assert!([0].iter().is_sorted_by(|a, b| true)); + /// assert!([0].iter().is_sorted_by(|a, b| false)); + /// + /// assert!(std::iter::empty::().is_sorted_by(|a, b| false)); + /// assert!(std::iter::empty::().is_sorted_by(|a, b| true)); + /// ``` #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")] #[rustc_do_not_const_check] fn is_sorted_by(mut self, compare: F) -> bool where Self: Sized, - F: FnMut(&Self::Item, &Self::Item) -> Option, + F: FnMut(&Self::Item, &Self::Item) -> bool, { #[inline] fn check<'a, T>( last: &'a mut T, - mut compare: impl FnMut(&T, &T) -> Option + 'a, + mut compare: impl FnMut(&T, &T) -> bool + 'a, ) -> impl FnMut(T) -> bool + 'a { move |curr| { - if let Some(Ordering::Greater) | None = compare(&last, &curr) { + if !compare(&last, &curr) { return false; } *last = curr; diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 1a8f245c8be3..24ad78efa83b 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -111,6 +111,7 @@ // // Library features: // tidy-alphabetical-start +#![cfg_attr(not(bootstrap), feature(offset_of_nested))] #![feature(char_indices_offset)] #![feature(const_align_of_val)] #![feature(const_align_of_val_raw)] @@ -160,6 +161,7 @@ #![feature(const_slice_ptr_len)] #![feature(const_slice_split_at_mut)] #![feature(const_str_from_utf8_unchecked_mut)] +#![feature(const_strict_overflow_ops)] #![feature(const_swap)] #![feature(const_try)] #![feature(const_type_id)] @@ -176,7 +178,6 @@ #![feature(isqrt)] #![feature(maybe_uninit_uninit_array)] #![feature(non_null_convenience)] -#![feature(offset_of)] #![feature(offset_of_enum)] #![feature(panic_internals)] #![feature(ptr_alignment_type)] diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index a2437feeeb9c..9bbaf62a5caa 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1596,7 +1596,7 @@ pub(crate) mod builtin { /// /// [the reference]: ../../../reference/attributes/testing.html#the-test-attribute #[stable(feature = "rust1", since = "1.0.0")] - #[allow_internal_unstable(test, rustc_attrs)] + #[allow_internal_unstable(test, rustc_attrs, coverage_attribute)] #[rustc_builtin_macro] pub macro test($item:item) { /* compiler built-in */ @@ -1609,7 +1609,7 @@ pub(crate) mod builtin { soft, reason = "`bench` is a part of custom test frameworks which are unstable" )] - #[allow_internal_unstable(test, rustc_attrs)] + #[allow_internal_unstable(test, rustc_attrs, coverage_attribute)] #[rustc_builtin_macro] pub macro bench($item:item) { /* compiler built-in */ diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 407954001e4c..318a99e23ec6 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -736,7 +736,7 @@ pub const fn swap(x: &mut T, y: &mut T) { // tends to copy the whole thing to stack rather than doing it one part // at a time, so instead treat them as one-element slices and piggy-back // the slice optimizations that will split up the swaps. - if size_of::() / align_of::() > 4 { + if const { size_of::() / align_of::() > 2 } { // SAFETY: exclusive references always point to one non-overlapping // element and are non-null and properly aligned. return unsafe { ptr::swap_nonoverlapping(x, y, 1) }; @@ -1303,11 +1303,12 @@ impl SizedTypeProperties for T {} /// Enum variants may be traversed as if they were fields. Variants themselves do /// not have an offset. /// +/// However, on stable only a single field name is supported, which blocks the use of +/// enum support. +/// /// Visibility is respected - all types and fields must be visible to the call site: /// /// ``` -/// #![feature(offset_of)] -/// /// mod nested { /// #[repr(C)] /// pub struct Struct { @@ -1330,8 +1331,6 @@ impl SizedTypeProperties for T {} /// not *identical*, e.g.: /// /// ``` -/// #![feature(offset_of)] -/// /// struct Wrapper(T, U); /// /// type A = Wrapper; @@ -1359,8 +1358,7 @@ impl SizedTypeProperties for T {} /// # Examples /// /// ``` -/// #![feature(offset_of)] -/// # #![feature(offset_of_enum)] +/// #![feature(offset_of_enum, offset_of_nested)] /// /// use std::mem; /// #[repr(C)] @@ -1396,7 +1394,7 @@ impl SizedTypeProperties for T {} /// assert_eq!(mem::offset_of!(Option<&u8>, Some.0), 0); /// ``` #[cfg(not(bootstrap))] -#[unstable(feature = "offset_of", issue = "106655")] +#[stable(feature = "offset_of", since = "CURRENT_RUSTC_VERSION")] #[allow_internal_unstable(builtin_syntax, hint_must_use)] pub macro offset_of($Container:ty, $($fields:expr)+ $(,)?) { // The `{}` is for better error messages @@ -1404,7 +1402,7 @@ pub macro offset_of($Container:ty, $($fields:expr)+ $(,)?) { } #[cfg(bootstrap)] -#[unstable(feature = "offset_of", issue = "106655")] +#[stable(feature = "offset_of", since = "CURRENT_RUSTC_VERSION")] #[allow_internal_unstable(builtin_syntax, hint_must_use)] #[allow(missing_docs)] pub macro offset_of($Container:ty, $($fields:tt).+ $(,)?) { diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs index 4b5862d98a3a..408002d18cad 100644 --- a/library/core/src/net/ip_addr.rs +++ b/library/core/src/net/ip_addr.rs @@ -1785,6 +1785,31 @@ impl Ipv6Addr { (self.segments()[0] & 0xff00) == 0xff00 } + /// Returns [`true`] if the address is an IPv4-mapped address (`::ffff:0:0/96`). + /// + /// IPv4-mapped addresses can be converted to their canonical IPv4 address with + /// [`to_ipv4_mapped`](Ipv6Addr::to_ipv4_mapped). + /// + /// # Examples + /// ``` + /// #![feature(ip)] + /// + /// use std::net::{Ipv4Addr, Ipv6Addr}; + /// + /// let ipv4_mapped = Ipv4Addr::new(192, 0, 2, 255).to_ipv6_mapped(); + /// assert_eq!(ipv4_mapped.is_ipv4_mapped(), true); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x2ff).is_ipv4_mapped(), true); + /// + /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_ipv4_mapped(), false); + /// ``` + #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] + #[unstable(feature = "ip", issue = "27709")] + #[must_use] + #[inline] + pub const fn is_ipv4_mapped(&self) -> bool { + matches!(self.segments(), [0, 0, 0, 0, 0, 0xffff, _, _]) + } + /// Converts this address to an [`IPv4` address] if it's an [IPv4-mapped] address, /// as defined in [IETF RFC 4291 section 2.5.5.2], otherwise returns [`None`]. /// diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index fd01f1b26101..451a2e14fe95 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -451,7 +451,40 @@ macro_rules! int_impl { #[inline] pub const fn checked_add(self, rhs: Self) -> Option { let (a, b) = self.overflowing_add(rhs); - if unlikely!(b) {None} else {Some(a)} + if unlikely!(b) { None } else { Some(a) } + } + + /// Strict integer addition. Computes `self + rhs`, panicking + /// if overflow occurred. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).strict_add(1), ", stringify!($SelfT), "::MAX - 1);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = (", stringify!($SelfT), "::MAX - 2).strict_add(3);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_add(self, rhs: Self) -> Self { + let (a, b) = self.overflowing_add(rhs); + if unlikely!(b) { overflow_panic::add() } else { a } } /// Unchecked integer addition. Computes `self + rhs`, assuming overflow @@ -498,7 +531,40 @@ macro_rules! int_impl { #[inline] pub const fn checked_add_unsigned(self, rhs: $UnsignedT) -> Option { let (a, b) = self.overflowing_add_unsigned(rhs); - if unlikely!(b) {None} else {Some(a)} + if unlikely!(b) { None } else { Some(a) } + } + + /// Strict addition with an unsigned integer. Computes `self + rhs`, + /// panicking if overflow occurred. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".strict_add_unsigned(2), 3);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = (", stringify!($SelfT), "::MAX - 2).strict_add_unsigned(3);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_add_unsigned(self, rhs: $UnsignedT) -> Self { + let (a, b) = self.overflowing_add_unsigned(rhs); + if unlikely!(b) { overflow_panic::add() } else { a } } /// Checked integer subtraction. Computes `self - rhs`, returning `None` if @@ -519,7 +585,40 @@ macro_rules! int_impl { #[inline] pub const fn checked_sub(self, rhs: Self) -> Option { let (a, b) = self.overflowing_sub(rhs); - if unlikely!(b) {None} else {Some(a)} + if unlikely!(b) { None } else { Some(a) } + } + + /// Strict integer subtraction. Computes `self - rhs`, panicking if + /// overflow occurred. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 2).strict_sub(1), ", stringify!($SelfT), "::MIN + 1);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = (", stringify!($SelfT), "::MIN + 2).strict_sub(3);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_sub(self, rhs: Self) -> Self { + let (a, b) = self.overflowing_sub(rhs); + if unlikely!(b) { overflow_panic::sub() } else { a } } /// Unchecked integer subtraction. Computes `self - rhs`, assuming overflow @@ -566,7 +665,40 @@ macro_rules! int_impl { #[inline] pub const fn checked_sub_unsigned(self, rhs: $UnsignedT) -> Option { let (a, b) = self.overflowing_sub_unsigned(rhs); - if unlikely!(b) {None} else {Some(a)} + if unlikely!(b) { None } else { Some(a) } + } + + /// Strict subtraction with an unsigned integer. Computes `self - rhs`, + /// panicking if overflow occurred. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".strict_sub_unsigned(2), -1);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = (", stringify!($SelfT), "::MIN + 2).strict_sub_unsigned(3);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_sub_unsigned(self, rhs: $UnsignedT) -> Self { + let (a, b) = self.overflowing_sub_unsigned(rhs); + if unlikely!(b) { overflow_panic::sub() } else { a } } /// Checked integer multiplication. Computes `self * rhs`, returning `None` if @@ -587,7 +719,40 @@ macro_rules! int_impl { #[inline] pub const fn checked_mul(self, rhs: Self) -> Option { let (a, b) = self.overflowing_mul(rhs); - if unlikely!(b) {None} else {Some(a)} + if unlikely!(b) { None } else { Some(a) } + } + + /// Strict integer multiplication. Computes `self * rhs`, panicking if + /// overflow occurred. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.strict_mul(1), ", stringify!($SelfT), "::MAX);")] + /// ``` + /// + /// ``` should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_mul(2);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_mul(self, rhs: Self) -> Self { + let (a, b) = self.overflowing_mul(rhs); + if unlikely!(b) { overflow_panic::mul() } else { a } } /// Unchecked integer multiplication. Computes `self * rhs`, assuming overflow @@ -642,6 +807,50 @@ macro_rules! int_impl { } } + /// Strict integer division. Computes `self / rhs`, panicking + /// if overflow occurred. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// The only case where such an overflow can occur is when one divides `MIN / -1` on a signed type (where + /// `MIN` is the negative minimal value for the type); this is equivalent to `-MIN`, a positive value + /// that is too large to represent in the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 1).strict_div(-1), ", stringify!($Max), ");")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_div(-1);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = (1", stringify!($SelfT), ").strict_div(0);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_div(self, rhs: Self) -> Self { + let (a, b) = self.overflowing_div(rhs); + if unlikely!(b) { overflow_panic::div() } else { a } + } + /// Checked Euclidean division. Computes `self.div_euclid(rhs)`, /// returning `None` if `rhs == 0` or the division results in overflow. /// @@ -668,6 +877,50 @@ macro_rules! int_impl { } } + /// Strict Euclidean division. Computes `self.div_euclid(rhs)`, panicking + /// if overflow occurred. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// The only case where such an overflow can occur is when one divides `MIN / -1` on a signed type (where + /// `MIN` is the negative minimal value for the type); this is equivalent to `-MIN`, a positive value + /// that is too large to represent in the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 1).strict_div_euclid(-1), ", stringify!($Max), ");")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_div_euclid(-1);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = (1", stringify!($SelfT), ").strict_div_euclid(0);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_div_euclid(self, rhs: Self) -> Self { + let (a, b) = self.overflowing_div_euclid(rhs); + if unlikely!(b) { overflow_panic::div() } else { a } + } + /// Checked integer remainder. Computes `self % rhs`, returning `None` if /// `rhs == 0` or the division results in overflow. /// @@ -694,6 +947,49 @@ macro_rules! int_impl { } } + /// Strict integer remainder. Computes `self % rhs`, panicking if + /// the division results in overflow. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// The only case where such an overflow can occur is `x % y` for `MIN / -1` on a + /// signed type (where `MIN` is the negative minimal value), which is invalid due to implementation artifacts. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".strict_rem(2), 1);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = 5", stringify!($SelfT), ".strict_rem(0);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_rem(-1);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_rem(self, rhs: Self) -> Self { + let (a, b) = self.overflowing_rem(rhs); + if unlikely!(b) { overflow_panic::rem() } else { a } + } + /// Checked Euclidean remainder. Computes `self.rem_euclid(rhs)`, returning `None` /// if `rhs == 0` or the division results in overflow. /// @@ -720,6 +1016,49 @@ macro_rules! int_impl { } } + /// Strict Euclidean remainder. Computes `self.rem_euclid(rhs)`, panicking if + /// the division results in overflow. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// The only case where such an overflow can occur is `x % y` for `MIN / -1` on a + /// signed type (where `MIN` is the negative minimal value), which is invalid due to implementation artifacts. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".strict_rem_euclid(2), 1);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = 5", stringify!($SelfT), ".strict_rem_euclid(0);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_rem_euclid(-1);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_rem_euclid(self, rhs: Self) -> Self { + let (a, b) = self.overflowing_rem_euclid(rhs); + if unlikely!(b) { overflow_panic::rem() } else { a } + } + /// Checked negation. Computes `-self`, returning `None` if `self == MIN`. /// /// # Examples @@ -737,7 +1076,7 @@ macro_rules! int_impl { #[inline] pub const fn checked_neg(self) -> Option { let (a, b) = self.overflowing_neg(); - if unlikely!(b) {None} else {Some(a)} + if unlikely!(b) { None } else { Some(a) } } /// Unchecked negation. Computes `-self`, assuming overflow cannot occur. @@ -765,6 +1104,38 @@ macro_rules! int_impl { unsafe { intrinsics::unchecked_sub(0, self) } } + /// Strict negation. Computes `-self`, panicking if `self == MIN`. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".strict_neg(), -5);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_neg();")] + /// + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_neg(self) -> Self { + let (a, b) = self.overflowing_neg(); + if unlikely!(b) { overflow_panic::neg() } else { a } + } + /// Checked shift left. Computes `self << rhs`, returning `None` if `rhs` is larger /// than or equal to the number of bits in `self`. /// @@ -783,7 +1154,40 @@ macro_rules! int_impl { #[inline] pub const fn checked_shl(self, rhs: u32) -> Option { let (a, b) = self.overflowing_shl(rhs); - if unlikely!(b) {None} else {Some(a)} + if unlikely!(b) { None } else { Some(a) } + } + + /// Strict shift left. Computes `self << rhs`, panicking if `rhs` is larger + /// than or equal to the number of bits in `self`. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".strict_shl(4), 0x10);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = 0x1", stringify!($SelfT), ".strict_shl(129);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_shl(self, rhs: u32) -> Self { + let (a, b) = self.overflowing_shl(rhs); + if unlikely!(b) { overflow_panic::shl() } else { a } } /// Unchecked shift left. Computes `self << rhs`, assuming that @@ -831,7 +1235,40 @@ macro_rules! int_impl { #[inline] pub const fn checked_shr(self, rhs: u32) -> Option { let (a, b) = self.overflowing_shr(rhs); - if unlikely!(b) {None} else {Some(a)} + if unlikely!(b) { None } else { Some(a) } + } + + /// Strict shift right. Computes `self >> rhs`, panicking `rhs` is + /// larger than or equal to the number of bits in `self`. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".strict_shr(4), 0x1);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = 0x10", stringify!($SelfT), ".strict_shr(128);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_shr(self, rhs: u32) -> Self { + let (a, b) = self.overflowing_shr(rhs); + if unlikely!(b) { overflow_panic::shr() } else { a } } /// Unchecked shift right. Computes `self >> rhs`, assuming that @@ -885,6 +1322,42 @@ macro_rules! int_impl { } } + /// Strict absolute value. Computes `self.abs()`, panicking if + /// `self == MIN`. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!((-5", stringify!($SelfT), ").strict_abs(), 5);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_abs();")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_abs(self) -> Self { + if self.is_negative() { + self.strict_neg() + } else { + self + } + } + /// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if /// overflow occurred. /// @@ -923,6 +1396,55 @@ macro_rules! int_impl { acc.checked_mul(base) } + /// Strict exponentiation. Computes `self.pow(exp)`, panicking if + /// overflow occurred. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(8", stringify!($SelfT), ".strict_pow(2), 64);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_pow(2);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_pow(self, mut exp: u32) -> Self { + if exp == 0 { + return 1; + } + let mut base = self; + let mut acc: Self = 1; + + while exp > 1 { + if (exp & 1) == 1 { + acc = acc.strict_mul(base); + } + exp /= 2; + base = base.strict_mul(base); + } + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + acc.strict_mul(base) + } + /// Returns the square root of the number, rounded down. /// /// Returns `None` if `self` is negative. diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 695e87aaabf8..4d85addadf52 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -44,6 +44,7 @@ mod uint_macros; // import uint_impl! mod error; mod int_log10; mod nonzero; +mod overflow_panic; mod saturating; mod wrapping; @@ -59,6 +60,8 @@ pub use dec2flt::ParseFloatError; #[stable(feature = "rust1", since = "1.0.0")] pub use error::ParseIntError; +pub(crate) use nonzero::NonZero; + #[stable(feature = "nonzero", since = "1.28.0")] pub use nonzero::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize}; @@ -482,7 +485,7 @@ impl u8 { Self = u8, ActualT = u8, SignedT = i8, - NonZeroT = NonZeroU8, + NonZeroT = NonZero, BITS = 8, MAX = 255, rot = 2, @@ -1097,7 +1100,7 @@ impl u16 { Self = u16, ActualT = u16, SignedT = i16, - NonZeroT = NonZeroU16, + NonZeroT = NonZero, BITS = 16, MAX = 65535, rot = 4, @@ -1146,7 +1149,7 @@ impl u32 { Self = u32, ActualT = u32, SignedT = i32, - NonZeroT = NonZeroU32, + NonZeroT = NonZero, BITS = 32, MAX = 4294967295, rot = 8, @@ -1170,7 +1173,7 @@ impl u64 { Self = u64, ActualT = u64, SignedT = i64, - NonZeroT = NonZeroU64, + NonZeroT = NonZero, BITS = 64, MAX = 18446744073709551615, rot = 12, @@ -1194,7 +1197,7 @@ impl u128 { Self = u128, ActualT = u128, SignedT = i128, - NonZeroT = NonZeroU128, + NonZeroT = NonZero, BITS = 128, MAX = 340282366920938463463374607431768211455, rot = 16, @@ -1220,7 +1223,7 @@ impl usize { Self = usize, ActualT = u16, SignedT = isize, - NonZeroT = NonZeroUsize, + NonZeroT = NonZero, BITS = 16, MAX = 65535, rot = 4, @@ -1245,7 +1248,7 @@ impl usize { Self = usize, ActualT = u32, SignedT = isize, - NonZeroT = NonZeroUsize, + NonZeroT = NonZero, BITS = 32, MAX = 4294967295, rot = 8, @@ -1270,7 +1273,7 @@ impl usize { Self = usize, ActualT = u64, SignedT = isize, - NonZeroT = NonZeroUsize, + NonZeroT = NonZero, BITS = 64, MAX = 18446744073709551615, rot = 12, diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 2df38ab5848a..bda691b16d4a 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -8,6 +8,69 @@ use super::from_str_radix; use super::{IntErrorKind, ParseIntError}; use crate::intrinsics; +mod private { + #[unstable( + feature = "nonzero_internals", + reason = "implementation detail which may disappear or be replaced at any time", + issue = "none" + )] + #[const_trait] + pub trait Sealed {} +} + +/// A marker trait for primitive types which can be zero. +/// +/// This is an implementation detail for [`NonZero`](NonZero) which may disappear or be replaced at any time. +#[unstable( + feature = "nonzero_internals", + reason = "implementation detail which may disappear or be replaced at any time", + issue = "none" +)] +#[const_trait] +pub trait ZeroablePrimitive: Sized + Copy + private::Sealed { + type NonZero; +} + +#[unstable( + feature = "nonzero_internals", + reason = "implementation detail which may disappear or be replaced at any time", + issue = "none" +)] +pub(crate) type NonZero = ::NonZero; + +macro_rules! impl_zeroable_primitive { + ($NonZero:ident ( $primitive:ty )) => { + #[unstable( + feature = "nonzero_internals", + reason = "implementation detail which may disappear or be replaced at any time", + issue = "none" + )] + impl const private::Sealed for $primitive {} + + #[unstable( + feature = "nonzero_internals", + reason = "implementation detail which may disappear or be replaced at any time", + issue = "none" + )] + impl const ZeroablePrimitive for $primitive { + type NonZero = $NonZero; + } + }; +} + +impl_zeroable_primitive!(NonZeroU8(u8)); +impl_zeroable_primitive!(NonZeroU16(u16)); +impl_zeroable_primitive!(NonZeroU32(u32)); +impl_zeroable_primitive!(NonZeroU64(u64)); +impl_zeroable_primitive!(NonZeroU128(u128)); +impl_zeroable_primitive!(NonZeroUsize(usize)); +impl_zeroable_primitive!(NonZeroI8(i8)); +impl_zeroable_primitive!(NonZeroI16(i16)); +impl_zeroable_primitive!(NonZeroI32(i32)); +impl_zeroable_primitive!(NonZeroI64(i64)); +impl_zeroable_primitive!(NonZeroI128(i128)); +impl_zeroable_primitive!(NonZeroIsize(isize)); + macro_rules! impl_nonzero_fmt { ( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => { $( @@ -22,193 +85,483 @@ macro_rules! impl_nonzero_fmt { } } -macro_rules! nonzero_integers { - ( $( #[$stability: meta] #[$const_new_unchecked_stability: meta] $Ty: ident($Int: ty); )+ ) => { - $( - /// An integer that is known not to equal zero. +macro_rules! nonzero_integer { + ( + #[$stability:meta] + #[$const_new_unchecked_stability:meta] + Self = $Ty:ident, + Primitive = $signedness:ident $Int:ident, + $(UnsignedNonZero = $UnsignedNonZero:ident,)? + UnsignedPrimitive = $UnsignedPrimitive:ty, + + // Used in doc comments. + leading_zeros_test = $leading_zeros_test:expr, + ) => { + /// An integer that is known not to equal zero. + /// + /// This enables some memory layout optimization. + #[doc = concat!("For example, `Option<", stringify!($Ty), ">` is the same size as `", stringify!($Int), "`:")] + /// + /// ```rust + /// use std::mem::size_of; + #[doc = concat!("assert_eq!(size_of::>(), size_of::<", stringify!($Int), ">());")] + /// ``` + /// + /// # Layout + /// + #[doc = concat!("`", stringify!($Ty), "` is guaranteed to have the same layout and bit validity as `", stringify!($Int), "`")] + /// with the exception that `0` is not a valid instance. + #[doc = concat!("`Option<", stringify!($Ty), ">` is guaranteed to be compatible with `", stringify!($Int), "`,")] + /// including in FFI. + /// + /// Thanks to the [null pointer optimization], + #[doc = concat!("`", stringify!($Ty), "` and `Option<", stringify!($Ty), ">`")] + /// are guaranteed to have the same size and alignment: + /// + /// ``` + /// # use std::mem::{size_of, align_of}; + #[doc = concat!("use std::num::", stringify!($Ty), ";")] + /// + #[doc = concat!("assert_eq!(size_of::<", stringify!($Ty), ">(), size_of::>());")] + #[doc = concat!("assert_eq!(align_of::<", stringify!($Ty), ">(), align_of::>());")] + /// ``` + /// + /// [null pointer optimization]: crate::option#representation + #[$stability] + #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] + #[repr(transparent)] + #[rustc_layout_scalar_valid_range_start(1)] + #[rustc_nonnull_optimization_guaranteed] + #[rustc_diagnostic_item = stringify!($Ty)] + pub struct $Ty($Int); + + impl $Ty { + /// Creates a non-zero without checking whether the value is non-zero. + /// This results in undefined behaviour if the value is zero. /// - /// This enables some memory layout optimization. - #[doc = concat!("For example, `Option<", stringify!($Ty), ">` is the same size as `", stringify!($Int), "`:")] + /// # Safety /// - /// ```rust - /// use std::mem::size_of; - #[doc = concat!("assert_eq!(size_of::>(), size_of::<", stringify!($Int), ">());")] - /// ``` - /// - /// # Layout - /// - #[doc = concat!("`", stringify!($Ty), "` is guaranteed to have the same layout and bit validity as `", stringify!($Int), "`")] - /// with the exception that `0` is not a valid instance. - #[doc = concat!("`Option<", stringify!($Ty), ">` is guaranteed to be compatible with `", stringify!($Int), "`,")] - /// including in FFI. - /// - /// Thanks to the [null pointer optimization], - #[doc = concat!("`", stringify!($Ty), "` and `Option<", stringify!($Ty), ">`")] - /// are guaranteed to have the same size and alignment: - /// - /// ``` - /// # use std::mem::{size_of, align_of}; - #[doc = concat!("use std::num::", stringify!($Ty), ";")] - /// - #[doc = concat!("assert_eq!(size_of::<", stringify!($Ty), ">(), size_of::>());")] - #[doc = concat!("assert_eq!(align_of::<", stringify!($Ty), ">(), align_of::>());")] - /// ``` - /// - /// [null pointer optimization]: crate::option#representation + /// The value must not be zero. #[$stability] - #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] - #[repr(transparent)] - #[rustc_layout_scalar_valid_range_start(1)] - #[rustc_nonnull_optimization_guaranteed] - #[rustc_diagnostic_item = stringify!($Ty)] - pub struct $Ty($Int); + #[$const_new_unchecked_stability] + #[must_use] + #[inline] + pub const unsafe fn new_unchecked(n: $Int) -> Self { + crate::panic::debug_assert_nounwind!( + n != 0, + concat!(stringify!($Ty), "::new_unchecked requires a non-zero argument") + ); + // SAFETY: this is guaranteed to be safe by the caller. + unsafe { + Self(n) + } + } - impl $Ty { - /// Creates a non-zero without checking whether the value is non-zero. - /// This results in undefined behaviour if the value is zero. - /// - /// # Safety - /// - /// The value must not be zero. - #[$stability] - #[$const_new_unchecked_stability] - #[must_use] - #[inline] - pub const unsafe fn new_unchecked(n: $Int) -> Self { - crate::panic::debug_assert_nounwind!( - n != 0, - concat!(stringify!($Ty), "::new_unchecked requires a non-zero argument") + /// Creates a non-zero if the given value is not zero. + #[$stability] + #[rustc_const_stable(feature = "const_nonzero_int_methods", since = "1.47.0")] + #[must_use] + #[inline] + pub const fn new(n: $Int) -> Option { + if n != 0 { + // SAFETY: we just checked that there's no `0` + Some(unsafe { Self(n) }) + } else { + None + } + } + + /// Converts a primitive mutable reference to a non-zero mutable reference + /// without checking whether the referenced value is non-zero. + /// This results in undefined behavior if `*n` is zero. + /// + /// # Safety + /// The referenced value must not be currently zero. + #[unstable(feature = "nonzero_from_mut", issue = "106290")] + #[must_use] + #[inline] + pub unsafe fn from_mut_unchecked(n: &mut $Int) -> &mut Self { + // SAFETY: Self is repr(transparent), and the value is assumed to be non-zero. + unsafe { + let n_alias = &mut *n; + core::intrinsics::assert_unsafe_precondition!( + concat!(stringify!($Ty), "::from_mut_unchecked requires the argument to dereference as non-zero"), + (n_alias: &mut $Int) => *n_alias != 0 ); - // SAFETY: this is guaranteed to be safe by the caller. - unsafe { - Self(n) - } + &mut *(n as *mut $Int as *mut Self) } + } - /// Creates a non-zero if the given value is not zero. - #[$stability] - #[rustc_const_stable(feature = "const_nonzero_int_methods", since = "1.47.0")] - #[must_use] - #[inline] - pub const fn new(n: $Int) -> Option { - if n != 0 { - // SAFETY: we just checked that there's no `0` - Some(unsafe { Self(n) }) - } else { - None - } + /// Converts a primitive mutable reference to a non-zero mutable reference + /// if the referenced integer is not zero. + #[unstable(feature = "nonzero_from_mut", issue = "106290")] + #[must_use] + #[inline] + pub fn from_mut(n: &mut $Int) -> Option<&mut Self> { + // SAFETY: Self is repr(transparent), and the value is non-zero. + // As long as the returned reference is alive, + // the user cannot `*n = 0` directly. + (*n != 0).then(|| unsafe { &mut *(n as *mut $Int as *mut Self) }) + } + + /// Returns the value as a primitive type. + #[$stability] + #[inline] + #[rustc_const_stable(feature = "const_nonzero_get", since = "1.34.0")] + pub const fn get(self) -> $Int { + // FIXME: Remove this after LLVM supports `!range` metadata for function + // arguments https://github.com/llvm/llvm-project/issues/76628 + // + // Rustc can set range metadata only if it loads `self` from + // memory somewhere. If the value of `self` was from by-value argument + // of some not-inlined function, LLVM don't have range metadata + // to understand that the value cannot be zero. + + // SAFETY: It is an invariant of this type. + unsafe { + intrinsics::assume(self.0 != 0); } + self.0 + } - /// Returns the value as a primitive type. - #[$stability] - #[inline] - #[rustc_const_stable(feature = "const_nonzero_get", since = "1.34.0")] - pub const fn get(self) -> $Int { - // FIXME: Remove this after LLVM supports `!range` metadata for function - // arguments https://github.com/llvm/llvm-project/issues/76628 + /// The size of this non-zero integer type in bits. + /// + #[doc = concat!("This value is equal to [`", stringify!($Int), "::BITS`].")] + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// + #[doc = concat!("assert_eq!(", stringify!($Ty), "::BITS, ", stringify!($Int), "::BITS);")] + /// ``` + #[stable(feature = "nonzero_bits", since = "1.67.0")] + pub const BITS: u32 = <$Int>::BITS; + + /// Returns the number of leading zeros in the binary representation of `self`. + /// + /// On many architectures, this function can perform better than `leading_zeros()` on the underlying integer type, as special handling of zero can be avoided. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = std::num::", stringify!($Ty), "::new(", $leading_zeros_test, ").unwrap();")] + /// + /// assert_eq!(n.leading_zeros(), 0); + /// ``` + #[stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] + #[rustc_const_stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn leading_zeros(self) -> u32 { + // SAFETY: since `self` cannot be zero, it is safe to call `ctlz_nonzero`. + unsafe { intrinsics::ctlz_nonzero(self.get() as $UnsignedPrimitive) as u32 } + } + + /// Returns the number of trailing zeros in the binary representation + /// of `self`. + /// + /// On many architectures, this function can perform better than `trailing_zeros()` on the underlying integer type, as special handling of zero can be avoided. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = std::num::", stringify!($Ty), "::new(0b0101000).unwrap();")] + /// + /// assert_eq!(n.trailing_zeros(), 3); + /// ``` + #[stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] + #[rustc_const_stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn trailing_zeros(self) -> u32 { + // SAFETY: since `self` cannot be zero, it is safe to call `cttz_nonzero`. + unsafe { intrinsics::cttz_nonzero(self.get() as $UnsignedPrimitive) as u32 } + } + + nonzero_integer_signedness_dependent_methods! { + Self = $Ty, + Primitive = $signedness $Int, + $(UnsignedNonZero = $UnsignedNonZero,)? + UnsignedPrimitive = $UnsignedPrimitive, + } + + /// Multiplies two non-zero integers together. + /// Checks for overflow and returns [`None`] on overflow. + /// As a consequence, the result cannot wrap to zero. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] + #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] + #[doc = concat!("let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(Some(four), two.checked_mul(two)); + /// assert_eq!(None, max.checked_mul(two)); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_mul(self, other: $Ty) -> Option<$Ty> { + if let Some(result) = self.get().checked_mul(other.get()) { + // SAFETY: + // - `checked_mul` returns `None` on overflow + // - `self` and `other` are non-zero + // - the only way to get zero from a multiplication without overflow is for one + // of the sides to be zero // - // Rustc can set range metadata only if it loads `self` from - // memory somewhere. If the value of `self` was from by-value argument - // of some not-inlined function, LLVM don't have range metadata - // to understand that the value cannot be zero. - - // SAFETY: It is an invariant of this type. - unsafe { - intrinsics::assume(self.0 != 0); - } - self.0 - } - - } - - #[stable(feature = "from_nonzero", since = "1.31.0")] - impl From<$Ty> for $Int { - #[doc = concat!("Converts a `", stringify!($Ty), "` into an `", stringify!($Int), "`")] - #[inline] - fn from(nonzero: $Ty) -> Self { - // Call nonzero to keep information range information - // from get method. - nonzero.get() + // So the result cannot be zero. + Some(unsafe { $Ty::new_unchecked(result) }) + } else { + None } } - #[stable(feature = "nonzero_bitor", since = "1.45.0")] - impl BitOr for $Ty { - type Output = Self; - #[inline] - fn bitor(self, rhs: Self) -> Self::Output { - // SAFETY: since `self` and `rhs` are both nonzero, the - // result of the bitwise-or will be nonzero. - unsafe { $Ty::new_unchecked(self.get() | rhs.get()) } + /// Multiplies two non-zero integers together. + #[doc = concat!("Return [`", stringify!($Ty), "::MAX`] on overflow.")] + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] + #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] + #[doc = concat!("let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(four, two.saturating_mul(two)); + /// assert_eq!(max, four.saturating_mul(max)); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_mul(self, other: $Ty) -> $Ty { + // SAFETY: + // - `saturating_mul` returns `u*::MAX`/`i*::MAX`/`i*::MIN` on overflow/underflow, + // all of which are non-zero + // - `self` and `other` are non-zero + // - the only way to get zero from a multiplication without overflow is for one + // of the sides to be zero + // + // So the result cannot be zero. + unsafe { $Ty::new_unchecked(self.get().saturating_mul(other.get())) } + } + + /// Multiplies two non-zero integers together, + /// assuming overflow cannot occur. + /// Overflow is unchecked, and it is undefined behaviour to overflow + /// *even if the result would wrap to a non-zero value*. + /// The behaviour is undefined as soon as + #[doc = sign_dependent_expr!{ + $signedness ? + if signed { + concat!("`self * rhs > ", stringify!($Int), "::MAX`, ", + "or `self * rhs < ", stringify!($Int), "::MIN`.") + } + if unsigned { + concat!("`self * rhs > ", stringify!($Int), "::MAX`.") + } + }] + /// + /// # Examples + /// + /// ``` + /// #![feature(nonzero_ops)] + /// + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] + #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] + /// + /// assert_eq!(four, unsafe { two.unchecked_mul(two) }); + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "nonzero_ops", issue = "84186")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const unsafe fn unchecked_mul(self, other: $Ty) -> $Ty { + // SAFETY: The caller ensures there is no overflow. + unsafe { $Ty::new_unchecked(self.get().unchecked_mul(other.get())) } + } + + /// Raises non-zero value to an integer power. + /// Checks for overflow and returns [`None`] on overflow. + /// As a consequence, the result cannot wrap to zero. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")] + #[doc = concat!("let twenty_seven = ", stringify!($Ty), "::new(27)?;")] + #[doc = concat!("let half_max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX / 2)?;")] + /// + /// assert_eq!(Some(twenty_seven), three.checked_pow(3)); + /// assert_eq!(None, half_max.checked_pow(3)); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_pow(self, other: u32) -> Option<$Ty> { + if let Some(result) = self.get().checked_pow(other) { + // SAFETY: + // - `checked_pow` returns `None` on overflow/underflow + // - `self` is non-zero + // - the only way to get zero from an exponentiation without overflow is + // for base to be zero + // + // So the result cannot be zero. + Some(unsafe { $Ty::new_unchecked(result) }) + } else { + None } } - #[stable(feature = "nonzero_bitor", since = "1.45.0")] - impl BitOr<$Int> for $Ty { - type Output = Self; - #[inline] - fn bitor(self, rhs: $Int) -> Self::Output { - // SAFETY: since `self` is nonzero, the result of the - // bitwise-or will be nonzero regardless of the value of - // `rhs`. - unsafe { $Ty::new_unchecked(self.get() | rhs) } + /// Raise non-zero value to an integer power. + #[doc = sign_dependent_expr!{ + $signedness ? + if signed { + concat!("Return [`", stringify!($Ty), "::MIN`] ", + "or [`", stringify!($Ty), "::MAX`] on overflow.") } - } - - #[stable(feature = "nonzero_bitor", since = "1.45.0")] - impl BitOr<$Ty> for $Int { - type Output = $Ty; - #[inline] - fn bitor(self, rhs: $Ty) -> Self::Output { - // SAFETY: since `rhs` is nonzero, the result of the - // bitwise-or will be nonzero regardless of the value of - // `self`. - unsafe { $Ty::new_unchecked(self | rhs.get()) } + if unsigned { + concat!("Return [`", stringify!($Ty), "::MAX`] on overflow.") } + }] + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")] + #[doc = concat!("let twenty_seven = ", stringify!($Ty), "::new(27)?;")] + #[doc = concat!("let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(twenty_seven, three.saturating_pow(3)); + /// assert_eq!(max, max.saturating_pow(3)); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_pow(self, other: u32) -> $Ty { + // SAFETY: + // - `saturating_pow` returns `u*::MAX`/`i*::MAX`/`i*::MIN` on overflow/underflow, + // all of which are non-zero + // - `self` is non-zero + // - the only way to get zero from an exponentiation without overflow is + // for base to be zero + // + // So the result cannot be zero. + unsafe { $Ty::new_unchecked(self.get().saturating_pow(other)) } } + } - #[stable(feature = "nonzero_bitor", since = "1.45.0")] - impl BitOrAssign for $Ty { - #[inline] - fn bitor_assign(&mut self, rhs: Self) { - *self = *self | rhs; - } + #[stable(feature = "from_nonzero", since = "1.31.0")] + impl From<$Ty> for $Int { + #[doc = concat!("Converts a `", stringify!($Ty), "` into an `", stringify!($Int), "`")] + #[inline] + fn from(nonzero: $Ty) -> Self { + // Call nonzero to keep information range information + // from get method. + nonzero.get() } + } - #[stable(feature = "nonzero_bitor", since = "1.45.0")] - impl BitOrAssign<$Int> for $Ty { - #[inline] - fn bitor_assign(&mut self, rhs: $Int) { - *self = *self | rhs; - } + #[stable(feature = "nonzero_bitor", since = "1.45.0")] + impl BitOr for $Ty { + type Output = Self; + #[inline] + fn bitor(self, rhs: Self) -> Self::Output { + // SAFETY: since `self` and `rhs` are both nonzero, the + // result of the bitwise-or will be nonzero. + unsafe { $Ty::new_unchecked(self.get() | rhs.get()) } } + } - impl_nonzero_fmt! { - #[$stability] (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty + #[stable(feature = "nonzero_bitor", since = "1.45.0")] + impl BitOr<$Int> for $Ty { + type Output = Self; + #[inline] + fn bitor(self, rhs: $Int) -> Self::Output { + // SAFETY: since `self` is nonzero, the result of the + // bitwise-or will be nonzero regardless of the value of + // `rhs`. + unsafe { $Ty::new_unchecked(self.get() | rhs) } } - )+ - } -} + } -nonzero_integers! { - #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU8(u8); - #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU16(u16); - #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU32(u32); - #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU64(u64); - #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU128(u128); - #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroUsize(usize); - #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI8(i8); - #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI16(i16); - #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI32(i32); - #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI64(i64); - #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI128(i128); - #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroIsize(isize); -} + #[stable(feature = "nonzero_bitor", since = "1.45.0")] + impl BitOr<$Ty> for $Int { + type Output = $Ty; + #[inline] + fn bitor(self, rhs: $Ty) -> Self::Output { + // SAFETY: since `rhs` is nonzero, the result of the + // bitwise-or will be nonzero regardless of the value of + // `self`. + unsafe { $Ty::new_unchecked(self | rhs.get()) } + } + } + + #[stable(feature = "nonzero_bitor", since = "1.45.0")] + impl BitOrAssign for $Ty { + #[inline] + fn bitor_assign(&mut self, rhs: Self) { + *self = *self | rhs; + } + } + + #[stable(feature = "nonzero_bitor", since = "1.45.0")] + impl BitOrAssign<$Int> for $Ty { + #[inline] + fn bitor_assign(&mut self, rhs: $Int) { + *self = *self | rhs; + } + } + + impl_nonzero_fmt! { + #[$stability] (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty + } -macro_rules! from_str_radix_nzint_impl { - ($($t:ty)*) => {$( #[stable(feature = "nonzero_parse", since = "1.35.0")] - impl FromStr for $t { + impl FromStr for $Ty { type Err = ParseIntError; fn from_str(src: &str) -> Result { Self::new(from_str_radix(src, 10)?) @@ -217,989 +570,791 @@ macro_rules! from_str_radix_nzint_impl { }) } } - )*} + + nonzero_integer_signedness_dependent_impls!($Ty $signedness $Int); + }; + + (Self = $Ty:ident, Primitive = unsigned $Int:ident $(,)?) => { + nonzero_integer! { + #[stable(feature = "nonzero", since = "1.28.0")] + #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] + Self = $Ty, + Primitive = unsigned $Int, + UnsignedPrimitive = $Int, + leading_zeros_test = concat!(stringify!($Int), "::MAX"), + } + }; + + (Self = $Ty:ident, Primitive = signed $Int:ident, $($rest:tt)*) => { + nonzero_integer! { + #[stable(feature = "signed_nonzero", since = "1.34.0")] + #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] + Self = $Ty, + Primitive = signed $Int, + $($rest)* + leading_zeros_test = concat!("-1", stringify!($Int)), + } + }; } -from_str_radix_nzint_impl! { NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 NonZeroU128 NonZeroUsize -NonZeroI8 NonZeroI16 NonZeroI32 NonZeroI64 NonZeroI128 NonZeroIsize } - -macro_rules! nonzero_leading_trailing_zeros { - ( $( $Ty: ident($Uint: ty) , $LeadingTestExpr:expr ;)+ ) => { - $( - impl $Ty { - /// Returns the number of leading zeros in the binary representation of `self`. - /// - /// On many architectures, this function can perform better than `leading_zeros()` on the underlying integer type, as special handling of zero can be avoided. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - #[doc = concat!("let n = std::num::", stringify!($Ty), "::new(", stringify!($LeadingTestExpr), ").unwrap();")] - /// - /// assert_eq!(n.leading_zeros(), 0); - /// ``` - #[stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] - #[rustc_const_stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn leading_zeros(self) -> u32 { - // SAFETY: since `self` cannot be zero, it is safe to call `ctlz_nonzero`. - unsafe { intrinsics::ctlz_nonzero(self.get() as $Uint) as u32 } - } - - /// Returns the number of trailing zeros in the binary representation - /// of `self`. - /// - /// On many architectures, this function can perform better than `trailing_zeros()` on the underlying integer type, as special handling of zero can be avoided. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - #[doc = concat!("let n = std::num::", stringify!($Ty), "::new(0b0101000).unwrap();")] - /// - /// assert_eq!(n.trailing_zeros(), 3); - /// ``` - #[stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] - #[rustc_const_stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn trailing_zeros(self) -> u32 { - // SAFETY: since `self` cannot be zero, it is safe to call `cttz_nonzero`. - unsafe { intrinsics::cttz_nonzero(self.get() as $Uint) as u32 } - } - +macro_rules! nonzero_integer_signedness_dependent_impls { + // Impls for unsigned nonzero types only. + ($Ty:ident unsigned $Int:ty) => { + #[stable(feature = "nonzero_div", since = "1.51.0")] + impl Div<$Ty> for $Int { + type Output = $Int; + /// This operation rounds towards zero, + /// truncating any fractional part of the exact result, and cannot panic. + #[inline] + fn div(self, other: $Ty) -> $Int { + // SAFETY: div by zero is checked because `other` is a nonzero, + // and MIN/-1 is checked because `self` is an unsigned int. + unsafe { crate::intrinsics::unchecked_div(self, other.get()) } } - )+ - } -} + } -nonzero_leading_trailing_zeros! { - NonZeroU8(u8), u8::MAX; - NonZeroU16(u16), u16::MAX; - NonZeroU32(u32), u32::MAX; - NonZeroU64(u64), u64::MAX; - NonZeroU128(u128), u128::MAX; - NonZeroUsize(usize), usize::MAX; - NonZeroI8(u8), -1i8; - NonZeroI16(u16), -1i16; - NonZeroI32(u32), -1i32; - NonZeroI64(u64), -1i64; - NonZeroI128(u128), -1i128; - NonZeroIsize(usize), -1isize; -} - -macro_rules! nonzero_integers_div { - ( $( $Ty: ident($Int: ty); )+ ) => { - $( - #[stable(feature = "nonzero_div", since = "1.51.0")] - impl Div<$Ty> for $Int { - type Output = $Int; - /// This operation rounds towards zero, - /// truncating any fractional part of the exact result, and cannot panic. - #[inline] - fn div(self, other: $Ty) -> $Int { - // SAFETY: div by zero is checked because `other` is a nonzero, - // and MIN/-1 is checked because `self` is an unsigned int. - unsafe { crate::intrinsics::unchecked_div(self, other.get()) } - } + #[stable(feature = "nonzero_div", since = "1.51.0")] + impl Rem<$Ty> for $Int { + type Output = $Int; + /// This operation satisfies `n % d == n - (n / d) * d`, and cannot panic. + #[inline] + fn rem(self, other: $Ty) -> $Int { + // SAFETY: rem by zero is checked because `other` is a nonzero, + // and MIN/-1 is checked because `self` is an unsigned int. + unsafe { crate::intrinsics::unchecked_rem(self, other.get()) } } + } + }; - #[stable(feature = "nonzero_div", since = "1.51.0")] - impl Rem<$Ty> for $Int { - type Output = $Int; - /// This operation satisfies `n % d == n - (n / d) * d`, and cannot panic. - #[inline] - fn rem(self, other: $Ty) -> $Int { - // SAFETY: rem by zero is checked because `other` is a nonzero, - // and MIN/-1 is checked because `self` is an unsigned int. - unsafe { crate::intrinsics::unchecked_rem(self, other.get()) } - } + // Impls for signed nonzero types only. + ($Ty:ident signed $Int:ty) => { + #[stable(feature = "signed_nonzero_neg", since = "1.71.0")] + impl Neg for $Ty { + type Output = $Ty; + + #[inline] + fn neg(self) -> $Ty { + // SAFETY: negation of nonzero cannot yield zero values. + unsafe { $Ty::new_unchecked(self.get().neg()) } } - )+ - } + } + + forward_ref_unop! { impl Neg, neg for $Ty, + #[stable(feature = "signed_nonzero_neg", since = "1.71.0")] } + }; } -nonzero_integers_div! { - NonZeroU8(u8); - NonZeroU16(u16); - NonZeroU32(u32); - NonZeroU64(u64); - NonZeroU128(u128); - NonZeroUsize(usize); -} +#[rustfmt::skip] // https://github.com/rust-lang/rustfmt/issues/5974 +macro_rules! nonzero_integer_signedness_dependent_methods { + // Associated items for unsigned nonzero types only. + ( + Self = $Ty:ident, + Primitive = unsigned $Int:ident, + UnsignedPrimitive = $Uint:ty, + ) => { + /// The smallest value that can be represented by this non-zero + /// integer type, 1. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::MIN.get(), 1", stringify!($Int), ");")] + /// ``` + #[stable(feature = "nonzero_min_max", since = "1.70.0")] + pub const MIN: Self = Self::new(1).unwrap(); -// A bunch of methods for unsigned nonzero types only. -macro_rules! nonzero_unsigned_operations { - ( $( $Ty: ident($Int: ident); )+ ) => { - $( - impl $Ty { - /// Adds an unsigned integer to a non-zero value. - /// Checks for overflow and returns [`None`] on overflow. - /// As a consequence, the result cannot wrap to zero. - /// - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")] - #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] - #[doc = concat!("let max = ", stringify!($Ty), "::new(", - stringify!($Int), "::MAX)?;")] - /// - /// assert_eq!(Some(two), one.checked_add(1)); - /// assert_eq!(None, max.checked_add(1)); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn checked_add(self, other: $Int) -> Option<$Ty> { - if let Some(result) = self.get().checked_add(other) { - // SAFETY: - // - `checked_add` returns `None` on overflow - // - `self` is non-zero - // - the only way to get zero from an addition without overflow is for both - // sides to be zero - // - // So the result cannot be zero. - Some(unsafe { $Ty::new_unchecked(result) }) - } else { - None - } - } + /// The largest value that can be represented by this non-zero + /// integer type, + #[doc = concat!("equal to [`", stringify!($Int), "::MAX`].")] + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::MAX.get(), ", stringify!($Int), "::MAX);")] + /// ``` + #[stable(feature = "nonzero_min_max", since = "1.70.0")] + pub const MAX: Self = Self::new(<$Int>::MAX).unwrap(); - /// Adds an unsigned integer to a non-zero value. - #[doc = concat!("Return [`", stringify!($Ty), "::MAX`] on overflow.")] - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")] - #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] - #[doc = concat!("let max = ", stringify!($Ty), "::new(", - stringify!($Int), "::MAX)?;")] - /// - /// assert_eq!(two, one.saturating_add(1)); - /// assert_eq!(max, max.saturating_add(1)); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn saturating_add(self, other: $Int) -> $Ty { - // SAFETY: - // - `saturating_add` returns `u*::MAX` on overflow, which is non-zero - // - `self` is non-zero - // - the only way to get zero from an addition without overflow is for both - // sides to be zero - // - // So the result cannot be zero. - unsafe { $Ty::new_unchecked(self.get().saturating_add(other)) } - } - - /// Adds an unsigned integer to a non-zero value, - /// assuming overflow cannot occur. - /// Overflow is unchecked, and it is undefined behaviour to overflow - /// *even if the result would wrap to a non-zero value*. - /// The behaviour is undefined as soon as - #[doc = concat!("`self + rhs > ", stringify!($Int), "::MAX`.")] - /// - /// # Examples - /// - /// ``` - /// #![feature(nonzero_ops)] - /// - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")] - #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] - /// - /// assert_eq!(two, unsafe { one.unchecked_add(1) }); - /// # Some(()) - /// # } - /// ``` - #[unstable(feature = "nonzero_ops", issue = "84186")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const unsafe fn unchecked_add(self, other: $Int) -> $Ty { - // SAFETY: The caller ensures there is no overflow. - unsafe { $Ty::new_unchecked(self.get().unchecked_add(other)) } - } - - /// Returns the smallest power of two greater than or equal to n. - /// Checks for overflow and returns [`None`] - /// if the next power of two is greater than the type’s maximum value. - /// As a consequence, the result cannot wrap to zero. - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] - #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")] - #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] - #[doc = concat!("let max = ", stringify!($Ty), "::new(", - stringify!($Int), "::MAX)?;")] - /// - /// assert_eq!(Some(two), two.checked_next_power_of_two() ); - /// assert_eq!(Some(four), three.checked_next_power_of_two() ); - /// assert_eq!(None, max.checked_next_power_of_two() ); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn checked_next_power_of_two(self) -> Option<$Ty> { - if let Some(nz) = self.get().checked_next_power_of_two() { - // SAFETY: The next power of two is positive - // and overflow is checked. - Some(unsafe { $Ty::new_unchecked(nz) }) - } else { - None - } - } - - /// Returns the base 2 logarithm of the number, rounded down. - /// - /// This is the same operation as - #[doc = concat!("[`", stringify!($Int), "::ilog2`],")] - /// except that it has no failure cases to worry about - /// since this value can never be zero. - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(7).unwrap().ilog2(), 2);")] - #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(8).unwrap().ilog2(), 3);")] - #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(9).unwrap().ilog2(), 3);")] - /// ``` - #[stable(feature = "int_log", since = "1.67.0")] - #[rustc_const_stable(feature = "int_log", since = "1.67.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn ilog2(self) -> u32 { - Self::BITS - 1 - self.leading_zeros() - } - - /// Returns the base 10 logarithm of the number, rounded down. - /// - /// This is the same operation as - #[doc = concat!("[`", stringify!($Int), "::ilog10`],")] - /// except that it has no failure cases to worry about - /// since this value can never be zero. - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(99).unwrap().ilog10(), 1);")] - #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(100).unwrap().ilog10(), 2);")] - #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(101).unwrap().ilog10(), 2);")] - /// ``` - #[stable(feature = "int_log", since = "1.67.0")] - #[rustc_const_stable(feature = "int_log", since = "1.67.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn ilog10(self) -> u32 { - super::int_log10::$Int(self.get()) - } - - /// Calculates the middle point of `self` and `rhs`. - /// - /// `midpoint(a, b)` is `(a + b) >> 1` as if it were performed in a - /// sufficiently-large signed integral type. This implies that the result is - /// always rounded towards negative infinity and that no overflow will ever occur. - /// - /// # Examples - /// - /// ``` - /// #![feature(num_midpoint)] - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")] - #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] - #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] - /// - /// assert_eq!(one.midpoint(four), two); - /// assert_eq!(four.midpoint(one), two); - /// # Some(()) - /// # } - /// ``` - #[unstable(feature = "num_midpoint", issue = "110840")] - #[rustc_const_unstable(feature = "const_num_midpoint", issue = "110840")] - #[rustc_allow_const_fn_unstable(const_num_midpoint)] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn midpoint(self, rhs: Self) -> Self { - // SAFETY: The only way to get `0` with midpoint is to have two opposite or - // near opposite numbers: (-5, 5), (0, 1), (0, 0) which is impossible because - // of the unsignedness of this number and also because $Ty is guaranteed to - // never being 0. - unsafe { $Ty::new_unchecked(self.get().midpoint(rhs.get())) } - } + /// Adds an unsigned integer to a non-zero value. + /// Checks for overflow and returns [`None`] on overflow. + /// As a consequence, the result cannot wrap to zero. + /// + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] + #[doc = concat!("let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(Some(two), one.checked_add(1)); + /// assert_eq!(None, max.checked_add(1)); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_add(self, other: $Int) -> Option<$Ty> { + if let Some(result) = self.get().checked_add(other) { + // SAFETY: + // - `checked_add` returns `None` on overflow + // - `self` is non-zero + // - the only way to get zero from an addition without overflow is for both + // sides to be zero + // + // So the result cannot be zero. + Some(unsafe { $Ty::new_unchecked(result) }) + } else { + None } - )+ - } -} + } -nonzero_unsigned_operations! { - NonZeroU8(u8); - NonZeroU16(u16); - NonZeroU32(u32); - NonZeroU64(u64); - NonZeroU128(u128); - NonZeroUsize(usize); -} + /// Adds an unsigned integer to a non-zero value. + #[doc = concat!("Return [`", stringify!($Ty), "::MAX`] on overflow.")] + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] + #[doc = concat!("let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(two, one.saturating_add(1)); + /// assert_eq!(max, max.saturating_add(1)); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_add(self, other: $Int) -> $Ty { + // SAFETY: + // - `saturating_add` returns `u*::MAX` on overflow, which is non-zero + // - `self` is non-zero + // - the only way to get zero from an addition without overflow is for both + // sides to be zero + // + // So the result cannot be zero. + unsafe { $Ty::new_unchecked(self.get().saturating_add(other)) } + } -// A bunch of methods for signed nonzero types only. -macro_rules! nonzero_signed_operations { - ( $( $Ty: ident($Int: ty) -> $Uty: ident($Uint: ty); )+ ) => { - $( - impl $Ty { - /// Computes the absolute value of self. - #[doc = concat!("See [`", stringify!($Int), "::abs`]")] - /// for documentation on overflow behaviour. - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] - #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] - /// - /// assert_eq!(pos, pos.abs()); - /// assert_eq!(pos, neg.abs()); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn abs(self) -> $Ty { - // SAFETY: This cannot overflow to zero. - unsafe { $Ty::new_unchecked(self.get().abs()) } - } + /// Adds an unsigned integer to a non-zero value, + /// assuming overflow cannot occur. + /// Overflow is unchecked, and it is undefined behaviour to overflow + /// *even if the result would wrap to a non-zero value*. + /// The behaviour is undefined as soon as + #[doc = concat!("`self + rhs > ", stringify!($Int), "::MAX`.")] + /// + /// # Examples + /// + /// ``` + /// #![feature(nonzero_ops)] + /// + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] + /// + /// assert_eq!(two, unsafe { one.unchecked_add(1) }); + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "nonzero_ops", issue = "84186")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const unsafe fn unchecked_add(self, other: $Int) -> $Ty { + // SAFETY: The caller ensures there is no overflow. + unsafe { $Ty::new_unchecked(self.get().unchecked_add(other)) } + } - /// Checked absolute value. - /// Checks for overflow and returns [`None`] if - #[doc = concat!("`self == ", stringify!($Ty), "::MIN`.")] - /// The result cannot be zero. - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] - #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] - #[doc = concat!("let min = ", stringify!($Ty), "::new(", - stringify!($Int), "::MIN)?;")] - /// - /// assert_eq!(Some(pos), neg.checked_abs()); - /// assert_eq!(None, min.checked_abs()); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn checked_abs(self) -> Option<$Ty> { - if let Some(nz) = self.get().checked_abs() { - // SAFETY: absolute value of nonzero cannot yield zero values. - Some(unsafe { $Ty::new_unchecked(nz) }) - } else { - None - } - } - - /// Computes the absolute value of self, - /// with overflow information, see - #[doc = concat!("[`", stringify!($Int), "::overflowing_abs`].")] - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] - #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] - #[doc = concat!("let min = ", stringify!($Ty), "::new(", - stringify!($Int), "::MIN)?;")] - /// - /// assert_eq!((pos, false), pos.overflowing_abs()); - /// assert_eq!((pos, false), neg.overflowing_abs()); - /// assert_eq!((min, true), min.overflowing_abs()); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn overflowing_abs(self) -> ($Ty, bool) { - let (nz, flag) = self.get().overflowing_abs(); - ( - // SAFETY: absolute value of nonzero cannot yield zero values. - unsafe { $Ty::new_unchecked(nz) }, - flag, - ) - } - - /// Saturating absolute value, see - #[doc = concat!("[`", stringify!($Int), "::saturating_abs`].")] - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] - #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] - #[doc = concat!("let min = ", stringify!($Ty), "::new(", - stringify!($Int), "::MIN)?;")] - #[doc = concat!("let min_plus = ", stringify!($Ty), "::new(", - stringify!($Int), "::MIN + 1)?;")] - #[doc = concat!("let max = ", stringify!($Ty), "::new(", - stringify!($Int), "::MAX)?;")] - /// - /// assert_eq!(pos, pos.saturating_abs()); - /// assert_eq!(pos, neg.saturating_abs()); - /// assert_eq!(max, min.saturating_abs()); - /// assert_eq!(max, min_plus.saturating_abs()); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn saturating_abs(self) -> $Ty { - // SAFETY: absolute value of nonzero cannot yield zero values. - unsafe { $Ty::new_unchecked(self.get().saturating_abs()) } - } - - /// Wrapping absolute value, see - #[doc = concat!("[`", stringify!($Int), "::wrapping_abs`].")] - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] - #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] - #[doc = concat!("let min = ", stringify!($Ty), "::new(", - stringify!($Int), "::MIN)?;")] - #[doc = concat!("# let max = ", stringify!($Ty), "::new(", - stringify!($Int), "::MAX)?;")] - /// - /// assert_eq!(pos, pos.wrapping_abs()); - /// assert_eq!(pos, neg.wrapping_abs()); - /// assert_eq!(min, min.wrapping_abs()); - /// assert_eq!(max, (-max).wrapping_abs()); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn wrapping_abs(self) -> $Ty { - // SAFETY: absolute value of nonzero cannot yield zero values. - unsafe { $Ty::new_unchecked(self.get().wrapping_abs()) } - } - - /// Computes the absolute value of self - /// without any wrapping or panicking. - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - #[doc = concat!("# use std::num::", stringify!($Uty), ";")] - /// - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let u_pos = ", stringify!($Uty), "::new(1)?;")] - #[doc = concat!("let i_pos = ", stringify!($Ty), "::new(1)?;")] - #[doc = concat!("let i_neg = ", stringify!($Ty), "::new(-1)?;")] - #[doc = concat!("let i_min = ", stringify!($Ty), "::new(", - stringify!($Int), "::MIN)?;")] - #[doc = concat!("let u_max = ", stringify!($Uty), "::new(", - stringify!($Uint), "::MAX / 2 + 1)?;")] - /// - /// assert_eq!(u_pos, i_pos.unsigned_abs()); - /// assert_eq!(u_pos, i_neg.unsigned_abs()); - /// assert_eq!(u_max, i_min.unsigned_abs()); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn unsigned_abs(self) -> $Uty { - // SAFETY: absolute value of nonzero cannot yield zero values. - unsafe { $Uty::new_unchecked(self.get().unsigned_abs()) } - } - - /// Returns `true` if `self` is positive and `false` if the - /// number is negative. - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] - #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] - /// - /// assert!(pos_five.is_positive()); - /// assert!(!neg_five.is_positive()); - /// # Some(()) - /// # } - /// ``` - #[must_use] - #[inline] - #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] - #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] - pub const fn is_positive(self) -> bool { - self.get().is_positive() - } - - /// Returns `true` if `self` is negative and `false` if the - /// number is positive. - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] - #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] - /// - /// assert!(neg_five.is_negative()); - /// assert!(!pos_five.is_negative()); - /// # Some(()) - /// # } - /// ``` - #[must_use] - #[inline] - #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] - #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] - pub const fn is_negative(self) -> bool { - self.get().is_negative() - } - - /// Checked negation. Computes `-self`, - #[doc = concat!("returning `None` if `self == ", stringify!($Ty), "::MIN`.")] - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] - #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] - #[doc = concat!("let min = ", stringify!($Ty), "::new(", - stringify!($Int), "::MIN)?;")] - /// - /// assert_eq!(pos_five.checked_neg(), Some(neg_five)); - /// assert_eq!(min.checked_neg(), None); - /// # Some(()) - /// # } - /// ``` - #[inline] - #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] - #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] - pub const fn checked_neg(self) -> Option<$Ty> { - if let Some(result) = self.get().checked_neg() { - // SAFETY: negation of nonzero cannot yield zero values. - return Some(unsafe { $Ty::new_unchecked(result) }); - } - None - } - - /// Negates self, overflowing if this is equal to the minimum value. - /// - #[doc = concat!("See [`", stringify!($Int), "::overflowing_neg`]")] - /// for documentation on overflow behaviour. - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] - #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] - #[doc = concat!("let min = ", stringify!($Ty), "::new(", - stringify!($Int), "::MIN)?;")] - /// - /// assert_eq!(pos_five.overflowing_neg(), (neg_five, false)); - /// assert_eq!(min.overflowing_neg(), (min, true)); - /// # Some(()) - /// # } - /// ``` - #[inline] - #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] - #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] - pub const fn overflowing_neg(self) -> ($Ty, bool) { - let (result, overflow) = self.get().overflowing_neg(); - // SAFETY: negation of nonzero cannot yield zero values. - ((unsafe { $Ty::new_unchecked(result) }), overflow) - } - - /// Saturating negation. Computes `-self`, - #[doc = concat!("returning [`", stringify!($Ty), "::MAX`]")] - #[doc = concat!("if `self == ", stringify!($Ty), "::MIN`")] - /// instead of overflowing. - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] - #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] - #[doc = concat!("let min = ", stringify!($Ty), "::new(", - stringify!($Int), "::MIN)?;")] - #[doc = concat!("let min_plus_one = ", stringify!($Ty), "::new(", - stringify!($Int), "::MIN + 1)?;")] - #[doc = concat!("let max = ", stringify!($Ty), "::new(", - stringify!($Int), "::MAX)?;")] - /// - /// assert_eq!(pos_five.saturating_neg(), neg_five); - /// assert_eq!(min.saturating_neg(), max); - /// assert_eq!(max.saturating_neg(), min_plus_one); - /// # Some(()) - /// # } - /// ``` - #[inline] - #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] - #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] - pub const fn saturating_neg(self) -> $Ty { - if let Some(result) = self.checked_neg() { - return result; - } - $Ty::MAX - } - - /// Wrapping (modular) negation. Computes `-self`, wrapping around at the boundary - /// of the type. - /// - #[doc = concat!("See [`", stringify!($Int), "::wrapping_neg`]")] - /// for documentation on overflow behaviour. - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] - #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] - #[doc = concat!("let min = ", stringify!($Ty), "::new(", - stringify!($Int), "::MIN)?;")] - /// - /// assert_eq!(pos_five.wrapping_neg(), neg_five); - /// assert_eq!(min.wrapping_neg(), min); - /// # Some(()) - /// # } - /// ``` - #[inline] - #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] - #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] - pub const fn wrapping_neg(self) -> $Ty { - let result = self.get().wrapping_neg(); - // SAFETY: negation of nonzero cannot yield zero values. - unsafe { $Ty::new_unchecked(result) } - } + /// Returns the smallest power of two greater than or equal to n. + /// Checks for overflow and returns [`None`] + /// if the next power of two is greater than the type’s maximum value. + /// As a consequence, the result cannot wrap to zero. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] + #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")] + #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] + #[doc = concat!("let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(Some(two), two.checked_next_power_of_two() ); + /// assert_eq!(Some(four), three.checked_next_power_of_two() ); + /// assert_eq!(None, max.checked_next_power_of_two() ); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_next_power_of_two(self) -> Option<$Ty> { + if let Some(nz) = self.get().checked_next_power_of_two() { + // SAFETY: The next power of two is positive + // and overflow is checked. + Some(unsafe { $Ty::new_unchecked(nz) }) + } else { + None } + } - #[stable(feature = "signed_nonzero_neg", since = "1.71.0")] - impl Neg for $Ty { - type Output = $Ty; + /// Returns the base 2 logarithm of the number, rounded down. + /// + /// This is the same operation as + #[doc = concat!("[`", stringify!($Int), "::ilog2`],")] + /// except that it has no failure cases to worry about + /// since this value can never be zero. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(7).unwrap().ilog2(), 2);")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(8).unwrap().ilog2(), 3);")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(9).unwrap().ilog2(), 3);")] + /// ``` + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn ilog2(self) -> u32 { + Self::BITS - 1 - self.leading_zeros() + } - #[inline] - fn neg(self) -> $Ty { - // SAFETY: negation of nonzero cannot yield zero values. - unsafe { $Ty::new_unchecked(self.get().neg()) } - } + /// Returns the base 10 logarithm of the number, rounded down. + /// + /// This is the same operation as + #[doc = concat!("[`", stringify!($Int), "::ilog10`],")] + /// except that it has no failure cases to worry about + /// since this value can never be zero. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(99).unwrap().ilog10(), 1);")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(100).unwrap().ilog10(), 2);")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(101).unwrap().ilog10(), 2);")] + /// ``` + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn ilog10(self) -> u32 { + super::int_log10::$Int(self.get()) + } + + /// Calculates the middle point of `self` and `rhs`. + /// + /// `midpoint(a, b)` is `(a + b) >> 1` as if it were performed in a + /// sufficiently-large signed integral type. This implies that the result is + /// always rounded towards negative infinity and that no overflow will ever occur. + /// + /// # Examples + /// + /// ``` + /// #![feature(num_midpoint)] + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] + #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] + /// + /// assert_eq!(one.midpoint(four), two); + /// assert_eq!(four.midpoint(one), two); + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "num_midpoint", issue = "110840")] + #[rustc_const_unstable(feature = "const_num_midpoint", issue = "110840")] + #[rustc_allow_const_fn_unstable(const_num_midpoint)] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn midpoint(self, rhs: Self) -> Self { + // SAFETY: The only way to get `0` with midpoint is to have two opposite or + // near opposite numbers: (-5, 5), (0, 1), (0, 0) which is impossible because + // of the unsignedness of this number and also because $Ty is guaranteed to + // never being 0. + unsafe { $Ty::new_unchecked(self.get().midpoint(rhs.get())) } + } + + /// Returns `true` if and only if `self == (1 << k)` for some `k`. + /// + /// On many architectures, this function can perform better than `is_power_of_two()` + /// on the underlying integer type, as special handling of zero can be avoided. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let eight = std::num::", stringify!($Ty), "::new(8).unwrap();")] + /// assert!(eight.is_power_of_two()); + #[doc = concat!("let ten = std::num::", stringify!($Ty), "::new(10).unwrap();")] + /// assert!(!ten.is_power_of_two()); + /// ``` + #[must_use] + #[stable(feature = "nonzero_is_power_of_two", since = "1.59.0")] + #[rustc_const_stable(feature = "nonzero_is_power_of_two", since = "1.59.0")] + #[inline] + pub const fn is_power_of_two(self) -> bool { + // LLVM 11 normalizes `unchecked_sub(x, 1) & x == 0` to the implementation seen here. + // On the basic x86-64 target, this saves 3 instructions for the zero check. + // On x86_64 with BMI1, being nonzero lets it codegen to `BLSR`, which saves an instruction + // compared to the `POPCNT` implementation on the underlying integer type. + + intrinsics::ctpop(self.get()) < 2 + } + }; + + // Associated items for signed nonzero types only. + ( + Self = $Ty:ident, + Primitive = signed $Int:ident, + UnsignedNonZero = $Uty:ident, + UnsignedPrimitive = $Uint:ty, + ) => { + /// The smallest value that can be represented by this non-zero + /// integer type, + #[doc = concat!("equal to [`", stringify!($Int), "::MIN`].")] + /// + /// Note: While most integer types are defined for every whole + /// number between `MIN` and `MAX`, signed non-zero integers are + /// a special case. They have a "gap" at 0. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::MIN.get(), ", stringify!($Int), "::MIN);")] + /// ``` + #[stable(feature = "nonzero_min_max", since = "1.70.0")] + pub const MIN: Self = Self::new(<$Int>::MIN).unwrap(); + + /// The largest value that can be represented by this non-zero + /// integer type, + #[doc = concat!("equal to [`", stringify!($Int), "::MAX`].")] + /// + /// Note: While most integer types are defined for every whole + /// number between `MIN` and `MAX`, signed non-zero integers are + /// a special case. They have a "gap" at 0. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::MAX.get(), ", stringify!($Int), "::MAX);")] + /// ``` + #[stable(feature = "nonzero_min_max", since = "1.70.0")] + pub const MAX: Self = Self::new(<$Int>::MAX).unwrap(); + + /// Computes the absolute value of self. + #[doc = concat!("See [`", stringify!($Int), "::abs`]")] + /// for documentation on overflow behaviour. + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] + /// + /// assert_eq!(pos, pos.abs()); + /// assert_eq!(pos, neg.abs()); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn abs(self) -> $Ty { + // SAFETY: This cannot overflow to zero. + unsafe { $Ty::new_unchecked(self.get().abs()) } + } + + /// Checked absolute value. + /// Checks for overflow and returns [`None`] if + #[doc = concat!("`self == ", stringify!($Ty), "::MIN`.")] + /// The result cannot be zero. + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + /// + /// assert_eq!(Some(pos), neg.checked_abs()); + /// assert_eq!(None, min.checked_abs()); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_abs(self) -> Option<$Ty> { + if let Some(nz) = self.get().checked_abs() { + // SAFETY: absolute value of nonzero cannot yield zero values. + Some(unsafe { $Ty::new_unchecked(nz) }) + } else { + None } + } - forward_ref_unop! { impl Neg, neg for $Ty, - #[stable(feature = "signed_nonzero_neg", since = "1.71.0")] } - )+ - } -} + /// Computes the absolute value of self, + /// with overflow information, see + #[doc = concat!("[`", stringify!($Int), "::overflowing_abs`].")] + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + /// + /// assert_eq!((pos, false), pos.overflowing_abs()); + /// assert_eq!((pos, false), neg.overflowing_abs()); + /// assert_eq!((min, true), min.overflowing_abs()); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn overflowing_abs(self) -> ($Ty, bool) { + let (nz, flag) = self.get().overflowing_abs(); + ( + // SAFETY: absolute value of nonzero cannot yield zero values. + unsafe { $Ty::new_unchecked(nz) }, + flag, + ) + } -nonzero_signed_operations! { - NonZeroI8(i8) -> NonZeroU8(u8); - NonZeroI16(i16) -> NonZeroU16(u16); - NonZeroI32(i32) -> NonZeroU32(u32); - NonZeroI64(i64) -> NonZeroU64(u64); - NonZeroI128(i128) -> NonZeroU128(u128); - NonZeroIsize(isize) -> NonZeroUsize(usize); -} + /// Saturating absolute value, see + #[doc = concat!("[`", stringify!($Int), "::saturating_abs`].")] + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + #[doc = concat!("let min_plus = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN + 1)?;")] + #[doc = concat!("let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(pos, pos.saturating_abs()); + /// assert_eq!(pos, neg.saturating_abs()); + /// assert_eq!(max, min.saturating_abs()); + /// assert_eq!(max, min_plus.saturating_abs()); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_abs(self) -> $Ty { + // SAFETY: absolute value of nonzero cannot yield zero values. + unsafe { $Ty::new_unchecked(self.get().saturating_abs()) } + } -// A bunch of methods for both signed and unsigned nonzero types. -macro_rules! nonzero_unsigned_signed_operations { - ( $( $signedness:ident $Ty: ident($Int: ty); )+ ) => { - $( - impl $Ty { - /// Multiplies two non-zero integers together. - /// Checks for overflow and returns [`None`] on overflow. - /// As a consequence, the result cannot wrap to zero. - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] - #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] - #[doc = concat!("let max = ", stringify!($Ty), "::new(", - stringify!($Int), "::MAX)?;")] - /// - /// assert_eq!(Some(four), two.checked_mul(two)); - /// assert_eq!(None, max.checked_mul(two)); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn checked_mul(self, other: $Ty) -> Option<$Ty> { - if let Some(result) = self.get().checked_mul(other.get()) { - // SAFETY: - // - `checked_mul` returns `None` on overflow - // - `self` and `other` are non-zero - // - the only way to get zero from a multiplication without overflow is for one - // of the sides to be zero - // - // So the result cannot be zero. - Some(unsafe { $Ty::new_unchecked(result) }) - } else { - None - } - } + /// Wrapping absolute value, see + #[doc = concat!("[`", stringify!($Int), "::wrapping_abs`].")] + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + #[doc = concat!("# let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(pos, pos.wrapping_abs()); + /// assert_eq!(pos, neg.wrapping_abs()); + /// assert_eq!(min, min.wrapping_abs()); + /// assert_eq!(max, (-max).wrapping_abs()); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn wrapping_abs(self) -> $Ty { + // SAFETY: absolute value of nonzero cannot yield zero values. + unsafe { $Ty::new_unchecked(self.get().wrapping_abs()) } + } - /// Multiplies two non-zero integers together. - #[doc = concat!("Return [`", stringify!($Ty), "::MAX`] on overflow.")] - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] - #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] - #[doc = concat!("let max = ", stringify!($Ty), "::new(", - stringify!($Int), "::MAX)?;")] - /// - /// assert_eq!(four, two.saturating_mul(two)); - /// assert_eq!(max, four.saturating_mul(max)); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn saturating_mul(self, other: $Ty) -> $Ty { - // SAFETY: - // - `saturating_mul` returns `u*::MAX`/`i*::MAX`/`i*::MIN` on overflow/underflow, - // all of which are non-zero - // - `self` and `other` are non-zero - // - the only way to get zero from a multiplication without overflow is for one - // of the sides to be zero - // - // So the result cannot be zero. - unsafe { $Ty::new_unchecked(self.get().saturating_mul(other.get())) } - } + /// Computes the absolute value of self + /// without any wrapping or panicking. + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + #[doc = concat!("# use std::num::", stringify!($Uty), ";")] + /// + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let u_pos = ", stringify!($Uty), "::new(1)?;")] + #[doc = concat!("let i_pos = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let i_neg = ", stringify!($Ty), "::new(-1)?;")] + #[doc = concat!("let i_min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + #[doc = concat!("let u_max = ", stringify!($Uty), "::new(", + stringify!($Uint), "::MAX / 2 + 1)?;")] + /// + /// assert_eq!(u_pos, i_pos.unsigned_abs()); + /// assert_eq!(u_pos, i_neg.unsigned_abs()); + /// assert_eq!(u_max, i_min.unsigned_abs()); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn unsigned_abs(self) -> $Uty { + // SAFETY: absolute value of nonzero cannot yield zero values. + unsafe { $Uty::new_unchecked(self.get().unsigned_abs()) } + } - /// Multiplies two non-zero integers together, - /// assuming overflow cannot occur. - /// Overflow is unchecked, and it is undefined behaviour to overflow - /// *even if the result would wrap to a non-zero value*. - /// The behaviour is undefined as soon as - #[doc = sign_dependent_expr!{ - $signedness ? - if signed { - concat!("`self * rhs > ", stringify!($Int), "::MAX`, ", - "or `self * rhs < ", stringify!($Int), "::MIN`.") - } - if unsigned { - concat!("`self * rhs > ", stringify!($Int), "::MAX`.") - } - }] - /// - /// # Examples - /// - /// ``` - /// #![feature(nonzero_ops)] - /// - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] - #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] - /// - /// assert_eq!(four, unsafe { two.unchecked_mul(two) }); - /// # Some(()) - /// # } - /// ``` - #[unstable(feature = "nonzero_ops", issue = "84186")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const unsafe fn unchecked_mul(self, other: $Ty) -> $Ty { - // SAFETY: The caller ensures there is no overflow. - unsafe { $Ty::new_unchecked(self.get().unchecked_mul(other.get())) } - } + /// Returns `true` if `self` is positive and `false` if the + /// number is negative. + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] + #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] + /// + /// assert!(pos_five.is_positive()); + /// assert!(!neg_five.is_positive()); + /// # Some(()) + /// # } + /// ``` + #[must_use] + #[inline] + #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] + #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] + pub const fn is_positive(self) -> bool { + self.get().is_positive() + } - /// Raises non-zero value to an integer power. - /// Checks for overflow and returns [`None`] on overflow. - /// As a consequence, the result cannot wrap to zero. - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")] - #[doc = concat!("let twenty_seven = ", stringify!($Ty), "::new(27)?;")] - #[doc = concat!("let half_max = ", stringify!($Ty), "::new(", - stringify!($Int), "::MAX / 2)?;")] - /// - /// assert_eq!(Some(twenty_seven), three.checked_pow(3)); - /// assert_eq!(None, half_max.checked_pow(3)); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn checked_pow(self, other: u32) -> Option<$Ty> { - if let Some(result) = self.get().checked_pow(other) { - // SAFETY: - // - `checked_pow` returns `None` on overflow/underflow - // - `self` is non-zero - // - the only way to get zero from an exponentiation without overflow is - // for base to be zero - // - // So the result cannot be zero. - Some(unsafe { $Ty::new_unchecked(result) }) - } else { - None - } - } + /// Returns `true` if `self` is negative and `false` if the + /// number is positive. + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] + #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] + /// + /// assert!(neg_five.is_negative()); + /// assert!(!pos_five.is_negative()); + /// # Some(()) + /// # } + /// ``` + #[must_use] + #[inline] + #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] + #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] + pub const fn is_negative(self) -> bool { + self.get().is_negative() + } - /// Raise non-zero value to an integer power. - #[doc = sign_dependent_expr!{ - $signedness ? - if signed { - concat!("Return [`", stringify!($Ty), "::MIN`] ", - "or [`", stringify!($Ty), "::MAX`] on overflow.") - } - if unsigned { - concat!("Return [`", stringify!($Ty), "::MAX`] on overflow.") - } - }] - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")] - #[doc = concat!("let twenty_seven = ", stringify!($Ty), "::new(27)?;")] - #[doc = concat!("let max = ", stringify!($Ty), "::new(", - stringify!($Int), "::MAX)?;")] - /// - /// assert_eq!(twenty_seven, three.saturating_pow(3)); - /// assert_eq!(max, max.saturating_pow(3)); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn saturating_pow(self, other: u32) -> $Ty { - // SAFETY: - // - `saturating_pow` returns `u*::MAX`/`i*::MAX`/`i*::MIN` on overflow/underflow, - // all of which are non-zero - // - `self` is non-zero - // - the only way to get zero from an exponentiation without overflow is - // for base to be zero - // - // So the result cannot be zero. - unsafe { $Ty::new_unchecked(self.get().saturating_pow(other)) } - } + /// Checked negation. Computes `-self`, + #[doc = concat!("returning `None` if `self == ", stringify!($Ty), "::MIN`.")] + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] + #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + /// + /// assert_eq!(pos_five.checked_neg(), Some(neg_five)); + /// assert_eq!(min.checked_neg(), None); + /// # Some(()) + /// # } + /// ``` + #[inline] + #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] + #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] + pub const fn checked_neg(self) -> Option<$Ty> { + if let Some(result) = self.get().checked_neg() { + // SAFETY: negation of nonzero cannot yield zero values. + return Some(unsafe { $Ty::new_unchecked(result) }); } - )+ - } + None + } + + /// Negates self, overflowing if this is equal to the minimum value. + /// + #[doc = concat!("See [`", stringify!($Int), "::overflowing_neg`]")] + /// for documentation on overflow behaviour. + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] + #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + /// + /// assert_eq!(pos_five.overflowing_neg(), (neg_five, false)); + /// assert_eq!(min.overflowing_neg(), (min, true)); + /// # Some(()) + /// # } + /// ``` + #[inline] + #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] + #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] + pub const fn overflowing_neg(self) -> ($Ty, bool) { + let (result, overflow) = self.get().overflowing_neg(); + // SAFETY: negation of nonzero cannot yield zero values. + ((unsafe { $Ty::new_unchecked(result) }), overflow) + } + + /// Saturating negation. Computes `-self`, + #[doc = concat!("returning [`", stringify!($Ty), "::MAX`]")] + #[doc = concat!("if `self == ", stringify!($Ty), "::MIN`")] + /// instead of overflowing. + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] + #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + #[doc = concat!("let min_plus_one = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN + 1)?;")] + #[doc = concat!("let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(pos_five.saturating_neg(), neg_five); + /// assert_eq!(min.saturating_neg(), max); + /// assert_eq!(max.saturating_neg(), min_plus_one); + /// # Some(()) + /// # } + /// ``` + #[inline] + #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] + #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] + pub const fn saturating_neg(self) -> $Ty { + if let Some(result) = self.checked_neg() { + return result; + } + $Ty::MAX + } + + /// Wrapping (modular) negation. Computes `-self`, wrapping around at the boundary + /// of the type. + /// + #[doc = concat!("See [`", stringify!($Int), "::wrapping_neg`]")] + /// for documentation on overflow behaviour. + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] + #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + /// + /// assert_eq!(pos_five.wrapping_neg(), neg_five); + /// assert_eq!(min.wrapping_neg(), min); + /// # Some(()) + /// # } + /// ``` + #[inline] + #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] + #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] + pub const fn wrapping_neg(self) -> $Ty { + let result = self.get().wrapping_neg(); + // SAFETY: negation of nonzero cannot yield zero values. + unsafe { $Ty::new_unchecked(result) } + } + }; } // Use this when the generated code should differ between signed and unsigned types. @@ -1212,187 +1367,74 @@ macro_rules! sign_dependent_expr { }; } -nonzero_unsigned_signed_operations! { - unsigned NonZeroU8(u8); - unsigned NonZeroU16(u16); - unsigned NonZeroU32(u32); - unsigned NonZeroU64(u64); - unsigned NonZeroU128(u128); - unsigned NonZeroUsize(usize); - signed NonZeroI8(i8); - signed NonZeroI16(i16); - signed NonZeroI32(i32); - signed NonZeroI64(i64); - signed NonZeroI128(i128); - signed NonZeroIsize(isize); +nonzero_integer! { + Self = NonZeroU8, + Primitive = unsigned u8, } -macro_rules! nonzero_unsigned_is_power_of_two { - ( $( $Ty: ident )+ ) => { - $( - impl $Ty { - - /// Returns `true` if and only if `self == (1 << k)` for some `k`. - /// - /// On many architectures, this function can perform better than `is_power_of_two()` - /// on the underlying integer type, as special handling of zero can be avoided. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - #[doc = concat!("let eight = std::num::", stringify!($Ty), "::new(8).unwrap();")] - /// assert!(eight.is_power_of_two()); - #[doc = concat!("let ten = std::num::", stringify!($Ty), "::new(10).unwrap();")] - /// assert!(!ten.is_power_of_two()); - /// ``` - #[must_use] - #[stable(feature = "nonzero_is_power_of_two", since = "1.59.0")] - #[rustc_const_stable(feature = "nonzero_is_power_of_two", since = "1.59.0")] - #[inline] - pub const fn is_power_of_two(self) -> bool { - // LLVM 11 normalizes `unchecked_sub(x, 1) & x == 0` to the implementation seen here. - // On the basic x86-64 target, this saves 3 instructions for the zero check. - // On x86_64 with BMI1, being nonzero lets it codegen to `BLSR`, which saves an instruction - // compared to the `POPCNT` implementation on the underlying integer type. - - intrinsics::ctpop(self.get()) < 2 - } - - } - )+ - } +nonzero_integer! { + Self = NonZeroU16, + Primitive = unsigned u16, } -nonzero_unsigned_is_power_of_two! { NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 NonZeroU128 NonZeroUsize } - -macro_rules! nonzero_min_max_unsigned { - ( $( $Ty: ident($Int: ident); )+ ) => { - $( - impl $Ty { - /// The smallest value that can be represented by this non-zero - /// integer type, 1. - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - #[doc = concat!("assert_eq!(", stringify!($Ty), "::MIN.get(), 1", stringify!($Int), ");")] - /// ``` - #[stable(feature = "nonzero_min_max", since = "1.70.0")] - pub const MIN: Self = Self::new(1).unwrap(); - - /// The largest value that can be represented by this non-zero - /// integer type, - #[doc = concat!("equal to [`", stringify!($Int), "::MAX`].")] - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - #[doc = concat!("assert_eq!(", stringify!($Ty), "::MAX.get(), ", stringify!($Int), "::MAX);")] - /// ``` - #[stable(feature = "nonzero_min_max", since = "1.70.0")] - pub const MAX: Self = Self::new(<$Int>::MAX).unwrap(); - } - )+ - } +nonzero_integer! { + Self = NonZeroU32, + Primitive = unsigned u32, } -macro_rules! nonzero_min_max_signed { - ( $( $Ty: ident($Int: ident); )+ ) => { - $( - impl $Ty { - /// The smallest value that can be represented by this non-zero - /// integer type, - #[doc = concat!("equal to [`", stringify!($Int), "::MIN`].")] - /// - /// Note: While most integer types are defined for every whole - /// number between `MIN` and `MAX`, signed non-zero integers are - /// a special case. They have a "gap" at 0. - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - #[doc = concat!("assert_eq!(", stringify!($Ty), "::MIN.get(), ", stringify!($Int), "::MIN);")] - /// ``` - #[stable(feature = "nonzero_min_max", since = "1.70.0")] - pub const MIN: Self = Self::new(<$Int>::MIN).unwrap(); - - /// The largest value that can be represented by this non-zero - /// integer type, - #[doc = concat!("equal to [`", stringify!($Int), "::MAX`].")] - /// - /// Note: While most integer types are defined for every whole - /// number between `MIN` and `MAX`, signed non-zero integers are - /// a special case. They have a "gap" at 0. - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - #[doc = concat!("assert_eq!(", stringify!($Ty), "::MAX.get(), ", stringify!($Int), "::MAX);")] - /// ``` - #[stable(feature = "nonzero_min_max", since = "1.70.0")] - pub const MAX: Self = Self::new(<$Int>::MAX).unwrap(); - } - )+ - } +nonzero_integer! { + Self = NonZeroU64, + Primitive = unsigned u64, } -nonzero_min_max_unsigned! { - NonZeroU8(u8); - NonZeroU16(u16); - NonZeroU32(u32); - NonZeroU64(u64); - NonZeroU128(u128); - NonZeroUsize(usize); +nonzero_integer! { + Self = NonZeroU128, + Primitive = unsigned u128, } -nonzero_min_max_signed! { - NonZeroI8(i8); - NonZeroI16(i16); - NonZeroI32(i32); - NonZeroI64(i64); - NonZeroI128(i128); - NonZeroIsize(isize); +nonzero_integer! { + Self = NonZeroUsize, + Primitive = unsigned usize, } -macro_rules! nonzero_bits { - ( $( $Ty: ident($Int: ty); )+ ) => { - $( - impl $Ty { - /// The size of this non-zero integer type in bits. - /// - #[doc = concat!("This value is equal to [`", stringify!($Int), "::BITS`].")] - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// - #[doc = concat!("assert_eq!(", stringify!($Ty), "::BITS, ", stringify!($Int), "::BITS);")] - /// ``` - #[stable(feature = "nonzero_bits", since = "1.67.0")] - pub const BITS: u32 = <$Int>::BITS; - } - )+ - } +nonzero_integer! { + Self = NonZeroI8, + Primitive = signed i8, + UnsignedNonZero = NonZeroU8, + UnsignedPrimitive = u8, } -nonzero_bits! { - NonZeroU8(u8); - NonZeroI8(i8); - NonZeroU16(u16); - NonZeroI16(i16); - NonZeroU32(u32); - NonZeroI32(i32); - NonZeroU64(u64); - NonZeroI64(i64); - NonZeroU128(u128); - NonZeroI128(i128); - NonZeroUsize(usize); - NonZeroIsize(isize); +nonzero_integer! { + Self = NonZeroI16, + Primitive = signed i16, + UnsignedNonZero = NonZeroU16, + UnsignedPrimitive = u16, +} + +nonzero_integer! { + Self = NonZeroI32, + Primitive = signed i32, + UnsignedNonZero = NonZeroU32, + UnsignedPrimitive = u32, +} + +nonzero_integer! { + Self = NonZeroI64, + Primitive = signed i64, + UnsignedNonZero = NonZeroU64, + UnsignedPrimitive = u64, +} + +nonzero_integer! { + Self = NonZeroI128, + Primitive = signed i128, + UnsignedNonZero = NonZeroU128, + UnsignedPrimitive = u128, +} + +nonzero_integer! { + Self = NonZeroIsize, + Primitive = signed isize, + UnsignedNonZero = NonZeroUsize, + UnsignedPrimitive = usize, } diff --git a/library/core/src/num/overflow_panic.rs b/library/core/src/num/overflow_panic.rs new file mode 100644 index 000000000000..203037ffb43e --- /dev/null +++ b/library/core/src/num/overflow_panic.rs @@ -0,0 +1,51 @@ +//! Functions for panicking on overflow. +//! +//! In particular, these are used by the `strict_` methods on integers. + +#[cold] +#[track_caller] +pub const fn add() -> ! { + panic!("attempt to add with overflow") +} + +#[cold] +#[track_caller] +pub const fn sub() -> ! { + panic!("attempt to subtract with overflow") +} + +#[cold] +#[track_caller] +pub const fn mul() -> ! { + panic!("attempt to multiply with overflow") +} + +#[cold] +#[track_caller] +pub const fn div() -> ! { + panic!("attempt to divide with overflow") +} + +#[cold] +#[track_caller] +pub const fn rem() -> ! { + panic!("attempt to calculate the remainder with overflow") +} + +#[cold] +#[track_caller] +pub const fn neg() -> ! { + panic!("attempt to negate with overflow") +} + +#[cold] +#[track_caller] +pub const fn shr() -> ! { + panic!("attempt to shift right with overflow") +} + +#[cold] +#[track_caller] +pub const fn shl() -> ! { + panic!("attempt to shift left with overflow") +} diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 11a53aaf122e..e70d043cb2c1 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -3,7 +3,7 @@ macro_rules! uint_impl { Self = $SelfT:ty, ActualT = $ActualT:ident, SignedT = $SignedT:ident, - NonZeroT = $NonZeroT:ident, + NonZeroT = $NonZeroT:ty, // There are all for use *only* in doc comments. // As such, they're all passed as literals -- passing them as a string @@ -459,9 +459,42 @@ macro_rules! uint_impl { #[inline] pub const fn checked_add(self, rhs: Self) -> Option { let (a, b) = self.overflowing_add(rhs); - if unlikely!(b) {None} else {Some(a)} + if unlikely!(b) { None } else { Some(a) } } + /// Strict integer addition. Computes `self + rhs`, panicking + /// if overflow occurred. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).strict_add(1), ", stringify!($SelfT), "::MAX - 1);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = (", stringify!($SelfT), "::MAX - 2).strict_add(3);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_add(self, rhs: Self) -> Self { + let (a, b) = self.overflowing_add(rhs); + if unlikely!(b) { overflow_panic ::add()} else {a} + } + /// Unchecked integer addition. Computes `self + rhs`, assuming overflow /// cannot occur. /// @@ -507,9 +540,47 @@ macro_rules! uint_impl { #[inline] pub const fn checked_add_signed(self, rhs: $SignedT) -> Option { let (a, b) = self.overflowing_add_signed(rhs); - if unlikely!(b) {None} else {Some(a)} + if unlikely!(b) { None } else { Some(a) } } + /// Strict addition with a signed integer. Computes `self + rhs`, + /// panicking if overflow occurred. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".strict_add_signed(2), 3);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = 1", stringify!($SelfT), ".strict_add_signed(-2);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = (", stringify!($SelfT), "::MAX - 2).strict_add_signed(3);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_add_signed(self, rhs: $SignedT) -> Self { + let (a, b) = self.overflowing_add_signed(rhs); + if unlikely!(b) { overflow_panic ::add()} else {a} + } + /// Checked integer subtraction. Computes `self - rhs`, returning /// `None` if overflow occurred. /// @@ -528,9 +599,42 @@ macro_rules! uint_impl { #[inline] pub const fn checked_sub(self, rhs: Self) -> Option { let (a, b) = self.overflowing_sub(rhs); - if unlikely!(b) {None} else {Some(a)} + if unlikely!(b) { None } else { Some(a) } } + /// Strict integer subtraction. Computes `self - rhs`, panicking if + /// overflow occurred. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".strict_sub(1), 0);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = 0", stringify!($SelfT), ".strict_sub(1);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_sub(self, rhs: Self) -> Self { + let (a, b) = self.overflowing_sub(rhs); + if unlikely!(b) { overflow_panic ::sub()} else {a} + } + /// Unchecked integer subtraction. Computes `self - rhs`, assuming overflow /// cannot occur. /// @@ -575,9 +679,42 @@ macro_rules! uint_impl { #[inline] pub const fn checked_mul(self, rhs: Self) -> Option { let (a, b) = self.overflowing_mul(rhs); - if unlikely!(b) {None} else {Some(a)} + if unlikely!(b) { None } else { Some(a) } } + /// Strict integer multiplication. Computes `self * rhs`, panicking if + /// overflow occurred. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".strict_mul(1), 5);")] + /// ``` + /// + /// ``` should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_mul(2);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_mul(self, rhs: Self) -> Self { + let (a, b) = self.overflowing_mul(rhs); + if unlikely!(b) { overflow_panic ::mul()} else {a} + } + /// Unchecked integer multiplication. Computes `self * rhs`, assuming overflow /// cannot occur. /// @@ -630,6 +767,34 @@ macro_rules! uint_impl { } } + /// Strict integer division. Computes `self / rhs`. + /// Strict division on unsigned types is just normal division. + /// There's no way overflow could ever happen. + /// This function exists, so that all operations + /// are accounted for in the strict operations. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".strict_div(10), 10);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + #[track_caller] + pub const fn strict_div(self, rhs: Self) -> Self { + self / rhs + } + /// Checked Euclidean division. Computes `self.div_euclid(rhs)`, returning `None` /// if `rhs == 0`. /// @@ -654,6 +819,36 @@ macro_rules! uint_impl { } } + /// Strict Euclidean division. Computes `self.div_euclid(rhs)`. + /// Strict division on unsigned types is just normal division. + /// There's no way overflow could ever happen. + /// This function exists, so that all operations + /// are accounted for in the strict operations. + /// Since, for the positive integers, all common + /// definitions of division are equal, this + /// is exactly equal to `self.strict_div(rhs)`. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".strict_div_euclid(10), 10);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + #[track_caller] + pub const fn strict_div_euclid(self, rhs: Self) -> Self { + self / rhs + } /// Checked integer remainder. Computes `self % rhs`, returning `None` /// if `rhs == 0`. @@ -681,6 +876,35 @@ macro_rules! uint_impl { } } + /// Strict integer remainder. Computes `self % rhs`. + /// Strict remainder calculation on unsigned types is + /// just the regular remainder calculation. + /// There's no way overflow could ever happen. + /// This function exists, so that all operations + /// are accounted for in the strict operations. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".strict_rem(10), 0);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + #[track_caller] + pub const fn strict_rem(self, rhs: Self) -> Self { + self % rhs + } + /// Checked Euclidean modulo. Computes `self.rem_euclid(rhs)`, returning `None` /// if `rhs == 0`. /// @@ -705,6 +929,38 @@ macro_rules! uint_impl { } } + /// Strict Euclidean modulo. Computes `self.rem_euclid(rhs)`. + /// Strict modulo calculation on unsigned types is + /// just the regular remainder calculation. + /// There's no way overflow could ever happen. + /// This function exists, so that all operations + /// are accounted for in the strict operations. + /// Since, for the positive integers, all common + /// definitions of division are equal, this + /// is exactly equal to `self.strict_rem(rhs)`. + /// + /// # Panics + /// + /// This function will panic if `rhs` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".strict_rem_euclid(10), 0);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + #[track_caller] + pub const fn strict_rem_euclid(self, rhs: Self) -> Self { + self % rhs + } + /// Returns the logarithm of the number with respect to an arbitrary base, /// rounded down. /// @@ -842,6 +1098,7 @@ macro_rules! uint_impl { without modifying the original"] #[inline] pub const fn checked_ilog2(self) -> Option { + // FIXME: Simply use `NonZero::new` once it is actually generic. if let Some(x) = <$NonZeroT>::new(self) { Some(x.ilog2()) } else { @@ -864,6 +1121,7 @@ macro_rules! uint_impl { without modifying the original"] #[inline] pub const fn checked_ilog10(self) -> Option { + // FIXME: Simply use `NonZero::new` once it is actually generic. if let Some(x) = <$NonZeroT>::new(self) { Some(x.ilog10()) } else { @@ -891,7 +1149,42 @@ macro_rules! uint_impl { #[inline] pub const fn checked_neg(self) -> Option { let (a, b) = self.overflowing_neg(); - if unlikely!(b) {None} else {Some(a)} + if unlikely!(b) { None } else { Some(a) } + } + + /// Strict negation. Computes `-self`, panicking unless `self == + /// 0`. + /// + /// Note that negating any positive integer will overflow. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".strict_neg(), 0);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = 1", stringify!($SelfT), ".strict_neg();")] + /// + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_neg(self) -> Self { + let (a, b) = self.overflowing_neg(); + if unlikely!(b) { overflow_panic::neg() } else { a } } /// Checked shift left. Computes `self << rhs`, returning `None` @@ -912,7 +1205,40 @@ macro_rules! uint_impl { #[inline] pub const fn checked_shl(self, rhs: u32) -> Option { let (a, b) = self.overflowing_shl(rhs); - if unlikely!(b) {None} else {Some(a)} + if unlikely!(b) { None } else { Some(a) } + } + + /// Strict shift left. Computes `self << rhs`, panicking if `rhs` is larger + /// than or equal to the number of bits in `self`. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".strict_shl(4), 0x10);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = 0x10", stringify!($SelfT), ".strict_shl(129);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_shl(self, rhs: u32) -> Self { + let (a, b) = self.overflowing_shl(rhs); + if unlikely!(b) { overflow_panic::shl() } else { a } } /// Unchecked shift left. Computes `self << rhs`, assuming that @@ -960,7 +1286,40 @@ macro_rules! uint_impl { #[inline] pub const fn checked_shr(self, rhs: u32) -> Option { let (a, b) = self.overflowing_shr(rhs); - if unlikely!(b) {None} else {Some(a)} + if unlikely!(b) { None } else { Some(a) } + } + + /// Strict shift right. Computes `self >> rhs`, panicking `rhs` is + /// larger than or equal to the number of bits in `self`. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".strict_shr(4), 0x1);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = 0x10", stringify!($SelfT), ".strict_shr(129);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_shr(self, rhs: u32) -> Self { + let (a, b) = self.overflowing_shr(rhs); + if unlikely!(b) { overflow_panic::shr() } else { a } } /// Unchecked shift right. Computes `self >> rhs`, assuming that @@ -1029,6 +1388,55 @@ macro_rules! uint_impl { acc.checked_mul(base) } + /// Strict exponentiation. Computes `self.pow(exp)`, panicking if + /// overflow occurred. + /// + /// # Panics + /// + /// ## Overflow behavior + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(strict_overflow_ops)] + #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".strict_pow(5), 32);")] + /// ``` + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_pow(2);")] + /// ``` + #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + pub const fn strict_pow(self, mut exp: u32) -> Self { + if exp == 0 { + return 1; + } + let mut base = self; + let mut acc: Self = 1; + + while exp > 1 { + if (exp & 1) == 1 { + acc = acc.strict_mul(base); + } + exp /= 2; + base = base.strict_mul(base); + } + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + acc.strict_mul(base) + } + /// Saturating integer addition. Computes `self + rhs`, saturating at /// the numeric bounds instead of overflowing. /// diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs index b419a738fbe3..e809273c9ed9 100644 --- a/library/core/src/ops/range.rs +++ b/library/core/src/ops/range.rs @@ -710,7 +710,6 @@ impl Bound { /// # Examples /// /// ``` - /// #![feature(bound_map)] /// use std::ops::Bound::*; /// /// let bound_string = Included("Hello, World!"); @@ -719,7 +718,6 @@ impl Bound { /// ``` /// /// ``` - /// #![feature(bound_map)] /// use std::ops::Bound; /// use Bound::*; /// @@ -728,7 +726,7 @@ impl Bound { /// assert_eq!(unbounded_string.map(|s| s.len()), Unbounded); /// ``` #[inline] - #[unstable(feature = "bound_map", issue = "86026")] + #[stable(feature = "bound_map", since = "CURRENT_RUSTC_VERSION")] pub fn map U>(self, f: F) -> Bound { match self { Unbounded => Unbounded, diff --git a/library/core/src/option.rs b/library/core/src/option.rs index ff4353492498..ce29352ba195 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -921,14 +921,14 @@ impl Option { /// let x: Option<&str> = None; /// assert_eq!(x.unwrap(), "air"); // fails /// ``` - #[inline] + #[inline(always)] #[track_caller] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option", issue = "67441")] pub const fn unwrap(self) -> T { match self { Some(val) => val, - None => panic("called `Option::unwrap()` on a `None` value"), + None => unwrap_failed(), } } @@ -1970,6 +1970,14 @@ impl Option> { } } +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[cold] +#[track_caller] +const fn unwrap_failed() -> ! { + panic("called `Option::unwrap()` on a `None` value") +} + // This is a separate function to reduce the code size of .expect() itself. #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] #[cfg_attr(feature = "panic_immediate_abort", inline)] @@ -2147,6 +2155,7 @@ impl PartialEq for Option { /// /// Once that's fixed, `Option` should go back to deriving `PartialEq`, as /// it used to do before . +/// The comment regarding this trait on the `newtype_index` macro should be removed if this is done. #[unstable(feature = "spec_option_partial_eq", issue = "none", reason = "exposed only for rustc")] #[doc(hidden)] pub trait SpecOptionPartialEq: Sized { diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 267d9b44ad76..7dee30585e9c 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -1634,9 +1634,8 @@ mod prim_ref {} /// function pointers of varying length. Note that this is a convenience notation to avoid /// repetitive documentation, not valid Rust syntax. /// -/// Due to a temporary restriction in Rust's type system, these traits are only implemented on -/// functions that take 12 arguments or less, with the `"Rust"` and `"C"` ABIs. In the future, this -/// may change: +/// The following traits are implemented for function pointers with any number of arguments and +/// any ABI. /// /// * [`PartialEq`] /// * [`Eq`] @@ -1645,11 +1644,6 @@ mod prim_ref {} /// * [`Hash`] /// * [`Pointer`] /// * [`Debug`] -/// -/// The following traits are implemented for function pointers with any number of arguments and -/// any ABI. These traits have implementations that are automatically generated by the compiler, -/// so are not limited by missing language features: -/// /// * [`Clone`] /// * [`Copy`] /// * [`Send`] diff --git a/library/core/src/result.rs b/library/core/src/result.rs index eff1b9b59b14..1f448984e531 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1061,7 +1061,7 @@ impl Result { /// let x: Result = Err("emergency failure"); /// x.unwrap(); // panics with `emergency failure` /// ``` - #[inline] + #[inline(always)] #[track_caller] #[stable(feature = "rust1", since = "1.0.0")] pub fn unwrap(self) -> T diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index ce04a9f40898..5c4f0bf9b2b4 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -5,6 +5,7 @@ use crate::fmt::{self, Write}; use crate::iter; use crate::mem; use crate::ops; +use core::ascii::EscapeDefault; #[cfg(not(test))] impl [u8] { @@ -253,7 +254,45 @@ impl<'a> iter::FusedIterator for EscapeAscii<'a> {} #[stable(feature = "inherent_ascii_escape", since = "1.60.0")] impl<'a> fmt::Display for EscapeAscii<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.clone().try_for_each(|b| f.write_char(b as char)) + // disassemble iterator, including front/back parts of flatmap in case it has been partially consumed + let (front, slice, back) = self.clone().inner.into_parts(); + let front = front.unwrap_or(EscapeDefault::empty()); + let mut bytes = slice.unwrap_or_default().as_slice(); + let back = back.unwrap_or(EscapeDefault::empty()); + + // usually empty, so the formatter won't have to do any work + for byte in front { + f.write_char(byte as char)?; + } + + fn needs_escape(b: u8) -> bool { + b > 0x7E || b < 0x20 || b == b'\\' || b == b'\'' || b == b'"' + } + + while bytes.len() > 0 { + // fast path for the printable, non-escaped subset of ascii + let prefix = bytes.iter().take_while(|&&b| !needs_escape(b)).count(); + // SAFETY: prefix length was derived by counting bytes in the same splice, so it's in-bounds + let (prefix, remainder) = unsafe { bytes.split_at_unchecked(prefix) }; + // SAFETY: prefix is a valid utf8 sequence, as it's a subset of ASCII + let prefix = unsafe { crate::str::from_utf8_unchecked(prefix) }; + + f.write_str(prefix)?; // the fast part + + bytes = remainder; + + if let Some(&b) = bytes.first() { + // guaranteed to be non-empty, better to write it as a str + f.write_str(ascii::escape_default(b).as_str())?; + bytes = &bytes[1..]; + } + } + + // also usually empty + for byte in back { + f.write_char(byte as char)?; + } + Ok(()) } } #[stable(feature = "inherent_ascii_escape", since = "1.60.0")] diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index 3d58afd26eac..cd9e18d1a2de 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -4,7 +4,6 @@ mod macros; use crate::cmp; -use crate::cmp::Ordering; use crate::fmt; use crate::intrinsics::assume; use crate::iter::{ @@ -12,7 +11,7 @@ use crate::iter::{ }; use crate::marker::PhantomData; use crate::mem::{self, SizedTypeProperties}; -use crate::num::NonZeroUsize; +use crate::num::{NonZero, NonZeroUsize}; use crate::ptr::{self, invalid, invalid_mut, NonNull}; use super::{from_raw_parts, from_raw_parts_mut}; @@ -133,7 +132,7 @@ iterator! {struct Iter -> *const T, &'a T, const, {/* no mut */}, as_ref, { fn is_sorted_by(self, mut compare: F) -> bool where Self: Sized, - F: FnMut(&Self::Item, &Self::Item) -> Option, + F: FnMut(&Self::Item, &Self::Item) -> bool, { self.as_slice().is_sorted_by(|a, b| compare(&a, &b)) } @@ -1305,12 +1304,12 @@ forward_iterator! { RSplitNMut: T, &'a mut [T] } #[must_use = "iterators are lazy and do nothing unless consumed"] pub struct Windows<'a, T: 'a> { v: &'a [T], - size: NonZeroUsize, + size: NonZero, } impl<'a, T: 'a> Windows<'a, T> { #[inline] - pub(super) fn new(slice: &'a [T], size: NonZeroUsize) -> Self { + pub(super) fn new(slice: &'a [T], size: NonZero) -> Self { Self { v: slice, size } } } diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 5edc89e4cb53..c191877c434f 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -296,7 +296,7 @@ impl [T] { if let [.., last] = self { Some(last) } else { None } } - /// Returns a mutable pointer to the last item in the slice. + /// Returns a mutable reference to the last item in the slice. /// /// # Examples /// @@ -316,13 +316,13 @@ impl [T] { if let [.., last] = self { Some(last) } else { None } } - /// Returns the first `N` elements of the slice, or `None` if it has fewer than `N` elements. + /// Return an array reference to the first `N` items in the slice. + /// + /// If the slice is not at least `N` in length, this will return `None`. /// /// # Examples /// /// ``` - /// #![feature(slice_first_last_chunk)] - /// /// let u = [10, 40, 30]; /// assert_eq!(Some(&[10, 40]), u.first_chunk::<2>()); /// @@ -332,27 +332,26 @@ impl [T] { /// let w: &[i32] = &[]; /// assert_eq!(Some(&[]), w.first_chunk::<0>()); /// ``` - #[unstable(feature = "slice_first_last_chunk", issue = "111774")] - #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")] #[inline] + #[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] pub const fn first_chunk(&self) -> Option<&[T; N]> { if self.len() < N { None } else { // SAFETY: We explicitly check for the correct number of elements, // and do not let the reference outlive the slice. - Some(unsafe { &*(self.as_ptr() as *const [T; N]) }) + Some(unsafe { &*(self.as_ptr().cast::<[T; N]>()) }) } } - /// Returns a mutable reference to the first `N` elements of the slice, - /// or `None` if it has fewer than `N` elements. + /// Return a mutable array reference to the first `N` items in the slice. + /// + /// If the slice is not at least `N` in length, this will return `None`. /// /// # Examples /// /// ``` - /// #![feature(slice_first_last_chunk)] - /// /// let x = &mut [0, 1, 2]; /// /// if let Some(first) = x.first_chunk_mut::<2>() { @@ -360,10 +359,12 @@ impl [T] { /// first[1] = 4; /// } /// assert_eq!(x, &[5, 4, 2]); + /// + /// assert_eq!(None, x.first_chunk_mut::<4>()); /// ``` - #[unstable(feature = "slice_first_last_chunk", issue = "111774")] - #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")] #[inline] + #[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_unstable(feature = "const_slice_first_last_chunk", issue = "111774")] pub const fn first_chunk_mut(&mut self) -> Option<&mut [T; N]> { if self.len() < N { None @@ -371,28 +372,29 @@ impl [T] { // SAFETY: We explicitly check for the correct number of elements, // do not let the reference outlive the slice, // and require exclusive access to the entire slice to mutate the chunk. - Some(unsafe { &mut *(self.as_mut_ptr() as *mut [T; N]) }) + Some(unsafe { &mut *(self.as_mut_ptr().cast::<[T; N]>()) }) } } - /// Returns the first `N` elements of the slice and the remainder, - /// or `None` if it has fewer than `N` elements. + /// Return an array reference to the first `N` items in the slice and the remaining slice. + /// + /// If the slice is not at least `N` in length, this will return `None`. /// /// # Examples /// /// ``` - /// #![feature(slice_first_last_chunk)] - /// /// let x = &[0, 1, 2]; /// /// if let Some((first, elements)) = x.split_first_chunk::<2>() { /// assert_eq!(first, &[0, 1]); /// assert_eq!(elements, &[2]); /// } + /// + /// assert_eq!(None, x.split_first_chunk::<4>()); /// ``` - #[unstable(feature = "slice_first_last_chunk", issue = "111774")] - #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")] #[inline] + #[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] pub const fn split_first_chunk(&self) -> Option<(&[T; N], &[T])> { if self.len() < N { None @@ -402,18 +404,18 @@ impl [T] { // SAFETY: We explicitly check for the correct number of elements, // and do not let the references outlive the slice. - Some((unsafe { &*(first.as_ptr() as *const [T; N]) }, tail)) + Some((unsafe { &*(first.as_ptr().cast::<[T; N]>()) }, tail)) } } - /// Returns a mutable reference to the first `N` elements of the slice and the remainder, - /// or `None` if it has fewer than `N` elements. + /// Return a mutable array reference to the first `N` items in the slice and the remaining + /// slice. + /// + /// If the slice is not at least `N` in length, this will return `None`. /// /// # Examples /// /// ``` - /// #![feature(slice_first_last_chunk)] - /// /// let x = &mut [0, 1, 2]; /// /// if let Some((first, elements)) = x.split_first_chunk_mut::<2>() { @@ -422,10 +424,12 @@ impl [T] { /// elements[0] = 5; /// } /// assert_eq!(x, &[3, 4, 5]); + /// + /// assert_eq!(None, x.split_first_chunk_mut::<4>()); /// ``` - #[unstable(feature = "slice_first_last_chunk", issue = "111774")] - #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")] #[inline] + #[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_unstable(feature = "const_slice_first_last_chunk", issue = "111774")] pub const fn split_first_chunk_mut( &mut self, ) -> Option<(&mut [T; N], &mut [T])> { @@ -438,29 +442,30 @@ impl [T] { // SAFETY: We explicitly check for the correct number of elements, // do not let the reference outlive the slice, // and enforce exclusive mutability of the chunk by the split. - Some((unsafe { &mut *(first.as_mut_ptr() as *mut [T; N]) }, tail)) + Some((unsafe { &mut *(first.as_mut_ptr().cast::<[T; N]>()) }, tail)) } } - /// Returns the last `N` elements of the slice and the remainder, - /// or `None` if it has fewer than `N` elements. + /// Return an array reference to the last `N` items in the slice and the remaining slice. + /// + /// If the slice is not at least `N` in length, this will return `None`. /// /// # Examples /// /// ``` - /// #![feature(slice_first_last_chunk)] - /// /// let x = &[0, 1, 2]; /// - /// if let Some((last, elements)) = x.split_last_chunk::<2>() { - /// assert_eq!(last, &[1, 2]); + /// if let Some((elements, last)) = x.split_last_chunk::<2>() { /// assert_eq!(elements, &[0]); + /// assert_eq!(last, &[1, 2]); /// } + /// + /// assert_eq!(None, x.split_last_chunk::<4>()); /// ``` - #[unstable(feature = "slice_first_last_chunk", issue = "111774")] - #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")] #[inline] - pub const fn split_last_chunk(&self) -> Option<(&[T; N], &[T])> { + #[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + pub const fn split_last_chunk(&self) -> Option<(&[T], &[T; N])> { if self.len() < N { None } else { @@ -469,32 +474,35 @@ impl [T] { // SAFETY: We explicitly check for the correct number of elements, // and do not let the references outlive the slice. - Some((unsafe { &*(last.as_ptr() as *const [T; N]) }, init)) + Some((init, unsafe { &*(last.as_ptr().cast::<[T; N]>()) })) } } - /// Returns the last and all the rest of the elements of the slice, or `None` if it is empty. + /// Return a mutable array reference to the last `N` items in the slice and the remaining + /// slice. + /// + /// If the slice is not at least `N` in length, this will return `None`. /// /// # Examples /// /// ``` - /// #![feature(slice_first_last_chunk)] - /// /// let x = &mut [0, 1, 2]; /// - /// if let Some((last, elements)) = x.split_last_chunk_mut::<2>() { + /// if let Some((elements, last)) = x.split_last_chunk_mut::<2>() { /// last[0] = 3; /// last[1] = 4; /// elements[0] = 5; /// } /// assert_eq!(x, &[5, 3, 4]); + /// + /// assert_eq!(None, x.split_last_chunk_mut::<4>()); /// ``` - #[unstable(feature = "slice_first_last_chunk", issue = "111774")] - #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")] #[inline] + #[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_unstable(feature = "const_slice_first_last_chunk", issue = "111774")] pub const fn split_last_chunk_mut( &mut self, - ) -> Option<(&mut [T; N], &mut [T])> { + ) -> Option<(&mut [T], &mut [T; N])> { if self.len() < N { None } else { @@ -504,17 +512,17 @@ impl [T] { // SAFETY: We explicitly check for the correct number of elements, // do not let the reference outlive the slice, // and enforce exclusive mutability of the chunk by the split. - Some((unsafe { &mut *(last.as_mut_ptr() as *mut [T; N]) }, init)) + Some((init, unsafe { &mut *(last.as_mut_ptr().cast::<[T; N]>()) })) } } - /// Returns the last element of the slice, or `None` if it is empty. + /// Return an array reference to the last `N` items in the slice. + /// + /// If the slice is not at least `N` in length, this will return `None`. /// /// # Examples /// /// ``` - /// #![feature(slice_first_last_chunk)] - /// /// let u = [10, 40, 30]; /// assert_eq!(Some(&[40, 30]), u.last_chunk::<2>()); /// @@ -524,9 +532,9 @@ impl [T] { /// let w: &[i32] = &[]; /// assert_eq!(Some(&[]), w.last_chunk::<0>()); /// ``` - #[unstable(feature = "slice_first_last_chunk", issue = "111774")] - #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")] #[inline] + #[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_unstable(feature = "const_slice_first_last_chunk", issue = "111774")] pub const fn last_chunk(&self) -> Option<&[T; N]> { if self.len() < N { None @@ -537,17 +545,17 @@ impl [T] { // SAFETY: We explicitly check for the correct number of elements, // and do not let the references outlive the slice. - Some(unsafe { &*(last.as_ptr() as *const [T; N]) }) + Some(unsafe { &*(last.as_ptr().cast::<[T; N]>()) }) } } - /// Returns a mutable pointer to the last item in the slice. + /// Return a mutable array reference to the last `N` items in the slice. + /// + /// If the slice is not at least `N` in length, this will return `None`. /// /// # Examples /// /// ``` - /// #![feature(slice_first_last_chunk)] - /// /// let x = &mut [0, 1, 2]; /// /// if let Some(last) = x.last_chunk_mut::<2>() { @@ -555,10 +563,12 @@ impl [T] { /// last[1] = 20; /// } /// assert_eq!(x, &[0, 10, 20]); + /// + /// assert_eq!(None, x.last_chunk_mut::<4>()); /// ``` - #[unstable(feature = "slice_first_last_chunk", issue = "111774")] - #[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")] #[inline] + #[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_unstable(feature = "const_slice_first_last_chunk", issue = "111774")] pub const fn last_chunk_mut(&mut self) -> Option<&mut [T; N]> { if self.len() < N { None @@ -570,7 +580,7 @@ impl [T] { // SAFETY: We explicitly check for the correct number of elements, // do not let the reference outlive the slice, // and require exclusive access to the entire slice to mutate the chunk. - Some(unsafe { &mut *(last.as_mut_ptr() as *mut [T; N]) }) + Some(unsafe { &mut *(last.as_mut_ptr().cast::<[T; N]>()) }) } } @@ -1859,7 +1869,6 @@ impl [T] { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_slice_split_at_not_mut", since = "1.71.0")] - #[rustc_allow_const_fn_unstable(slice_split_at_unchecked)] #[inline] #[track_caller] #[must_use] @@ -1946,7 +1955,10 @@ impl [T] { /// } /// ``` #[unstable(feature = "slice_split_at_unchecked", reason = "new API", issue = "76014")] - #[rustc_const_unstable(feature = "slice_split_at_unchecked", issue = "76014")] + #[rustc_const_stable( + feature = "const_slice_split_at_unchecked", + since = "CURRENT_RUSTC_VERSION" + )] #[inline] #[must_use] pub const unsafe fn split_at_unchecked(&self, mid: usize) -> (&[T], &[T]) { @@ -2019,164 +2031,6 @@ impl [T] { unsafe { (from_raw_parts_mut(ptr, mid), from_raw_parts_mut(ptr.add(mid), len - mid)) } } - /// Divides one slice into an array and a remainder slice at an index. - /// - /// The array will contain all indices from `[0, N)` (excluding - /// the index `N` itself) and the slice will contain all - /// indices from `[N, len)` (excluding the index `len` itself). - /// - /// # Panics - /// - /// Panics if `N > len`. - /// - /// # Examples - /// - /// ``` - /// #![feature(split_array)] - /// - /// let v = &[1, 2, 3, 4, 5, 6][..]; - /// - /// { - /// let (left, right) = v.split_array_ref::<0>(); - /// assert_eq!(left, &[]); - /// assert_eq!(right, [1, 2, 3, 4, 5, 6]); - /// } - /// - /// { - /// let (left, right) = v.split_array_ref::<2>(); - /// assert_eq!(left, &[1, 2]); - /// assert_eq!(right, [3, 4, 5, 6]); - /// } - /// - /// { - /// let (left, right) = v.split_array_ref::<6>(); - /// assert_eq!(left, &[1, 2, 3, 4, 5, 6]); - /// assert_eq!(right, []); - /// } - /// ``` - #[unstable(feature = "split_array", reason = "new API", issue = "90091")] - #[inline] - #[track_caller] - #[must_use] - pub fn split_array_ref(&self) -> (&[T; N], &[T]) { - let (a, b) = self.split_at(N); - // SAFETY: a points to [T; N]? Yes it's [T] of length N (checked by split_at) - unsafe { (&*(a.as_ptr() as *const [T; N]), b) } - } - - /// Divides one mutable slice into an array and a remainder slice at an index. - /// - /// The array will contain all indices from `[0, N)` (excluding - /// the index `N` itself) and the slice will contain all - /// indices from `[N, len)` (excluding the index `len` itself). - /// - /// # Panics - /// - /// Panics if `N > len`. - /// - /// # Examples - /// - /// ``` - /// #![feature(split_array)] - /// - /// let mut v = &mut [1, 0, 3, 0, 5, 6][..]; - /// let (left, right) = v.split_array_mut::<2>(); - /// assert_eq!(left, &mut [1, 0]); - /// assert_eq!(right, [3, 0, 5, 6]); - /// left[1] = 2; - /// right[1] = 4; - /// assert_eq!(v, [1, 2, 3, 4, 5, 6]); - /// ``` - #[unstable(feature = "split_array", reason = "new API", issue = "90091")] - #[inline] - #[track_caller] - #[must_use] - pub fn split_array_mut(&mut self) -> (&mut [T; N], &mut [T]) { - let (a, b) = self.split_at_mut(N); - // SAFETY: a points to [T; N]? Yes it's [T] of length N (checked by split_at_mut) - unsafe { (&mut *(a.as_mut_ptr() as *mut [T; N]), b) } - } - - /// Divides one slice into an array and a remainder slice at an index from - /// the end. - /// - /// The slice will contain all indices from `[0, len - N)` (excluding - /// the index `len - N` itself) and the array will contain all - /// indices from `[len - N, len)` (excluding the index `len` itself). - /// - /// # Panics - /// - /// Panics if `N > len`. - /// - /// # Examples - /// - /// ``` - /// #![feature(split_array)] - /// - /// let v = &[1, 2, 3, 4, 5, 6][..]; - /// - /// { - /// let (left, right) = v.rsplit_array_ref::<0>(); - /// assert_eq!(left, [1, 2, 3, 4, 5, 6]); - /// assert_eq!(right, &[]); - /// } - /// - /// { - /// let (left, right) = v.rsplit_array_ref::<2>(); - /// assert_eq!(left, [1, 2, 3, 4]); - /// assert_eq!(right, &[5, 6]); - /// } - /// - /// { - /// let (left, right) = v.rsplit_array_ref::<6>(); - /// assert_eq!(left, []); - /// assert_eq!(right, &[1, 2, 3, 4, 5, 6]); - /// } - /// ``` - #[unstable(feature = "split_array", reason = "new API", issue = "90091")] - #[inline] - #[must_use] - pub fn rsplit_array_ref(&self) -> (&[T], &[T; N]) { - assert!(N <= self.len()); - let (a, b) = self.split_at(self.len() - N); - // SAFETY: b points to [T; N]? Yes it's [T] of length N (checked by split_at) - unsafe { (a, &*(b.as_ptr() as *const [T; N])) } - } - - /// Divides one mutable slice into an array and a remainder slice at an - /// index from the end. - /// - /// The slice will contain all indices from `[0, len - N)` (excluding - /// the index `N` itself) and the array will contain all - /// indices from `[len - N, len)` (excluding the index `len` itself). - /// - /// # Panics - /// - /// Panics if `N > len`. - /// - /// # Examples - /// - /// ``` - /// #![feature(split_array)] - /// - /// let mut v = &mut [1, 0, 3, 0, 5, 6][..]; - /// let (left, right) = v.rsplit_array_mut::<4>(); - /// assert_eq!(left, [1, 0]); - /// assert_eq!(right, &mut [3, 0, 5, 6]); - /// left[1] = 2; - /// right[1] = 4; - /// assert_eq!(v, [1, 2, 3, 4, 5, 6]); - /// ``` - #[unstable(feature = "split_array", reason = "new API", issue = "90091")] - #[inline] - #[must_use] - pub fn rsplit_array_mut(&mut self) -> (&mut [T], &mut [T; N]) { - assert!(N <= self.len()); - let (a, b) = self.split_at_mut(self.len() - N); - // SAFETY: b points to [T; N]? Yes it's [T] of length N (checked by split_at_mut) - unsafe { (a, &mut *(b.as_mut_ptr() as *mut [T; N])) } - } - /// Returns an iterator over subslices separated by elements that match /// `pred`. The matched element is not contained in the subslices. /// @@ -4103,23 +3957,36 @@ impl [T] { where T: PartialOrd, { - self.is_sorted_by(|a, b| a.partial_cmp(b)) + self.is_sorted_by(|a, b| a <= b) } /// Checks if the elements of this slice are sorted using the given comparator function. /// /// Instead of using `PartialOrd::partial_cmp`, this function uses the given `compare` - /// function to determine the ordering of two elements. Apart from that, it's equivalent to - /// [`is_sorted`]; see its documentation for more information. + /// function to determine whether two elements are to be considered in sorted order. /// - /// [`is_sorted`]: slice::is_sorted + /// # Examples + /// + /// ``` + /// #![feature(is_sorted)] + /// + /// assert!([1, 2, 2, 9].is_sorted_by(|a, b| a <= b)); + /// assert!(![1, 2, 2, 9].is_sorted_by(|a, b| a < b)); + /// + /// assert!([0].is_sorted_by(|a, b| true)); + /// assert!([0].is_sorted_by(|a, b| false)); + /// + /// let empty: [i32; 0] = []; + /// assert!(empty.is_sorted_by(|a, b| false)); + /// assert!(empty.is_sorted_by(|a, b| true)); + /// ``` #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")] #[must_use] pub fn is_sorted_by<'a, F>(&'a self, mut compare: F) -> bool where - F: FnMut(&'a T, &'a T) -> Option, + F: FnMut(&'a T, &'a T) -> bool, { - self.array_windows().all(|[a, b]| compare(a, b).map_or(false, Ordering::is_le)) + self.array_windows().all(|[a, b]| compare(a, b)) } /// Checks if the elements of this slice are sorted using the given key extraction function. diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 5f1f41e68658..ad8c70c6a3ca 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -138,7 +138,7 @@ //! //! In general, *all* atomic accesses on read-only memory are Undefined Behavior. For instance, attempting //! to do a `compare_exchange` that will definitely fail (making it conceptually a read-only -//! operation) can still cause a page fault if the underlying memory page is mapped read-only. Since +//! operation) can still cause a segmentation fault if the underlying memory page is mapped read-only. Since //! atomic `load`s might be implemented using compare-exchange operations, even a `load` can fault //! on read-only memory. //! @@ -181,12 +181,13 @@ //! let spinlock = Arc::new(AtomicUsize::new(1)); //! //! let spinlock_clone = Arc::clone(&spinlock); +//! //! let thread = thread::spawn(move|| { -//! spinlock_clone.store(0, Ordering::SeqCst); +//! spinlock_clone.store(0, Ordering::Release); //! }); //! //! // Wait for the other thread to release the lock -//! while spinlock.load(Ordering::SeqCst) != 0 { +//! while spinlock.load(Ordering::Acquire) != 0 { //! hint::spin_loop(); //! } //! @@ -203,7 +204,11 @@ //! //! static GLOBAL_THREAD_COUNT: AtomicUsize = AtomicUsize::new(0); //! -//! let old_thread_count = GLOBAL_THREAD_COUNT.fetch_add(1, Ordering::SeqCst); +//! // Note that Relaxed ordering doesn't synchronize anything +//! // except the global thread counter itself. +//! let old_thread_count = GLOBAL_THREAD_COUNT.fetch_add(1, Ordering::Relaxed); +//! // Note that this number may not be true at the moment of printing +//! // because some other thread may have changed static value already. //! println!("live threads: {}", old_thread_count + 1); //! ``` diff --git a/library/core/tests/ascii.rs b/library/core/tests/ascii.rs index f5f2dd047788..3d3f8ac10c60 100644 --- a/library/core/tests/ascii.rs +++ b/library/core/tests/ascii.rs @@ -479,3 +479,13 @@ fn ascii_ctype_const() { is_ascii_control => [false, false, false, false, false]; } } + +#[test] +fn test_ascii_display() { + assert_eq!(b"foo'bar".escape_ascii().to_string(), r#"foo\'bar"#); + assert_eq!(b"\0\xff".escape_ascii().to_string(), r#"\x00\xff"#); + let mut it = b"\0fastpath\xffremainder\xff".escape_ascii(); + let _ = it.advance_by(4); + let _ = it.advance_back_by(4); + assert_eq!(it.to_string(), r#"fastpath\xffremainder"#); +} diff --git a/library/core/tests/async_iter/mod.rs b/library/core/tests/async_iter/mod.rs index 0c30bd1dfeac..4f425d7286d0 100644 --- a/library/core/tests/async_iter/mod.rs +++ b/library/core/tests/async_iter/mod.rs @@ -7,8 +7,7 @@ fn into_async_iter() { let async_iter = async_iter::from_iter(0..3); let mut async_iter = pin!(async_iter.into_async_iter()); - let waker = core::task::Waker::noop(); - let mut cx = &mut core::task::Context::from_waker(&waker); + let mut cx = &mut core::task::Context::from_waker(core::task::Waker::noop()); assert_eq!(async_iter.as_mut().poll_next(&mut cx), Poll::Ready(Some(0))); assert_eq!(async_iter.as_mut().poll_next(&mut cx), Poll::Ready(Some(1))); diff --git a/library/core/tests/iter/traits/iterator.rs b/library/core/tests/iter/traits/iterator.rs index 9c1dce7b66df..4c2d843eaa0d 100644 --- a/library/core/tests/iter/traits/iterator.rs +++ b/library/core/tests/iter/traits/iterator.rs @@ -1,4 +1,3 @@ -use core::cmp::Ordering; use core::num::NonZeroUsize; /// A wrapper struct that implements `Eq` and `Ord` based on the wrapped @@ -408,7 +407,7 @@ fn test_is_sorted() { // Tests for is_sorted_by assert!(![6, 2, 8, 5, 1, -60, 1337].iter().is_sorted()); - assert!([6, 2, 8, 5, 1, -60, 1337].iter().is_sorted_by(|_, _| Some(Ordering::Less))); + assert!([6, 2, 8, 5, 1, -60, 1337].iter().is_sorted_by(|_, _| true)); // Tests for is_sorted_by_key assert!([-2, -1, 0, 3].iter().is_sorted()); diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 8604d41eb686..13fb97fdc7f3 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -59,6 +59,7 @@ #![feature(noop_waker)] #![feature(numfmt)] #![feature(num_midpoint)] +#![cfg_attr(not(bootstrap), feature(offset_of_nested))] #![feature(isqrt)] #![feature(step_trait)] #![feature(str_internals)] @@ -115,7 +116,6 @@ #![feature(utf8_chunks)] #![feature(is_ascii_octdigit)] #![feature(get_many_mut)] -#![feature(offset_of)] #![feature(iter_map_windows)] #![allow(internal_features)] #![deny(unsafe_op_in_unsafe_fn)] diff --git a/library/core/tests/net/ip_addr.rs b/library/core/tests/net/ip_addr.rs index 3d13bffba92a..f9b351ef1980 100644 --- a/library/core/tests/net/ip_addr.rs +++ b/library/core/tests/net/ip_addr.rs @@ -516,6 +516,7 @@ fn ipv6_properties() { | multicast_realm_local | multicast_site_local | multicast_organization_local; + let ipv4_mapped: u32 = 1 << 17; if ($mask & unspecified) == unspecified { assert!(ip!($s).is_unspecified()); @@ -592,6 +593,11 @@ fn ipv6_properties() { assert_eq!(ip!($s).multicast_scope().unwrap(), Ipv6MulticastScope::Global); } + if ($mask & ipv4_mapped) == ipv4_mapped { + assert!(ip!($s).is_ipv4_mapped()); + } else { + assert!(!ip!($s).is_ipv4_mapped()); + } } } @@ -610,6 +616,7 @@ fn ipv6_properties() { let multicast_site_local: u32 = 1 << 13; let multicast_organization_local: u32 = 1 << 14; let multicast_global: u32 = 1 << 15; + let ipv4_mapped: u32 = 1 << 17; check!("::", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unspecified); @@ -622,7 +629,7 @@ fn ipv6_properties() { check!( "::ffff:127.0.0.1", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x7f, 0, 0, 1], - unicast_global + unicast_global | ipv4_mapped ); check!( @@ -996,6 +1003,9 @@ fn ipv6_const() { const IS_MULTICAST: bool = IP_ADDRESS.is_multicast(); assert!(!IS_MULTICAST); + const IS_IPV4_MAPPED: bool = IP_ADDRESS.is_ipv4_mapped(); + assert!(!IS_IPV4_MAPPED); + const IP_V4: Option = IP_ADDRESS.to_ipv4(); assert_eq!(IP_V4.unwrap(), Ipv4Addr::new(0, 0, 0, 1)); } diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs index cc1fc7e4d7ea..bcf7b5e59775 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs @@ -2307,7 +2307,7 @@ fn test_is_sorted() { // Tests for is_sorted_by assert!(![6, 2, 8, 5, 1, -60, 1337].is_sorted()); - assert!([6, 2, 8, 5, 1, -60, 1337].is_sorted_by(|_, _| Some(Ordering::Less))); + assert!([6, 2, 8, 5, 1, -60, 1337].is_sorted_by(|_, _| true)); // Tests for is_sorted_by_key assert!([-2, -1, 0, 3].is_sorted()); @@ -2398,37 +2398,45 @@ mod swap_panics { } #[test] -fn slice_split_array_mut() { +fn slice_split_first_chunk_mut() { let v = &mut [1, 2, 3, 4, 5, 6][..]; { - let (left, right) = v.split_array_mut::<0>(); + let (left, right) = v.split_first_chunk_mut::<0>().unwrap(); assert_eq!(left, &mut []); assert_eq!(right, [1, 2, 3, 4, 5, 6]); } { - let (left, right) = v.split_array_mut::<6>(); + let (left, right) = v.split_first_chunk_mut::<6>().unwrap(); assert_eq!(left, &mut [1, 2, 3, 4, 5, 6]); assert_eq!(right, []); } + + { + assert!(v.split_first_chunk_mut::<7>().is_none()); + } } #[test] -fn slice_rsplit_array_mut() { +fn slice_split_last_chunk_mut() { let v = &mut [1, 2, 3, 4, 5, 6][..]; { - let (left, right) = v.rsplit_array_mut::<0>(); + let (left, right) = v.split_last_chunk_mut::<0>().unwrap(); assert_eq!(left, [1, 2, 3, 4, 5, 6]); assert_eq!(right, &mut []); } { - let (left, right) = v.rsplit_array_mut::<6>(); + let (left, right) = v.split_last_chunk_mut::<6>().unwrap(); assert_eq!(left, []); assert_eq!(right, &mut [1, 2, 3, 4, 5, 6]); } + + { + assert!(v.split_last_chunk_mut::<7>().is_none()); + } } #[test] @@ -2443,38 +2451,6 @@ fn split_as_slice() { assert_eq!(split.as_slice(), &[]); } -#[should_panic] -#[test] -fn slice_split_array_ref_out_of_bounds() { - let v = &[1, 2, 3, 4, 5, 6][..]; - - let _ = v.split_array_ref::<7>(); -} - -#[should_panic] -#[test] -fn slice_split_array_mut_out_of_bounds() { - let v = &mut [1, 2, 3, 4, 5, 6][..]; - - let _ = v.split_array_mut::<7>(); -} - -#[should_panic] -#[test] -fn slice_rsplit_array_ref_out_of_bounds() { - let v = &[1, 2, 3, 4, 5, 6][..]; - - let _ = v.rsplit_array_ref::<7>(); -} - -#[should_panic] -#[test] -fn slice_rsplit_array_mut_out_of_bounds() { - let v = &mut [1, 2, 3, 4, 5, 6][..]; - - let _ = v.rsplit_array_mut::<7>(); -} - #[test] fn slice_split_once() { let v = &[1, 2, 3, 2, 4][..]; diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 6e664a162df9..ca83e2be5c14 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -45,6 +45,7 @@ mod diagnostic; #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] pub use diagnostic::{Diagnostic, Level, MultiSpan}; +use std::ffi::CStr; use std::ops::{Range, RangeBounds}; use std::path::PathBuf; use std::str::FromStr; @@ -1351,6 +1352,13 @@ impl Literal { Literal::new(bridge::LitKind::ByteStr, &string, None) } + /// C string literal. + #[unstable(feature = "proc_macro_c_str_literals", issue = "119750")] + pub fn c_string(string: &CStr) -> Literal { + let string = string.to_bytes().escape_ascii().to_string(); + Literal::new(bridge::LitKind::CStr, &string, None) + } + /// Returns the span encompassing this literal. #[stable(feature = "proc_macro_lib2", since = "1.29.0")] pub fn span(&self) -> Span { diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 5dbfe4aa2ac1..5b32bc5117c0 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -18,7 +18,7 @@ panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core", public = true } libc = { version = "0.2.150", default-features = false, features = ['rustc-dep-of-std'], public = true } -compiler_builtins = { version = "0.1.104" } +compiler_builtins = { version = "0.1.105" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } hashbrown = { version = "0.14", default-features = false, features = ['rustc-dep-of-std'] } diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs index 9638f4919871..835e35eac34f 100644 --- a/library/std/src/backtrace.rs +++ b/library/std/src/backtrace.rs @@ -93,7 +93,7 @@ use crate::env; use crate::ffi::c_void; use crate::fmt; use crate::panic::UnwindSafe; -use crate::sync::atomic::{AtomicUsize, Ordering::Relaxed}; +use crate::sync::atomic::{AtomicU8, Ordering::Relaxed}; use crate::sync::LazyLock; use crate::sys_common::backtrace::{lock, output_filename, set_image_base}; @@ -254,7 +254,7 @@ impl Backtrace { // Cache the result of reading the environment variables to make // backtrace captures speedy, because otherwise reading environment // variables every time can be somewhat slow. - static ENABLED: AtomicUsize = AtomicUsize::new(0); + static ENABLED: AtomicU8 = AtomicU8::new(0); match ENABLED.load(Relaxed) { 0 => {} 1 => return false, @@ -267,7 +267,7 @@ impl Backtrace { Err(_) => false, }, }; - ENABLED.store(enabled as usize + 1, Relaxed); + ENABLED.store(enabled as u8 + 1, Relaxed); enabled } diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 39e94902cfe5..fc27b6a67bfc 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -2232,6 +2232,18 @@ impl<'a, K, V> Iterator for Iter<'a, K, V> { fn size_hint(&self) -> (usize, Option) { self.base.size_hint() } + #[inline] + fn count(self) -> usize { + self.base.len() + } + #[inline] + fn fold(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.base.fold(init, f) + } } #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Iter<'_, K, V> { @@ -2256,6 +2268,18 @@ impl<'a, K, V> Iterator for IterMut<'a, K, V> { fn size_hint(&self) -> (usize, Option) { self.base.size_hint() } + #[inline] + fn count(self) -> usize { + self.base.len() + } + #[inline] + fn fold(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.base.fold(init, f) + } } #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for IterMut<'_, K, V> { @@ -2290,6 +2314,18 @@ impl Iterator for IntoIter { fn size_hint(&self) -> (usize, Option) { self.base.size_hint() } + #[inline] + fn count(self) -> usize { + self.base.len() + } + #[inline] + fn fold(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.base.fold(init, f) + } } #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for IntoIter { @@ -2320,6 +2356,18 @@ impl<'a, K, V> Iterator for Keys<'a, K, V> { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } + #[inline] + fn count(self) -> usize { + self.inner.len() + } + #[inline] + fn fold(self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.inner.fold(init, |acc, (k, _)| f(acc, k)) + } } #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Keys<'_, K, V> { @@ -2343,6 +2391,18 @@ impl<'a, K, V> Iterator for Values<'a, K, V> { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } + #[inline] + fn count(self) -> usize { + self.inner.len() + } + #[inline] + fn fold(self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.inner.fold(init, |acc, (_, v)| f(acc, v)) + } } #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Values<'_, K, V> { @@ -2366,6 +2426,18 @@ impl<'a, K, V> Iterator for ValuesMut<'a, K, V> { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } + #[inline] + fn count(self) -> usize { + self.inner.len() + } + #[inline] + fn fold(self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.inner.fold(init, |acc, (_, v)| f(acc, v)) + } } #[stable(feature = "map_values_mut", since = "1.10.0")] impl ExactSizeIterator for ValuesMut<'_, K, V> { @@ -2396,6 +2468,18 @@ impl Iterator for IntoKeys { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } + #[inline] + fn count(self) -> usize { + self.inner.len() + } + #[inline] + fn fold(self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.inner.fold(init, |acc, (k, _)| f(acc, k)) + } } #[stable(feature = "map_into_keys_values", since = "1.54.0")] impl ExactSizeIterator for IntoKeys { @@ -2426,6 +2510,18 @@ impl Iterator for IntoValues { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } + #[inline] + fn count(self) -> usize { + self.inner.len() + } + #[inline] + fn fold(self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.inner.fold(init, |acc, (_, v)| f(acc, v)) + } } #[stable(feature = "map_into_keys_values", since = "1.54.0")] impl ExactSizeIterator for IntoValues { @@ -2456,6 +2552,14 @@ impl<'a, K, V> Iterator for Drain<'a, K, V> { fn size_hint(&self) -> (usize, Option) { self.base.size_hint() } + #[inline] + fn fold(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.base.fold(init, f) + } } #[stable(feature = "drain", since = "1.6.0")] impl ExactSizeIterator for Drain<'_, K, V> { diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index 8bc596082906..dcb2fa0f771b 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -1500,6 +1500,18 @@ impl<'a, K> Iterator for Iter<'a, K> { fn size_hint(&self) -> (usize, Option) { self.base.size_hint() } + #[inline] + fn count(self) -> usize { + self.base.len() + } + #[inline] + fn fold(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.base.fold(init, f) + } } #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Iter<'_, K> { @@ -1530,6 +1542,18 @@ impl Iterator for IntoIter { fn size_hint(&self) -> (usize, Option) { self.base.size_hint() } + #[inline] + fn count(self) -> usize { + self.base.len() + } + #[inline] + fn fold(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.base.fold(init, f) + } } #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for IntoIter { @@ -1560,6 +1584,14 @@ impl<'a, K> Iterator for Drain<'a, K> { fn size_hint(&self) -> (usize, Option) { self.base.size_hint() } + #[inline] + fn fold(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.base.fold(init, f) + } } #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Drain<'_, K> { @@ -1639,6 +1671,15 @@ where let (_, upper) = self.iter.size_hint(); (0, upper) } + + #[inline] + fn fold(self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.iter.fold(init, |acc, elt| if self.other.contains(elt) { f(acc, elt) } else { acc }) + } } #[stable(feature = "std_debug", since = "1.16.0")] @@ -1691,6 +1732,15 @@ where let (_, upper) = self.iter.size_hint(); (0, upper) } + + #[inline] + fn fold(self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.iter.fold(init, |acc, elt| if self.other.contains(elt) { acc } else { f(acc, elt) }) + } } #[stable(feature = "fused", since = "1.26.0")] @@ -1736,6 +1786,14 @@ where fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } + #[inline] + fn fold(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.iter.fold(init, f) + } } #[stable(feature = "fused", since = "1.26.0")] @@ -1800,6 +1858,18 @@ where fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } + #[inline] + fn count(self) -> usize { + self.iter.count() + } + #[inline] + fn fold(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.iter.fold(init, f) + } } #[allow(dead_code)] diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index c3506175715f..1b38ba721147 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -102,8 +102,6 @@ impl f32 { /// # Examples /// /// ``` - /// #![feature(round_ties_even)] - /// /// let f = 3.3_f32; /// let g = -3.3_f32; /// let h = 3.5_f32; @@ -116,7 +114,7 @@ impl f32 { /// ``` #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] - #[unstable(feature = "round_ties_even", issue = "96710")] + #[stable(feature = "round_ties_even", since = "CURRENT_RUSTC_VERSION")] #[inline] pub fn round_ties_even(self) -> f32 { unsafe { intrinsics::rintf32(self) } diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index e4b7bfeeb84a..f8fc84440ae5 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -102,8 +102,6 @@ impl f64 { /// # Examples /// /// ``` - /// #![feature(round_ties_even)] - /// /// let f = 3.3_f64; /// let g = -3.3_f64; /// let h = 3.5_f64; @@ -116,7 +114,7 @@ impl f64 { /// ``` #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] - #[unstable(feature = "round_ties_even", issue = "96710")] + #[stable(feature = "round_ties_even", since = "CURRENT_RUSTC_VERSION")] #[inline] pub fn round_ties_even(self) -> f64 { unsafe { intrinsics::rintf64(self) } diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 7a8d9d0ceeca..568645ddf731 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -329,7 +329,6 @@ #![feature(maybe_uninit_slice)] #![feature(maybe_uninit_uninit_array)] #![feature(maybe_uninit_write_slice)] -#![feature(offset_of)] #![feature(panic_can_unwind)] #![feature(panic_info_message)] #![feature(panic_internals)] @@ -338,7 +337,6 @@ #![feature(prelude_2024)] #![feature(ptr_as_uninit)] #![feature(raw_os_nonzero)] -#![feature(round_ties_even)] #![feature(slice_internals)] #![feature(slice_ptr_get)] #![feature(slice_range)] diff --git a/library/std/src/os/unix/net/listener.rs b/library/std/src/os/unix/net/listener.rs index f6835472e2ca..8bf1e2dca6f7 100644 --- a/library/std/src/os/unix/net/listener.rs +++ b/library/std/src/os/unix/net/listener.rs @@ -73,7 +73,12 @@ impl UnixListener { unsafe { let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?; let (addr, len) = sockaddr_un(path.as_ref())?; - #[cfg(any(target_os = "windows", target_os = "redox", target_os = "espidf"))] + #[cfg(any( + target_os = "windows", + target_os = "redox", + target_os = "espidf", + target_os = "horizon" + ))] const backlog: libc::c_int = 128; #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "openbsd"))] const backlog: libc::c_int = -1; @@ -83,7 +88,8 @@ impl UnixListener { target_os = "linux", target_os = "freebsd", target_os = "openbsd", - target_os = "espidf" + target_os = "espidf", + target_os = "horizon" )))] const backlog: libc::c_int = libc::SOMAXCONN; diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs index 3598598cfa02..27b59cfc8c24 100644 --- a/library/std/src/sync/lazy_lock.rs +++ b/library/std/src/sync/lazy_lock.rs @@ -20,6 +20,9 @@ union Data { /// A value which is initialized on the first access. /// /// This type is a thread-safe [`LazyCell`], and can be used in statics. +/// Since initialization may be called from multiple threads, any +/// dereferencing call will block the calling thread if another +/// initialization routine is currently running. /// /// [`LazyCell`]: crate::cell::LazyCell /// @@ -81,8 +84,7 @@ pub struct LazyLock T> { } impl T> LazyLock { - /// Creates a new lazy value with the given initializing - /// function. + /// Creates a new lazy value with the given initializing function. #[inline] #[unstable(feature = "lazy_cell", issue = "109736")] pub const fn new(f: F) -> LazyLock { @@ -134,9 +136,11 @@ impl T> LazyLock { } } - /// Forces the evaluation of this lazy value and - /// returns a reference to result. This is equivalent - /// to the `Deref` impl, but is explicit. + /// Forces the evaluation of this lazy value and returns a reference to + /// result. This is equivalent to the `Deref` impl, but is explicit. + /// + /// This method will block the calling thread if another initialization + /// routine is currently running. /// /// # Examples /// @@ -204,6 +208,11 @@ impl Drop for LazyLock { impl T> Deref for LazyLock { type Target = T; + /// Dereferences the value. + /// + /// This method will block the calling thread if another initialization + /// routine is currently running. + /// #[inline] fn deref(&self) -> &T { LazyLock::force(self) @@ -232,7 +241,7 @@ impl fmt::Debug for LazyLock { } // We never create a `&F` from a `&LazyLock` so it is fine -// to not impl `Sync` for `F` +// to not impl `Sync` for `F`. #[unstable(feature = "lazy_cell", issue = "109736")] unsafe impl Sync for LazyLock {} // auto-derived `Send` impl is OK. diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index bbdcb32606cc..d95c0d8d0628 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -3,6 +3,7 @@ /// descriptors. mod pal; +pub mod os_str; mod personality; // FIXME(117276): remove this, move feature implementations into individual diff --git a/library/std/src/sys/pal/unix/os_str.rs b/library/std/src/sys/os_str/bytes.rs similarity index 99% rename from library/std/src/sys/pal/unix/os_str.rs rename to library/std/src/sys/os_str/bytes.rs index 7bd2f656a24e..3a75ce9ebb78 100644 --- a/library/std/src/sys/pal/unix/os_str.rs +++ b/library/std/src/sys/os_str/bytes.rs @@ -14,7 +14,6 @@ use crate::sys_common::{AsInner, IntoInner}; use core::str::Utf8Chunks; #[cfg(test)] -#[path = "../unix/os_str/tests.rs"] mod tests; #[derive(Hash)] diff --git a/library/std/src/sys/pal/unix/os_str/tests.rs b/library/std/src/sys/os_str/bytes/tests.rs similarity index 100% rename from library/std/src/sys/pal/unix/os_str/tests.rs rename to library/std/src/sys/os_str/bytes/tests.rs diff --git a/library/std/src/sys/os_str/mod.rs b/library/std/src/sys/os_str/mod.rs new file mode 100644 index 000000000000..b509729475bf --- /dev/null +++ b/library/std/src/sys/os_str/mod.rs @@ -0,0 +1,12 @@ +cfg_if::cfg_if! { + if #[cfg(any( + target_os = "windows", + target_os = "uefi", + ))] { + mod wtf8; + pub use wtf8::{Buf, Slice}; + } else { + mod bytes; + pub use bytes::{Buf, Slice}; + } +} diff --git a/library/std/src/sys/pal/windows/os_str.rs b/library/std/src/sys/os_str/wtf8.rs similarity index 100% rename from library/std/src/sys/pal/windows/os_str.rs rename to library/std/src/sys/os_str/wtf8.rs diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs index 937603cfd8a0..503362969196 100644 --- a/library/std/src/sys/pal/hermit/mod.rs +++ b/library/std/src/sys/pal/hermit/mod.rs @@ -30,8 +30,6 @@ pub mod io; pub mod memchr; pub mod net; pub mod os; -#[path = "../unix/os_str.rs"] -pub mod os_str; #[path = "../unix/path.rs"] pub mod path; #[path = "../unsupported/pipe.rs"] diff --git a/library/std/src/sys/pal/sgx/mod.rs b/library/std/src/sys/pal/sgx/mod.rs index 09d3f7638ca2..893c5f765a79 100644 --- a/library/std/src/sys/pal/sgx/mod.rs +++ b/library/std/src/sys/pal/sgx/mod.rs @@ -24,8 +24,6 @@ pub mod io; pub mod memchr; pub mod net; pub mod os; -#[path = "../unix/os_str.rs"] -pub mod os_str; pub mod path; #[path = "../unsupported/pipe.rs"] pub mod pipe; diff --git a/library/std/src/sys/pal/solid/mod.rs b/library/std/src/sys/pal/solid/mod.rs index 5af83653cf84..5742ce9d72c6 100644 --- a/library/std/src/sys/pal/solid/mod.rs +++ b/library/std/src/sys/pal/solid/mod.rs @@ -31,8 +31,6 @@ pub mod fs; pub mod io; pub mod net; pub mod os; -#[path = "../unix/os_str.rs"] -pub mod os_str; pub mod path; #[path = "../unsupported/pipe.rs"] pub mod pipe; diff --git a/library/std/src/sys/pal/teeos/mod.rs b/library/std/src/sys/pal/teeos/mod.rs index ed8c54b2c36f..764a4e6ad35e 100644 --- a/library/std/src/sys/pal/teeos/mod.rs +++ b/library/std/src/sys/pal/teeos/mod.rs @@ -27,8 +27,6 @@ pub mod net; #[path = "../unsupported/once.rs"] pub mod once; pub mod os; -#[path = "../unix/os_str.rs"] -pub mod os_str; #[path = "../unix/path.rs"] pub mod path; #[path = "../unsupported/pipe.rs"] diff --git a/library/std/src/sys/pal/uefi/mod.rs b/library/std/src/sys/pal/uefi/mod.rs index 4edc00e3ea02..fb1a531182a7 100644 --- a/library/std/src/sys/pal/uefi/mod.rs +++ b/library/std/src/sys/pal/uefi/mod.rs @@ -28,8 +28,6 @@ pub mod net; #[path = "../unsupported/once.rs"] pub mod once; pub mod os; -#[path = "../windows/os_str.rs"] -pub mod os_str; pub mod path; #[path = "../unsupported/pipe.rs"] pub mod pipe; diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index b5da5f870ec1..86027c2b0b0a 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -29,7 +29,6 @@ pub mod net; #[cfg(target_os = "l4re")] pub use self::l4re::net; pub mod os; -pub mod os_str; pub mod path; pub mod pipe; pub mod process; diff --git a/library/std/src/sys/pal/unsupported/mod.rs b/library/std/src/sys/pal/unsupported/mod.rs index e1a38de64711..6254c67a2a3b 100644 --- a/library/std/src/sys/pal/unsupported/mod.rs +++ b/library/std/src/sys/pal/unsupported/mod.rs @@ -11,8 +11,6 @@ pub mod locks; pub mod net; pub mod once; pub mod os; -#[path = "../unix/os_str.rs"] -pub mod os_str; #[path = "../unix/path.rs"] pub mod path; pub mod pipe; diff --git a/library/std/src/sys/pal/wasi/mod.rs b/library/std/src/sys/pal/wasi/mod.rs index 5919cc506d92..c1fc053bf049 100644 --- a/library/std/src/sys/pal/wasi/mod.rs +++ b/library/std/src/sys/pal/wasi/mod.rs @@ -32,8 +32,6 @@ pub mod io; pub mod net; pub mod os; -#[path = "../unix/os_str.rs"] -pub mod os_str; #[path = "../unix/path.rs"] pub mod path; #[path = "../unsupported/pipe.rs"] diff --git a/library/std/src/sys/pal/wasm/mod.rs b/library/std/src/sys/pal/wasm/mod.rs index 6c05b56e1bfc..d2181565887f 100644 --- a/library/std/src/sys/pal/wasm/mod.rs +++ b/library/std/src/sys/pal/wasm/mod.rs @@ -30,8 +30,6 @@ pub mod io; pub mod net; #[path = "../unsupported/os.rs"] pub mod os; -#[path = "../unix/os_str.rs"] -pub mod os_str; #[path = "../unix/path.rs"] pub mod path; #[path = "../unsupported/pipe.rs"] diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs index 8b722f01a5d3..d097a7b8bb26 100644 --- a/library/std/src/sys/pal/windows/mod.rs +++ b/library/std/src/sys/pal/windows/mod.rs @@ -24,7 +24,6 @@ pub mod locks; pub mod memchr; pub mod net; pub mod os; -pub mod os_str; pub mod path; pub mod pipe; pub mod process; diff --git a/library/std/src/sys/pal/xous/mod.rs b/library/std/src/sys/pal/xous/mod.rs index c2550dcfd831..230067907c8f 100644 --- a/library/std/src/sys/pal/xous/mod.rs +++ b/library/std/src/sys/pal/xous/mod.rs @@ -17,8 +17,6 @@ pub mod net; #[path = "../unsupported/once.rs"] pub mod once; pub mod os; -#[path = "../unix/os_str.rs"] -pub mod os_str; #[path = "../unix/path.rs"] pub mod path; #[path = "../unsupported/pipe.rs"] diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index eeee98f754e0..f5988a4df136 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -121,10 +121,16 @@ extern "C" {} #[link(name = "unwind", kind = "static", modifiers = "-bundle")] extern "C" {} -#[cfg(any(target_os = "freebsd", target_os = "netbsd"))] +#[cfg(target_os = "netbsd")] #[link(name = "gcc_s")] extern "C" {} +#[cfg(target_os = "freebsd")] +#[link(name = "gcc", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] +#[link(name = "gcc_eh", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] +#[link(name = "gcc_s", cfg(not(target_feature = "crt-static")))] +extern "C" {} + #[cfg(all(target_os = "openbsd", target_arch = "sparc64"))] #[link(name = "gcc")] extern "C" {} diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index fea194a80efb..28d96cb1cfe5 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -917,8 +917,24 @@ class RustBuild(object): if toml_val is not None: env["{}_{}".format(var_name, host_triple_sanitized)] = toml_val - # preserve existing RUSTFLAGS - env.setdefault("RUSTFLAGS", "") + # In src/etc/rust_analyzer_settings.json, we configure rust-analyzer to + # pass RUSTC_BOOTSTRAP=1 to all cargo invocations because the standard + # library uses unstable Cargo features. Without RUSTC_BOOTSTRAP, + # rust-analyzer would fail to fetch workspace layout when the system's + # default toolchain is not nightly. + # + # But that setting has the collateral effect of rust-analyzer also + # passing RUSTC_BOOTSTRAP=1 to all x.py invocations too (the various overrideCommand). + # For compiling bootstrap that can cause spurious rebuilding of bootstrap when + # rust-analyzer x.py invocations are interleaved with handwritten ones on the + # command line. + # + # Set RUSTC_BOOTSTRAP=1 consistently. + env["RUSTC_BOOTSTRAP"] = "1" + + default_rustflags = "" if env.get("RUSTFLAGS_BOOTSTRAP", "") else "-Zallow-features=" + + env.setdefault("RUSTFLAGS", default_rustflags) target_features = [] if self.get_toml("crt-static", build_section) == "true": diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs index 9c897ae1bb78..dd9c68aba7f7 100644 --- a/src/bootstrap/src/core/build_steps/setup.rs +++ b/src/bootstrap/src/core/build_steps/setup.rs @@ -37,6 +37,7 @@ static SETTINGS_HASHES: &[&str] = &[ "3468fea433c25fff60be6b71e8a215a732a7b1268b6a83bf10d024344e140541", "47d227f424bf889b0d899b9cc992d5695e1b78c406e183cd78eafefbe5488923", "b526bd58d0262dd4dda2bff5bc5515b705fb668a46235ace3e057f807963a11a", + "828666b021d837a33e78d870b56d34c88a5e2c85de58b693607ec574f0c27000", ]; static RUST_ANALYZER_SETTINGS: &str = include_str!("../../../../etc/rust_analyzer_settings.json"); diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 4e20babc55a6..3770d0687b24 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -1799,15 +1799,20 @@ impl<'a> Builder<'a> { } if self.config.rust_remap_debuginfo { - // FIXME: handle vendored sources - let registry_src = t!(home::cargo_home()).join("registry").join("src"); let mut env_var = OsString::new(); - for entry in t!(std::fs::read_dir(registry_src)) { - if !env_var.is_empty() { - env_var.push("\t"); - } - env_var.push(t!(entry).path()); + if self.config.vendor { + let vendor = self.build.src.join("vendor"); + env_var.push(vendor); env_var.push("=/rust/deps"); + } else { + let registry_src = t!(home::cargo_home()).join("registry").join("src"); + for entry in t!(std::fs::read_dir(registry_src)) { + if !env_var.is_empty() { + env_var.push("\t"); + } + env_var.push(t!(entry).path()); + env_var.push("=/rust/deps"); + } } cargo.env("RUSTC_CARGO_REGISTRY_SRC_TO_REMAP", env_var); } diff --git a/src/doc/nomicon b/src/doc/nomicon index f6bd083c4ccf..6bc2415218d4 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit f6bd083c4ccfc4ce6699b8b4154e3c45c5a27a8c +Subproject commit 6bc2415218d4dd0cb01433d8320f5ccf79c343a1 diff --git a/src/doc/reference b/src/doc/reference index 3565c7978cfc..8c77e8be9da1 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 3565c7978cfc9662f5963b135690ff9cbbfa0318 +Subproject commit 8c77e8be9da1a9c70545556218d563c8d061f1fd diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index c0be6299e52e..ddf5cb0e6ee5 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit c0be6299e52e4164c30ba6f41bd0ad0aaee64972 +Subproject commit ddf5cb0e6ee54ba2dd84c8ca3e1314120014e20d diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide index d13e85152a97..4af29d1a7f64 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit d13e85152a977cd0bcaf583cf5f49e86225697de +Subproject commit 4af29d1a7f64f88a36539662c6a84fe1fbe6cde1 diff --git a/src/doc/rustc/src/target-tier-policy.md b/src/doc/rustc/src/target-tier-policy.md index 95932db14e1f..48b58f6f06ad 100644 --- a/src/doc/rustc/src/target-tier-policy.md +++ b/src/doc/rustc/src/target-tier-policy.md @@ -246,6 +246,8 @@ approved by the appropriate team for that shared code before acceptance. introducing unconditional uses of features that another variation of the target may not have; use conditional compilation or runtime detection, as appropriate, to let each target run code supported by that target. +- Tier 3 targets must be able to produce assembly using at least one of + rustc's supported backends from any host target. If a tier 3 target stops meeting these requirements, or the target maintainers no longer have interest or time, or the target shows no signs of activity and diff --git a/src/doc/unstable-book/src/compiler-flags/check-cfg.md b/src/doc/unstable-book/src/compiler-flags/check-cfg.md index 78bc8dceb782..bf83f6ad7c5f 100644 --- a/src/doc/unstable-book/src/compiler-flags/check-cfg.md +++ b/src/doc/unstable-book/src/compiler-flags/check-cfg.md @@ -44,15 +44,20 @@ To enable checking of values, but to provide an *none*/empty set of expected val ```bash rustc --check-cfg 'cfg(name)' -rustc --check-cfg 'cfg(name, values())' rustc --check-cfg 'cfg(name, values(none()))' ``` -To enable checking of name but not values (i.e. unknown expected values), use this form: +To enable checking of name but not values, use one of these forms: -```bash -rustc --check-cfg 'cfg(name, values(any()))' -``` + - No expected values (_will lint on every value_): + ```bash + rustc --check-cfg 'cfg(name, values())' + ``` + + - Unknown expected values (_will never lint_): + ```bash + rustc --check-cfg 'cfg(name, values(any()))' + ``` To avoid repeating the same set of values, use this form: @@ -114,18 +119,14 @@ as argument to `--check-cfg`. This table describe the equivalence of a `--cfg` argument to a `--check-cfg` argument. | `--cfg` | `--check-cfg` | -|-----------------------------|----------------------------------------------------------| +|-------------------------------|------------------------------------------------------------| | *nothing* | *nothing* or `--check-cfg=cfg()` (to enable the checking) | -| `--cfg foo` | `--check-cfg=cfg(foo), --check-cfg=cfg(foo, values())` or `--check-cfg=cfg(foo, values(none()))` | +| `--cfg foo` | `--check-cfg=cfg(foo)` or `--check-cfg=cfg(foo, values(none()))` | | `--cfg foo=""` | `--check-cfg=cfg(foo, values(""))` | | `--cfg foo="bar"` | `--check-cfg=cfg(foo, values("bar"))` | | `--cfg foo="1" --cfg foo="2"` | `--check-cfg=cfg(foo, values("1", "2"))` | | `--cfg foo="1" --cfg bar="2"` | `--check-cfg=cfg(foo, values("1")) --check-cfg=cfg(bar, values("2"))` | -| `--cfg foo --cfg foo="bar"` | `--check-cfg=cfg(foo) --check-cfg=cfg(foo, values("bar"))` | - -NOTE: There is (currently) no way to express that a condition name is expected but no (!= none) -values are expected. Passing an empty `values()` means *(none)* in the sense of `#[cfg(foo)]` -with no value. Users are expected to NOT pass a `--check-cfg` with that condition name. +| `--cfg foo --cfg foo="bar"` | `--check-cfg=cfg(foo, values(none(), "bar"))` | ### Example: Cargo-like `feature` example diff --git a/src/etc/rust_analyzer_settings.json b/src/etc/rust_analyzer_settings.json index 32a04cfd5d16..d329fe997cd7 100644 --- a/src/etc/rust_analyzer_settings.json +++ b/src/etc/rust_analyzer_settings.json @@ -1,4 +1,5 @@ { + "git.detectSubmodulesLimit": 20, "rust-analyzer.check.invocationLocation": "root", "rust-analyzer.check.invocationStrategy": "once", "rust-analyzer.check.overrideCommand": [ diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 014bcb1a8817..aab974ad79ed 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -312,7 +312,7 @@ pub(crate) fn build_impls( let tcx = cx.tcx; // for each implementation of an item represented by `did`, build the clean::Item for that impl - for &did in tcx.inherent_impls(did).iter() { + for &did in tcx.inherent_impls(did).into_iter().flatten() { build_impl(cx, did, attrs, ret); } @@ -325,7 +325,7 @@ pub(crate) fn build_impls( if tcx.has_attr(did, sym::rustc_has_incoherent_inherent_impls) { let type_ = if tcx.is_trait(did) { SimplifiedType::Trait(did) } else { SimplifiedType::Adt(did) }; - for &did in tcx.incoherent_impls(type_) { + for &did in tcx.incoherent_impls(type_).into_iter().flatten() { build_impl(cx, did, attrs, ret); } } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 90eb783c7cae..6710193f9611 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1862,7 +1862,7 @@ impl PrimitiveType { .get(self) .into_iter() .flatten() - .flat_map(move |&simp| tcx.incoherent_impls(simp)) + .flat_map(move |&simp| tcx.incoherent_impls(simp).into_iter().flatten()) .copied() } @@ -1870,7 +1870,7 @@ impl PrimitiveType { Self::simplified_types() .values() .flatten() - .flat_map(move |&simp| tcx.incoherent_impls(simp)) + .flat_map(move |&simp| tcx.incoherent_impls(simp).into_iter().flatten()) .copied() } diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 437517598ac4..b2b20c95a7e6 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -312,7 +312,9 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol { Symbol::intern(&match p.kind { // FIXME(never_patterns): does this make sense? - PatKind::Wild | PatKind::Never | PatKind::Struct(..) => return kw::Underscore, + PatKind::Wild | PatKind::Err(_) | PatKind::Never | PatKind::Struct(..) => { + return kw::Underscore; + } PatKind::Binding(_, _, ident, _) => return ident.name, PatKind::TupleStruct(ref p, ..) | PatKind::Path(ref p) => qpath_to_string(p), PatKind::Or(pats) => { diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 642265f5f6be..bad1511dfd29 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -530,7 +530,6 @@ impl<'a, 'b, 'ids, I: Iterator>> Iterator for event in &mut self.inner { match &event.0 { Event::End(Tag::Heading(..)) => break, - Event::Start(Tag::Link(_, _, _)) | Event::End(Tag::Link(..)) => {} Event::Text(text) | Event::Code(text) => { id.extend(text.chars().filter_map(slugify)); self.buf.push_back(event); @@ -549,12 +548,10 @@ impl<'a, 'b, 'ids, I: Iterator>> Iterator let level = std::cmp::min(level as u32 + (self.heading_offset as u32), MAX_HEADER_LEVEL); - self.buf.push_back((Event::Html(format!("").into()), 0..0)); + self.buf.push_back((Event::Html(format!("").into()), 0..0)); - let start_tags = format!( - "\ - ", - ); + let start_tags = + format!("§"); return Some((Event::Html(start_tags.into()), 0..0)); } event diff --git a/src/librustdoc/html/markdown/tests.rs b/src/librustdoc/html/markdown/tests.rs index 5eba1d0609f3..4dd176b3a692 100644 --- a/src/librustdoc/html/markdown/tests.rs +++ b/src/librustdoc/html/markdown/tests.rs @@ -311,26 +311,38 @@ fn test_header() { assert_eq!(output, expect, "original: {}", input); } - t("# Foo bar", "

Foo bar

"); + t( + "# Foo bar", + "

§Foo bar

", + ); t( "## Foo-bar_baz qux", "

\ - Foo-bar_baz qux

", + §\ + Foo-bar_baz qux\ + ", ); t( "### **Foo** *bar* baz!?!& -_qux_-%", "

\ - Foo \ - bar baz!?!& -qux-%\ + §\ + Foo bar baz!?!& -qux-%\

", ); t( "#### **Foo?** & \\*bar?!* _`baz`_ ❤ #qux", "
\ - Foo? & *bar?!* \ - baz ❤ #qux\ + §\ + Foo? & *bar?!* baz ❤ #qux\
", ); + t( + "# Foo [bar](https://hello.yo)", + "

\ + §\ + Foo bar\ +

", + ); } #[test] @@ -351,12 +363,36 @@ fn test_header_ids_multiple_blocks() { assert_eq!(output, expect, "original: {}", input); } - t(&mut map, "# Example", "

Example

"); - t(&mut map, "# Panics", "

Panics

"); - t(&mut map, "# Example", "

Example

"); - t(&mut map, "# Search", "

Search

"); - t(&mut map, "# Example", "

Example

"); - t(&mut map, "# Panics", "

Panics

"); + t( + &mut map, + "# Example", + "

§Example

", + ); + t( + &mut map, + "# Panics", + "

§Panics

", + ); + t( + &mut map, + "# Example", + "

§Example

", + ); + t( + &mut map, + "# Search", + "

§Search

", + ); + t( + &mut map, + "# Example", + "

§Example

", + ); + t( + &mut map, + "# Panics", + "

§Panics

", + ); } #[test] diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index bea5ccd7c860..ac7ae291d29b 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1207,17 +1207,31 @@ impl<'a> AssocItemLink<'a> { } } -fn write_impl_section_heading(mut w: impl fmt::Write, title: &str, id: &str) { +pub fn write_section_heading( + w: &mut impl fmt::Write, + title: &str, + id: &str, + extra_class: Option<&str>, + extra: impl fmt::Display, +) { + let (extra_class, whitespace) = match extra_class { + Some(extra) => (extra, " "), + None => ("", ""), + }; write!( w, - "

\ + "

\ {title}\ §\ -

" + {extra}", ) .unwrap(); } +fn write_impl_section_heading(w: &mut impl fmt::Write, title: &str, id: &str) { + write_section_heading(w, title, id, None, "") +} + pub(crate) fn render_all_impls( mut w: impl Write, cx: &mut Context<'_>, diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 3b91fbdcb29d..71186319e07d 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -19,8 +19,8 @@ use super::{ item_ty_to_section, notable_traits_button, notable_traits_json, render_all_impls, render_assoc_item, render_assoc_items, render_attributes_in_code, render_attributes_in_pre, render_impl, render_rightside, render_stability_since_raw, - render_stability_since_raw_with_extra, AssocItemLink, AssocItemRender, Context, - ImplRenderingParameters, RenderMode, + render_stability_since_raw_with_extra, write_section_heading, AssocItemLink, AssocItemRender, + Context, ImplRenderingParameters, RenderMode, }; use crate::clean; use crate::config::ModuleSorting; @@ -425,13 +425,12 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: w.write_str(ITEM_TABLE_CLOSE); } last_section = Some(my_section); - write!( + write_section_heading( w, - "

\ - {name}\ -

{ITEM_TABLE_OPEN}", - id = cx.derive_id(my_section.id()), - name = my_section.name(), + my_section.name(), + &cx.derive_id(my_section.id()), + None, + ITEM_TABLE_OPEN, ); } @@ -814,16 +813,6 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: // Trait documentation write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); - fn write_small_section_header(w: &mut Buffer, id: &str, title: &str, extra_content: &str) { - write!( - w, - "

\ - {1}§\ -

{2}", - id, title, extra_content - ) - } - fn trait_item(w: &mut Buffer, cx: &mut Context<'_>, m: &clean::Item, t: &clean::Item) { let name = m.name.unwrap(); info!("Documenting {name} on {ty_name:?}", ty_name = t.name); @@ -857,10 +846,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: } if !required_types.is_empty() { - write_small_section_header( + write_section_heading( w, - "required-associated-types", "Required Associated Types", + "required-associated-types", + None, "
", ); for t in required_types { @@ -869,10 +859,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: w.write_str("
"); } if !provided_types.is_empty() { - write_small_section_header( + write_section_heading( w, - "provided-associated-types", "Provided Associated Types", + "provided-associated-types", + None, "
", ); for t in provided_types { @@ -882,10 +873,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: } if !required_consts.is_empty() { - write_small_section_header( + write_section_heading( w, - "required-associated-consts", "Required Associated Constants", + "required-associated-consts", + None, "
", ); for t in required_consts { @@ -894,10 +886,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: w.write_str("
"); } if !provided_consts.is_empty() { - write_small_section_header( + write_section_heading( w, - "provided-associated-consts", "Provided Associated Constants", + "provided-associated-consts", + None, "
", ); for t in provided_consts { @@ -908,10 +901,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: // Output the documentation for each function individually if !required_methods.is_empty() || must_implement_one_of_functions.is_some() { - write_small_section_header( + write_section_heading( w, - "required-methods", "Required Methods", + "required-methods", + None, "
", ); @@ -929,10 +923,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: w.write_str("
"); } if !provided_methods.is_empty() { - write_small_section_header( + write_section_heading( w, - "provided-methods", "Provided Methods", + "provided-methods", + None, "
", ); for m in provided_methods { @@ -949,10 +944,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: let mut extern_crates = FxHashSet::default(); if !t.is_object_safe(cx.tcx()) { - write_small_section_header( + write_section_heading( w, - "object-safety", "Object Safety", + "object-safety", + None, &format!( "
This trait is not \ \ @@ -996,7 +992,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: foreign.sort_by_cached_key(|i| ImplString::new(i, cx)); if !foreign.is_empty() { - write_small_section_header(w, "foreign-impls", "Implementations on Foreign Types", ""); + write_section_heading(w, "Implementations on Foreign Types", "foreign-impls", None, ""); for implementor in foreign { let provided_methods = implementor.inner_impl().provided_trait_methods(tcx); @@ -1021,10 +1017,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: } } - write_small_section_header( + write_section_heading( w, - "implementors", "Implementors", + "implementors", + None, "
", ); for implementor in concrete { @@ -1033,10 +1030,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: w.write_str("
"); if t.is_auto(tcx) { - write_small_section_header( + write_section_heading( w, - "synthetic-implementors", "Auto implementors", + "synthetic-implementors", + None, "
", ); for implementor in synthetic { @@ -1054,18 +1052,20 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: } else { // even without any implementations to write in, we still want the heading and list, so the // implementors javascript file pulled in below has somewhere to write the impls into - write_small_section_header( + write_section_heading( w, - "implementors", "Implementors", + "implementors", + None, "
", ); if t.is_auto(tcx) { - write_small_section_header( + write_section_heading( w, - "synthetic-implementors", "Auto implementors", + "synthetic-implementors", + None, "
", ); } @@ -1248,11 +1248,7 @@ fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &c write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); if let Some(inner_type) = &t.inner_type { - write!( - w, - "

\ - Aliased Type§

" - ); + write_section_heading(w, "Aliased Type", "aliased-type", None, ""); match inner_type { clean::TypeAliasInnerType::Enum { variants, is_non_exhaustive } => { @@ -1673,16 +1669,14 @@ fn item_variants( enum_def_id: DefId, ) { let tcx = cx.tcx(); - write!( + write_section_heading( w, - "

\ - Variants{}§\ -

\ - {}\ -
", - document_non_exhaustive_header(it), - document_non_exhaustive(it) + &format!("Variants{}", document_non_exhaustive_header(it)), + "variants", + Some("variants"), + format!("{}
", document_non_exhaustive(it)), ); + let should_show_enum_discriminant = should_show_enum_discriminant(cx, enum_def_id, variants); for (index, variant) in variants.iter_enumerated() { if variant.is_stripped() { @@ -1930,16 +1924,12 @@ fn item_fields( .peekable(); if let None | Some(CtorKind::Fn) = ctor_kind { if fields.peek().is_some() { - write!( - w, - "

\ - {}{}§\ -

\ - {}", + let title = format!( + "{}{}", if ctor_kind.is_none() { "Fields" } else { "Tuple Fields" }, document_non_exhaustive_header(it), - document_non_exhaustive(it) ); + write_section_heading(w, &title, "fields", Some("fields"), document_non_exhaustive(it)); for (index, (field, ty)) in fields.enumerate() { let field_name = field.name.map_or_else(|| index.to_string(), |sym| sym.as_str().to_string()); diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index cd53fcb8b7c1..9c593aa85d98 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -849,11 +849,30 @@ nav.sub { h2.section-header > .anchor { padding-right: 6px; } +a.doc-anchor { + color: var(--main-color); + display: none; + position: absolute; + left: -17px; + /* We add this padding so that when the cursor moves from the heading's text to the anchor, + the anchor doesn't disappear. */ + padding-right: 5px; + /* And this padding is used to make the anchor larger and easier to click on. */ + padding-left: 3px; +} +*:hover > .doc-anchor { + display: block; +} +/* If the first element of the top doc block is a heading, we don't want to ever display its anchor +because of the `[-]` element which would overlap with it. */ +.top-doc > .docblock > *:first-child > .doc-anchor { + display: none !important; +} .main-heading a:hover, .example-wrap .rust a:hover, .all-items a:hover, -.docblock a:not(.test-arrow):not(.scrape-help):not(.tooltip):hover, +.docblock a:not(.test-arrow):not(.scrape-help):not(.tooltip):hover:not(.doc-anchor), .docblock-short a:not(.test-arrow):not(.scrape-help):not(.tooltip):hover, .item-info a { text-decoration: underline; diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index dbff33dc1ecf..30b3e5c784dc 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -624,7 +624,8 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { // Checks if item_name belongs to `impl SomeItem` let mut assoc_items: Vec<_> = tcx .inherent_impls(did) - .iter() + .into_iter() + .flatten() .flat_map(|&imp| { filter_assoc_items_by_name_and_namespace( tcx, diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs index df955421ba48..1bea93c78421 100644 --- a/src/librustdoc/passes/stripper.rs +++ b/src/librustdoc/passes/stripper.rs @@ -56,13 +56,10 @@ impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> { | clean::TraitItem(..) | clean::FunctionItem(..) | clean::VariantItem(..) - | clean::MethodItem(..) | clean::ForeignFunctionItem(..) | clean::ForeignStaticItem(..) | clean::ConstantItem(..) | clean::UnionItem(..) - | clean::AssocConstItem(..) - | clean::AssocTypeItem(..) | clean::TraitAliasItem(..) | clean::MacroItem(..) | clean::ForeignTypeItem => { @@ -80,6 +77,16 @@ impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> { } } + clean::MethodItem(..) | clean::AssocConstItem(..) | clean::AssocTypeItem(..) => { + let item_id = i.item_id; + if item_id.is_local() + && !self.effective_visibilities.is_reachable(self.tcx, item_id.expect_def_id()) + { + debug!("Stripper: stripping {:?} {:?}", i.type_(), i.name); + return None; + } + } + clean::StructFieldItem(..) => { if i.visibility(self.tcx) != Some(Visibility::Public) { return Some(strip_item(i)); @@ -192,16 +199,16 @@ impl<'a> DocFolder for ImplStripper<'a, '_> { && imp.items.iter().all(|i| { let item_id = i.item_id; item_id.is_local() - && !is_item_reachable( - self.tcx, - self.is_json_output, - &self.cache.effective_visibilities, - item_id, - ) + && !self + .cache + .effective_visibilities + .is_reachable(self.tcx, item_id.expect_def_id()) }) { + debug!("ImplStripper: no public item; removing {imp:?}"); return None; } else if imp.items.is_empty() && i.doc_value().is_empty() { + debug!("ImplStripper: no item and no doc; removing {imp:?}"); return None; } } @@ -212,13 +219,13 @@ impl<'a> DocFolder for ImplStripper<'a, '_> { && !imp.for_.is_assoc_ty() && !self.should_keep_impl(&i, did) { - debug!("ImplStripper: impl item for stripped type; removing"); + debug!("ImplStripper: impl item for stripped type; removing {imp:?}"); return None; } if let Some(did) = imp.trait_.as_ref().map(|t| t.def_id()) && !self.should_keep_impl(&i, did) { - debug!("ImplStripper: impl item for stripped trait; removing"); + debug!("ImplStripper: impl item for stripped trait; removing {imp:?}"); return None; } if let Some(generics) = imp.trait_.as_ref().and_then(|t| t.generics()) { @@ -226,7 +233,7 @@ impl<'a> DocFolder for ImplStripper<'a, '_> { if let Some(did) = typaram.def_id(self.cache) && !self.should_keep_impl(&i, did) { - debug!("ImplStripper: stripped item in trait's generics; removing impl"); + debug!("ImplStripper: stripped item in trait's generics; removing {imp:?}"); return None; } } diff --git a/src/tools/cargo b/src/tools/cargo index 84976cd699f4..1ae631085f01 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 84976cd699f4aea56cb3a90ce3eedeed9e20d5a5 +Subproject commit 1ae631085f01c1a72d05df1ec81f3759a8360042 diff --git a/src/tools/clippy/clippy_lints/src/async_yields_async.rs b/src/tools/clippy/clippy_lints/src/async_yields_async.rs index bb08ac7508bc..eeaa3de3725f 100644 --- a/src/tools/clippy/clippy_lints/src/async_yields_async.rs +++ b/src/tools/clippy/clippy_lints/src/async_yields_async.rs @@ -45,50 +45,72 @@ declare_lint_pass!(AsyncYieldsAsync => [ASYNC_YIELDS_ASYNC]); impl<'tcx> LateLintPass<'tcx> for AsyncYieldsAsync { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { - // For functions, with explicitly defined types, don't warn. - // XXXkhuey maybe we should? - if let ExprKind::Closure(Closure { - kind: - ClosureKind::Coroutine(CoroutineKind::Desugared( - CoroutineDesugaring::Async, - CoroutineSource::Block | CoroutineSource::Closure, - )), + let ExprKind::Closure(Closure { + kind: ClosureKind::Coroutine(CoroutineKind::Desugared(CoroutineDesugaring::Async, kind)), body: body_id, .. }) = expr.kind - { - if let Some(future_trait_def_id) = cx.tcx.lang_items().future_trait() { - let typeck_results = cx.tcx.typeck_body(*body_id); - let body = cx.tcx.hir().body(*body_id); - let expr_ty = typeck_results.expr_ty(body.value); + else { + return; + }; - if implements_trait(cx, expr_ty, future_trait_def_id, &[]) { - let return_expr_span = match &body.value.kind { - // XXXkhuey there has to be a better way. - ExprKind::Block(block, _) => block.expr.map(|e| e.span), - ExprKind::Path(QPath::Resolved(_, path)) => Some(path.span), - _ => None, - }; - if let Some(return_expr_span) = return_expr_span { - span_lint_hir_and_then( - cx, - ASYNC_YIELDS_ASYNC, - body.value.hir_id, + let body_expr = match kind { + CoroutineSource::Fn => { + // For functions, with explicitly defined types, don't warn. + // XXXkhuey maybe we should? + return; + }, + CoroutineSource::Block => cx.tcx.hir().body(*body_id).value, + CoroutineSource::Closure => { + // Like `async fn`, async closures are wrapped in an additional block + // to move all of the closure's arguments into the future. + + let async_closure_body = cx.tcx.hir().body(*body_id).value; + let ExprKind::Block(block, _) = async_closure_body.kind else { + return; + }; + let Some(block_expr) = block.expr else { + return; + }; + let ExprKind::DropTemps(body_expr) = block_expr.kind else { + return; + }; + body_expr + }, + }; + + let Some(future_trait_def_id) = cx.tcx.lang_items().future_trait() else { + return; + }; + + let typeck_results = cx.tcx.typeck_body(*body_id); + let expr_ty = typeck_results.expr_ty(body_expr); + + if implements_trait(cx, expr_ty, future_trait_def_id, &[]) { + let return_expr_span = match &body_expr.kind { + // XXXkhuey there has to be a better way. + ExprKind::Block(block, _) => block.expr.map(|e| e.span), + ExprKind::Path(QPath::Resolved(_, path)) => Some(path.span), + _ => None, + }; + if let Some(return_expr_span) = return_expr_span { + span_lint_hir_and_then( + cx, + ASYNC_YIELDS_ASYNC, + body_expr.hir_id, + return_expr_span, + "an async construct yields a type which is itself awaitable", + |db| { + db.span_label(body_expr.span, "outer async construct"); + db.span_label(return_expr_span, "awaitable value not awaited"); + db.span_suggestion( return_expr_span, - "an async construct yields a type which is itself awaitable", - |db| { - db.span_label(body.value.span, "outer async construct"); - db.span_label(return_expr_span, "awaitable value not awaited"); - db.span_suggestion( - return_expr_span, - "consider awaiting this value", - format!("{}.await", snippet(cx, return_expr_span, "..")), - Applicability::MaybeIncorrect, - ); - }, + "consider awaiting this value", + format!("{}.await", snippet(cx, return_expr_span, "..")), + Applicability::MaybeIncorrect, ); - } - } + }, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/default_union_representation.rs b/src/tools/clippy/clippy_lints/src/default_union_representation.rs index db01ff2cd220..bfd89bfd2c72 100644 --- a/src/tools/clippy/clippy_lints/src/default_union_representation.rs +++ b/src/tools/clippy/clippy_lints/src/default_union_representation.rs @@ -75,7 +75,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultUnionRepresentation { /// (ZST fields having an arbitrary offset is completely inconsequential, and /// if there is only one field left after ignoring ZST fields then the offset /// of that field does not matter either.) -fn is_union_with_two_non_zst_fields(cx: &LateContext<'_>, item: &Item<'_>) -> bool { +fn is_union_with_two_non_zst_fields<'tcx>(cx: &LateContext<'tcx>, item: &Item<'tcx>) -> bool { if let ItemKind::Union(..) = &item.kind && let ty::Adt(adt_def, args) = cx.tcx.type_of(item.owner_id).instantiate_identity().kind() { diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs index d8abe411030b..df596338b950 100644 --- a/src/tools/clippy/clippy_lints/src/derive.rs +++ b/src/tools/clippy/clippy_lints/src/derive.rs @@ -386,7 +386,8 @@ fn check_unsafe_derive_deserialize<'tcx>( && cx .tcx .inherent_impls(def.did()) - .iter() + .into_iter() + .flatten() .map(|imp_did| cx.tcx.hir().expect_item(imp_did.expect_local())) .any(|imp| has_unsafe(cx, imp)) { @@ -450,12 +451,12 @@ fn check_partial_eq_without_eq<'tcx>(cx: &LateContext<'tcx>, span: Span, trait_r && let Some(def_id) = trait_ref.trait_def_id() && cx.tcx.is_diagnostic_item(sym::PartialEq, def_id) && let param_env = param_env_for_derived_eq(cx.tcx, adt.did(), eq_trait_def_id) - && !implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, adt.did(),&[]) + && !implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, None, &[]) // If all of our fields implement `Eq`, we can implement `Eq` too && adt .all_fields() .map(|f| f.ty(cx.tcx, args)) - .all(|ty| implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, adt.did(), &[])) + .all(|ty| implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, None, &[])) { span_lint_and_sugg( cx, diff --git a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs index 3c4352942526..4e728d61b853 100644 --- a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs +++ b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs @@ -51,7 +51,8 @@ fn unary_pattern(pat: &Pat<'_>) -> bool { | PatKind::Binding(..) | PatKind::Wild | PatKind::Never - | PatKind::Or(_) => false, + | PatKind::Or(_) + | PatKind::Err(_) => false, PatKind::Struct(_, a, etc) => !etc && a.iter().all(|x| unary_pattern(x.pat)), PatKind::Tuple(a, etc) | PatKind::TupleStruct(_, a, etc) => etc.as_opt_usize().is_none() && array_rec(a), PatKind::Ref(x, _) | PatKind::Box(x) => unary_pattern(x), diff --git a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs index 788fe8287278..87f6f5e7959e 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs @@ -210,7 +210,7 @@ enum ImplicitHasherType<'tcx> { impl<'tcx> ImplicitHasherType<'tcx> { /// Checks that `ty` is a target type without a `BuildHasher`. - fn new(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'_>) -> Option { + fn new(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Option { if let TyKind::Path(QPath::Resolved(None, path)) = hir_ty.kind { let params: Vec<_> = path .segments diff --git a/src/tools/clippy/clippy_lints/src/inherent_impl.rs b/src/tools/clippy/clippy_lints/src/inherent_impl.rs index e4781752e757..fb7b82ec304e 100644 --- a/src/tools/clippy/clippy_lints/src/inherent_impl.rs +++ b/src/tools/clippy/clippy_lints/src/inherent_impl.rs @@ -53,9 +53,10 @@ impl<'tcx> LateLintPass<'tcx> for MultipleInherentImpl { // List of spans to lint. (lint_span, first_span) let mut lint_spans = Vec::new(); + let Ok(impls) = cx.tcx.crate_inherent_impls(()) else { return }; let inherent_impls = cx .tcx - .with_stable_hashing_context(|hcx| cx.tcx.crate_inherent_impls(()).inherent_impls.to_sorted(&hcx, true)); + .with_stable_hashing_context(|hcx| impls.inherent_impls.to_sorted(&hcx, true)); for (_, impl_ids) in inherent_impls.into_iter().filter(|(&id, impls)| { impls.len() > 1 diff --git a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs index 903d3a2ab896..82a37bb4f278 100644 --- a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs +++ b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs @@ -139,7 +139,7 @@ fn deref_chain<'cx, 'tcx>(cx: &'cx LateContext<'tcx>, ty: Ty<'tcx>) -> impl Iter fn adt_has_inherent_method(cx: &LateContext<'_>, ty: Ty<'_>, method_name: Symbol) -> bool { if let Some(ty_did) = ty.ty_adt_def().map(ty::AdtDef::did) { - cx.tcx.inherent_impls(ty_did).iter().any(|&did| { + cx.tcx.inherent_impls(ty_did).into_iter().flatten().any(|&did| { cx.tcx .associated_items(did) .filter_by_name_unhygienic(method_name) diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index c09d3d1862b0..c1ab020117ca 100644 --- a/src/tools/clippy/clippy_lints/src/len_zero.rs +++ b/src/tools/clippy/clippy_lints/src/len_zero.rs @@ -441,7 +441,8 @@ fn check_for_is_empty( let is_empty = cx .tcx .inherent_impls(impl_ty) - .iter() + .into_iter() + .flatten() .flat_map(|&id| cx.tcx.associated_items(id).filter_by_name_unhygienic(is_empty)) .find(|item| item.kind == AssocKind::Fn); @@ -605,7 +606,7 @@ fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { /// Checks the inherent impl's items for an `is_empty(self)` method. fn has_is_empty_impl(cx: &LateContext<'_>, id: DefId) -> bool { let is_empty = sym!(is_empty); - cx.tcx.inherent_impls(id).iter().any(|imp| { + cx.tcx.inherent_impls(id).into_iter().flatten().any(|imp| { cx.tcx .associated_items(*imp) .filter_by_name_unhygienic(is_empty) diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs index c7980060807c..814ccaa36f5a 100644 --- a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs @@ -118,7 +118,7 @@ fn is_ref_iterable<'tcx>( .liberate_late_bound_regions(fn_id, cx.tcx.fn_sig(fn_id).skip_binder()) && let &[req_self_ty, req_res_ty] = &**sig.inputs_and_output && let param_env = cx.tcx.param_env(fn_id) - && implements_trait_with_env(cx.tcx, param_env, req_self_ty, trait_id, fn_id, &[]) + && implements_trait_with_env(cx.tcx, param_env, req_self_ty, trait_id, Some(fn_id), &[]) && let Some(into_iter_ty) = make_normalized_projection_with_regions(cx.tcx, param_env, trait_id, sym!(IntoIter), [req_self_ty]) && let req_res_ty = normalize_with_regions(cx.tcx, param_env, req_res_ty) diff --git a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs index c823d07e2bd3..5ca161e93096 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs @@ -11,7 +11,7 @@ use rustc_hir::{Arm, Expr, ExprKind, HirId, HirIdMap, HirIdMapEntry, HirIdSet, P use rustc_lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; use rustc_lint::LateContext; use rustc_middle::ty; -use rustc_span::Symbol; +use rustc_span::{ErrorGuaranteed, Symbol}; use super::MATCH_SAME_ARMS; @@ -167,6 +167,8 @@ enum NormalizedPat<'a> { /// contains everything afterwards. Note that either side, or both sides, may contain zero /// patterns. Slice(&'a [Self], Option<&'a [Self]>), + /// A placeholder for a pattern that wasn't well formed in some way. + Err(ErrorGuaranteed), } #[derive(Clone, Copy)] @@ -329,6 +331,7 @@ impl<'a> NormalizedPat<'a> { arena.alloc_from_iter(front.iter().map(|pat| Self::from_pat(cx, arena, pat))), wild_pat.map(|_| &*arena.alloc_from_iter(back.iter().map(|pat| Self::from_pat(cx, arena, pat)))), ), + PatKind::Err(guar) => Self::Err(guar), } } diff --git a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs index e38c66f6741d..0602eeaa7041 100644 --- a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs +++ b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs @@ -73,7 +73,8 @@ pub(super) fn check<'tcx>( let has_suggested_method = receiver_ty.ty_adt_def().is_some_and(|adt_def| { cx.tcx .inherent_impls(adt_def.did()) - .iter() + .into_iter() + .flatten() .flat_map(|impl_id| cx.tcx.associated_items(impl_id).filter_by_name_unhygienic(sugg)) .any(|assoc| { assoc.fn_has_self_parameter diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs index c62c351e7167..3416a93e3c4a 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs @@ -257,9 +257,9 @@ fn is_call_with_ref_arg<'tcx>( .. } = kind && args.len() == 1 - && let mir::Operand::Move(mir::Place { local, .. }) = &args[0] + && let mir::Operand::Move(mir::Place { local, .. }) = &args[0].node && let ty::FnDef(def_id, _) = *func.ty(mir, cx.tcx).kind() - && let (inner_ty, 1) = walk_ptrs_ty_depth(args[0].ty(mir, cx.tcx)) + && let (inner_ty, 1) = walk_ptrs_ty_depth(args[0].node.ty(mir, cx.tcx)) && !is_copy(cx, inner_ty) { Some((def_id, *local, inner_ty, destination.as_local()?)) diff --git a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs index cde08dfcc748..334e6770ae40 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs @@ -5,7 +5,9 @@ use clippy_utils::sugg::Sugg; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::intravisit::{Visitor as HirVisitor, Visitor}; -use rustc_hir::{intravisit as hir_visit, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, Node}; +use rustc_hir::{ + intravisit as hir_visit, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, ExprKind, Node, +}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_middle::lint::in_external_macro; @@ -166,10 +168,22 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { if coroutine_kind.is_async() && let hir::ExprKind::Closure(closure) = body.kind { - let async_closure_body = cx.tcx.hir().body(closure.body); + // Like `async fn`, async closures are wrapped in an additional block + // to move all of the closure's arguments into the future. + + let async_closure_body = cx.tcx.hir().body(closure.body).value; + let ExprKind::Block(block, _) = async_closure_body.kind else { + return; + }; + let Some(block_expr) = block.expr else { + return; + }; + let ExprKind::DropTemps(body_expr) = block_expr.kind else { + return; + }; // `async x` is a syntax error, so it becomes `async { x }` - if !matches!(async_closure_body.value.kind, hir::ExprKind::Block(_, _)) { + if !matches!(body_expr.kind, hir::ExprKind::Block(_, _)) { hint = hint.blockify(); } diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs index 81efec65343d..7882bfdd09fa 100644 --- a/src/tools/clippy/clippy_lints/src/types/mod.rs +++ b/src/tools/clippy/clippy_lints/src/types/mod.rs @@ -314,9 +314,9 @@ impl_lint_pass!(Types => [BOX_COLLECTION, VEC_BOX, OPTION_OPTION, LINKEDLIST, BO impl<'tcx> LateLintPass<'tcx> for Types { fn check_fn( &mut self, - cx: &LateContext<'_>, + cx: &LateContext<'tcx>, fn_kind: FnKind<'_>, - decl: &FnDecl<'_>, + decl: &FnDecl<'tcx>, _: &Body<'_>, _: Span, def_id: LocalDefId, @@ -346,7 +346,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { ); } - fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { let is_exported = cx.effective_visibilities.is_exported(item.owner_id.def_id); match item.kind { @@ -363,7 +363,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { } } - fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) { + fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'tcx>) { match item.kind { ImplItemKind::Const(ty, _) => { let is_in_trait_impl = if let Some(hir::Node::Item(item)) = cx @@ -391,7 +391,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { } } - fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) { + fn check_field_def(&mut self, cx: &LateContext<'tcx>, field: &hir::FieldDef<'tcx>) { let is_exported = cx.effective_visibilities.is_exported(field.def_id); self.check_ty( @@ -404,7 +404,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { ); } - fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &TraitItem<'_>) { + fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &TraitItem<'tcx>) { let is_exported = cx.effective_visibilities.is_exported(item.owner_id.def_id); let context = CheckTyContext { @@ -421,7 +421,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { } } - fn check_local(&mut self, cx: &LateContext<'_>, local: &Local<'_>) { + fn check_local(&mut self, cx: &LateContext<'tcx>, local: &Local<'tcx>) { if let Some(ty) = local.ty { self.check_ty( cx, @@ -444,7 +444,7 @@ impl Types { } } - fn check_fn_decl(&mut self, cx: &LateContext<'_>, decl: &FnDecl<'_>, context: CheckTyContext) { + fn check_fn_decl<'tcx>(&mut self, cx: &LateContext<'tcx>, decl: &FnDecl<'tcx>, context: CheckTyContext) { // Ignore functions in trait implementations as they are usually forced by the trait definition. // // FIXME: ideally we would like to warn *if the complicated type can be simplified*, but it's hard @@ -466,7 +466,7 @@ impl Types { /// lint found. /// /// The parameter `is_local` distinguishes the context of the type. - fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, mut context: CheckTyContext) { + fn check_ty<'tcx>(&mut self, cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>, mut context: CheckTyContext) { if hir_ty.span.from_expansion() { return; } diff --git a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs index 5a986254fad5..a0d609501a0c 100644 --- a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs +++ b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs @@ -11,7 +11,7 @@ use rustc_span::symbol::sym; use super::{utils, REDUNDANT_ALLOCATION}; -pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool { +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>, qpath: &QPath<'tcx>, def_id: DefId) -> bool { let mut applicability = Applicability::MaybeIncorrect; let outer_sym = if Some(def_id) == cx.tcx.lang_items().owned_box() { "Box" diff --git a/src/tools/clippy/clippy_lints/src/types/vec_box.rs b/src/tools/clippy/clippy_lints/src/types/vec_box.rs index 9d5066199bde..a285f771f1b1 100644 --- a/src/tools/clippy/clippy_lints/src/types/vec_box.rs +++ b/src/tools/clippy/clippy_lints/src/types/vec_box.rs @@ -13,10 +13,10 @@ use rustc_span::symbol::sym; use super::VEC_BOX; -pub(super) fn check( - cx: &LateContext<'_>, +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'_>, - qpath: &QPath<'_>, + qpath: &QPath<'tcx>, def_id: DefId, box_size_threshold: u64, ) -> bool { diff --git a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs index e90306ded61c..b418db53ea47 100644 --- a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs +++ b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs @@ -77,7 +77,7 @@ fn get_ty_def_id(ty: Ty<'_>) -> Option { } } -fn get_hir_ty_def_id(tcx: TyCtxt<'_>, hir_ty: rustc_hir::Ty<'_>) -> Option { +fn get_hir_ty_def_id<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: rustc_hir::Ty<'tcx>) -> Option { let TyKind::Path(qpath) = hir_ty.kind else { return None }; match qpath { QPath::Resolved(_, path) => path.res.opt_def_id(), @@ -229,7 +229,7 @@ fn check_to_string(cx: &LateContext<'_>, method_span: Span, method_def_id: Local } } -fn is_default_method_on_current_ty(tcx: TyCtxt<'_>, qpath: QPath<'_>, implemented_ty_id: DefId) -> bool { +fn is_default_method_on_current_ty<'tcx>(tcx: TyCtxt<'tcx>, qpath: QPath<'tcx>, implemented_ty_id: DefId) -> bool { match qpath { QPath::Resolved(_, path) => match path.segments { [first, .., last] => last.ident.name == kw::Default && first.res.opt_def_id() == Some(implemented_ty_id), diff --git a/src/tools/clippy/clippy_lints/src/uninhabited_references.rs b/src/tools/clippy/clippy_lints/src/uninhabited_references.rs index 903593ecfd7d..6732a43a19ec 100644 --- a/src/tools/clippy/clippy_lints/src/uninhabited_references.rs +++ b/src/tools/clippy/clippy_lints/src/uninhabited_references.rs @@ -57,11 +57,11 @@ impl LateLintPass<'_> for UninhabitedReferences { } } - fn check_fn( + fn check_fn<'tcx>( &mut self, - cx: &LateContext<'_>, + cx: &LateContext<'tcx>, kind: FnKind<'_>, - fndecl: &'_ FnDecl<'_>, + fndecl: &'_ FnDecl<'tcx>, _: &'_ Body<'_>, span: Span, _: LocalDefId, diff --git a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs index 77adcdd0e6bf..7246214f9bf8 100644 --- a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs +++ b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs @@ -226,7 +226,7 @@ fn transform_with_focus_on_idx(alternatives: &mut ThinVec>, focus_idx: us // Therefore they are not some form of constructor `C`, // with which a pattern `C(p_0)` may be formed, // which we would want to join with other `C(p_j)`s. - Ident(.., None) | Lit(_) | Wild | Never | Path(..) | Range(..) | Rest | MacCall(_) + Ident(.., None) | Lit(_) | Wild | Err(_) | Never | Path(..) | Range(..) | Rest | MacCall(_) // Skip immutable refs, as grouping them saves few characters, // and almost always requires adding parens (increasing noisiness). // In the case of only two patterns, replacement adds net characters. diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs index fa033838ef35..a1b08d105b9d 100644 --- a/src/tools/clippy/clippy_lints/src/use_self.rs +++ b/src/tools/clippy/clippy_lints/src/use_self.rs @@ -207,7 +207,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { } } - fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>) { + fn check_ty(&mut self, cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) { if !hir_ty.span.from_expansion() && self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS) && let Some(&StackItem::Check { diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index 8d38b87e1d79..b26ebe5cee32 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -710,6 +710,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { self.slice(start, |pat| self.pat(pat)); self.slice(end, |pat| self.pat(pat)); }, + PatKind::Err(_) => kind!("Err"), } } diff --git a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs index b36c4ef91dc6..81d4a26e9da4 100644 --- a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs +++ b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs @@ -44,7 +44,7 @@ declare_clippy_lint! { declare_lint_pass!(ZeroSizedMapValues => [ZERO_SIZED_MAP_VALUES]); impl LateLintPass<'_> for ZeroSizedMapValues { - fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>) { + fn check_ty<'tcx>(&mut self, cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) { if !hir_ty.span.from_expansion() && !in_trait_impl(cx, hir_ty.hir_id) && let ty = ty_from_hir_ty(cx, hir_ty) @@ -82,7 +82,7 @@ fn in_trait_impl(cx: &LateContext<'_>, hir_id: HirId) -> bool { false } -fn ty_from_hir_ty<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> { +fn ty_from_hir_ty<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { cx.maybe_typeck_results() .and_then(|results| { if results.hir_owner == hir_ty.hir_id.owner { diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 482eaed77d1d..979b117db256 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -1007,7 +1007,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } e.hash(&mut self.s); }, - PatKind::Never | PatKind::Wild => {}, + PatKind::Never | PatKind::Wild | PatKind::Err(_) => {}, } } diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index cdf8528f48a2..d264e46f1332 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -534,10 +534,11 @@ fn find_primitive_impls<'tcx>(tcx: TyCtxt<'tcx>, name: &str) -> impl Iterator SimplifiedType::Uint(UintTy::U128), "f32" => SimplifiedType::Float(FloatTy::F32), "f64" => SimplifiedType::Float(FloatTy::F64), - _ => return [].iter().copied(), + #[allow(trivial_casts)] + _ => return Result::<_, rustc_errors::ErrorGuaranteed>::Ok(&[] as &[_]).into_iter().flatten().copied(), }; - tcx.incoherent_impls(ty).iter().copied() + tcx.incoherent_impls(ty).into_iter().flatten().copied() } fn non_local_item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Vec { @@ -663,7 +664,8 @@ pub fn def_path_res(cx: &LateContext<'_>, path: &[&str]) -> Vec { // `impl S { ... }` let inherent_impl_children = tcx .inherent_impls(def_id) - .iter() + .into_iter() + .flatten() .flat_map(|&impl_def_id| item_children_by_name(tcx, impl_def_id, segment)); let direct_children = item_children_by_name(tcx, def_id, segment); @@ -1733,6 +1735,7 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool { }, } }, + PatKind::Err(_) => true, } } diff --git a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs index 703985b9d4b3..f9cc5f191253 100644 --- a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs +++ b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs @@ -104,7 +104,7 @@ impl<'a, 'b, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'b, let mut mutable_borrowers = vec![]; for op in args { - match op { + match &op.node { mir::Operand::Copy(p) | mir::Operand::Move(p) => { if let ty::Ref(_, _, Mutability::Mut) = self.body.local_decls[p.local].ty.kind() { mutable_borrowers.push(p.local); diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 668ea9fcf3b4..81f4fcc2133d 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -345,7 +345,7 @@ fn check_terminator<'tcx>( check_operand(tcx, func, span, body)?; for arg in args { - check_operand(tcx, arg, span, body)?; + check_operand(tcx, &arg.node, span, body)?; } Ok(()) } else { diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 61d0663aa839..59ebe685c11e 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -214,36 +214,21 @@ pub fn implements_trait<'tcx>( trait_id: DefId, args: &[GenericArg<'tcx>], ) -> bool { - let callee_id = cx - .enclosing_body - .map(|body| cx.tcx.hir().body_owner(body).owner.to_def_id()); - implements_trait_with_env_from_iter( - cx.tcx, - cx.param_env, - ty, - trait_id, - callee_id, - args.iter().map(|&x| Some(x)), - ) + implements_trait_with_env_from_iter(cx.tcx, cx.param_env, ty, trait_id, None, args.iter().map(|&x| Some(x))) } /// Same as `implements_trait` but allows using a `ParamEnv` different from the lint context. +/// +/// The `callee_id` argument is used to determine whether this is a function call in a `const fn` environment, used for checking const traits. pub fn implements_trait_with_env<'tcx>( tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>, trait_id: DefId, - callee_id: DefId, + callee_id: Option, args: &[GenericArg<'tcx>], ) -> bool { - implements_trait_with_env_from_iter( - tcx, - param_env, - ty, - trait_id, - Some(callee_id), - args.iter().map(|&x| Some(x)), - ) + implements_trait_with_env_from_iter(tcx, param_env, ty, trait_id, callee_id, args.iter().map(|&x| Some(x))) } /// Same as `implements_trait_from_env` but takes the arguments as an iterator. @@ -258,6 +243,13 @@ pub fn implements_trait_with_env_from_iter<'tcx>( // Clippy shouldn't have infer types assert!(!ty.has_infer()); + // If a `callee_id` is passed, then we assert that it is a body owner + // through calling `body_owner_kind`, which would panic if the callee + // does not have a body. + if let Some(callee_id) = callee_id { + let _ = tcx.hir().body_owner_kind(callee_id); + } + let ty = tcx.erase_regions(ty); if ty.has_escaping_bound_vars() { return false; diff --git a/src/tools/clippy/tests/ui/author/blocks.stdout b/src/tools/clippy/tests/ui/author/blocks.stdout index 62de661f8ff8..8c4d71e68f80 100644 --- a/src/tools/clippy/tests/ui/author/blocks.stdout +++ b/src/tools/clippy/tests/ui/author/blocks.stdout @@ -48,7 +48,11 @@ if let ExprKind::Closure { capture_clause: CaptureBy::Value { .. }, fn_decl: fn_ && expr2 = &cx.tcx.hir().body(body_id1).value && let ExprKind::Block(block, None) = expr2.kind && block.stmts.is_empty() - && block.expr.is_none() + && let Some(trailing_expr) = block.expr + && let ExprKind::DropTemps(expr3) = trailing_expr.kind + && let ExprKind::Block(block1, None) = expr3.kind + && block1.stmts.is_empty() + && block1.expr.is_none() { // report your lint here } diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 34d48559c378..42c751bb6bed 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -15,6 +15,15 @@ fn main() { eprintln!("warning: `tidy` is not installed; diffs will not be generated"); } + if !config.profiler_support && config.mode == Mode::CoverageRun { + let actioned = if config.bless { "blessed" } else { "checked" }; + eprintln!( + r#" +WARNING: profiler runtime is not available, so `.coverage` files won't be {actioned} +help: try setting `profiler = true` in the `[build]` section of `config.toml`"# + ); + } + log_config(&config); run_tests(config); } diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock index 6cd22a915189..8cd996d85645 100644 --- a/src/tools/miri/Cargo.lock +++ b/src/tools/miri/Cargo.lock @@ -486,9 +486,9 @@ checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "measureme" -version = "10.1.2" +version = "11.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45e381dcdad44c3c435f8052b08c5c4a1449c48ab56f312345eae12d7a693dbe" +checksum = "dfa4a40f09af7aa6faef38285402a78847d0d72bf8827006cd2a332e1e6e4a8d" dependencies = [ "log", "memmap2", diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml index 3da751c69a9f..a65010b055b6 100644 --- a/src/tools/miri/Cargo.toml +++ b/src/tools/miri/Cargo.toml @@ -24,7 +24,7 @@ log = "0.4" rand = "0.8" smallvec = "1.7" aes = { version = "0.8.3", features = ["hazmat"] } -measureme = "10.0.0" +measureme = "11" ctrlc = "3.2.5" # Copied from `compiler/rustc/Cargo.toml`. diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index ad3a534b7ed0..aa05d224c21f 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -3deb9bbf84f6431ebcbb7cbdbe3d89bc2636bc1b +867d39cdf625e4db4b381faff993346582e598b4 diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index cacd02bbfaee..80a47c852692 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -8,7 +8,6 @@ #![feature(variant_count)] #![feature(yeet_expr)] #![feature(nonzero_ops)] -#![feature(round_ties_even)] #![feature(let_chains)] #![feature(lint_reasons)] #![feature(int_roundings)] diff --git a/src/tools/miri/tests/fail-dep/shims/munmap_partial.rs b/src/tools/miri/tests/fail-dep/shims/munmap_partial.rs index 1d6e4796d0a5..d7aef47235f1 100644 --- a/src/tools/miri/tests/fail-dep/shims/munmap_partial.rs +++ b/src/tools/miri/tests/fail-dep/shims/munmap_partial.rs @@ -1,5 +1,5 @@ //! The man pages for mmap/munmap suggest that it is possible to partly unmap a previously-mapped -//! region of addres space, but to LLVM that would be partial deallocation, which LLVM does not +//! region of address space, but to LLVM that would be partial deallocation, which LLVM does not //! support. So even though the man pages say this sort of use is possible, we must report UB. //@ignore-target-windows: No libc on Windows //@normalize-stderr-test: "size [0-9]+ and alignment" -> "size SIZE and alignment" diff --git a/src/tools/miri/tests/fail/issue-miri-1112.rs b/src/tools/miri/tests/fail/issue-miri-1112.rs index 9542673b0d9e..387253a3f987 100644 --- a/src/tools/miri/tests/fail/issue-miri-1112.rs +++ b/src/tools/miri/tests/fail/issue-miri-1112.rs @@ -1,7 +1,7 @@ trait Empty {} #[repr(transparent)] -pub struct FunnyPointer(#[allow(dead_code)] dyn Empty); +pub struct FunnyPointer(dyn Empty); #[repr(C)] pub struct Meta { diff --git a/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs b/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs index 2283231eb010..d71d5954a40c 100644 --- a/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs +++ b/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs @@ -1,7 +1,7 @@ //@compile-flags: -Cdebug-assertions=no #[repr(transparent)] -struct HasDrop(#[allow(dead_code)] u8); +struct HasDrop(u8); impl Drop for HasDrop { fn drop(&mut self) {} diff --git a/src/tools/miri/tests/pass/async-fn.rs b/src/tools/miri/tests/pass/async-fn.rs index 6c92735df0af..13400c88c711 100644 --- a/src/tools/miri/tests/pass/async-fn.rs +++ b/src/tools/miri/tests/pass/async-fn.rs @@ -76,8 +76,7 @@ async fn uninhabited_variant() { fn run_fut(fut: impl Future) -> T { use std::task::{Context, Poll, Waker}; - let waker = Waker::noop(); - let mut context = Context::from_waker(&waker); + let mut context = Context::from_waker(Waker::noop()); let mut pinned = Box::pin(fut); loop { diff --git a/src/tools/miri/tests/pass/dyn-star.rs b/src/tools/miri/tests/pass/dyn-star.rs index 8e26c4850fa8..dab589b46518 100644 --- a/src/tools/miri/tests/pass/dyn-star.rs +++ b/src/tools/miri/tests/pass/dyn-star.rs @@ -93,8 +93,7 @@ fn dispatch_on_pin_mut() { let mut fut = async_main(); // Poll loop, just to test the future... - let waker = Waker::noop(); - let ctx = &mut Context::from_waker(&waker); + let ctx = &mut Context::from_waker(Waker::noop()); loop { match unsafe { Pin::new_unchecked(&mut fut).poll(ctx) } { diff --git a/src/tools/miri/tests/pass/float.rs b/src/tools/miri/tests/pass/float.rs index 5f2d4489f4ac..1bb44d56bf6b 100644 --- a/src/tools/miri/tests/pass/float.rs +++ b/src/tools/miri/tests/pass/float.rs @@ -1,5 +1,4 @@ #![feature(stmt_expr_attributes)] -#![feature(round_ties_even)] #![feature(float_gamma)] #![allow(arithmetic_overflow)] diff --git a/src/tools/miri/tests/pass/future-self-referential.rs b/src/tools/miri/tests/pass/future-self-referential.rs index 38cb700fd584..8aeb26a7a957 100644 --- a/src/tools/miri/tests/pass/future-self-referential.rs +++ b/src/tools/miri/tests/pass/future-self-referential.rs @@ -77,8 +77,7 @@ impl Future for DoStuff { } fn run_fut(fut: impl Future) -> T { - let waker = Waker::noop(); - let mut context = Context::from_waker(&waker); + let mut context = Context::from_waker(Waker::noop()); let mut pinned = pin!(fut); loop { @@ -90,8 +89,7 @@ fn run_fut(fut: impl Future) -> T { } fn self_referential_box() { - let waker = Waker::noop(); - let cx = &mut Context::from_waker(&waker); + let cx = &mut Context::from_waker(Waker::noop()); async fn my_fut() -> i32 { let val = 10; diff --git a/src/tools/miri/tests/pass/issues/issue-miri-2068.rs b/src/tools/miri/tests/pass/issues/issue-miri-2068.rs index f18c4a3a0655..ccee2221e295 100644 --- a/src/tools/miri/tests/pass/issues/issue-miri-2068.rs +++ b/src/tools/miri/tests/pass/issues/issue-miri-2068.rs @@ -6,8 +6,7 @@ use std::task::{Context, Poll, Waker}; pub fn fuzzing_block_on>(fut: F) -> O { let mut fut = std::pin::pin!(fut); - let waker = Waker::noop(); - let mut context = Context::from_waker(&waker); + let mut context = Context::from_waker(Waker::noop()); loop { match fut.as_mut().poll(&mut context) { Poll::Ready(v) => return v, diff --git a/src/tools/miri/tests/pass/move-data-across-await-point.rs b/src/tools/miri/tests/pass/move-data-across-await-point.rs index 9bea6ea57420..1a93a6bf6649 100644 --- a/src/tools/miri/tests/pass/move-data-across-await-point.rs +++ b/src/tools/miri/tests/pass/move-data-across-await-point.rs @@ -56,8 +56,7 @@ fn data_moved() { fn run_fut(fut: impl Future) -> T { use std::task::{Context, Poll, Waker}; - let waker = Waker::noop(); - let mut context = Context::from_waker(&waker); + let mut context = Context::from_waker(Waker::noop()); let mut pinned = Box::pin(fut); loop { diff --git a/src/tools/miropt-test-tools/src/lib.rs b/src/tools/miropt-test-tools/src/lib.rs index cae96f593199..7d60033c3e82 100644 --- a/src/tools/miropt-test-tools/src/lib.rs +++ b/src/tools/miropt-test-tools/src/lib.rs @@ -98,11 +98,12 @@ pub fn files_for_miropt_test( from_file = format!("{}.{}.mir", test_name, first_pass); to_file = Some(second_file); } else { - let ext_re = regex::Regex::new(r#"(\.(mir|dot|html))$"#).unwrap(); - let cap = ext_re - .captures_iter(test_name) - .next() - .expect("test_name has an invalid extension"); + // Allow-list for file extensions that can be produced by MIR dumps. + // Other extensions can be added here, as needed by new dump flags. + let ext_re = regex::Regex::new(r#"(\.(mir|dot))$"#).unwrap(); + let cap = ext_re.captures_iter(test_name).next().unwrap_or_else(|| { + panic!("in {testfile:?}:\nEMIT_MIR has an unrecognized extension: {test_name}") + }); let extension = cap.get(1).unwrap().as_str(); expected_file = diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index 6670e92f51bc..15d06222eb42 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -513,7 +513,8 @@ dependencies = [ "mbe", "once_cell", "profile", - "rustc-dependencies", + "ra-ap-rustc_abi", + "ra-ap-rustc_parse_format", "rustc-hash", "smallvec", "span", @@ -579,7 +580,8 @@ dependencies = [ "oorandom", "profile", "project-model", - "rustc-dependencies", + "ra-ap-rustc_abi", + "ra-ap-rustc_index", "rustc-hash", "scoped-tls", "smallvec", @@ -1196,7 +1198,7 @@ dependencies = [ "drop_bomb", "expect-test", "limit", - "rustc-dependencies", + "ra-ap-rustc_lexer", "sourcegen", "stdx", ] @@ -1540,7 +1542,6 @@ dependencies = [ "profile", "project-model", "rayon", - "rustc-dependencies", "rustc-hash", "scip", "serde", @@ -1567,9 +1568,9 @@ dependencies = [ [[package]] name = "rust-analyzer-salsa" -version = "0.17.0-pre.4" +version = "0.17.0-pre.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16c42b8737c320578b441a82daf7cdf8d897468de64e8a774fa54b53a50b6cc0" +checksum = "ca9d387a9801f4fb9b366789ad1bfc08448cafc49cf148d907cfcd88ab665d7f" dependencies = [ "indexmap", "lock_api", @@ -1579,13 +1580,14 @@ dependencies = [ "rust-analyzer-salsa-macros", "rustc-hash", "smallvec", + "triomphe", ] [[package]] name = "rust-analyzer-salsa-macros" -version = "0.17.0-pre.4" +version = "0.17.0-pre.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db72b0883f3592ade2be15a10583c75e0b269ec26e1190800fda2e2ce5ae6634" +checksum = "a2035f385d7fae31e9b086f40b272ee1d79c484472f31c9a10348a406e841eaf" dependencies = [ "heck", "proc-macro2", @@ -1599,16 +1601,6 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" -[[package]] -name = "rustc-dependencies" -version = "0.0.0" -dependencies = [ - "ra-ap-rustc_abi", - "ra-ap-rustc_index", - "ra-ap-rustc_lexer", - "ra-ap-rustc_parse_format", -] - [[package]] name = "rustc-hash" version = "1.1.0" @@ -1751,6 +1743,12 @@ dependencies = [ "vfs", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "static_assertions" version = "1.1.0" @@ -1808,9 +1806,9 @@ dependencies = [ "proc-macro2", "profile", "quote", + "ra-ap-rustc_lexer", "rayon", "rowan", - "rustc-dependencies", "rustc-hash", "smol_str", "sourcegen", @@ -2028,9 +2026,13 @@ dependencies = [ [[package]] name = "triomphe" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c5a71827ac326072b6405552093e2ad2accd25a32fd78d4edc82d98c7f2409" +checksum = "859eb650cfee7434994602c3a68b25d77ad9e68c8a6cd491616ef86661382eb3" +dependencies = [ + "serde", + "stable_deref_trait", +] [[package]] name = "tt" diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml index 4ee8064b5e34..35bef151196f 100644 --- a/src/tools/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/Cargo.toml @@ -78,7 +78,11 @@ toolchain = { path = "./crates/toolchain", version = "0.0.0" } tt = { path = "./crates/tt", version = "0.0.0" } vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" } vfs = { path = "./crates/vfs", version = "0.0.0" } -rustc-dependencies = { path = "./crates/rustc-dependencies", version = "0.0.0" } + +ra-ap-rustc_lexer = { version = "0.21.0", default-features = false } +ra-ap-rustc_parse_format = { version = "0.21.0", default-features = false } +ra-ap-rustc_index = { version = "0.21.0", default-features = false } +ra-ap-rustc_abi = { version = "0.21.0", default-features = false } # local crates that aren't published to crates.io. These should not have versions. sourcegen = { path = "./crates/sourcegen" } @@ -108,7 +112,7 @@ itertools = "0.12.0" libc = "0.2.150" nohash-hasher = "0.2.0" rayon = "1.8.0" -rust-analyzer-salsa = "0.17.0-pre.4" +rust-analyzer-salsa = "0.17.0-pre.5" rustc-hash = "1.1.0" semver = "1.0.14" serde = { version = "1.0.192", features = ["derive"] } diff --git a/src/tools/rust-analyzer/crates/base-db/src/lib.rs b/src/tools/rust-analyzer/crates/base-db/src/lib.rs index a0a55df5f99a..92d2b9c3f57c 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/lib.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/lib.rs @@ -7,7 +7,6 @@ mod change; use std::panic; -use rustc_hash::FxHashSet; use syntax::{ast, Parse, SourceFile}; use triomphe::Arc; @@ -44,12 +43,13 @@ pub trait Upcast { } pub const DEFAULT_PARSE_LRU_CAP: usize = 128; +pub const DEFAULT_BORROWCK_LRU_CAP: usize = 256; pub trait FileLoader { /// Text of the file. fn file_text(&self, file_id: FileId) -> Arc; fn resolve_path(&self, path: AnchoredPath<'_>) -> Option; - fn relevant_crates(&self, file_id: FileId) -> Arc>; + fn relevant_crates(&self, file_id: FileId) -> Arc<[CrateId]>; } /// Database which stores all significant input facts: source code and project @@ -84,19 +84,21 @@ pub trait SourceDatabaseExt: SourceDatabase { #[salsa::input] fn source_root(&self, id: SourceRootId) -> Arc; - fn source_root_crates(&self, id: SourceRootId) -> Arc>; + fn source_root_crates(&self, id: SourceRootId) -> Arc<[CrateId]>; } -fn source_root_crates(db: &dyn SourceDatabaseExt, id: SourceRootId) -> Arc> { +fn source_root_crates(db: &dyn SourceDatabaseExt, id: SourceRootId) -> Arc<[CrateId]> { let graph = db.crate_graph(); - let res = graph + let mut crates = graph .iter() .filter(|&krate| { let root_file = graph[krate].root_file_id; db.file_source_root(root_file) == id }) - .collect(); - Arc::new(res) + .collect::>(); + crates.sort(); + crates.dedup(); + crates.into_iter().collect() } /// Silly workaround for cyclic deps between the traits @@ -113,7 +115,7 @@ impl FileLoader for FileLoaderDelegate<&'_ T> { source_root.resolve_path(path) } - fn relevant_crates(&self, file_id: FileId) -> Arc> { + fn relevant_crates(&self, file_id: FileId) -> Arc<[CrateId]> { let _p = profile::span("relevant_crates"); let source_root = self.0.file_source_root(file_id); self.0.source_root_crates(source_root) diff --git a/src/tools/rust-analyzer/crates/hir-def/Cargo.toml b/src/tools/rust-analyzer/crates/hir-def/Cargo.toml index 5933d30040fa..523ff6fc404e 100644 --- a/src/tools/rust-analyzer/crates/hir-def/Cargo.toml +++ b/src/tools/rust-analyzer/crates/hir-def/Cargo.toml @@ -29,7 +29,8 @@ smallvec.workspace = true hashbrown.workspace = true triomphe.workspace = true -rustc-dependencies.workspace = true +ra-ap-rustc_parse_format.workspace = true +ra-ap-rustc_abi.workspace = true # local deps stdx.workspace = true @@ -53,7 +54,7 @@ test-utils.workspace = true test-fixture.workspace = true [features] -in-rust-tree = ["rustc-dependencies/in-rust-tree"] +in-rust-tree = [] [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs index 26f76afb1f09..30452e34aac3 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs @@ -207,6 +207,13 @@ impl Attrs { }) } + pub fn has_doc_notable_trait(&self) -> bool { + self.by_key("doc").tt_values().any(|tt| { + tt.delimiter.kind == DelimiterKind::Parenthesis && + matches!(&*tt.token_trees, [tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] if ident.text == "notable_trait") + }) + } + pub fn doc_exprs(&self) -> impl Iterator + '_ { self.by_key("doc").tt_values().map(DocExpr::parse) } @@ -355,7 +362,7 @@ fn parse_comma_sep(subtree: &tt::Subtree) -> Vec { } impl AttrsWithOwner { - pub(crate) fn attrs_with_owner(db: &dyn DefDatabase, owner: AttrDefId) -> Self { + pub fn attrs_with_owner(db: &dyn DefDatabase, owner: AttrDefId) -> Self { Self { attrs: db.attrs(owner), owner } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs index c728570d9866..fc0a4eb43dc2 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs @@ -965,11 +965,10 @@ impl ExprCollector<'_> { let res = match self.def_map.modules[module] .scope - .macro_invocations - .get(&InFile::new(outer_file, self.ast_id_map.ast_id_for_ptr(syntax_ptr))) + .macro_invoc(InFile::new(outer_file, self.ast_id_map.ast_id_for_ptr(syntax_ptr))) { // fast path, macro call is in a block module - Some(&call) => Ok(self.expander.enter_expand_id(self.db, call)), + Some(call) => Ok(self.expander.enter_expand_id(self.db, call)), None => self.expander.enter_expand(self.db, mcall, |path| { self.def_map .resolve_path( diff --git a/src/tools/rust-analyzer/crates/hir-def/src/child_by_source.rs b/src/tools/rust-analyzer/crates/hir-def/src/child_by_source.rs index c82d2347de5c..32c53cb95031 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/child_by_source.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/child_by_source.rs @@ -92,7 +92,7 @@ impl ChildBySource for ItemScope { self.impls().for_each(|imp| add_impl(db, res, file_id, imp)); self.extern_crate_decls().for_each(|ext| add_extern_crate(db, res, file_id, ext)); self.use_decls().for_each(|ext| add_use(db, res, file_id, ext)); - self.unnamed_consts().for_each(|konst| { + self.unnamed_consts(db).for_each(|konst| { let loc = konst.lookup(db); if loc.id.file_id() == file_id { res[keys::CONST].insert(loc.source(db).value, konst); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs index a95b78614e82..8772c34f02f1 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs @@ -11,7 +11,7 @@ use hir_expand::{ }; use intern::Interned; use la_arena::{Arena, ArenaMap}; -use rustc_dependencies::abi::{Align, Integer, IntegerType, ReprFlags, ReprOptions}; +use rustc_abi::{Align, Integer, IntegerType, ReprFlags, ReprOptions}; use syntax::ast::{self, HasName, HasVisibility}; use triomphe::Arc; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/db.rs b/src/tools/rust-analyzer/crates/hir-def/src/db.rs index d5831022f28f..70c0d5193d4b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs @@ -210,13 +210,10 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast Attrs; + #[salsa::transparent] #[salsa::invoke(lang_item::lang_attr_query)] fn lang_attr(&self, def: AttrDefId) -> Option; - #[salsa::transparent] - #[salsa::invoke(AttrsWithOwner::attrs_with_owner)] - fn attrs_with_owner(&self, def: AttrDefId) -> AttrsWithOwner; - // endregion:attrs #[salsa::invoke(LangItems::lang_item_query)] @@ -240,7 +237,7 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast Arc; + fn crate_lang_items(&self, krate: CrateId) -> Option>; fn crate_supports_no_std(&self, crate_id: CrateId) -> bool; } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs index 4737b48703db..67e43f15cd3f 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs @@ -10,7 +10,7 @@ use crate::{ item_scope::ItemInNs, nameres::DefMap, path::{ModPath, PathKind}, - visibility::Visibility, + visibility::{Visibility, VisibilityExplicity}, CrateRootModuleId, ModuleDefId, ModuleId, }; @@ -24,7 +24,7 @@ pub fn find_path( prefer_prelude: bool, ) -> Option { let _p = profile::span("find_path"); - find_path_inner(db, item, from, None, prefer_no_std, prefer_prelude) + find_path_inner(FindPathCtx { db, prefixed: None, prefer_no_std, prefer_prelude }, item, from) } pub fn find_path_prefixed( @@ -36,7 +36,11 @@ pub fn find_path_prefixed( prefer_prelude: bool, ) -> Option { let _p = profile::span("find_path_prefixed"); - find_path_inner(db, item, from, Some(prefix_kind), prefer_no_std, prefer_prelude) + find_path_inner( + FindPathCtx { db, prefixed: Some(prefix_kind), prefer_no_std, prefer_prelude }, + item, + from, + ) } #[derive(Copy, Clone, Debug)] @@ -83,64 +87,60 @@ impl PrefixKind { } } -/// Attempts to find a path to refer to the given `item` visible from the `from` ModuleId -fn find_path_inner( - db: &dyn DefDatabase, - item: ItemInNs, - from: ModuleId, +#[derive(Copy, Clone)] +struct FindPathCtx<'db> { + db: &'db dyn DefDatabase, prefixed: Option, prefer_no_std: bool, prefer_prelude: bool, -) -> Option { +} + +/// Attempts to find a path to refer to the given `item` visible from the `from` ModuleId +fn find_path_inner(ctx: FindPathCtx<'_>, item: ItemInNs, from: ModuleId) -> Option { // - if the item is a builtin, it's in scope if let ItemInNs::Types(ModuleDefId::BuiltinType(builtin)) = item { return Some(ModPath::from_segments(PathKind::Plain, Some(builtin.as_name()))); } - let def_map = from.def_map(db); + let def_map = from.def_map(ctx.db); let crate_root = def_map.crate_root(); // - if the item is a module, jump straight to module search if let ItemInNs::Types(ModuleDefId::ModuleId(module_id)) = item { let mut visited_modules = FxHashSet::default(); return find_path_for_module( - db, + FindPathCtx { + prefer_no_std: ctx.prefer_no_std || ctx.db.crate_supports_no_std(crate_root.krate), + ..ctx + }, &def_map, &mut visited_modules, crate_root, from, module_id, MAX_PATH_LEN, - prefixed, - prefer_no_std || db.crate_supports_no_std(crate_root.krate), - prefer_prelude, ) .map(|(item, _)| item); } // - if the item is already in scope, return the name under which it is - let scope_name = find_in_scope(db, &def_map, from, item); - if prefixed.is_none() { + let scope_name = find_in_scope(ctx.db, &def_map, from, item); + if ctx.prefixed.is_none() { if let Some(scope_name) = scope_name { return Some(ModPath::from_segments(PathKind::Plain, Some(scope_name))); } } // - if the item is in the prelude, return the name from there - if let value @ Some(_) = find_in_prelude(db, &crate_root.def_map(db), &def_map, item, from) { + if let value @ Some(_) = + find_in_prelude(ctx.db, &crate_root.def_map(ctx.db), &def_map, item, from) + { return value; } if let Some(ModuleDefId::EnumVariantId(variant)) = item.as_module_def_id() { // - if the item is an enum variant, refer to it via the enum - if let Some(mut path) = find_path_inner( - db, - ItemInNs::Types(variant.parent.into()), - from, - prefixed, - prefer_no_std, - prefer_prelude, - ) { - let data = db.enum_data(variant.parent); + if let Some(mut path) = find_path_inner(ctx, ItemInNs::Types(variant.parent.into()), from) { + let data = ctx.db.enum_data(variant.parent); path.push_segment(data.variants[variant.local_id].name.clone()); return Some(path); } @@ -152,32 +152,29 @@ fn find_path_inner( let mut visited_modules = FxHashSet::default(); calculate_best_path( - db, + FindPathCtx { + prefer_no_std: ctx.prefer_no_std || ctx.db.crate_supports_no_std(crate_root.krate), + ..ctx + }, &def_map, &mut visited_modules, crate_root, MAX_PATH_LEN, item, from, - prefixed, - prefer_no_std || db.crate_supports_no_std(crate_root.krate), - prefer_prelude, scope_name, ) .map(|(item, _)| item) } fn find_path_for_module( - db: &dyn DefDatabase, + ctx: FindPathCtx<'_>, def_map: &DefMap, visited_modules: &mut FxHashSet, crate_root: CrateRootModuleId, from: ModuleId, module_id: ModuleId, max_len: usize, - prefixed: Option, - prefer_no_std: bool, - prefer_prelude: bool, ) -> Option<(ModPath, Stability)> { if max_len == 0 { return None; @@ -185,8 +182,8 @@ fn find_path_for_module( // Base cases: // - if the item is already in scope, return the name under which it is - let scope_name = find_in_scope(db, def_map, from, ItemInNs::Types(module_id.into())); - if prefixed.is_none() { + let scope_name = find_in_scope(ctx.db, def_map, from, ItemInNs::Types(module_id.into())); + if ctx.prefixed.is_none() { if let Some(scope_name) = scope_name { return Some((ModPath::from_segments(PathKind::Plain, Some(scope_name)), Stable)); } @@ -198,20 +195,20 @@ fn find_path_for_module( } // - if relative paths are fine, check if we are searching for a parent - if prefixed.filter(PrefixKind::is_absolute).is_none() { + if ctx.prefixed.filter(PrefixKind::is_absolute).is_none() { if let modpath @ Some(_) = find_self_super(def_map, module_id, from) { return modpath.zip(Some(Stable)); } } // - if the item is the crate root of a dependency crate, return the name from the extern prelude - let root_def_map = crate_root.def_map(db); + let root_def_map = crate_root.def_map(ctx.db); for (name, (def_id, _extern_crate)) in root_def_map.extern_prelude() { if module_id == def_id { let name = scope_name.unwrap_or_else(|| name.clone()); let name_already_occupied_in_type_ns = def_map - .with_ancestor_maps(db, from.local_id, &mut |def_map, local_id| { + .with_ancestor_maps(ctx.db, from.local_id, &mut |def_map, local_id| { def_map[local_id] .scope .type_(&name) @@ -229,21 +226,18 @@ fn find_path_for_module( } if let value @ Some(_) = - find_in_prelude(db, &root_def_map, &def_map, ItemInNs::Types(module_id.into()), from) + find_in_prelude(ctx.db, &root_def_map, &def_map, ItemInNs::Types(module_id.into()), from) { return value.zip(Some(Stable)); } calculate_best_path( - db, + ctx, def_map, visited_modules, crate_root, max_len, ItemInNs::Types(module_id.into()), from, - prefixed, - prefer_no_std, - prefer_prelude, scope_name, ) } @@ -256,7 +250,7 @@ fn find_in_scope( item: ItemInNs, ) -> Option { def_map.with_ancestor_maps(db, from.local_id, &mut |def_map, local_id| { - def_map[local_id].scope.name_of(item).map(|(name, _)| name.clone()) + def_map[local_id].scope.name_of(item).map(|(name, _, _)| name.clone()) }) } @@ -273,7 +267,7 @@ fn find_in_prelude( // Preludes in block DefMaps are ignored, only the crate DefMap is searched let prelude_def_map = prelude_module.def_map(db); let prelude_scope = &prelude_def_map[prelude_module.local_id].scope; - let (name, vis) = prelude_scope.name_of(item)?; + let (name, vis, _declared) = prelude_scope.name_of(item)?; if !vis.is_visible_from(db, from) { return None; } @@ -315,16 +309,13 @@ fn find_self_super(def_map: &DefMap, item: ModuleId, from: ModuleId) -> Option, def_map: &DefMap, visited_modules: &mut FxHashSet, crate_root: CrateRootModuleId, max_len: usize, item: ItemInNs, from: ModuleId, - mut prefixed: Option, - prefer_no_std: bool, - prefer_prelude: bool, scope_name: Option, ) -> Option<(ModPath, Stability)> { if max_len <= 1 { @@ -341,32 +332,29 @@ fn calculate_best_path( }; // Recursive case: // - otherwise, look for modules containing (reexporting) it and import it from one of those - if item.krate(db) == Some(from.krate) { + if item.krate(ctx.db) == Some(from.krate) { let mut best_path_len = max_len; // Item was defined in the same crate that wants to import it. It cannot be found in any // dependency in this case. - for (module_id, name) in find_local_import_locations(db, item, from) { + for (module_id, name) in find_local_import_locations(ctx.db, item, from) { if !visited_modules.insert(module_id) { cov_mark::hit!(recursive_imports); continue; } if let Some(mut path) = find_path_for_module( - db, + ctx, def_map, visited_modules, crate_root, from, module_id, best_path_len - 1, - prefixed, - prefer_no_std, - prefer_prelude, ) { path.0.push_segment(name); let new_path = match best_path.take() { Some(best_path) => { - select_best_path(best_path, path, prefer_no_std, prefer_prelude) + select_best_path(best_path, path, ctx.prefer_no_std, ctx.prefer_prelude) } None => path, }; @@ -379,8 +367,8 @@ fn calculate_best_path( // too (unless we can't name it at all). It could *also* be (re)exported by the same crate // that wants to import it here, but we always prefer to use the external path here. - for dep in &db.crate_graph()[from.krate].dependencies { - let import_map = db.import_map(dep.crate_id); + for dep in &ctx.db.crate_graph()[from.krate].dependencies { + let import_map = ctx.db.import_map(dep.crate_id); let Some(import_info_for) = import_map.import_info_for(item) else { continue }; for info in import_info_for { if info.is_doc_hidden { @@ -391,16 +379,13 @@ fn calculate_best_path( // Determine best path for containing module and append last segment from `info`. // FIXME: we should guide this to look up the path locally, or from the same crate again? let Some((mut path, path_stability)) = find_path_for_module( - db, + ctx, def_map, visited_modules, crate_root, from, info.container, max_len - 1, - prefixed, - prefer_no_std, - prefer_prelude, ) else { continue; }; @@ -413,17 +398,21 @@ fn calculate_best_path( ); let new_path_with_stab = match best_path.take() { - Some(best_path) => { - select_best_path(best_path, path_with_stab, prefer_no_std, prefer_prelude) - } + Some(best_path) => select_best_path( + best_path, + path_with_stab, + ctx.prefer_no_std, + ctx.prefer_prelude, + ), None => path_with_stab, }; update_best_path(&mut best_path, new_path_with_stab); } } } - if let Some(module) = item.module(db) { - if module.containing_block().is_some() && prefixed.is_some() { + let mut prefixed = ctx.prefixed; + if let Some(module) = item.module(ctx.db) { + if module.containing_block().is_some() && ctx.prefixed.is_some() { cov_mark::hit!(prefixed_in_block_expression); prefixed = Some(PrefixKind::Plain); } @@ -548,34 +537,35 @@ fn find_local_import_locations( &ext_def_map[module.local_id] }; - if let Some((name, vis)) = data.scope.name_of(item) { + if let Some((name, vis, declared)) = data.scope.name_of(item) { if vis.is_visible_from(db, from) { - let is_private = match vis { - Visibility::Module(private_to) => private_to.local_id == module.local_id, - Visibility::Public => false, - }; - let is_original_def = match item.as_module_def_id() { - Some(module_def_id) => data.scope.declarations().any(|it| it == module_def_id), - None => false, + let is_pub_or_explicit = match vis { + Visibility::Module(_, VisibilityExplicity::Explicit) => { + cov_mark::hit!(explicit_private_imports); + true + } + Visibility::Module(_, VisibilityExplicity::Implicit) => { + cov_mark::hit!(discount_private_imports); + false + } + Visibility::Public => true, }; - // Ignore private imports. these could be used if we are + // Ignore private imports unless they are explicit. these could be used if we are // in a submodule of this module, but that's usually not // what the user wants; and if this module can import // the item and we're a submodule of it, so can we. // Also this keeps the cached data smaller. - if !is_private || is_original_def { + if is_pub_or_explicit || declared { locations.push((module, name.clone())); } } } // Descend into all modules visible from `from`. - for (ty, vis) in data.scope.types() { - if let ModuleDefId::ModuleId(module) = ty { - if vis.is_visible_from(db, from) { - worklist.push(module); - } + for (module, vis) in data.scope.modules_in_scope() { + if vis.is_visible_from(db, from) { + worklist.push(module); } } } @@ -625,16 +615,14 @@ mod tests { .expect("path does not resolve to a type"); let found_path = find_path_inner( - &db, + FindPathCtx { prefer_no_std: false, db: &db, prefixed: prefix_kind, prefer_prelude }, ItemInNs::Types(resolved), module, - prefix_kind, - false, - prefer_prelude, ); assert_eq!(found_path, Some(mod_path), "on kind: {prefix_kind:?}"); } + #[track_caller] fn check_found_path( ra_fixture: &str, unprefixed: &str, @@ -1004,6 +992,7 @@ pub use crate::foo::bar::S; #[test] fn discount_private_imports() { + cov_mark::check!(discount_private_imports); check_found_path( r#" //- /main.rs @@ -1021,6 +1010,47 @@ $0 ); } + #[test] + fn explicit_private_imports_crate() { + cov_mark::check!(explicit_private_imports); + check_found_path( + r#" +//- /main.rs +mod foo; +pub mod bar { pub struct S; } +pub(crate) use bar::S; +//- /foo.rs +$0 + "#, + "crate::S", + "crate::S", + "crate::S", + "crate::S", + ); + } + + #[test] + fn explicit_private_imports() { + cov_mark::check!(explicit_private_imports); + check_found_path( + r#" +//- /main.rs +pub mod bar { + mod foo; + pub mod baz { pub struct S; } + pub(self) use baz::S; +} + +//- /bar/foo.rs +$0 + "#, + "super::S", + "super::S", + "crate::bar::S", + "super::S", + ); + } + #[test] fn import_cycle() { check_found_path( diff --git a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs index f5324f052e59..6cb9b8448d14 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs @@ -107,11 +107,11 @@ impl TypeOrConstParamData { impl_from!(TypeParamData, ConstParamData for TypeOrConstParamData); /// Data about the generic parameters of a function, struct, impl, etc. -#[derive(Clone, PartialEq, Eq, Debug, Default, Hash)] +#[derive(Clone, PartialEq, Eq, Debug, Hash)] pub struct GenericParams { pub type_or_consts: Arena, pub lifetimes: Arena, - pub where_predicates: Vec, + pub where_predicates: Box<[WherePredicate]>, } /// A single predicate from a where clause, i.e. `where Type: Trait`. Combined @@ -142,109 +142,14 @@ pub enum WherePredicateTypeTarget { TypeOrConstParam(LocalTypeOrConstParamId), } -impl GenericParams { - /// Iterator of type_or_consts field - pub fn iter( - &self, - ) -> impl DoubleEndedIterator, &TypeOrConstParamData)> { - self.type_or_consts.iter() - } - - pub(crate) fn generic_params_query( - db: &dyn DefDatabase, - def: GenericDefId, - ) -> Interned { - let _p = profile::span("generic_params_query"); - - let krate = def.module(db).krate; - let cfg_options = db.crate_graph(); - let cfg_options = &cfg_options[krate].cfg_options; - - // Returns the generic parameters that are enabled under the current `#[cfg]` options - let enabled_params = |params: &Interned, item_tree: &ItemTree| { - let enabled = |param| item_tree.attrs(db, krate, param).is_cfg_enabled(cfg_options); - - // In the common case, no parameters will by disabled by `#[cfg]` attributes. - // Therefore, make a first pass to check if all parameters are enabled and, if so, - // clone the `Interned` instead of recreating an identical copy. - let all_type_or_consts_enabled = - params.type_or_consts.iter().all(|(idx, _)| enabled(idx.into())); - let all_lifetimes_enabled = params.lifetimes.iter().all(|(idx, _)| enabled(idx.into())); - - if all_type_or_consts_enabled && all_lifetimes_enabled { - params.clone() - } else { - Interned::new(GenericParams { - type_or_consts: all_type_or_consts_enabled - .then(|| params.type_or_consts.clone()) - .unwrap_or_else(|| { - params - .type_or_consts - .iter() - .filter_map(|(idx, param)| { - enabled(idx.into()).then(|| param.clone()) - }) - .collect() - }), - lifetimes: all_lifetimes_enabled - .then(|| params.lifetimes.clone()) - .unwrap_or_else(|| { - params - .lifetimes - .iter() - .filter_map(|(idx, param)| { - enabled(idx.into()).then(|| param.clone()) - }) - .collect() - }), - where_predicates: params.where_predicates.clone(), - }) - } - }; - macro_rules! id_to_generics { - ($id:ident) => {{ - let id = $id.lookup(db).id; - let tree = id.item_tree(db); - let item = &tree[id.value]; - enabled_params(&item.generic_params, &tree) - }}; - } - - match def { - GenericDefId::FunctionId(id) => { - let loc = id.lookup(db); - let tree = loc.id.item_tree(db); - let item = &tree[loc.id.value]; - - let enabled_params = enabled_params(&item.explicit_generic_params, &tree); - let mut generic_params = GenericParams::clone(&enabled_params); - - let module = loc.container.module(db); - let func_data = db.function_data(id); - - // Don't create an `Expander` if not needed since this - // could cause a reparse after the `ItemTree` has been created due to the spanmap. - let mut expander = - Lazy::new(|| (module.def_map(db), Expander::new(db, loc.id.file_id(), module))); - for param in func_data.params.iter() { - generic_params.fill_implicit_impl_trait_args(db, &mut expander, param); - } - - Interned::new(generic_params) - } - GenericDefId::AdtId(AdtId::StructId(id)) => id_to_generics!(id), - GenericDefId::AdtId(AdtId::EnumId(id)) => id_to_generics!(id), - GenericDefId::AdtId(AdtId::UnionId(id)) => id_to_generics!(id), - GenericDefId::TraitId(id) => id_to_generics!(id), - GenericDefId::TraitAliasId(id) => id_to_generics!(id), - GenericDefId::TypeAliasId(id) => id_to_generics!(id), - GenericDefId::ImplId(id) => id_to_generics!(id), - GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => { - Interned::new(GenericParams::default()) - } - } - } +#[derive(Clone, Default)] +pub(crate) struct GenericParamsCollector { + pub(crate) type_or_consts: Arena, + lifetimes: Arena, + where_predicates: Vec, +} +impl GenericParamsCollector { pub(crate) fn fill( &mut self, lower_ctx: &LowerCtx<'_>, @@ -444,11 +349,131 @@ impl GenericParams { }); } - pub(crate) fn shrink_to_fit(&mut self) { - let Self { lifetimes, type_or_consts: types, where_predicates } = self; + pub(crate) fn finish(self) -> GenericParams { + let Self { mut lifetimes, mut type_or_consts, where_predicates } = self; lifetimes.shrink_to_fit(); - types.shrink_to_fit(); - where_predicates.shrink_to_fit(); + type_or_consts.shrink_to_fit(); + GenericParams { + type_or_consts, + lifetimes, + where_predicates: where_predicates.into_boxed_slice(), + } + } +} + +impl GenericParams { + /// Iterator of type_or_consts field + pub fn iter( + &self, + ) -> impl DoubleEndedIterator, &TypeOrConstParamData)> { + self.type_or_consts.iter() + } + + pub(crate) fn generic_params_query( + db: &dyn DefDatabase, + def: GenericDefId, + ) -> Interned { + let _p = profile::span("generic_params_query"); + + let krate = def.module(db).krate; + let cfg_options = db.crate_graph(); + let cfg_options = &cfg_options[krate].cfg_options; + + // Returns the generic parameters that are enabled under the current `#[cfg]` options + let enabled_params = |params: &Interned, item_tree: &ItemTree| { + let enabled = |param| item_tree.attrs(db, krate, param).is_cfg_enabled(cfg_options); + + // In the common case, no parameters will by disabled by `#[cfg]` attributes. + // Therefore, make a first pass to check if all parameters are enabled and, if so, + // clone the `Interned` instead of recreating an identical copy. + let all_type_or_consts_enabled = + params.type_or_consts.iter().all(|(idx, _)| enabled(idx.into())); + let all_lifetimes_enabled = params.lifetimes.iter().all(|(idx, _)| enabled(idx.into())); + + if all_type_or_consts_enabled && all_lifetimes_enabled { + params.clone() + } else { + Interned::new(GenericParams { + type_or_consts: all_type_or_consts_enabled + .then(|| params.type_or_consts.clone()) + .unwrap_or_else(|| { + params + .type_or_consts + .iter() + .filter_map(|(idx, param)| { + enabled(idx.into()).then(|| param.clone()) + }) + .collect() + }), + lifetimes: all_lifetimes_enabled + .then(|| params.lifetimes.clone()) + .unwrap_or_else(|| { + params + .lifetimes + .iter() + .filter_map(|(idx, param)| { + enabled(idx.into()).then(|| param.clone()) + }) + .collect() + }), + where_predicates: params.where_predicates.clone(), + }) + } + }; + macro_rules! id_to_generics { + ($id:ident) => {{ + let id = $id.lookup(db).id; + let tree = id.item_tree(db); + let item = &tree[id.value]; + enabled_params(&item.generic_params, &tree) + }}; + } + + match def { + GenericDefId::FunctionId(id) => { + let loc = id.lookup(db); + let tree = loc.id.item_tree(db); + let item = &tree[loc.id.value]; + + let enabled_params = enabled_params(&item.explicit_generic_params, &tree); + + let module = loc.container.module(db); + let func_data = db.function_data(id); + if func_data.params.is_empty() { + enabled_params + } else { + let mut generic_params = GenericParamsCollector { + type_or_consts: enabled_params.type_or_consts.clone(), + lifetimes: enabled_params.lifetimes.clone(), + where_predicates: enabled_params.where_predicates.clone().into(), + }; + + // Don't create an `Expander` if not needed since this + // could cause a reparse after the `ItemTree` has been created due to the spanmap. + let mut expander = Lazy::new(|| { + (module.def_map(db), Expander::new(db, loc.id.file_id(), module)) + }); + for param in func_data.params.iter() { + generic_params.fill_implicit_impl_trait_args(db, &mut expander, param); + } + Interned::new(generic_params.finish()) + } + } + GenericDefId::AdtId(AdtId::StructId(id)) => id_to_generics!(id), + GenericDefId::AdtId(AdtId::EnumId(id)) => id_to_generics!(id), + GenericDefId::AdtId(AdtId::UnionId(id)) => id_to_generics!(id), + GenericDefId::TraitId(id) => id_to_generics!(id), + GenericDefId::TraitAliasId(id) => id_to_generics!(id), + GenericDefId::TypeAliasId(id) => id_to_generics!(id), + GenericDefId::ImplId(id) => id_to_generics!(id), + GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => { + Interned::new(GenericParams { + type_or_consts: Default::default(), + lifetimes: Default::default(), + where_predicates: Default::default(), + }) + } + } } pub fn find_type_by_name(&self, name: &Name, parent: GenericDefId) -> Option { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs index 7fc33abc7c9a..c0d1738b5048 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs @@ -2,7 +2,7 @@ use std::mem; use hir_expand::name::Name; -use rustc_dependencies::parse_format as parse; +use rustc_parse_format as parse; use stdx::TupleExt; use syntax::{ ast::{self, IsString}, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs index 75adf21abdcb..935a8ebad165 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs @@ -116,8 +116,7 @@ pub enum TypeRef { Path(Path), RawPtr(Box, Mutability), Reference(Box, Option, Mutability), - // FIXME: for full const generics, the latter element (length) here is going to have to be an - // expression that is further lowered later in hir_ty. + // FIXME: This should be Array(Box, Ast), Array(Box, ConstRef), Slice(Box), /// A fn pointer. Last element of the vector is the return type. diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs index 4902f24e2e3a..168ee4acffbe 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs @@ -15,9 +15,11 @@ use stdx::format_to; use syntax::ast; use crate::{ - db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, ConstId, - ExternCrateId, HasModule, ImplId, LocalModuleId, Lookup, MacroId, ModuleDefId, ModuleId, - TraitId, UseId, + db::DefDatabase, + per_ns::PerNs, + visibility::{Visibility, VisibilityExplicity}, + AdtId, BuiltinType, ConstId, ExternCrateId, HasModule, ImplId, LocalModuleId, Lookup, MacroId, + ModuleDefId, ModuleId, TraitId, UseId, }; #[derive(Debug, Default)] @@ -105,7 +107,7 @@ pub struct ItemScope { /// The attribute macro invocations in this scope. attr_macros: FxHashMap, MacroCallId>, /// The macro invocations in this scope. - pub macro_invocations: FxHashMap, MacroCallId>, + macro_invocations: FxHashMap, MacroCallId>, /// The derive macro invocations in this scope, keyed by the owner item over the actual derive attributes /// paired with the derive macro invocations for the specific attribute. derive_macros: FxHashMap, SmallVec<[DeriveMacroInvocation; 1]>>, @@ -145,8 +147,8 @@ impl ItemScope { .chain(self.values.keys()) .chain(self.macros.keys()) .chain(self.unresolved.iter()) - .unique() .sorted() + .dedup() .map(move |name| (name, self.get(name))) } @@ -157,8 +159,8 @@ impl ItemScope { .filter_map(ImportOrExternCrate::into_import) .chain(self.use_imports_values.keys().copied()) .chain(self.use_imports_macros.keys().copied()) - .unique() .sorted() + .dedup() } pub fn fully_resolve_import(&self, db: &dyn DefDatabase, mut import: ImportId) -> PerNs { @@ -234,20 +236,37 @@ impl ItemScope { self.impls.iter().copied() } - pub fn values( - &self, - ) -> impl Iterator + ExactSizeIterator + '_ { - self.values.values().copied().map(|(a, b, _)| (a, b)) + pub(crate) fn modules_in_scope(&self) -> impl Iterator + '_ { + self.types.values().copied().filter_map(|(def, vis, _)| match def { + ModuleDefId::ModuleId(module) => Some((module, vis)), + _ => None, + }) } - pub(crate) fn types( - &self, - ) -> impl Iterator + ExactSizeIterator + '_ { - self.types.values().copied().map(|(def, vis, _)| (def, vis)) - } + pub fn unnamed_consts<'a>( + &'a self, + db: &'a dyn DefDatabase, + ) -> impl Iterator + 'a { + // FIXME: Also treat consts named `_DERIVE_*` as unnamed, since synstructure generates those. + // Should be removed once synstructure stops doing that. + let synstructure_hack_consts = self.values.values().filter_map(|(item, _, _)| match item { + &ModuleDefId::ConstId(id) => { + let loc = id.lookup(db); + let item_tree = loc.id.item_tree(db); + if item_tree[loc.id.value] + .name + .as_ref() + .map_or(false, |n| n.to_smol_str().starts_with("_DERIVE_")) + { + Some(id) + } else { + None + } + } + _ => None, + }); - pub fn unnamed_consts(&self) -> impl Iterator + '_ { - self.unnamed_consts.iter().copied() + self.unnamed_consts.iter().copied().chain(synstructure_hack_consts) } /// Iterate over all module scoped macros @@ -274,21 +293,18 @@ impl ItemScope { } /// XXX: this is O(N) rather than O(1), try to not introduce new usages. - pub(crate) fn name_of(&self, item: ItemInNs) -> Option<(&Name, Visibility)> { + pub(crate) fn name_of(&self, item: ItemInNs) -> Option<(&Name, Visibility, /*declared*/ bool)> { match item { - ItemInNs::Macros(def) => self - .macros - .iter() - .find_map(|(name, &(other_def, vis, _))| (other_def == def).then_some((name, vis))), - ItemInNs::Types(def) => self - .types - .iter() - .find_map(|(name, &(other_def, vis, _))| (other_def == def).then_some((name, vis))), + ItemInNs::Macros(def) => self.macros.iter().find_map(|(name, &(other_def, vis, i))| { + (other_def == def).then_some((name, vis, i.is_none())) + }), + ItemInNs::Types(def) => self.types.iter().find_map(|(name, &(other_def, vis, i))| { + (other_def == def).then_some((name, vis, i.is_none())) + }), - ItemInNs::Values(def) => self - .values - .iter() - .find_map(|(name, &(other_def, vis, _))| (other_def == def).then_some((name, vis))), + ItemInNs::Values(def) => self.values.iter().find_map(|(name, &(other_def, vis, i))| { + (other_def == def).then_some((name, vis, i.is_none())) + }), } } @@ -316,6 +332,10 @@ impl ItemScope { }), ) } + + pub(crate) fn macro_invoc(&self, call: AstId) -> Option { + self.macro_invocations.get(&call).copied() + } } impl ItemScope { @@ -624,18 +644,17 @@ impl ItemScope { pub(crate) fn censor_non_proc_macros(&mut self, this_module: ModuleId) { self.types .values_mut() - .map(|(def, vis, _)| (def, vis)) - .chain(self.values.values_mut().map(|(def, vis, _)| (def, vis))) - .map(|(_, v)| v) + .map(|(_, vis, _)| vis) + .chain(self.values.values_mut().map(|(_, vis, _)| vis)) .chain(self.unnamed_trait_imports.values_mut().map(|(vis, _)| vis)) - .for_each(|vis| *vis = Visibility::Module(this_module)); + .for_each(|vis| *vis = Visibility::Module(this_module, VisibilityExplicity::Implicit)); for (mac, vis, import) in self.macros.values_mut() { if matches!(mac, MacroId::ProcMacroId(_) if import.is_none()) { continue; } - *vis = Visibility::Module(this_module); + *vis = Visibility::Module(this_module, VisibilityExplicity::Implicit); } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs index 20e4e44339e9..82ea5ffeba17 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs @@ -69,7 +69,7 @@ use crate::{ generics::{GenericParams, LifetimeParamData, TypeOrConstParamData}, path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind}, type_ref::{Mutability, TraitRef, TypeBound, TypeRef}, - visibility::RawVisibility, + visibility::{RawVisibility, VisibilityExplicity}, BlockId, Lookup, }; @@ -78,8 +78,9 @@ pub struct RawVisibilityId(u32); impl RawVisibilityId { pub const PUB: Self = RawVisibilityId(u32::max_value()); - pub const PRIV: Self = RawVisibilityId(u32::max_value() - 1); - pub const PUB_CRATE: Self = RawVisibilityId(u32::max_value() - 2); + pub const PRIV_IMPLICIT: Self = RawVisibilityId(u32::max_value() - 1); + pub const PRIV_EXPLICIT: Self = RawVisibilityId(u32::max_value() - 2); + pub const PUB_CRATE: Self = RawVisibilityId(u32::max_value() - 3); } impl fmt::Debug for RawVisibilityId { @@ -87,7 +88,7 @@ impl fmt::Debug for RawVisibilityId { let mut f = f.debug_tuple("RawVisibilityId"); match *self { Self::PUB => f.field(&"pub"), - Self::PRIV => f.field(&"pub(self)"), + Self::PRIV_IMPLICIT | Self::PRIV_EXPLICIT => f.field(&"pub(self)"), Self::PUB_CRATE => f.field(&"pub(crate)"), _ => f.field(&self.0), }; @@ -249,19 +250,30 @@ impl ItemVisibilities { fn alloc(&mut self, vis: RawVisibility) -> RawVisibilityId { match &vis { RawVisibility::Public => RawVisibilityId::PUB, - RawVisibility::Module(path) if path.segments().is_empty() => match &path.kind { - PathKind::Super(0) => RawVisibilityId::PRIV, - PathKind::Crate => RawVisibilityId::PUB_CRATE, - _ => RawVisibilityId(self.arena.alloc(vis).into_raw().into()), - }, + RawVisibility::Module(path, explicitiy) if path.segments().is_empty() => { + match (&path.kind, explicitiy) { + (PathKind::Super(0), VisibilityExplicity::Explicit) => { + RawVisibilityId::PRIV_EXPLICIT + } + (PathKind::Super(0), VisibilityExplicity::Implicit) => { + RawVisibilityId::PRIV_IMPLICIT + } + (PathKind::Crate, _) => RawVisibilityId::PUB_CRATE, + _ => RawVisibilityId(self.arena.alloc(vis).into_raw().into()), + } + } _ => RawVisibilityId(self.arena.alloc(vis).into_raw().into()), } } } static VIS_PUB: RawVisibility = RawVisibility::Public; -static VIS_PRIV: RawVisibility = RawVisibility::Module(ModPath::from_kind(PathKind::Super(0))); -static VIS_PUB_CRATE: RawVisibility = RawVisibility::Module(ModPath::from_kind(PathKind::Crate)); +static VIS_PRIV_IMPLICIT: RawVisibility = + RawVisibility::Module(ModPath::from_kind(PathKind::Super(0)), VisibilityExplicity::Implicit); +static VIS_PRIV_EXPLICIT: RawVisibility = + RawVisibility::Module(ModPath::from_kind(PathKind::Super(0)), VisibilityExplicity::Explicit); +static VIS_PUB_CRATE: RawVisibility = + RawVisibility::Module(ModPath::from_kind(PathKind::Crate), VisibilityExplicity::Explicit); #[derive(Default, Debug, Eq, PartialEq)] struct ItemTreeData { @@ -540,7 +552,8 @@ impl Index for ItemTree { type Output = RawVisibility; fn index(&self, index: RawVisibilityId) -> &Self::Output { match index { - RawVisibilityId::PRIV => &VIS_PRIV, + RawVisibilityId::PRIV_IMPLICIT => &VIS_PRIV_IMPLICIT, + RawVisibilityId::PRIV_EXPLICIT => &VIS_PRIV_EXPLICIT, RawVisibilityId::PUB => &VIS_PUB, RawVisibilityId::PUB_CRATE => &VIS_PUB_CRATE, _ => &self.data().vis.arena[Idx::from_raw(index.0.into())], diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs index 8e2fafe81b50..6343b43a016b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs @@ -6,7 +6,7 @@ use hir_expand::{ast_id_map::AstIdMap, span_map::SpanMapRef, HirFileId}; use syntax::ast::{self, HasModuleItem, HasTypeBounds}; use crate::{ - generics::{GenericParams, TypeParamData, TypeParamProvenance}, + generics::{GenericParams, GenericParamsCollector, TypeParamData, TypeParamProvenance}, type_ref::{LifetimeRef, TraitBoundModifier, TraitRef}, LocalLifetimeParamId, LocalTypeOrConstParamId, }; @@ -386,17 +386,16 @@ impl<'a> Ctx<'a> { flags |= FnFlags::HAS_UNSAFE_KW; } - let mut res = Function { + let res = Function { name, visibility, - explicit_generic_params: Interned::new(GenericParams::default()), + explicit_generic_params: self.lower_generic_params(HasImplicitSelf::No, func), abi, params, ret_type: Interned::new(ret_type), ast_id, flags, }; - res.explicit_generic_params = self.lower_generic_params(HasImplicitSelf::No, func); Some(id(self.data().functions.alloc(res))) } @@ -604,7 +603,7 @@ impl<'a> Ctx<'a> { has_implicit_self: HasImplicitSelf, node: &dyn ast::HasGenericParams, ) -> Interned { - let mut generics = GenericParams::default(); + let mut generics = GenericParamsCollector::default(); if let HasImplicitSelf::Yes(bounds) = has_implicit_self { // Traits and trait aliases get the Self type as an implicit first type parameter. @@ -642,8 +641,7 @@ impl<'a> Ctx<'a> { }; generics.fill(&self.body_ctx, node, add_param_attrs); - generics.shrink_to_fit(); - Interned::new(generics) + Interned::new(generics.finish()) } fn lower_type_bounds(&mut self, node: &dyn ast::HasTypeBounds) -> Box<[Interned]> { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs index 6d92fce07272..8693b9a98c9d 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs @@ -104,7 +104,9 @@ impl Printer<'_> { fn print_visibility(&mut self, vis: RawVisibilityId) { match &self.tree[vis] { - RawVisibility::Module(path) => w!(self, "pub({}) ", path.display(self.db.upcast())), + RawVisibility::Module(path, _expl) => { + w!(self, "pub({}) ", path.display(self.db.upcast())) + } RawVisibility::Public => w!(self, "pub "), }; } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs index 1ae6bd4c9194..66e0d2cc346b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs @@ -87,7 +87,10 @@ impl LangItems { } /// Salsa query. This will look for lang items in a specific crate. - pub(crate) fn crate_lang_items_query(db: &dyn DefDatabase, krate: CrateId) -> Arc { + pub(crate) fn crate_lang_items_query( + db: &dyn DefDatabase, + krate: CrateId, + ) -> Option> { let _p = profile::span("crate_lang_items_query"); let mut lang_items = LangItems::default(); @@ -150,7 +153,11 @@ impl LangItems { } } - Arc::new(lang_items) + if lang_items.items.is_empty() { + None + } else { + Some(Arc::new(lang_items)) + } } /// Salsa query. Look for a lang item, starting from the specified crate and recursively @@ -161,9 +168,9 @@ impl LangItems { item: LangItem, ) -> Option { let _p = profile::span("lang_item_query"); - let lang_items = db.crate_lang_items(start_crate); - let start_crate_target = lang_items.items.get(&item); - if let Some(&target) = start_crate_target { + if let Some(target) = + db.crate_lang_items(start_crate).and_then(|it| it.items.get(&item).copied()) + { return Some(target); } db.crate_graph()[start_crate] diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs index 250d7b677b5d..aa84ccaee6ee 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs @@ -10,10 +10,17 @@ #![warn(rust_2018_idioms, unused_lifetimes)] #![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] -#[allow(unused)] -macro_rules! eprintln { - ($($tt:tt)*) => { stdx::eprintln!($($tt)*) }; -} +#[cfg(feature = "in-rust-tree")] +extern crate rustc_parse_format; + +#[cfg(not(feature = "in-rust-tree"))] +extern crate ra_ap_rustc_parse_format as rustc_parse_format; + +#[cfg(feature = "in-rust-tree")] +extern crate rustc_abi; + +#[cfg(not(feature = "in-rust-tree"))] +extern crate ra_ap_rustc_abi as rustc_abi; pub mod db; @@ -49,7 +56,7 @@ pub mod visibility; pub mod find_path; pub mod import_map; -pub use rustc_dependencies::abi as layout; +pub use rustc_abi as layout; use triomphe::Arc; #[cfg(test)] diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs index abd84c6a46de..553c0b795336 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs @@ -16,13 +16,12 @@ struct Foo; #[derive(Copy)] struct Foo; -impl < > core::marker::Copy for Foo< > where {}"#]], +impl < > $crate::marker::Copy for Foo< > where {}"#]], ); } #[test] fn test_copy_expand_in_core() { - cov_mark::check!(test_copy_expand_in_core); check( r#" //- /lib.rs crate:core @@ -41,7 +40,7 @@ macro Copy {} #[derive(Copy)] struct Foo; -impl < > crate ::marker::Copy for Foo< > where {}"#]], +impl < > $crate::marker::Copy for Foo< > where {}"#]], ); } @@ -57,7 +56,7 @@ struct Foo; #[derive(Copy)] struct Foo; -impl core::marker::Copy for Foo where {}"#]], +impl $crate::marker::Copy for Foo where {}"#]], ); } @@ -74,7 +73,7 @@ struct Foo; #[derive(Copy)] struct Foo; -impl core::marker::Copy for Foo where {}"#]], +impl $crate::marker::Copy for Foo where {}"#]], ); } @@ -98,7 +97,7 @@ enum Command { Jump, } -impl core::clone::Clone for Command where { +impl $crate::clone::Clone for Command where { fn clone(&self ) -> Self { match self { Command::Move { @@ -158,7 +157,7 @@ where generic: Vec, } -impl core::clone::Clone for Foo where T: Trait, T::InFieldShorthand: core::clone::Clone, T::InGenericArg: core::clone::Clone, { +impl $crate::clone::Clone for Foo where T: Trait, T::InFieldShorthand: $crate::clone::Clone, T::InGenericArg: $crate::clone::Clone, { fn clone(&self ) -> Self { match self { Foo { @@ -186,7 +185,7 @@ struct Foo(u32); #[derive(Clone)] struct Foo(u32); -impl core::clone::Clone for Foo where { +impl $crate::clone::Clone for Foo where { fn clone(&self ) -> Self { match self { Foo(f0, )=>Foo(f0.clone(), ), @@ -226,14 +225,14 @@ enum Bar { Bar, } -impl < > core::default::Default for Foo< > where { +impl < > $crate::default::Default for Foo< > where { fn default() -> Self { Foo { - field1: core::default::Default::default(), field2: core::default::Default::default(), + field1: $crate::default::Default::default(), field2: $crate::default::Default::default(), } } } -impl < > core::default::Default for Bar< > where { +impl < > $crate::default::Default for Bar< > where { fn default() -> Self { Bar::Bar } @@ -261,7 +260,7 @@ enum Command { Jump, } -impl < > core::cmp::PartialEq for Command< > where { +impl < > $crate::cmp::PartialEq for Command< > where { fn eq(&self , other: &Self ) -> bool { match (self , other) { (Command::Move { @@ -274,7 +273,7 @@ impl < > core::cmp::PartialEq for Command< > where { } } } -impl < > core::cmp::Eq for Command< > where {}"#]], +impl < > $crate::cmp::Eq for Command< > where {}"#]], ); } @@ -299,7 +298,7 @@ enum Command { Jump, } -impl < > core::cmp::PartialEq for Command< > where { +impl < > $crate::cmp::PartialEq for Command< > where { fn eq(&self , other: &Self ) -> bool { match (self , other) { (Command::Move { @@ -312,7 +311,7 @@ impl < > core::cmp::PartialEq for Command< > where { } } } -impl < > core::cmp::Eq for Command< > where {}"#]], +impl < > $crate::cmp::Eq for Command< > where {}"#]], ); } @@ -336,10 +335,10 @@ enum Command { Jump, } -impl < > core::cmp::PartialOrd for Command< > where { - fn partial_cmp(&self , other: &Self ) -> core::option::Option::Option { - match core::intrinsics::discriminant_value(self ).partial_cmp(&core::intrinsics::discriminant_value(other)) { - core::option::Option::Some(core::cmp::Ordering::Equal)=> { +impl < > $crate::cmp::PartialOrd for Command< > where { + fn partial_cmp(&self , other: &Self ) -> $crate::option::Option::Option<$crate::cmp::Ordering> { + match $crate::intrinsics::discriminant_value(self ).partial_cmp(&$crate::intrinsics::discriminant_value(other)) { + $crate::option::Option::Some($crate::cmp::Ordering::Equal)=> { match (self , other) { (Command::Move { x: x_self, y: y_self, @@ -348,10 +347,10 @@ impl < > core::cmp::PartialOrd for Command< > where { x: x_other, y: y_other, } )=>match x_self.partial_cmp(&x_other) { - core::option::Option::Some(core::cmp::Ordering::Equal)=> { + $crate::option::Option::Some($crate::cmp::Ordering::Equal)=> { match y_self.partial_cmp(&y_other) { - core::option::Option::Some(core::cmp::Ordering::Equal)=> { - core::option::Option::Some(core::cmp::Ordering::Equal) + $crate::option::Option::Some($crate::cmp::Ordering::Equal)=> { + $crate::option::Option::Some($crate::cmp::Ordering::Equal) } c=>return c, } @@ -359,22 +358,22 @@ impl < > core::cmp::PartialOrd for Command< > where { c=>return c, } , (Command::Do(f0_self, ), Command::Do(f0_other, ))=>match f0_self.partial_cmp(&f0_other) { - core::option::Option::Some(core::cmp::Ordering::Equal)=> { - core::option::Option::Some(core::cmp::Ordering::Equal) + $crate::option::Option::Some($crate::cmp::Ordering::Equal)=> { + $crate::option::Option::Some($crate::cmp::Ordering::Equal) } c=>return c, } - , (Command::Jump, Command::Jump)=>core::option::Option::Some(core::cmp::Ordering::Equal), _unused=>core::option::Option::Some(core::cmp::Ordering::Equal) + , (Command::Jump, Command::Jump)=>$crate::option::Option::Some($crate::cmp::Ordering::Equal), _unused=>$crate::option::Option::Some($crate::cmp::Ordering::Equal) } } c=>return c, } } } -impl < > core::cmp::Ord for Command< > where { - fn cmp(&self , other: &Self ) -> core::cmp::Ordering { - match core::intrinsics::discriminant_value(self ).cmp(&core::intrinsics::discriminant_value(other)) { - core::cmp::Ordering::Equal=> { +impl < > $crate::cmp::Ord for Command< > where { + fn cmp(&self , other: &Self ) -> $crate::cmp::Ordering { + match $crate::intrinsics::discriminant_value(self ).cmp(&$crate::intrinsics::discriminant_value(other)) { + $crate::cmp::Ordering::Equal=> { match (self , other) { (Command::Move { x: x_self, y: y_self, @@ -383,10 +382,10 @@ impl < > core::cmp::Ord for Command< > where { x: x_other, y: y_other, } )=>match x_self.cmp(&x_other) { - core::cmp::Ordering::Equal=> { + $crate::cmp::Ordering::Equal=> { match y_self.cmp(&y_other) { - core::cmp::Ordering::Equal=> { - core::cmp::Ordering::Equal + $crate::cmp::Ordering::Equal=> { + $crate::cmp::Ordering::Equal } c=>return c, } @@ -394,12 +393,12 @@ impl < > core::cmp::Ord for Command< > where { c=>return c, } , (Command::Do(f0_self, ), Command::Do(f0_other, ))=>match f0_self.cmp(&f0_other) { - core::cmp::Ordering::Equal=> { - core::cmp::Ordering::Equal + $crate::cmp::Ordering::Equal=> { + $crate::cmp::Ordering::Equal } c=>return c, } - , (Command::Jump, Command::Jump)=>core::cmp::Ordering::Equal, _unused=>core::cmp::Ordering::Equal + , (Command::Jump, Command::Jump)=>$crate::cmp::Ordering::Equal, _unused=>$crate::cmp::Ordering::Equal } } c=>return c, @@ -433,8 +432,8 @@ struct Foo { z: (i32, u64), } -impl < > core::hash::Hash for Foo< > where { - fn hash(&self , ra_expand_state: &mut H) { +impl < > $crate::hash::Hash for Foo< > where { + fn hash(&self , ra_expand_state: &mut H) { match self { Foo { x: x, y: y, z: z, @@ -471,9 +470,9 @@ enum Command { Jump, } -impl < > core::hash::Hash for Command< > where { - fn hash(&self , ra_expand_state: &mut H) { - core::mem::discriminant(self ).hash(ra_expand_state); +impl < > $crate::hash::Hash for Command< > where { + fn hash(&self , ra_expand_state: &mut H) { + $crate::mem::discriminant(self ).hash(ra_expand_state); match self { Command::Move { x: x, y: y, @@ -517,8 +516,8 @@ enum Command { Jump, } -impl < > core::fmt::Debug for Command< > where { - fn fmt(&self , f: &mut core::fmt::Formatter) -> core::fmt::Result { +impl < > $crate::fmt::Debug for Command< > where { + fn fmt(&self , f: &mut $crate::fmt::Formatter) -> $crate::fmt::Result { match self { Command::Move { x: x, y: y, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs index d4798f4507d1..4690ca5d363c 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs @@ -136,7 +136,7 @@ fn main() { option_env!("TEST_ENV_VAR"); } #[rustc_builtin_macro] macro_rules! option_env {() => {}} -fn main() { ::core::option::Option::None:: < &str>; } +fn main() { $crate::option::Option::None:: < &str>; } "#]], ); } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs index 52a981fd19eb..53644f58efc4 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs @@ -79,7 +79,7 @@ use crate::{ nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode}, path::ModPath, per_ns::PerNs, - visibility::Visibility, + visibility::{Visibility, VisibilityExplicity}, AstId, BlockId, BlockLoc, CrateRootModuleId, ExternCrateId, FunctionId, LocalModuleId, Lookup, MacroExpander, MacroId, ModuleId, ProcMacroId, UseId, }; @@ -332,7 +332,10 @@ impl DefMap { // NB: we use `None` as block here, which would be wrong for implicit // modules declared by blocks with items. At the moment, we don't use // this visibility for anything outside IDE, so that's probably OK. - let visibility = Visibility::Module(ModuleId { krate, local_id, block: None }); + let visibility = Visibility::Module( + ModuleId { krate, local_id, block: None }, + VisibilityExplicity::Implicit, + ); let module_data = ModuleData::new( ModuleOrigin::BlockExpr { block: block.ast_id, id: block_id }, visibility, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs index be3438e427db..389dabdbc867 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs @@ -87,7 +87,7 @@ impl DefMap { within_impl: bool, ) -> Option { let mut vis = match visibility { - RawVisibility::Module(path) => { + RawVisibility::Module(path, explicity) => { let (result, remaining) = self.resolve_path(db, original_module, path, BuiltinShadowMode::Module, None); if remaining.is_some() { @@ -95,7 +95,7 @@ impl DefMap { } let types = result.take_types()?; match types { - ModuleDefId::ModuleId(m) => Visibility::Module(m), + ModuleDefId::ModuleId(m) => Visibility::Module(m, *explicity), // error: visibility needs to refer to module _ => { return None; @@ -108,11 +108,11 @@ impl DefMap { // In block expressions, `self` normally refers to the containing non-block module, and // `super` to its parent (etc.). However, visibilities must only refer to a module in the // DefMap they're written in, so we restrict them when that happens. - if let Visibility::Module(m) = vis { + if let Visibility::Module(m, mv) = vis { // ...unless we're resolving visibility for an associated item in an impl. if self.block_id() != m.block && !within_impl { cov_mark::hit!(adjust_vis_in_block_def_map); - vis = Visibility::Module(self.module_id(Self::ROOT)); + vis = Visibility::Module(self.module_id(Self::ROOT), mv); tracing::debug!("visibility {:?} points outside DefMap, adjusting to {:?}", m, vis); } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs index 48fe43450a71..0f6e64016f18 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs @@ -1264,6 +1264,54 @@ struct A; ); } +#[test] +fn nested_include() { + check( + r#" +//- minicore: include +//- /lib.rs +include!("out_dir/includes.rs"); + +//- /out_dir/includes.rs +pub mod company_name { + pub mod network { + pub mod v1 { + include!("company_name.network.v1.rs"); + } + } +} +//- /out_dir/company_name.network.v1.rs +pub struct IpAddress { + pub ip_type: &'static str, +} +/// Nested message and enum types in `IpAddress`. +pub mod ip_address { + pub enum IpType { + IpV4(u32), + } +} + +"#, + expect![[r#" + crate + company_name: t + + crate::company_name + network: t + + crate::company_name::network + v1: t + + crate::company_name::network::v1 + IpAddress: t + ip_address: t + + crate::company_name::network::v1::ip_address + IpType: t + "#]], + ); +} + #[test] fn macro_use_imports_all_macro_types() { let db = TestDB::with_files( diff --git a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs index 301391516d64..1d850f721c1f 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs @@ -242,7 +242,7 @@ impl Resolver { let within_impl = self.scopes().find(|scope| matches!(scope, Scope::ImplDefScope(_))).is_some(); match visibility { - RawVisibility::Module(_) => { + RawVisibility::Module(_, _) => { let (item_map, module) = self.item_scope(); item_map.resolve_visibility(db, module, visibility, within_impl) } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs b/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs index f4a6b61f7af5..c992c3c92048 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs @@ -8,7 +8,6 @@ use base_db::{ Upcast, }; use hir_expand::{db::ExpandDatabase, InFile}; -use rustc_hash::FxHashSet; use syntax::{algo, ast, AstNode}; use triomphe::Arc; @@ -76,7 +75,7 @@ impl FileLoader for TestDB { fn resolve_path(&self, path: AnchoredPath<'_>) -> Option { FileLoaderDelegate(self).resolve_path(path) } - fn relevant_crates(&self, file_id: FileId) -> Arc> { + fn relevant_crates(&self, file_id: FileId) -> Arc<[CrateId]> { FileLoaderDelegate(self).relevant_crates(file_id) } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs b/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs index 49688c5ee9c2..cd8023f5d7d7 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs @@ -20,14 +20,14 @@ use crate::{ pub enum RawVisibility { /// `pub(in module)`, `pub(crate)` or `pub(super)`. Also private, which is /// equivalent to `pub(self)`. - Module(ModPath), + Module(ModPath, VisibilityExplicity), /// `pub`. Public, } impl RawVisibility { pub(crate) const fn private() -> RawVisibility { - RawVisibility::Module(ModPath::from_kind(PathKind::Super(0))) + RawVisibility::Module(ModPath::from_kind(PathKind::Super(0)), VisibilityExplicity::Implicit) } pub(crate) fn from_ast( @@ -41,18 +41,9 @@ impl RawVisibility { db: &dyn DefDatabase, node: Option, span_map: SpanMapRef<'_>, - ) -> RawVisibility { - Self::from_ast_with_span_map_and_default(db, node, RawVisibility::private(), span_map) - } - - pub(crate) fn from_ast_with_span_map_and_default( - db: &dyn DefDatabase, - node: Option, - default: RawVisibility, - span_map: SpanMapRef<'_>, ) -> RawVisibility { let node = match node { - None => return default, + None => return RawVisibility::private(), Some(node) => node, }; match node.kind() { @@ -62,19 +53,19 @@ impl RawVisibility { None => return RawVisibility::private(), Some(path) => path, }; - RawVisibility::Module(path) + RawVisibility::Module(path, VisibilityExplicity::Explicit) } ast::VisibilityKind::PubCrate => { let path = ModPath::from_kind(PathKind::Crate); - RawVisibility::Module(path) + RawVisibility::Module(path, VisibilityExplicity::Explicit) } ast::VisibilityKind::PubSuper => { let path = ModPath::from_kind(PathKind::Super(1)); - RawVisibility::Module(path) + RawVisibility::Module(path, VisibilityExplicity::Explicit) } ast::VisibilityKind::PubSelf => { let path = ModPath::from_kind(PathKind::Super(0)); - RawVisibility::Module(path) + RawVisibility::Module(path, VisibilityExplicity::Explicit) } ast::VisibilityKind::Pub => RawVisibility::Public, } @@ -94,7 +85,7 @@ impl RawVisibility { #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum Visibility { /// Visibility is restricted to a certain module. - Module(ModuleId), + Module(ModuleId, VisibilityExplicity), /// Visibility is unrestricted. Public, } @@ -102,7 +93,7 @@ pub enum Visibility { impl Visibility { pub fn is_visible_from(self, db: &dyn DefDatabase, from_module: ModuleId) -> bool { let to_module = match self { - Visibility::Module(m) => m, + Visibility::Module(m, _) => m, Visibility::Public => return true, }; // if they're not in the same crate, it can't be visible @@ -124,7 +115,7 @@ impl Visibility { mut from_module: LocalModuleId, ) -> bool { let mut to_module = match self { - Visibility::Module(m) => m, + Visibility::Module(m, _) => m, Visibility::Public => return true, }; @@ -181,9 +172,9 @@ impl Visibility { /// visible in unrelated modules). pub(crate) fn max(self, other: Visibility, def_map: &DefMap) -> Option { match (self, other) { - (Visibility::Module(_) | Visibility::Public, Visibility::Public) - | (Visibility::Public, Visibility::Module(_)) => Some(Visibility::Public), - (Visibility::Module(mod_a), Visibility::Module(mod_b)) => { + (Visibility::Module(_, _) | Visibility::Public, Visibility::Public) + | (Visibility::Public, Visibility::Module(_, _)) => Some(Visibility::Public), + (Visibility::Module(mod_a, vis_a), Visibility::Module(mod_b, vis_b)) => { if mod_a.krate != mod_b.krate { return None; } @@ -199,12 +190,12 @@ impl Visibility { if a_ancestors.any(|m| m == mod_b.local_id) { // B is above A - return Some(Visibility::Module(mod_b)); + return Some(Visibility::Module(mod_b, vis_b)); } if b_ancestors.any(|m| m == mod_a.local_id) { // A is above B - return Some(Visibility::Module(mod_a)); + return Some(Visibility::Module(mod_a, vis_a)); } None @@ -213,6 +204,19 @@ impl Visibility { } } +/// Whether the item was imported through `pub(crate) use` or just `use`. +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum VisibilityExplicity { + Explicit, + Implicit, +} + +impl VisibilityExplicity { + pub fn is_explicit(&self) -> bool { + matches!(self, Self::Explicit) + } +} + /// Resolve visibility of all specific fields of a struct or union variant. pub(crate) fn field_visibilities_query( db: &dyn DefDatabase, diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_derive_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_derive_macro.rs index 8f240ef07320..46bbb7f92c07 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_derive_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_derive_macro.rs @@ -1,6 +1,5 @@ //! Builtin derives. -use base_db::{CrateOrigin, LangCrateOrigin}; use itertools::izip; use rustc_hash::FxHashSet; use span::{MacroCallId, Span}; @@ -10,6 +9,7 @@ use tracing::debug; use crate::{ hygiene::span_with_def_site_ctxt, name::{AsName, Name}, + quote::dollar_crate, span_map::SpanMapRef, tt, }; @@ -38,7 +38,7 @@ macro_rules! register_builtin { let span = db.lookup_intern_macro_call(id).call_site; let span = span_with_def_site_ctxt(db, span, id); - expander(db, id, span, tt, token_map) + expander(span, tt, token_map) } fn find_by_name(name: &name::Name) -> Option { @@ -398,41 +398,13 @@ fn expand_simple_derive( ExpandResult::ok(expanded) } -fn find_builtin_crate(db: &dyn ExpandDatabase, id: MacroCallId, span: Span) -> tt::TokenTree { - // FIXME: make hygiene works for builtin derive macro - // such that $crate can be used here. - let cg = db.crate_graph(); - let krate = db.lookup_intern_macro_call(id).krate; - - let tt = if matches!(cg[krate].origin, CrateOrigin::Lang(LangCrateOrigin::Core)) { - cov_mark::hit!(test_copy_expand_in_core); - quote! {span => crate } - } else { - quote! {span => core } - }; - - tt.token_trees[0].clone() -} - -fn copy_expand( - db: &dyn ExpandDatabase, - id: MacroCallId, - span: Span, - tt: &ast::Adt, - tm: SpanMapRef<'_>, -) -> ExpandResult { - let krate = find_builtin_crate(db, id, span); +fn copy_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult { + let krate = dollar_crate(span); expand_simple_derive(span, tt, tm, quote! {span => #krate::marker::Copy }, |_| quote! {span =>}) } -fn clone_expand( - db: &dyn ExpandDatabase, - id: MacroCallId, - span: Span, - tt: &ast::Adt, - tm: SpanMapRef<'_>, -) -> ExpandResult { - let krate = find_builtin_crate(db, id, span); +fn clone_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult { + let krate = dollar_crate(span); expand_simple_derive(span, tt, tm, quote! {span => #krate::clone::Clone }, |adt| { if matches!(adt.shape, AdtShape::Union) { let star = tt::Punct { char: '*', spacing: ::tt::Spacing::Alone, span }; @@ -482,14 +454,8 @@ fn and_and(span: Span) -> tt::Subtree { quote! {span => #and& } } -fn default_expand( - db: &dyn ExpandDatabase, - id: MacroCallId, - span: Span, - tt: &ast::Adt, - tm: SpanMapRef<'_>, -) -> ExpandResult { - let krate = &find_builtin_crate(db, id, span); +fn default_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult { + let krate = &dollar_crate(span); expand_simple_derive(span, tt, tm, quote! {span => #krate::default::Default }, |adt| { let body = match &adt.shape { AdtShape::Struct(fields) => { @@ -527,14 +493,8 @@ fn default_expand( }) } -fn debug_expand( - db: &dyn ExpandDatabase, - id: MacroCallId, - span: Span, - tt: &ast::Adt, - tm: SpanMapRef<'_>, -) -> ExpandResult { - let krate = &find_builtin_crate(db, id, span); +fn debug_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult { + let krate = &dollar_crate(span); expand_simple_derive(span, tt, tm, quote! {span => #krate::fmt::Debug }, |adt| { let for_variant = |name: String, v: &VariantShape| match v { VariantShape::Struct(fields) => { @@ -605,14 +565,8 @@ fn debug_expand( }) } -fn hash_expand( - db: &dyn ExpandDatabase, - id: MacroCallId, - span: Span, - tt: &ast::Adt, - tm: SpanMapRef<'_>, -) -> ExpandResult { - let krate = &find_builtin_crate(db, id, span); +fn hash_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult { + let krate = &dollar_crate(span); expand_simple_derive(span, tt, tm, quote! {span => #krate::hash::Hash }, |adt| { if matches!(adt.shape, AdtShape::Union) { // FIXME: Return expand error here @@ -658,25 +612,13 @@ fn hash_expand( }) } -fn eq_expand( - db: &dyn ExpandDatabase, - id: MacroCallId, - span: Span, - tt: &ast::Adt, - tm: SpanMapRef<'_>, -) -> ExpandResult { - let krate = find_builtin_crate(db, id, span); +fn eq_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult { + let krate = dollar_crate(span); expand_simple_derive(span, tt, tm, quote! {span => #krate::cmp::Eq }, |_| quote! {span =>}) } -fn partial_eq_expand( - db: &dyn ExpandDatabase, - id: MacroCallId, - span: Span, - tt: &ast::Adt, - tm: SpanMapRef<'_>, -) -> ExpandResult { - let krate = find_builtin_crate(db, id, span); +fn partial_eq_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult { + let krate = dollar_crate(span); expand_simple_derive(span, tt, tm, quote! {span => #krate::cmp::PartialEq }, |adt| { if matches!(adt.shape, AdtShape::Union) { // FIXME: Return expand error here @@ -747,17 +689,11 @@ fn self_and_other_patterns( (self_patterns, other_patterns) } -fn ord_expand( - db: &dyn ExpandDatabase, - id: MacroCallId, - span: Span, - tt: &ast::Adt, - tm: SpanMapRef<'_>, -) -> ExpandResult { - let krate = &find_builtin_crate(db, id, span); +fn ord_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult { + let krate = &dollar_crate(span); expand_simple_derive(span, tt, tm, quote! {span => #krate::cmp::Ord }, |adt| { fn compare( - krate: &tt::TokenTree, + krate: &tt::Ident, left: tt::Subtree, right: tt::Subtree, rest: tt::Subtree, @@ -811,17 +747,11 @@ fn ord_expand( }) } -fn partial_ord_expand( - db: &dyn ExpandDatabase, - id: MacroCallId, - span: Span, - tt: &ast::Adt, - tm: SpanMapRef<'_>, -) -> ExpandResult { - let krate = &find_builtin_crate(db, id, span); +fn partial_ord_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult { + let krate = &dollar_crate(span); expand_simple_derive(span, tt, tm, quote! {span => #krate::cmp::PartialOrd }, |adt| { fn compare( - krate: &tt::TokenTree, + krate: &tt::Ident, left: tt::Subtree, right: tt::Subtree, rest: tt::Subtree, diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs index f99a89176233..c892f462d2c7 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs @@ -6,18 +6,16 @@ use either::Either; use itertools::Itertools; use mbe::{parse_exprs_with_sep, parse_to_token_tree}; use span::{Span, SpanAnchor, SyntaxContextId, ROOT_ERASED_FILE_AST_ID}; -use syntax::{ - ast::{self, AstToken}, - SmolStr, -}; +use syntax::ast::{self, AstToken}; use crate::{ db::ExpandDatabase, hygiene::{span_with_call_site_ctxt, span_with_def_site_ctxt}, name::{self, known}, quote, + quote::dollar_crate, tt::{self, DelimSpan}, - ExpandError, ExpandResult, HirFileIdExt, MacroCallId, + ExpandError, ExpandResult, HirFileIdExt, MacroCallId, MacroFileIdExt, }; macro_rules! register_builtin { @@ -205,7 +203,7 @@ fn assert_expand( ) -> ExpandResult { let call_site_span = span_with_call_site_ctxt(db, span, id); let args = parse_exprs_with_sep(tt, ',', call_site_span); - let dollar_crate = tt::Ident { text: SmolStr::new_inline("$crate"), span }; + let dollar_crate = dollar_crate(span); let expanded = match &*args { [cond, panic_args @ ..] => { let comma = tt::Subtree { @@ -300,7 +298,7 @@ fn asm_expand( [tt::TokenTree::Leaf(tt::Leaf::Literal(lit))] | [tt::TokenTree::Leaf(tt::Leaf::Literal(lit)), tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: ',', span: _, spacing: _ }))] => { - let dollar_krate = tt::Ident { text: SmolStr::new_inline("$crate"), span }; + let dollar_krate = dollar_crate(span); literals.push(quote!(span=>#dollar_krate::format_args!(#lit);)); } _ => break, @@ -345,7 +343,7 @@ fn panic_expand( tt: &tt::Subtree, span: Span, ) -> ExpandResult { - let dollar_crate = tt::Ident { text: SmolStr::new_inline("$crate"), span }; + let dollar_crate = dollar_crate(span); let call_site_span = span_with_call_site_ctxt(db, span, id); let mac = @@ -371,7 +369,7 @@ fn unreachable_expand( tt: &tt::Subtree, span: Span, ) -> ExpandResult { - let dollar_crate = tt::Ident { text: SmolStr::new_inline("$crate"), span }; + let dollar_crate = dollar_crate(span); let call_site_span = span_with_call_site_ctxt(db, span, id); let mac = if use_panic_2021(db, call_site_span) { @@ -611,7 +609,7 @@ fn relative_file( path_str: &str, allow_recursion: bool, ) -> Result { - let call_site = call_id.as_file().original_file(db); + let call_site = call_id.as_macro_file().parent(db).original_file_respecting_includes(db); let path = AnchoredPath { anchor: call_site, path: path_str }; let res = db .resolve_path(path) @@ -763,10 +761,10 @@ fn option_env_expand( return ExpandResult::new(tt::Subtree::empty(DelimSpan { open: span, close: span }), e) } }; - // FIXME: Use `DOLLAR_CRATE` when that works in eager macros. + let dollar_crate = dollar_crate(span); let expanded = match get_env_inner(db, arg_id, &key) { - None => quote! {span => ::core::option::Option::None::<&str> }, - Some(s) => quote! {span => ::core::option::Option::Some(#s) }, + None => quote! {span => #dollar_crate::option::Option::None::<&str> }, + Some(s) => quote! {span => #dollar_crate::option::Option::Some(#s) }, }; ExpandResult::ok(expanded) diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs index 6a122e0859cc..ae7d17e49a90 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs @@ -318,6 +318,7 @@ pub trait MacroFileIdExt { fn expansion_level(self, db: &dyn ExpandDatabase) -> u32; /// If this is a macro call, returns the syntax node of the call. fn call_node(self, db: &dyn ExpandDatabase) -> InFile; + fn parent(self, db: &dyn ExpandDatabase) -> HirFileId; fn expansion_info(self, db: &dyn ExpandDatabase) -> ExpansionInfo; @@ -353,6 +354,9 @@ impl MacroFileIdExt for MacroFileId { }; } } + fn parent(self, db: &dyn ExpandDatabase) -> HirFileId { + self.macro_call_id.lookup(db).kind.file_id() + } /// Return expansion information if it is a macro-expansion file fn expansion_info(self, db: &dyn ExpandDatabase) -> ExpansionInfo { diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/quote.rs b/src/tools/rust-analyzer/crates/hir-expand/src/quote.rs index 9bdd75f9d224..a3b84afd2ae4 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/quote.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/quote.rs @@ -4,6 +4,10 @@ use span::Span; use crate::name::Name; +pub(crate) fn dollar_crate(span: Span) -> tt::Ident { + tt::Ident { text: syntax::SmolStr::new_inline("$crate"), span } +} + // A helper macro quote macro // FIXME: // 1. Not all puncts are handled diff --git a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml index c7807bcf9aa1..803c18677da5 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml +++ b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml @@ -34,7 +34,9 @@ nohash-hasher.workspace = true typed-arena = "2.0.1" indexmap.workspace = true -rustc-dependencies.workspace = true +ra-ap-rustc_abi.workspace = true +ra-ap-rustc_index.workspace = true + # local deps stdx.workspace = true @@ -58,7 +60,7 @@ test-utils.workspace = true test-fixture.workspace = true [features] -in-rust-tree = ["rustc-dependencies/in-rust-tree"] +in-rust-tree = [] [lints] workspace = true diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs index f4fbace19e35..e81d4ced5543 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs @@ -167,7 +167,7 @@ impl chalk_solve::RustIrDatabase for ChalkContext<'_> { } }); }) - .map(|block_id| self.db.trait_impls_in_block(block_id)); + .filter_map(|block_id| self.db.trait_impls_in_block(block_id)); let id_to_chalk = |id: hir_def::ImplId| id.to_chalk(self.db); let mut result = vec![]; @@ -183,7 +183,8 @@ impl chalk_solve::RustIrDatabase for ChalkContext<'_> { def_blocks .into_iter() .flatten() - .for_each(|it| f(&self.db.trait_impls_in_block(it))); + .filter_map(|it| self.db.trait_impls_in_block(it)) + .for_each(|it| f(&it)); } fps => { let mut f = @@ -198,7 +199,8 @@ impl chalk_solve::RustIrDatabase for ChalkContext<'_> { def_blocks .into_iter() .flatten() - .for_each(|it| f(&self.db.trait_impls_in_block(it))); + .filter_map(|it| self.db.trait_impls_in_block(it)) + .for_each(|it| f(&it)); } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs index 410bcbf0356f..ad790fa094d8 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs @@ -34,6 +34,8 @@ pub trait HirDatabase: DefDatabase + Upcast { #[salsa::invoke(crate::infer::infer_query)] fn infer_query(&self, def: DefWithBodyId) -> Arc; + // region:mir + #[salsa::invoke(crate::mir::mir_body_query)] #[salsa::cycle(crate::mir::mir_body_recover)] fn mir_body(&self, def: DefWithBodyId) -> Result, MirLowerError>; @@ -61,20 +63,6 @@ pub trait HirDatabase: DefDatabase + Upcast { #[salsa::invoke(crate::mir::borrowck_query)] fn borrowck(&self, def: DefWithBodyId) -> Result, MirLowerError>; - #[salsa::invoke(crate::lower::ty_query)] - #[salsa::cycle(crate::lower::ty_recover)] - fn ty(&self, def: TyDefId) -> Binders; - - #[salsa::invoke(crate::lower::value_ty_query)] - fn value_ty(&self, def: ValueTyDefId) -> Binders; - - #[salsa::invoke(crate::lower::impl_self_ty_query)] - #[salsa::cycle(crate::lower::impl_self_ty_recover)] - fn impl_self_ty(&self, def: ImplId) -> Binders; - - #[salsa::invoke(crate::lower::const_param_ty_query)] - fn const_param_ty(&self, def: ConstParamId) -> Ty; - #[salsa::invoke(crate::consteval::const_eval_query)] #[salsa::cycle(crate::consteval::const_eval_recover)] fn const_eval( @@ -92,6 +80,22 @@ pub trait HirDatabase: DefDatabase + Upcast { #[salsa::cycle(crate::consteval::const_eval_discriminant_recover)] fn const_eval_discriminant(&self, def: EnumVariantId) -> Result; + // endregion:mir + + #[salsa::invoke(crate::lower::ty_query)] + #[salsa::cycle(crate::lower::ty_recover)] + fn ty(&self, def: TyDefId) -> Binders; + + #[salsa::invoke(crate::lower::value_ty_query)] + fn value_ty(&self, def: ValueTyDefId) -> Binders; + + #[salsa::invoke(crate::lower::impl_self_ty_query)] + #[salsa::cycle(crate::lower::impl_self_ty_recover)] + fn impl_self_ty(&self, def: ImplId) -> Binders; + + #[salsa::invoke(crate::lower::const_param_ty_query)] + fn const_param_ty(&self, def: ConstParamId) -> Ty; + #[salsa::invoke(crate::lower::impl_trait_query)] fn impl_trait(&self, def: ImplId) -> Option>; @@ -158,7 +162,7 @@ pub trait HirDatabase: DefDatabase + Upcast { fn inherent_impls_in_crate(&self, krate: CrateId) -> Arc; #[salsa::invoke(InherentImpls::inherent_impls_in_block_query)] - fn inherent_impls_in_block(&self, block: BlockId) -> Arc; + fn inherent_impls_in_block(&self, block: BlockId) -> Option>; /// Collects all crates in the dependency graph that have impls for the /// given fingerprint. This is only used for primitive types and types @@ -175,7 +179,7 @@ pub trait HirDatabase: DefDatabase + Upcast { fn trait_impls_in_crate(&self, krate: CrateId) -> Arc; #[salsa::invoke(TraitImpls::trait_impls_in_block_query)] - fn trait_impls_in_block(&self, block: BlockId) -> Arc; + fn trait_impls_in_block(&self, block: BlockId) -> Option>; #[salsa::invoke(TraitImpls::trait_impls_in_deps_query)] fn trait_impls_in_deps(&self, krate: CrateId) -> Arc<[Arc]>; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs index 23d951542214..d63a64a70de2 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs @@ -1629,7 +1629,7 @@ pub fn write_visibility( ) -> Result<(), HirDisplayError> { match vis { Visibility::Public => write!(f, "pub "), - Visibility::Module(vis_id) => { + Visibility::Module(vis_id, _) => { let def_map = module_id.def_map(f.db.upcast()); let root_module_id = def_map.module_id(DefMap::ROOT); if vis_id == module_id { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs index 68619bb8b18c..b7bfaf2931b6 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs @@ -12,10 +12,9 @@ use hir_def::{ LocalEnumVariantId, LocalFieldId, StructId, }; use la_arena::{Idx, RawIdx}; -use rustc_dependencies::{ - abi::AddressSpace, - index::{IndexSlice, IndexVec}, -}; +use rustc_abi::AddressSpace; +use rustc_index::{IndexSlice, IndexVec}; + use stdx::never; use triomphe::Arc; @@ -35,7 +34,7 @@ mod target; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct RustcEnumVariantIdx(pub LocalEnumVariantId); -impl rustc_dependencies::index::Idx for RustcEnumVariantIdx { +impl rustc_index::Idx for RustcEnumVariantIdx { fn new(idx: usize) -> Self { RustcEnumVariantIdx(Idx::from_raw(RawIdx::from(idx as u32))) } @@ -54,7 +53,7 @@ impl RustcFieldIdx { } } -impl rustc_dependencies::index::Idx for RustcFieldIdx { +impl rustc_index::Idx for RustcFieldIdx { fn new(idx: usize) -> Self { RustcFieldIdx(Idx::from_raw(RawIdx::from(idx as u32))) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs index 39788a950299..8a7715ce8729 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs @@ -9,7 +9,7 @@ use hir_def::{ AdtId, EnumVariantId, LocalEnumVariantId, VariantId, }; use la_arena::RawIdx; -use rustc_dependencies::index::IndexVec; +use rustc_index::IndexVec; use smallvec::SmallVec; use triomphe::Arc; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs index ef0be7ab2daf..57214193cfbc 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs @@ -118,7 +118,7 @@ fn check_fail(ra_fixture: &str, e: LayoutError) { macro_rules! size_and_align { (minicore: $($x:tt),*;$($t:tt)*) => { { - #[allow(dead_code)] + #![allow(dead_code)] $($t)* check_size_and_align( stringify!($($t)*), @@ -130,7 +130,7 @@ macro_rules! size_and_align { }; ($($t:tt)*) => { { - #[allow(dead_code)] + #![allow(dead_code)] $($t)* check_size_and_align( stringify!($($t)*), diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs index 793b52b49faa..e72864a12eec 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs @@ -3,10 +3,17 @@ #![warn(rust_2018_idioms, unused_lifetimes)] #![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] -#[allow(unused)] -macro_rules! eprintln { - ($($tt:tt)*) => { stdx::eprintln!($($tt)*) }; -} +#[cfg(feature = "in-rust-tree")] +extern crate rustc_index; + +#[cfg(not(feature = "in-rust-tree"))] +extern crate ra_ap_rustc_index as rustc_index; + +#[cfg(feature = "in-rust-tree")] +extern crate rustc_abi; + +#[cfg(not(feature = "in-rust-tree"))] +extern crate ra_ap_rustc_abi as rustc_abi; mod builder; mod chalk_db; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs index 97c4a741ff2a..e371e4276156 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs @@ -1601,7 +1601,7 @@ fn implicitly_sized_clauses<'a>( pub(crate) fn generic_defaults_query( db: &dyn HirDatabase, def: GenericDefId, -) -> Arc<[Binders>]> { +) -> Arc<[Binders]> { let resolver = def.resolver(db.upcast()); let ctx = TyLoweringContext::new(db, &resolver, def.into()) .with_type_param_mode(ParamLoweringMode::Variable); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs index 33619edfee93..03ed8d36a1dd 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs @@ -8,10 +8,9 @@ use base_db::{CrateId, Edition}; use chalk_ir::{cast::Cast, Mutability, TyKind, UniverseIndex, WhereClause}; use hir_def::{ data::{adt::StructFlags, ImplData}, - item_scope::ItemScope, nameres::DefMap, AssocItemId, BlockId, ConstId, FunctionId, HasModule, ImplId, ItemContainerId, Lookup, - ModuleDefId, ModuleId, TraitId, + ModuleId, TraitId, }; use hir_expand::name::Name; use rustc_hash::{FxHashMap, FxHashSet}; @@ -132,34 +131,40 @@ pub(crate) const ALL_FLOAT_FPS: [TyFingerprint; 2] = [ TyFingerprint::Scalar(Scalar::Float(FloatTy::F64)), ]; +type TraitFpMap = FxHashMap, Box<[ImplId]>>>; +type TraitFpMapCollector = FxHashMap, Vec>>; + /// Trait impls defined or available in some crate. #[derive(Debug, Eq, PartialEq)] pub struct TraitImpls { // If the `Option` is `None`, the impl may apply to any self type. - map: FxHashMap, Vec>>, + map: TraitFpMap, } impl TraitImpls { pub(crate) fn trait_impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc { let _p = profile::span("trait_impls_in_crate_query").detail(|| format!("{krate:?}")); - let mut impls = Self { map: FxHashMap::default() }; + let mut impls = FxHashMap::default(); - let crate_def_map = db.crate_def_map(krate); - impls.collect_def_map(db, &crate_def_map); - impls.shrink_to_fit(); + Self::collect_def_map(db, &mut impls, &db.crate_def_map(krate)); - Arc::new(impls) + Arc::new(Self::finish(impls)) } - pub(crate) fn trait_impls_in_block_query(db: &dyn HirDatabase, block: BlockId) -> Arc { + pub(crate) fn trait_impls_in_block_query( + db: &dyn HirDatabase, + block: BlockId, + ) -> Option> { let _p = profile::span("trait_impls_in_block_query"); - let mut impls = Self { map: FxHashMap::default() }; + let mut impls = FxHashMap::default(); - let block_def_map = db.block_def_map(block); - impls.collect_def_map(db, &block_def_map); - impls.shrink_to_fit(); + Self::collect_def_map(db, &mut impls, &db.block_def_map(block)); - Arc::new(impls) + if impls.is_empty() { + None + } else { + Some(Arc::new(Self::finish(impls))) + } } pub(crate) fn trait_impls_in_deps_query( @@ -174,15 +179,16 @@ impl TraitImpls { ) } - fn shrink_to_fit(&mut self) { - self.map.shrink_to_fit(); - self.map.values_mut().for_each(|map| { - map.shrink_to_fit(); - map.values_mut().for_each(Vec::shrink_to_fit); - }); + fn finish(map: TraitFpMapCollector) -> TraitImpls { + TraitImpls { + map: map + .into_iter() + .map(|(k, v)| (k, v.into_iter().map(|(k, v)| (k, v.into_boxed_slice())).collect())) + .collect(), + } } - fn collect_def_map(&mut self, db: &dyn HirDatabase, def_map: &DefMap) { + fn collect_def_map(db: &dyn HirDatabase, map: &mut TraitFpMapCollector, def_map: &DefMap) { for (_module_id, module_data) in def_map.modules() { for impl_id in module_data.scope.impls() { // Reservation impls should be ignored during trait resolution, so we never need @@ -200,20 +206,15 @@ impl TraitImpls { }; let self_ty = db.impl_self_ty(impl_id); let self_ty_fp = TyFingerprint::for_trait_impl(self_ty.skip_binders()); - self.map - .entry(target_trait) - .or_default() - .entry(self_ty_fp) - .or_default() - .push(impl_id); + map.entry(target_trait).or_default().entry(self_ty_fp).or_default().push(impl_id); } // To better support custom derives, collect impls in all unnamed const items. // const _: () = { ... }; - for konst in collect_unnamed_consts(db, &module_data.scope) { + for konst in module_data.scope.unnamed_consts(db.upcast()) { let body = db.body(konst.into()); for (_, block_def_map) in body.blocks(db.upcast()) { - self.collect_def_map(db, &block_def_map); + Self::collect_def_map(db, map, &block_def_map); } } } @@ -281,7 +282,10 @@ impl InherentImpls { Arc::new(impls) } - pub(crate) fn inherent_impls_in_block_query(db: &dyn HirDatabase, block: BlockId) -> Arc { + pub(crate) fn inherent_impls_in_block_query( + db: &dyn HirDatabase, + block: BlockId, + ) -> Option> { let _p = profile::span("inherent_impls_in_block_query"); let mut impls = Self { map: FxHashMap::default(), invalid_impls: Vec::default() }; @@ -289,7 +293,11 @@ impl InherentImpls { impls.collect_def_map(db, &block_def_map); impls.shrink_to_fit(); - Arc::new(impls) + if impls.map.is_empty() && impls.invalid_impls.is_empty() { + None + } else { + Some(Arc::new(impls)) + } } fn shrink_to_fit(&mut self) { @@ -321,7 +329,7 @@ impl InherentImpls { // To better support custom derives, collect impls in all unnamed const items. // const _: () = { ... }; - for konst in collect_unnamed_consts(db, &module_data.scope) { + for konst in module_data.scope.unnamed_consts(db.upcast()) { let body = db.body(konst.into()); for (_, block_def_map) in body.blocks(db.upcast()) { self.collect_def_map(db, &block_def_map); @@ -367,34 +375,6 @@ pub(crate) fn incoherent_inherent_impl_crates( res } -fn collect_unnamed_consts<'a>( - db: &'a dyn HirDatabase, - scope: &'a ItemScope, -) -> impl Iterator + 'a { - let unnamed_consts = scope.unnamed_consts(); - - // FIXME: Also treat consts named `_DERIVE_*` as unnamed, since synstructure generates those. - // Should be removed once synstructure stops doing that. - let synstructure_hack_consts = scope.values().filter_map(|(item, _)| match item { - ModuleDefId::ConstId(id) => { - let loc = id.lookup(db.upcast()); - let item_tree = loc.id.item_tree(db.upcast()); - if item_tree[loc.id.value] - .name - .as_ref() - .map_or(false, |n| n.to_smol_str().starts_with("_DERIVE_")) - { - Some(id) - } else { - None - } - } - _ => None, - }); - - unnamed_consts.chain(synstructure_hack_consts) -} - pub fn def_crates( db: &dyn HirDatabase, ty: &Ty, @@ -737,7 +717,7 @@ fn lookup_impl_assoc_item_for_trait_ref( let impls = db.trait_impls_in_deps(env.krate); let self_impls = match self_ty.kind(Interner) { TyKind::Adt(id, _) => { - id.0.module(db.upcast()).containing_block().map(|it| db.trait_impls_in_block(it)) + id.0.module(db.upcast()).containing_block().and_then(|it| db.trait_impls_in_block(it)) } _ => None, }; @@ -1254,17 +1234,18 @@ fn iterate_inherent_methods( }; while let Some(block_id) = block { - let impls = db.inherent_impls_in_block(block_id); - impls_for_self_ty( - &impls, - self_ty, - table, - name, - receiver_ty, - receiver_adjustments.clone(), - module, - callback, - )?; + if let Some(impls) = db.inherent_impls_in_block(block_id) { + impls_for_self_ty( + &impls, + self_ty, + table, + name, + receiver_ty, + receiver_adjustments.clone(), + module, + callback, + )?; + } block = db.block_def_map(block_id).parent().and_then(|module| module.containing_block()); } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs index 6f4aef22d2f7..d0a1fb1d5769 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs @@ -9,7 +9,6 @@ use base_db::{ use hir_def::{db::DefDatabase, ModuleId}; use hir_expand::db::ExpandDatabase; use nohash_hasher::IntMap; -use rustc_hash::FxHashSet; use syntax::TextRange; use test_utils::extract_annotations; use triomphe::Arc; @@ -81,7 +80,7 @@ impl FileLoader for TestDB { fn resolve_path(&self, path: AnchoredPath<'_>) -> Option { FileLoaderDelegate(self).resolve_path(path) } - fn relevant_crates(&self, file_id: FileId) -> Arc> { + fn relevant_crates(&self, file_id: FileId) -> Arc<[CrateId]> { FileLoaderDelegate(self).relevant_crates(file_id) } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs index d16e0eb0137b..622b4f56d4ff 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs @@ -987,15 +987,12 @@ fn infer_builtin_macros_env() { fn infer_builtin_macros_option_env() { check_types( r#" - //- minicore: option - //- /main.rs env:foo=bar - #[rustc_builtin_macro] - macro_rules! option_env {() => {}} - - fn main() { - let x = option_env!("foo"); - //^ Option<&str> - } +//- minicore: env +//- /main.rs env:foo=bar +fn main() { + let x = option_env!("foo"); + //^ Option<&str> +} "#, ); } @@ -1014,6 +1011,21 @@ fn test() { ); } +#[test] +fn infer_builtin_derive_resolves_with_core_module() { + check_types( + r#" +//- minicore: derive, clone +mod core {} +#[derive(Clone)] +struct S; +fn test() { + S.clone(); +} //^^^^^^^^^ S +"#, + ); +} + #[test] fn infer_derive_clone_with_params() { check_types( diff --git a/src/tools/rust-analyzer/crates/hir/src/attrs.rs b/src/tools/rust-analyzer/crates/hir/src/attrs.rs index 60ddc4aa86fe..5a21f41dca84 100644 --- a/src/tools/rust-analyzer/crates/hir/src/attrs.rs +++ b/src/tools/rust-analyzer/crates/hir/src/attrs.rs @@ -35,7 +35,7 @@ macro_rules! impl_has_attrs { impl HasAttrs for $def { fn attrs(self, db: &dyn HirDatabase) -> AttrsWithOwner { let def = AttrDefId::$def_id(self.into()); - db.attrs_with_owner(def) + AttrsWithOwner::attrs_with_owner(db.upcast(), def) } fn attr_id(self) -> AttrDefId { AttrDefId::$def_id(self.into()) diff --git a/src/tools/rust-analyzer/crates/hir/src/db.rs b/src/tools/rust-analyzer/crates/hir/src/db.rs index 7204868464b3..403a6c88ab0f 100644 --- a/src/tools/rust-analyzer/crates/hir/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir/src/db.rs @@ -15,8 +15,8 @@ pub use hir_def::db::{ InternExternBlockQuery, InternExternCrateQuery, InternFunctionQuery, InternImplQuery, InternInTypeConstQuery, InternMacro2Query, InternMacroRulesQuery, InternProcMacroQuery, InternStaticQuery, InternStructQuery, InternTraitAliasQuery, InternTraitQuery, - InternTypeAliasQuery, InternUnionQuery, InternUseQuery, LangAttrQuery, LangItemQuery, - Macro2DataQuery, MacroRulesDataQuery, ProcMacroDataQuery, StaticDataQuery, StructDataQuery, + InternTypeAliasQuery, InternUnionQuery, InternUseQuery, LangItemQuery, Macro2DataQuery, + MacroRulesDataQuery, ProcMacroDataQuery, StaticDataQuery, StructDataQuery, StructDataWithDiagnosticsQuery, TraitAliasDataQuery, TraitDataQuery, TraitDataWithDiagnosticsQuery, TypeAliasDataQuery, UnionDataQuery, UnionDataWithDiagnosticsQuery, VariantsAttrsQuery, VariantsAttrsSourceMapQuery, diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 0266915c39b6..3180a2b713a8 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -754,7 +754,7 @@ impl Module { scope .declarations() .map(ModuleDef::from) - .chain(scope.unnamed_consts().map(|id| ModuleDef::Const(Const::from(id)))) + .chain(scope.unnamed_consts(db.upcast()).map(|id| ModuleDef::Const(Const::from(id)))) .collect() } diff --git a/src/tools/rust-analyzer/crates/hir/src/symbols.rs b/src/tools/rust-analyzer/crates/hir/src/symbols.rs index 841ddfb9c437..e1101dd8236e 100644 --- a/src/tools/rust-analyzer/crates/hir/src/symbols.rs +++ b/src/tools/rust-analyzer/crates/hir/src/symbols.rs @@ -165,6 +165,7 @@ impl<'a> SymbolCollector<'a> { // Record renamed imports. // FIXME: In case it imports multiple items under different namespaces we just pick one arbitrarily // for now. + // FIXME: This parses! for id in scope.imports() { let source = id.import.child_source(self.db.upcast()); let Some(use_tree_src) = source.value.get(id.idx) else { continue }; @@ -195,7 +196,7 @@ impl<'a> SymbolCollector<'a> { }); } - for const_id in scope.unnamed_consts() { + for const_id in scope.unnamed_consts(self.db.upcast()) { self.collect_from_body(const_id); } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs index 7b71d9b86968..a64591c9ca09 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs @@ -1551,4 +1551,39 @@ use foo::Foo$0; ", ); } + + #[test] + fn considers_pub_crate() { + check_assist( + auto_import, + r#" +mod foo { + pub struct Foo; +} + +pub(crate) use self::foo::*; + +mod bar { + fn main() { + Foo$0; + } +} +"#, + r#" +mod foo { + pub struct Foo; +} + +pub(crate) use self::foo::*; + +mod bar { + use crate::Foo; + + fn main() { + Foo; + } +} +"#, + ); + } } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs index 347a3e9ba074..1eb28626f75d 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs @@ -25,7 +25,7 @@ use syntax::{ edit::{AstNodeEdit, IndentLevel}, AstNode, HasGenericParams, }, - match_ast, ted, SyntaxElement, + match_ast, ted, AstToken, SyntaxElement, SyntaxKind::{self, COMMENT}, SyntaxNode, SyntaxToken, TextRange, TextSize, TokenAtOffset, WalkEvent, T, }; @@ -1733,8 +1733,23 @@ fn make_body( ast::Expr::BlockExpr(block) => { // If the extracted expression is itself a block, there is no need to wrap it inside another block. let block = block.dedent(old_indent); - // Recreate the block for formatting consistency with other extracted functions. - make::block_expr(block.statements(), block.tail_expr()) + let elements = block.stmt_list().map_or_else( + || Either::Left(iter::empty()), + |stmt_list| { + let elements = stmt_list.syntax().children_with_tokens().filter_map( + |node_or_token| match &node_or_token { + syntax::NodeOrToken::Node(node) => { + ast::Stmt::cast(node.clone()).map(|_| node_or_token) + } + syntax::NodeOrToken::Token(token) => { + ast::Comment::cast(token.clone()).map(|_| node_or_token) + } + }, + ); + Either::Right(elements) + }, + ); + make::hacky_block_expr(elements, block.tail_expr()) } _ => { let expr = expr.dedent(old_indent).indent(IndentLevel(1)); @@ -5961,6 +5976,37 @@ fn $0fun_name() -> ControlFlow<()> { ); } + #[test] + fn comments_in_block_expr() { + check_assist( + extract_function, + r#" +fn f() { + let c = $0{ + // comment 1 + let a = 2 + 3; + // comment 2 + let b = 5; + a + b + }$0; +} +"#, + r#" +fn f() { + let c = fun_name(); +} + +fn $0fun_name() -> i32 { + // comment 1 + let a = 2 + 3; + // comment 2 + let b = 5; + a + b +} +"#, + ); + } + #[test] fn in_left_curly_is_not_applicable() { cov_mark::check!(extract_function_in_braces_is_not_applicable); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_constant.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_constant.rs index a4e8e7388f62..8b8c6ceee99e 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_constant.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_constant.rs @@ -50,6 +50,10 @@ pub(crate) fn generate_constant(acc: &mut Assists, ctx: &AssistContext<'_>) -> O ty.original().display_source_code(ctx.db(), constant_module.into(), false).ok()?; let target = statement.syntax().parent()?.text_range(); let path = constant_token.syntax().ancestors().find_map(ast::Path::cast)?; + if path.parent_path().is_some() { + cov_mark::hit!(not_last_path_segment); + return None; + } let name_refs = path.segments().map(|s| s.name_ref()); let mut outer_exists = false; @@ -250,6 +254,18 @@ fn bar() -> i32 { } fn bar() -> i32 { foo::goo::A_CONSTANT +}"#, + ); + } + + #[test] + fn test_wont_apply_when_not_last_path_segment() { + cov_mark::check!(not_last_path_segment); + check_assist_not_applicable( + generate_constant, + r#"mod foo {} +fn bar() -> i32 { + foo::A_CON$0STANT::invalid_segment }"#, ); } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs index dc02aaf9af68..1f5c24f8ea44 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs @@ -107,31 +107,48 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<' |edit| { // Create the function let method_source = match ctx.sema.source(method) { - Some(source) => source.value, + Some(source) => { + let v = source.value.clone_for_update(); + let source_scope = ctx.sema.scope(v.syntax()); + let target_scope = ctx.sema.scope(strukt.syntax()); + if let (Some(s), Some(t)) = (source_scope, target_scope) { + PathTransform::generic_transformation(&t, &s).apply(v.syntax()); + } + v + } None => return, }; + let vis = method_source.visibility(); - let fn_name = make::name(&name); - let params = - method_source.param_list().unwrap_or_else(|| make::param_list(None, [])); - let type_params = method_source.generic_param_list(); - let arg_list = match method_source.param_list() { - Some(list) => convert_param_list_to_arg_list(list), - None => make::arg_list([]), - }; - let tail_expr = make::expr_method_call(field, make::name_ref(&name), arg_list); - let ret_type = method_source.ret_type(); let is_async = method_source.async_token().is_some(); let is_const = method_source.const_token().is_some(); let is_unsafe = method_source.unsafe_token().is_some(); + + let fn_name = make::name(&name); + + let type_params = method_source.generic_param_list(); + let where_clause = method_source.where_clause(); + let params = + method_source.param_list().unwrap_or_else(|| make::param_list(None, [])); + + // compute the `body` + let arg_list = method_source + .param_list() + .map(|list| convert_param_list_to_arg_list(list)) + .unwrap_or_else(|| make::arg_list([])); + + let tail_expr = make::expr_method_call(field, make::name_ref(&name), arg_list); let tail_expr_finished = if is_async { make::expr_await(tail_expr) } else { tail_expr }; let body = make::block_expr([], Some(tail_expr_finished)); + + let ret_type = method_source.ret_type(); + let f = make::fn_( vis, fn_name, type_params, - method_source.where_clause(), + where_clause, params, body, ret_type, @@ -184,12 +201,6 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<' let assoc_items = impl_def.get_or_create_assoc_item_list(); assoc_items.add_item(f.clone().into()); - if let Some((target, source)) = - ctx.sema.scope(strukt.syntax()).zip(ctx.sema.scope(method_source.syntax())) - { - PathTransform::generic_transformation(&target, &source).apply(f.syntax()); - } - if let Some(cap) = ctx.config.snippet_cap { edit.add_tabstop_before(cap, f) } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_nested_if.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_nested_if.rs new file mode 100644 index 000000000000..2f3136f027b0 --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_nested_if.rs @@ -0,0 +1,246 @@ +use ide_db::syntax_helpers::node_ext::is_pattern_cond; +use syntax::{ + ast::{self, AstNode, BinaryOp}, + T, +}; + +use crate::{ + assist_context::{AssistContext, Assists}, + AssistId, AssistKind, +}; +// Assist: merge_nested_if +// +// This transforms if expressions of the form `if x { if y {A} }` into `if x && y {A}` +// This assist can only be applied with the cursor on `if`. +// +// ``` +// fn main() { +// i$0f x == 3 { if y == 4 { 1 } } +// } +// ``` +// -> +// ``` +// fn main() { +// if x == 3 && y == 4 { 1 } +// } +// ``` +pub(crate) fn merge_nested_if(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { + let if_keyword = ctx.find_token_syntax_at_offset(T![if])?; + let expr = ast::IfExpr::cast(if_keyword.parent()?)?; + let if_range = if_keyword.text_range(); + let cursor_in_range = if_range.contains_range(ctx.selection_trimmed()); + if !cursor_in_range { + return None; + } + + //should not apply to if with else branch. + if expr.else_branch().is_some() { + return None; + } + + let cond = expr.condition()?; + //should not apply for if-let + if is_pattern_cond(cond.clone()) { + return None; + } + + let cond_range = cond.syntax().text_range(); + + //check if the then branch is a nested if + let then_branch = expr.then_branch()?; + let stmt = then_branch.stmt_list()?; + if stmt.statements().count() != 0 { + return None; + } + + let nested_if_to_merge = then_branch.tail_expr().and_then(|e| match e { + ast::Expr::IfExpr(e) => Some(e), + _ => None, + })?; + // should not apply to nested if with else branch. + if nested_if_to_merge.else_branch().is_some() { + return None; + } + let nested_if_cond = nested_if_to_merge.condition()?; + if is_pattern_cond(nested_if_cond.clone()) { + return None; + } + + let nested_if_then_branch = nested_if_to_merge.then_branch()?; + let then_branch_range = then_branch.syntax().text_range(); + + acc.add( + AssistId("merge_nested_if", AssistKind::RefactorRewrite), + "Merge nested if", + if_range, + |edit| { + let cond_text = if has_logic_op_or(&cond) { + format!("({})", cond.syntax().text()) + } else { + cond.syntax().text().to_string() + }; + + let nested_if_cond_text = if has_logic_op_or(&nested_if_cond) { + format!("({})", nested_if_cond.syntax().text()) + } else { + nested_if_cond.syntax().text().to_string() + }; + + let replace_cond = format!("{} && {}", cond_text, nested_if_cond_text); + + edit.replace(cond_range, replace_cond); + edit.replace(then_branch_range, nested_if_then_branch.syntax().text()); + }, + ) +} + +/// Returns whether the given if condition has logical operators. +fn has_logic_op_or(expr: &ast::Expr) -> bool { + match expr { + ast::Expr::BinExpr(bin_expr) => { + if let Some(kind) = bin_expr.op_kind() { + matches!(kind, BinaryOp::LogicOp(ast::LogicOp::Or)) + } else { + false + } + } + _ => false, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::tests::{check_assist, check_assist_not_applicable}; + + #[test] + fn merge_nested_if_test1() { + check_assist( + merge_nested_if, + "fn f() { i$0f x == 3 { if y == 4 { 1 } } }", + "fn f() { if x == 3 && y == 4 { 1 } }", + ) + } + + #[test] + fn merge_nested_if_test2() { + check_assist( + merge_nested_if, + "fn f() { i$0f x == 3 || y == 1 { if z == 4 { 1 } } }", + "fn f() { if (x == 3 || y == 1) && z == 4 { 1 } }", + ) + } + + #[test] + fn merge_nested_if_test3() { + check_assist( + merge_nested_if, + "fn f() { i$0f x == 3 && y == 1 { if z == 4 { 1 } } }", + "fn f() { if x == 3 && y == 1 && z == 4 { 1 } }", + ) + } + + #[test] + fn merge_nested_if_test4() { + check_assist( + merge_nested_if, + "fn f() { i$0f x == 3 && y == 1 { if z == 4 && q == 3 { 1 } } }", + "fn f() { if x == 3 && y == 1 && z == 4 && q == 3 { 1 } }", + ) + } + + #[test] + fn merge_nested_if_test5() { + check_assist( + merge_nested_if, + "fn f() { i$0f x == 3 && y == 1 { if z == 4 || q == 3 { 1 } } }", + "fn f() { if x == 3 && y == 1 && (z == 4 || q == 3) { 1 } }", + ) + } + + #[test] + fn merge_nested_if_test6() { + check_assist( + merge_nested_if, + "fn f() { i$0f x == 3 || y == 1 { if z == 4 || q == 3 { 1 } } }", + "fn f() { if (x == 3 || y == 1) && (z == 4 || q == 3) { 1 } }", + ) + } + + #[test] + fn merge_nested_if_test7() { + check_assist( + merge_nested_if, + "fn f() { i$0f x == 3 || y == 1 { if z == 4 && q == 3 { 1 } } }", + "fn f() { if (x == 3 || y == 1) && z == 4 && q == 3 { 1 } }", + ) + } + + #[test] + fn merge_nested_if_do_not_apply_to_if_with_else_branch() { + check_assist_not_applicable( + merge_nested_if, + "fn f() { i$0f x == 3 { if y == 4 { 1 } } else { 2 } }", + ) + } + + #[test] + fn merge_nested_if_do_not_apply_to_nested_if_with_else_branch() { + check_assist_not_applicable( + merge_nested_if, + "fn f() { i$0f x == 3 { if y == 4 { 1 } else { 2 } } }", + ) + } + + #[test] + fn merge_nested_if_do_not_apply_to_if_let() { + check_assist_not_applicable( + merge_nested_if, + "fn f() { i$0f let Some(x) = y { if x == 4 { 1 } } }", + ) + } + + #[test] + fn merge_nested_if_do_not_apply_to_nested_if_let() { + check_assist_not_applicable( + merge_nested_if, + "fn f() { i$0f y == 0 { if let Some(x) = y { 1 } } }", + ) + } + + #[test] + fn merge_nested_if_do_not_apply_to_if_with_else_branch_and_nested_if() { + check_assist_not_applicable( + merge_nested_if, + "fn f() { i$0f x == 3 { if y == 4 { 1 } } else { if z == 5 { 2 } } }", + ) + } + + #[test] + fn merge_nested_if_do_not_apply_with_cursor_not_on_if() { + check_assist_not_applicable(merge_nested_if, "fn f() { if $0x==0 { if y == 3 { 1 } } }") + } + + #[test] + fn merge_nested_if_do_not_apply_with_mulpiple_if() { + check_assist_not_applicable( + merge_nested_if, + "fn f() { i$0f x == 0 { if y == 3 { 1 } else if y == 4 { 2 } } }", + ) + } + #[test] + fn merge_nested_if_do_not_apply_with_not_only_has_nested_if() { + check_assist_not_applicable( + merge_nested_if, + "fn f() { i$0f x == 0 { if y == 3 { foo(); } foo(); } }", + ) + } + + #[test] + fn merge_nested_if_do_not_apply_with_multiply_nested_if() { + check_assist_not_applicable( + merge_nested_if, + "fn f() { i$0f x == 0 { if y == 3 { foo(); } if z == 3 { 2 } } }", + ) + } +} diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs index 1e4d1c94f5be..1eb4903ab203 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs @@ -217,6 +217,7 @@ mod handlers { mod unqualify_method_call; mod wrap_return_type_in_result; mod into_to_qualified_from; + mod merge_nested_if; pub(crate) fn all() -> &'static [Handler] { &[ @@ -291,6 +292,7 @@ mod handlers { invert_if::invert_if, merge_imports::merge_imports, merge_match_arms::merge_match_arms, + merge_nested_if::merge_nested_if, move_bounds::move_bounds_to_where_clause, move_const_to_impl::move_const_to_impl, move_guard::move_arm_cond_to_match_guard, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs index 0c2331796f9e..0ce89ae0a9a5 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs @@ -2051,6 +2051,23 @@ fn handle(action: Action) { ) } +#[test] +fn doctest_merge_nested_if() { + check_doc_test( + "merge_nested_if", + r#####" +fn main() { + i$0f x == 3 { if y == 4 { 1 } } +} +"#####, + r#####" +fn main() { + if x == 3 && y == 4 { 1 } +} +"#####, + ) +} + #[test] fn doctest_move_arm_cond_to_match_guard() { check_doc_test( diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs index 108b040de6ba..92aa1da89c41 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs @@ -529,6 +529,11 @@ impl CompletionContext<'_> { } } + /// Whether the given trait has `#[doc(notable_trait)]` + pub(crate) fn is_doc_notable_trait(&self, trait_: hir::Trait) -> bool { + trait_.attrs(self.db).has_doc_notable_trait() + } + /// Returns the traits in scope, with the [`Drop`] trait removed. pub(crate) fn traits_in_scope(&self) -> hir::VisibleTraits { let mut traits_in_scope = self.scope.visible_traits(); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs index de41a5bd70c4..affd9b729646 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs @@ -152,6 +152,8 @@ pub struct CompletionRelevance { pub is_local: bool, /// This is set when trait items are completed in an impl of that trait. pub is_item_from_trait: bool, + /// This is set for when trait items are from traits with `#[doc(notable_trait)]` + pub is_item_from_notable_trait: bool, /// This is set when an import is suggested whose name is already imported. pub is_name_already_imported: bool, /// This is set for completions that will insert a `use` item. @@ -228,6 +230,7 @@ impl CompletionRelevance { is_private_editable, postfix_match, is_definite, + is_item_from_notable_trait, } = self; // lower rank private things @@ -266,6 +269,9 @@ impl CompletionRelevance { if is_item_from_trait { score += 1; } + if is_item_from_notable_trait { + score += 1; + } if is_definite { score += 10; } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs index 581d557e831a..8c0e6694761e 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs @@ -1170,6 +1170,7 @@ fn main() { let _: m::Spam = S$0 } ), is_local: false, is_item_from_trait: false, + is_item_from_notable_trait: false, is_name_already_imported: false, requires_import: false, is_op_method: false, @@ -1196,6 +1197,7 @@ fn main() { let _: m::Spam = S$0 } ), is_local: false, is_item_from_trait: false, + is_item_from_notable_trait: false, is_name_already_imported: false, requires_import: false, is_op_method: false, @@ -1274,6 +1276,7 @@ fn foo() { A { the$0 } } ), is_local: false, is_item_from_trait: false, + is_item_from_notable_trait: false, is_name_already_imported: false, requires_import: false, is_op_method: false, @@ -2089,6 +2092,7 @@ fn foo() { ), is_local: false, is_item_from_trait: false, + is_item_from_notable_trait: false, is_name_already_imported: false, requires_import: false, is_op_method: false, @@ -2439,4 +2443,81 @@ impl S { "#, ) } + + #[test] + fn notable_traits_method_relevance() { + check_kinds( + r#" +#[doc(notable_trait)] +trait Write { + fn write(&self); + fn flush(&self); +} + +struct Writer; + +impl Write for Writer { + fn write(&self) {} + fn flush(&self) {} +} + +fn main() { + Writer.$0 +} +"#, + &[ + CompletionItemKind::Method, + CompletionItemKind::SymbolKind(SymbolKind::Field), + CompletionItemKind::SymbolKind(SymbolKind::Function), + ], + expect![[r#" + [ + CompletionItem { + label: "flush()", + source_range: 193..193, + delete: 193..193, + insert: "flush()$0", + kind: Method, + lookup: "flush", + detail: "fn(&self)", + relevance: CompletionRelevance { + exact_name_match: false, + type_match: None, + is_local: false, + is_item_from_trait: false, + is_item_from_notable_trait: true, + is_name_already_imported: false, + requires_import: false, + is_op_method: false, + is_private_editable: false, + postfix_match: None, + is_definite: false, + }, + }, + CompletionItem { + label: "write()", + source_range: 193..193, + delete: 193..193, + insert: "write()$0", + kind: Method, + lookup: "write", + detail: "fn(&self)", + relevance: CompletionRelevance { + exact_name_match: false, + type_match: None, + is_local: false, + is_item_from_trait: false, + is_item_from_notable_trait: true, + is_name_already_imported: false, + requires_import: false, + is_op_method: false, + is_private_editable: false, + postfix_match: None, + is_definite: false, + }, + }, + ] + "#]], + ); + } } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs index b306bede653b..6ad84eba33be 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs @@ -74,10 +74,13 @@ fn render( ); let ret_type = func.ret_type(db); - let is_op_method = func - .as_assoc_item(ctx.db()) - .and_then(|trait_| trait_.containing_trait_or_trait_impl(ctx.db())) - .map_or(false, |trait_| completion.is_ops_trait(trait_)); + let assoc_item = func.as_assoc_item(db); + + let trait_ = assoc_item.and_then(|trait_| trait_.containing_trait_or_trait_impl(db)); + let is_op_method = trait_.map_or(false, |trait_| completion.is_ops_trait(trait_)); + + let is_item_from_notable_trait = + trait_.map_or(false, |trait_| completion.is_doc_notable_trait(trait_)); let (has_dot_receiver, has_call_parens, cap) = match func_kind { FuncKind::Function(&PathCompletionCtx { @@ -105,6 +108,7 @@ fn render( }, exact_name_match: compute_exact_name_match(completion, &call), is_op_method, + is_item_from_notable_trait, ..ctx.completion_relevance() }); @@ -141,7 +145,7 @@ fn render( item.add_import(import_to_add); } None => { - if let Some(actm) = func.as_assoc_item(db) { + if let Some(actm) = assoc_item { if let Some(trt) = actm.containing_trait_or_trait_impl(db) { item.trait_name(trt.name(db).to_smol_str()); } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs b/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs index db6cd128e83d..259d141404d3 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs @@ -84,73 +84,11 @@ impl RootDatabase { )*} } purge_each_query![ - // SourceDatabase - base_db::ParseQuery - base_db::CrateGraphQuery - - // SourceDatabaseExt - base_db::FileTextQuery - base_db::FileSourceRootQuery - base_db::SourceRootQuery - base_db::SourceRootCratesQuery - - // ExpandDatabase - hir::db::AstIdMapQuery - hir::db::DeclMacroExpanderQuery - hir::db::ExpandProcMacroQuery - hir::db::InternMacroCallQuery - hir::db::InternSyntaxContextQuery - hir::db::MacroArgQuery - hir::db::ParseMacroExpansionQuery - hir::db::RealSpanMapQuery - hir::db::ProcMacrosQuery - - // DefDatabase - hir::db::FileItemTreeQuery - hir::db::CrateDefMapQueryQuery - hir::db::BlockDefMapQuery - hir::db::StructDataQuery - hir::db::StructDataWithDiagnosticsQuery - hir::db::UnionDataQuery - hir::db::UnionDataWithDiagnosticsQuery - hir::db::EnumDataQuery - hir::db::EnumDataWithDiagnosticsQuery - hir::db::ImplDataQuery - hir::db::ImplDataWithDiagnosticsQuery - hir::db::TraitDataQuery - hir::db::TraitDataWithDiagnosticsQuery - hir::db::TraitAliasDataQuery - hir::db::TypeAliasDataQuery - hir::db::FunctionDataQuery - hir::db::ConstDataQuery - hir::db::StaticDataQuery - hir::db::Macro2DataQuery - hir::db::MacroRulesDataQuery - hir::db::ProcMacroDataQuery - hir::db::BodyWithSourceMapQuery - hir::db::BodyQuery - hir::db::ExprScopesQuery - hir::db::GenericParamsQuery - hir::db::VariantsAttrsQuery - hir::db::FieldsAttrsQuery - hir::db::VariantsAttrsSourceMapQuery - hir::db::FieldsAttrsSourceMapQuery - hir::db::AttrsQuery - hir::db::CrateLangItemsQuery - hir::db::LangItemQuery - hir::db::ImportMapQuery - hir::db::FieldVisibilitiesQuery - hir::db::FunctionVisibilityQuery - hir::db::ConstVisibilityQuery - hir::db::CrateSupportsNoStdQuery - hir::db::BlockItemTreeQueryQuery - hir::db::ExternCrateDeclDataQuery - hir::db::LangAttrQuery - hir::db::InternAnonymousConstQuery - hir::db::InternExternCrateQuery - hir::db::InternInTypeConstQuery - hir::db::InternUseQuery - + // SymbolsDatabase + crate::symbol_index::ModuleSymbolsQuery + crate::symbol_index::LibrarySymbolsQuery + crate::symbol_index::LocalRootsQuery + crate::symbol_index::LibraryRootsQuery // HirDatabase hir::db::InferQueryQuery hir::db::MirBodyQuery @@ -194,14 +132,50 @@ impl RootDatabase { hir::db::TraitSolveQueryQuery hir::db::ProgramClausesForChalkEnvQuery - // SymbolsDatabase - crate::symbol_index::ModuleSymbolsQuery - crate::symbol_index::LibrarySymbolsQuery - crate::symbol_index::LocalRootsQuery - crate::symbol_index::LibraryRootsQuery - - // LineIndexDatabase - crate::LineIndexQuery + // DefDatabase + hir::db::FileItemTreeQuery + hir::db::CrateDefMapQueryQuery + hir::db::BlockDefMapQuery + hir::db::StructDataQuery + hir::db::StructDataWithDiagnosticsQuery + hir::db::UnionDataQuery + hir::db::UnionDataWithDiagnosticsQuery + hir::db::EnumDataQuery + hir::db::EnumDataWithDiagnosticsQuery + hir::db::ImplDataQuery + hir::db::ImplDataWithDiagnosticsQuery + hir::db::TraitDataQuery + hir::db::TraitDataWithDiagnosticsQuery + hir::db::TraitAliasDataQuery + hir::db::TypeAliasDataQuery + hir::db::FunctionDataQuery + hir::db::ConstDataQuery + hir::db::StaticDataQuery + hir::db::Macro2DataQuery + hir::db::MacroRulesDataQuery + hir::db::ProcMacroDataQuery + hir::db::BodyWithSourceMapQuery + hir::db::BodyQuery + hir::db::ExprScopesQuery + hir::db::GenericParamsQuery + hir::db::VariantsAttrsQuery + hir::db::FieldsAttrsQuery + hir::db::VariantsAttrsSourceMapQuery + hir::db::FieldsAttrsSourceMapQuery + hir::db::AttrsQuery + hir::db::CrateLangItemsQuery + hir::db::LangItemQuery + hir::db::ImportMapQuery + hir::db::FieldVisibilitiesQuery + hir::db::FunctionVisibilityQuery + hir::db::ConstVisibilityQuery + hir::db::CrateSupportsNoStdQuery + hir::db::BlockItemTreeQueryQuery + hir::db::ExternCrateDeclDataQuery + hir::db::InternAnonymousConstQuery + hir::db::InternExternCrateQuery + hir::db::InternInTypeConstQuery + hir::db::InternUseQuery // InternDatabase hir::db::InternFunctionQuery @@ -219,6 +193,30 @@ impl RootDatabase { hir::db::InternMacro2Query hir::db::InternProcMacroQuery hir::db::InternMacroRulesQuery + + // ExpandDatabase + hir::db::AstIdMapQuery + hir::db::DeclMacroExpanderQuery + hir::db::ExpandProcMacroQuery + hir::db::InternMacroCallQuery + hir::db::InternSyntaxContextQuery + hir::db::MacroArgQuery + hir::db::ParseMacroExpansionQuery + hir::db::RealSpanMapQuery + hir::db::ProcMacrosQuery + + // LineIndexDatabase + crate::LineIndexQuery + + // SourceDatabase + base_db::ParseQuery + base_db::CrateGraphQuery + + // SourceDatabaseExt + base_db::FileTextQuery + base_db::FileSourceRootQuery + base_db::SourceRootQuery + base_db::SourceRootCratesQuery ]; acc.sort_by_key(|it| std::cmp::Reverse(it.1)); diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs index 652968d808fa..b834f517d491 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs @@ -681,11 +681,10 @@ fn path_import_candidate( Some(qualifier) => match sema.resolve_path(&qualifier) { None => { if qualifier.first_qualifier().map_or(true, |it| sema.resolve_path(&it).is_none()) { - let mut qualifier = qualifier - .segments_of_this_path_only_rev() + let qualifier = qualifier + .segments() .map(|seg| seg.name_ref().map(|name| SmolStr::new(name.text()))) .collect::>>()?; - qualifier.reverse(); ImportCandidate::Path(PathImportCandidate { qualifier: Some(qualifier), name }) } else { return None; diff --git a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs index 128971994f64..eae23e954824 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs @@ -124,7 +124,7 @@ impl FileLoader for RootDatabase { fn resolve_path(&self, path: AnchoredPath<'_>) -> Option { FileLoaderDelegate(self).resolve_path(path) } - fn relevant_crates(&self, file_id: FileId) -> Arc> { + fn relevant_crates(&self, file_id: FileId) -> Arc<[CrateId]> { FileLoaderDelegate(self).relevant_crates(file_id) } } @@ -145,7 +145,7 @@ impl RootDatabase { db.set_local_roots_with_durability(Default::default(), Durability::HIGH); db.set_library_roots_with_durability(Default::default(), Durability::HIGH); db.set_expand_proc_attr_macros_with_durability(false, Durability::HIGH); - db.update_parse_query_lru_capacity(lru_capacity); + db.update_base_query_lru_capacities(lru_capacity); db.setup_syntax_context_root(); db } @@ -154,11 +154,12 @@ impl RootDatabase { self.set_expand_proc_attr_macros_with_durability(true, Durability::HIGH); } - pub fn update_parse_query_lru_capacity(&mut self, lru_capacity: Option) { + pub fn update_base_query_lru_capacities(&mut self, lru_capacity: Option) { let lru_capacity = lru_capacity.unwrap_or(base_db::DEFAULT_PARSE_LRU_CAP); base_db::ParseQuery.in_db_mut(self).set_lru_capacity(lru_capacity); // macro expansions are usually rather small, so we can afford to keep more of them alive hir::db::ParseMacroExpansionQuery.in_db_mut(self).set_lru_capacity(4 * lru_capacity); + hir::db::BorrowckQuery.in_db_mut(self).set_lru_capacity(base_db::DEFAULT_BORROWCK_LRU_CAP); } pub fn update_lru_capacities(&mut self, lru_capacities: &FxHashMap, usize>) { @@ -176,6 +177,12 @@ impl RootDatabase { .copied() .unwrap_or(4 * base_db::DEFAULT_PARSE_LRU_CAP), ); + hir_db::BorrowckQuery.in_db_mut(self).set_lru_capacity( + lru_capacities + .get(stringify!(BorrowckQuery)) + .copied() + .unwrap_or(base_db::DEFAULT_BORROWCK_LRU_CAP), + ); macro_rules! update_lru_capacity_per_query { ($( $module:ident :: $query:ident )*) => {$( diff --git a/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs b/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs index edfeddc1bc9c..47bcaae259b4 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs @@ -3,6 +3,7 @@ use crate::helpers::mod_path_to_ast; use either::Either; use hir::{AsAssocItem, HirDisplay, ModuleDef, SemanticsScope}; +use itertools::Itertools; use rustc_hash::FxHashMap; use syntax::{ ast::{self, make, AstNode}, @@ -227,11 +228,15 @@ struct Ctx<'a> { same_self_type: bool, } -fn postorder(item: &SyntaxNode) -> impl Iterator { - item.preorder().filter_map(|event| match event { - syntax::WalkEvent::Enter(_) => None, - syntax::WalkEvent::Leave(node) => Some(node), - }) +fn preorder_rev(item: &SyntaxNode) -> impl Iterator { + let x = item + .preorder() + .filter_map(|event| match event { + syntax::WalkEvent::Enter(node) => Some(node), + syntax::WalkEvent::Leave(_) => None, + }) + .collect_vec(); + x.into_iter().rev() } impl Ctx<'_> { @@ -239,12 +244,12 @@ impl Ctx<'_> { // `transform_path` may update a node's parent and that would break the // tree traversal. Thus all paths in the tree are collected into a vec // so that such operation is safe. - let paths = postorder(item).filter_map(ast::Path::cast).collect::>(); + let paths = preorder_rev(item).filter_map(ast::Path::cast).collect::>(); for path in paths { self.transform_path(path); } - postorder(item).filter_map(ast::Lifetime::cast).for_each(|lifetime| { + preorder_rev(item).filter_map(ast::Lifetime::cast).for_each(|lifetime| { if let Some(subst) = self.lifetime_substs.get(&lifetime.syntax().text().to_string()) { ted::replace(lifetime.syntax(), subst.clone_subtree().clone_for_update().syntax()); } @@ -263,7 +268,7 @@ impl Ctx<'_> { // `transform_path` may update a node's parent and that would break the // tree traversal. Thus all paths in the tree are collected into a vec // so that such operation is safe. - let paths = postorder(value).filter_map(ast::Path::cast).collect::>(); + let paths = preorder_rev(value).filter_map(ast::Path::cast).collect::>(); for path in paths { self.transform_path(path); } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/search.rs b/src/tools/rust-analyzer/crates/ide-db/src/search.rs index a40dd2692cfd..e2b20ef92fc4 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/search.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/search.rs @@ -356,7 +356,7 @@ impl Definition { if let Some(Visibility::Public) = vis { return SearchScope::reverse_dependencies(db, module.krate()); } - if let Some(Visibility::Module(module)) = vis { + if let Some(Visibility::Module(module, _)) = vis { return SearchScope::module_and_children(db, module.into()); } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_assoc_item.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_assoc_item.rs index f1c95993c843..551021c55a98 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_assoc_item.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_assoc_item.rs @@ -13,6 +13,7 @@ pub(crate) fn unresolved_assoc_item( "no such associated item", d.expr_or_pat.clone().map(Into::into), ) + .experimental() } #[cfg(test)] diff --git a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs index 024053effe42..17c701ad0359 100644 --- a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs +++ b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs @@ -481,7 +481,7 @@ struct Foo {} "#, expect![[r#" Clone - impl < >core::clone::Clone for Foo< >where { + impl < >$crate::clone::Clone for Foo< >where { fn clone(&self) -> Self { match self { Foo{} @@ -507,7 +507,7 @@ struct Foo {} "#, expect![[r#" Copy - impl < >core::marker::Copy for Foo< >where{}"#]], + impl < >$crate::marker::Copy for Foo< >where{}"#]], ); } @@ -522,7 +522,7 @@ struct Foo {} "#, expect![[r#" Copy - impl < >core::marker::Copy for Foo< >where{}"#]], + impl < >$crate::marker::Copy for Foo< >where{}"#]], ); check( r#" @@ -533,7 +533,7 @@ struct Foo {} "#, expect![[r#" Clone - impl < >core::clone::Clone for Foo< >where { + impl < >$crate::clone::Clone for Foo< >where { fn clone(&self) -> Self { match self { Foo{} diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs index c98e9fba120a..60a9367adcee 100644 --- a/src/tools/rust-analyzer/crates/ide/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs @@ -171,7 +171,7 @@ impl AnalysisHost { } pub fn update_lru_capacity(&mut self, lru_capacity: Option) { - self.db.update_parse_query_lru_capacity(lru_capacity); + self.db.update_base_query_lru_capacities(lru_capacity); } pub fn update_lru_capacities(&mut self, lru_capacities: &FxHashMap, usize>) { diff --git a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs index 556ed73a04c2..e6ddfd580c30 100644 --- a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs +++ b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs @@ -322,7 +322,7 @@ fn load_crate_graph( break; } } - vfs::loader::Message::Loaded { files } => { + vfs::loader::Message::Loaded { files } | vfs::loader::Message::Changed { files } => { for (path, contents) in files { vfs.set_file_contents(path.into(), contents); } @@ -331,9 +331,8 @@ fn load_crate_graph( } let changes = vfs.take_changes(); for file in changes { - if file.exists() { - let contents = vfs.file_contents(file.file_id); - if let Ok(text) = std::str::from_utf8(contents) { + if let vfs::Change::Create(v) | vfs::Change::Modify(v) = file.change { + if let Ok(text) = std::str::from_utf8(&v) { analysis_change.change_file(file.file_id, Some(text.into())) } } diff --git a/src/tools/rust-analyzer/crates/parser/Cargo.toml b/src/tools/rust-analyzer/crates/parser/Cargo.toml index 0c63484634be..e74b340126c0 100644 --- a/src/tools/rust-analyzer/crates/parser/Cargo.toml +++ b/src/tools/rust-analyzer/crates/parser/Cargo.toml @@ -13,8 +13,7 @@ doctest = false [dependencies] drop_bomb = "0.1.5" -rustc-dependencies.workspace = true - +ra-ap-rustc_lexer.workspace = true limit.workspace = true [dev-dependencies] @@ -24,7 +23,7 @@ stdx.workspace = true sourcegen.workspace = true [features] -in-rust-tree = ["rustc-dependencies/in-rust-tree"] +in-rust-tree = [] [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs index e346ece2f94b..c8626111145d 100644 --- a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs +++ b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs @@ -371,7 +371,15 @@ fn lhs(p: &mut Parser<'_>, r: Restrictions) -> Option<(CompletedMarker, BlockLik if p.at(op) { m = p.start(); p.bump(op); - if p.at_ts(EXPR_FIRST) && !(r.forbid_structs && p.at(T!['{'])) { + + // test closure_range_method_call + // fn foo() { + // || .. .method(); + // || .. .field; + // } + let has_access_after = p.at(T![.]) && p.nth_at(1, SyntaxKind::IDENT); + let struct_forbidden = r.forbid_structs && p.at(T!['{']); + if p.at_ts(EXPR_FIRST) && !has_access_after && !struct_forbidden { expr_bp(p, None, r, 2); } let cm = m.complete(p, RANGE_EXPR); diff --git a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs index b9e7566fdf9b..aa25f82ae1d8 100644 --- a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs +++ b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs @@ -8,8 +8,6 @@ //! Note that these tokens, unlike the tokens we feed into the parser, do //! include info about comments and whitespace. -use rustc_dependencies::lexer as rustc_lexer; - use std::ops; use rustc_lexer::unescape::{EscapeError, Mode}; @@ -371,6 +369,7 @@ fn error_to_diagnostic_message(error: EscapeError, mode: Mode) -> &'static str { "non-ASCII character in byte string literal" } EscapeError::NonAsciiCharInByte => "non-ASCII character in raw byte string literal", + EscapeError::NulInCStr => "null character in C string literal", EscapeError::UnskippedWhitespaceWarning => "", EscapeError::MultipleSkippedLinesWarning => "", } diff --git a/src/tools/rust-analyzer/crates/parser/src/lib.rs b/src/tools/rust-analyzer/crates/parser/src/lib.rs index d9b3f46f2001..ed0aec3cab32 100644 --- a/src/tools/rust-analyzer/crates/parser/src/lib.rs +++ b/src/tools/rust-analyzer/crates/parser/src/lib.rs @@ -21,6 +21,11 @@ #![allow(rustdoc::private_intra_doc_links)] #![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] +#[cfg(not(feature = "in-rust-tree"))] +extern crate ra_ap_rustc_lexer as rustc_lexer; +#[cfg(feature = "in-rust-tree")] +extern crate rustc_lexer; + mod lexed_str; mod token_set; mod syntax_kind; diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0208_closure_range_method_call.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0208_closure_range_method_call.rast new file mode 100644 index 000000000000..542711339d19 --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0208_closure_range_method_call.rast @@ -0,0 +1,49 @@ +SOURCE_FILE + FN + FN_KW "fn" + WHITESPACE " " + NAME + IDENT "foo" + PARAM_LIST + L_PAREN "(" + R_PAREN ")" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE "\n " + EXPR_STMT + METHOD_CALL_EXPR + CLOSURE_EXPR + PARAM_LIST + PIPE "|" + PIPE "|" + WHITESPACE " " + RANGE_EXPR + DOT2 ".." + WHITESPACE " " + DOT "." + NAME_REF + IDENT "method" + ARG_LIST + L_PAREN "(" + R_PAREN ")" + SEMICOLON ";" + WHITESPACE "\n " + EXPR_STMT + FIELD_EXPR + CLOSURE_EXPR + PARAM_LIST + PIPE "|" + PIPE "|" + WHITESPACE " " + RANGE_EXPR + DOT2 ".." + WHITESPACE " " + DOT "." + NAME_REF + IDENT "field" + SEMICOLON ";" + WHITESPACE "\n" + R_CURLY "}" + WHITESPACE "\n" diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0208_closure_range_method_call.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0208_closure_range_method_call.rs new file mode 100644 index 000000000000..a81d3c37133a --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0208_closure_range_method_call.rs @@ -0,0 +1,4 @@ +fn foo() { + || .. .method(); + || .. .field; +} diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs index a87becd63e28..208051113a7d 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs @@ -14,8 +14,10 @@ mod version; use indexmap::IndexSet; use paths::AbsPathBuf; use span::Span; -use std::{fmt, io, sync::Mutex}; -use triomphe::Arc; +use std::{ + fmt, io, + sync::{Arc, Mutex}, +}; use serde::{Deserialize, Serialize}; @@ -81,9 +83,11 @@ impl PartialEq for ProcMacro { } } +#[derive(Clone, Debug)] pub struct ServerError { pub message: String, - pub io: Option, + // io::Error isn't Clone for some reason + pub io: Option>, } impl fmt::Display for ServerError { diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs index 3494164c0675..5ce601bce692 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs @@ -1,8 +1,9 @@ //! Handle process life-time and message passing for proc-macro client use std::{ - io::{self, BufRead, BufReader, Write}, + io::{self, BufRead, BufReader, Read, Write}, process::{Child, ChildStdin, ChildStdout, Command, Stdio}, + sync::Arc, }; use paths::{AbsPath, AbsPathBuf}; @@ -15,9 +16,11 @@ use crate::{ #[derive(Debug)] pub(crate) struct ProcMacroProcessSrv { - _process: Process, + process: Process, stdin: ChildStdin, stdout: BufReader, + /// Populated when the server exits. + server_exited: Option, version: u32, mode: SpanMode, } @@ -29,9 +32,10 @@ impl ProcMacroProcessSrv { let (stdin, stdout) = process.stdio().expect("couldn't access child stdio"); io::Result::Ok(ProcMacroProcessSrv { - _process: process, + process, stdin, stdout, + server_exited: None, version: 0, mode: SpanMode::Id, }) @@ -105,8 +109,35 @@ impl ProcMacroProcessSrv { } pub(crate) fn send_task(&mut self, req: Request) -> Result { + if let Some(server_error) = &self.server_exited { + return Err(server_error.clone()); + } + let mut buf = String::new(); - send_request(&mut self.stdin, &mut self.stdout, req, &mut buf) + send_request(&mut self.stdin, &mut self.stdout, req, &mut buf).map_err(|e| { + if e.io.as_ref().map(|it| it.kind()) == Some(io::ErrorKind::BrokenPipe) { + match self.process.child.try_wait() { + Ok(None) => e, + Ok(Some(status)) => { + let mut msg = String::new(); + if !status.success() { + if let Some(stderr) = self.process.child.stderr.as_mut() { + _ = stderr.read_to_string(&mut msg); + } + } + let server_error = ServerError { + message: format!("server exited with {status}: {msg}"), + io: None, + }; + self.server_exited = Some(server_error.clone()); + server_error + } + Err(_) => e, + } + } else { + e + } + }) } } @@ -131,12 +162,19 @@ impl Process { } fn mk_child(path: &AbsPath, null_stderr: bool) -> io::Result { - Command::new(path.as_os_str()) - .env("RUST_ANALYZER_INTERNALS_DO_NOT_USE", "this is unstable") + let mut cmd = Command::new(path.as_os_str()); + cmd.env("RUST_ANALYZER_INTERNALS_DO_NOT_USE", "this is unstable") .stdin(Stdio::piped()) .stdout(Stdio::piped()) - .stderr(if null_stderr { Stdio::null() } else { Stdio::inherit() }) - .spawn() + .stderr(if null_stderr { Stdio::null() } else { Stdio::inherit() }); + if cfg!(windows) { + let mut path_var = std::ffi::OsString::new(); + path_var.push(path.parent().unwrap().parent().unwrap().as_os_str()); + path_var.push("\\bin;"); + path_var.push(std::env::var_os("PATH").unwrap_or_default()); + cmd.env("PATH", path_var); + } + cmd.spawn() } fn send_request( @@ -145,9 +183,13 @@ fn send_request( req: Request, buf: &mut String, ) -> Result { - req.write(&mut writer) - .map_err(|err| ServerError { message: "failed to write request".into(), io: Some(err) })?; - let res = Response::read(&mut reader, buf) - .map_err(|err| ServerError { message: "failed to read response".into(), io: Some(err) })?; + req.write(&mut writer).map_err(|err| ServerError { + message: "failed to write request".into(), + io: Some(Arc::new(err)), + })?; + let res = Response::read(&mut reader, buf).map_err(|err| ServerError { + message: "failed to read response".into(), + io: Some(Arc::new(err)), + })?; res.ok_or_else(|| ServerError { message: "server exited".into(), io: None }) } diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main.rs b/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main.rs index 87f7555b02ce..af9a03826ffc 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main.rs @@ -24,7 +24,8 @@ fn main() -> std::io::Result<()> { #[cfg(not(any(feature = "sysroot-abi", rust_analyzer)))] fn run() -> io::Result<()> { - panic!("proc-macro-srv-cli requires the `sysroot-abi` feature to be enabled"); + eprintln!("proc-macro-srv-cli requires the `sysroot-abi` feature to be enabled"); + std::process::exit(70); } #[cfg(any(feature = "sysroot-abi", rust_analyzer))] diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml index 9c4375559c11..ba17ea6f7b43 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml @@ -37,7 +37,7 @@ expect-test = "1.4.0" proc-macro-test.path = "./proc-macro-test" [features] -sysroot-abi = ["proc-macro-test/sysroot-abi"] +sysroot-abi = [] in-rust-tree = ["mbe/in-rust-tree", "sysroot-abi"] [lints] diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/Cargo.toml index 90545bb5130c..7977afb1cbd2 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/Cargo.toml +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/Cargo.toml @@ -14,6 +14,3 @@ cargo_metadata = "0.18.1" # local deps toolchain.workspace = true - -[features] -sysroot-abi = [] diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/build.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/build.rs index 7299147686df..e6903fb8d4ae 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/build.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/build.rs @@ -17,11 +17,24 @@ use cargo_metadata::Message; fn main() { println!("cargo:rerun-if-changed=imp"); - println!("cargo:rerun-if-env-changed=PROC_MACRO_TEST_TOOLCHAIN"); + + let has_features = env::var_os("RUSTC_BOOTSTRAP").is_some() + || String::from_utf8( + Command::new(toolchain::cargo()).arg("--version").output().unwrap().stdout, + ) + .unwrap() + .contains("nightly"); let out_dir = env::var_os("OUT_DIR").unwrap(); let out_dir = Path::new(&out_dir); + if !has_features { + println!("proc-macro-test testing only works on nightly toolchains"); + let info_path = out_dir.join("proc_macro_test_location.txt"); + fs::File::create(info_path).unwrap(); + return; + } + let name = "proc-macro-test-impl"; let version = "0.0.0"; @@ -53,15 +66,7 @@ fn main() { let target_dir = out_dir.join("target"); - let mut cmd = if let Ok(toolchain) = std::env::var("PROC_MACRO_TEST_TOOLCHAIN") { - // leverage rustup to find user-specific toolchain - let mut cmd = Command::new("cargo"); - cmd.arg(format!("+{toolchain}")); - cmd - } else { - Command::new(toolchain::cargo()) - }; - + let mut cmd = Command::new(toolchain::cargo()); cmd.current_dir(&staging_dir) .args(["build", "-p", "proc-macro-test-impl", "--message-format", "json"]) // Explicit override the target directory to avoid using the same one which the parent @@ -70,9 +75,6 @@ fn main() { // instance to use the same target directory. .arg("--target-dir") .arg(&target_dir); - if cfg!(feature = "sysroot-abi") { - cmd.args(["--features", "sysroot-abi"]); - } if let Ok(target) = std::env::var("TARGET") { cmd.args(["--target", &target]); @@ -90,12 +92,24 @@ fn main() { panic!("proc-macro-test-impl failed to build"); } + // Old Package ID Spec + let repr = format!("{name} {version}"); + // New Package Id Spec since rust-lang/cargo#13311 + let pkgid = String::from_utf8( + Command::new(toolchain::cargo()) + .current_dir(&staging_dir) + .args(["pkgid", name]) + .output() + .unwrap().stdout, + ) + .unwrap(); + let pkgid = pkgid.trim(); + let mut artifact_path = None; for message in Message::parse_stream(output.stdout.as_slice()) { if let Message::CompilerArtifact(artifact) = message.unwrap() { if artifact.target.kind.contains(&"proc-macro".to_string()) { - let repr = format!("{name} {version}"); - if artifact.package_id.repr.starts_with(&repr) { + if artifact.package_id.repr.starts_with(&repr) || artifact.package_id.repr == pkgid { artifact_path = Some(PathBuf::from(&artifact.filenames[0])); } } diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/Cargo.toml index dc94fcd61a4f..fa189752b76f 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/Cargo.toml +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/Cargo.toml @@ -13,7 +13,4 @@ proc-macro = true # this crate should not have any dependencies, since it uses its own workspace, # and its own `Cargo.lock` -[features] -sysroot-abi = [] - [workspace] diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/src/lib.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/src/lib.rs index b8aad4acefcf..d9018b1b87d3 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/src/lib.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/src/lib.rs @@ -1,8 +1,5 @@ //! Exports a few trivial procedural macros for testing. -#![allow(unexpected_cfgs)] -#![cfg(feature = "sysroot-abi")] -#![cfg(any(feature = "sysroot-abi", rust_analyzer))] #![warn(rust_2018_idioms, unused_lifetimes)] #![feature(proc_macro_span, proc_macro_def_site)] diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs index f1575a5b0bd8..67b9f57a1636 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs @@ -11,11 +11,13 @@ //! rustc rather than `unstable`. (Although in general ABI compatibility is still an issue)… #![cfg(any(feature = "sysroot-abi", rust_analyzer))] -#![feature(proc_macro_internals, proc_macro_diagnostic, proc_macro_span, rustc_private)] +#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] +#![feature(proc_macro_internals, proc_macro_diagnostic, proc_macro_span)] #![warn(rust_2018_idioms, unused_lifetimes)] #![allow(unreachable_pub, internal_features)] extern crate proc_macro; +#[cfg(feature = "in-rust-tree")] extern crate rustc_driver as _; mod dylib; diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs index 00cc7c30ee3e..c04eddc56fb7 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs @@ -1398,7 +1398,7 @@ fn sysroot_to_crate_graph( let public_deps = SysrootPublicDeps { deps: sysroot .public_deps() - .map(|(name, idx, prelude)| (name, sysroot_crates[&idx], prelude)) + .filter_map(|(name, idx, prelude)| Some((name, *sysroot_crates.get(&idx)?, prelude))) .collect::>(), }; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml index ad24d6d28cd7..76414160716c 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml @@ -49,7 +49,6 @@ flycheck.workspace = true hir-def.workspace = true hir-ty.workspace = true hir.workspace = true -rustc-dependencies.workspace = true ide-db.workspace = true # This should only be used in CLI ide-ssr.workspace = true @@ -89,11 +88,10 @@ in-rust-tree = [ "ide/in-rust-tree", "syntax/in-rust-tree", "parser/in-rust-tree", - "rustc-dependencies/in-rust-tree", "hir/in-rust-tree", "hir-def/in-rust-tree", "hir-ty/in-rust-tree", ] [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs index f57a27305f03..c4a29e0cbb03 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs @@ -3,7 +3,7 @@ //! //! Each tick provides an immutable snapshot of the state as `WorldSnapshot`. -use std::time::Instant; +use std::{collections::hash_map::Entry, time::Instant}; use crossbeam_channel::{unbounded, Receiver, Sender}; use flycheck::FlycheckHandle; @@ -21,7 +21,7 @@ use proc_macro_api::ProcMacroServer; use project_model::{CargoWorkspace, ProjectWorkspace, Target, WorkspaceBuildScripts}; use rustc_hash::{FxHashMap, FxHashSet}; use triomphe::Arc; -use vfs::{AnchoredPathBuf, Vfs}; +use vfs::{AnchoredPathBuf, ChangedFile, Vfs}; use crate::{ config::{Config, ConfigError}, @@ -217,8 +217,8 @@ impl GlobalState { pub(crate) fn process_changes(&mut self) -> bool { let _p = profile::span("GlobalState::process_changes"); - let mut file_changes = FxHashMap::default(); - let (change, changed_files, workspace_structure_change) = { + let mut file_changes = FxHashMap::<_, (bool, ChangedFile)>::default(); + let (change, modified_rust_files, workspace_structure_change) = { let mut change = Change::new(); let mut guard = self.vfs.write(); let changed_files = guard.0.take_changes(); @@ -233,64 +233,63 @@ impl GlobalState { // id that is followed by a delete we actually skip observing the file text from the // earlier event, to avoid problems later on. for changed_file in changed_files { - use vfs::ChangeKind::*; - - file_changes - .entry(changed_file.file_id) - .and_modify(|(change, just_created)| { - // None -> Delete => keep - // Create -> Delete => collapse - // - match (change, just_created, changed_file.change_kind) { + use vfs::Change::*; + match file_changes.entry(changed_file.file_id) { + Entry::Occupied(mut o) => { + let (just_created, change) = o.get_mut(); + match (&mut change.change, just_created, changed_file.change) { // latter `Delete` wins (change, _, Delete) => *change = Delete, // merge `Create` with `Create` or `Modify` - (Create, _, Create | Modify) => {} + (Create(prev), _, Create(new) | Modify(new)) => *prev = new, // collapse identical `Modify`es - (Modify, _, Modify) => {} + (Modify(prev), _, Modify(new)) => *prev = new, // equivalent to `Modify` - (change @ Delete, just_created, Create) => { - *change = Modify; + (change @ Delete, just_created, Create(new)) => { + *change = Modify(new); *just_created = true; } // shouldn't occur, but collapse into `Create` - (change @ Delete, just_created, Modify) => { - *change = Create; + (change @ Delete, just_created, Modify(new)) => { + *change = Create(new); *just_created = true; } - // shouldn't occur, but collapse into `Modify` - (Modify, _, Create) => {} + // shouldn't occur, but keep the Create + (prev @ Modify(_), _, new @ Create(_)) => *prev = new, } - }) - .or_insert(( - changed_file.change_kind, - matches!(changed_file.change_kind, Create), - )); + } + Entry::Vacant(v) => { + _ = v.insert((matches!(&changed_file.change, Create(_)), changed_file)) + } + } } let changed_files: Vec<_> = file_changes .into_iter() - .filter(|(_, (change_kind, just_created))| { - !matches!((change_kind, just_created), (vfs::ChangeKind::Delete, true)) + .filter(|(_, (just_created, change))| { + !(*just_created && matches!(change.change, vfs::Change::Delete)) }) - .map(|(file_id, (change_kind, _))| vfs::ChangedFile { file_id, change_kind }) + .map(|(file_id, (_, change))| vfs::ChangedFile { file_id, ..change }) .collect(); let mut workspace_structure_change = None; // A file was added or deleted let mut has_structure_changes = false; let mut bytes = vec![]; - for file in &changed_files { + let mut modified_rust_files = vec![]; + for file in changed_files { let vfs_path = &vfs.file_path(file.file_id); if let Some(path) = vfs_path.as_path() { let path = path.to_path_buf(); - if reload::should_refresh_for_change(&path, file.change_kind) { + if reload::should_refresh_for_change(&path, file.kind()) { workspace_structure_change = Some((path.clone(), false)); } if file.is_created_or_deleted() { has_structure_changes = true; workspace_structure_change = Some((path, self.crate_graph_file_dependencies.contains(vfs_path))); + } else if path.extension() == Some("rs".as_ref()) { + modified_rust_files.push(file.file_id); } } @@ -299,10 +298,8 @@ impl GlobalState { self.diagnostics.clear_native_for(file.file_id); } - let text = if file.exists() { - let bytes = vfs.file_contents(file.file_id).to_vec(); - - String::from_utf8(bytes).ok().and_then(|text| { + let text = if let vfs::Change::Create(v) | vfs::Change::Modify(v) = file.change { + String::from_utf8(v).ok().and_then(|text| { // FIXME: Consider doing normalization in the `vfs` instead? That allows // getting rid of some locking let (text, line_endings) = LineEndings::normalize(text); @@ -327,11 +324,10 @@ impl GlobalState { let roots = self.source_root_config.partition(vfs); change.set_roots(roots); } - (change, changed_files, workspace_structure_change) + (change, modified_rust_files, workspace_structure_change) }; self.analysis_host.apply_change(change); - { let raw_database = self.analysis_host.raw_database(); // FIXME: ideally we should only trigger a workspace fetch for non-library changes @@ -343,13 +339,12 @@ impl GlobalState { force_crate_graph_reload, ); } - self.proc_macro_changed = - changed_files.iter().filter(|file| !file.is_created_or_deleted()).any(|file| { - let crates = raw_database.relevant_crates(file.file_id); - let crate_graph = raw_database.crate_graph(); + self.proc_macro_changed = modified_rust_files.into_iter().any(|file_id| { + let crates = raw_database.relevant_crates(file_id); + let crate_graph = raw_database.crate_graph(); - crates.iter().any(|&krate| crate_graph[krate].is_proc_macro) - }); + crates.iter().any(|&krate| crate_graph[krate].is_proc_macro) + }); } true @@ -494,10 +489,6 @@ impl GlobalStateSnapshot { }) } - pub(crate) fn vfs_memory_usage(&self) -> usize { - self.vfs_read().memory_usage() - } - pub(crate) fn file_exists(&self, file_id: FileId) -> bool { self.vfs.read().0.exists(file_id) } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs index 7e6219991b66..ce69d612255a 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs @@ -59,7 +59,13 @@ pub(crate) fn handle_did_open_text_document( if let Ok(path) = from_proto::vfs_path(¶ms.text_document.uri) { let already_exists = state .mem_docs - .insert(path.clone(), DocumentData::new(params.text_document.version)) + .insert( + path.clone(), + DocumentData::new( + params.text_document.version, + params.text_document.text.clone().into_bytes(), + ), + ) .is_err(); if already_exists { tracing::error!("duplicate DidOpenTextDocument: {}", path); @@ -76,11 +82,12 @@ pub(crate) fn handle_did_change_text_document( let _p = profile::span("handle_did_change_text_document"); if let Ok(path) = from_proto::vfs_path(¶ms.text_document.uri) { - match state.mem_docs.get_mut(&path) { + let data = match state.mem_docs.get_mut(&path) { Some(doc) => { // The version passed in DidChangeTextDocument is the version after all edits are applied // so we should apply it before the vfs is notified. doc.version = params.text_document.version; + &mut doc.data } None => { tracing::error!("unexpected DidChangeTextDocument: {}", path); @@ -88,16 +95,16 @@ pub(crate) fn handle_did_change_text_document( } }; - let text = apply_document_changes( + let new_contents = apply_document_changes( state.config.position_encoding(), - || { - let vfs = &state.vfs.read().0; - let file_id = vfs.file_id(&path).unwrap(); - std::str::from_utf8(vfs.file_contents(file_id)).unwrap().into() - }, + std::str::from_utf8(data).unwrap(), params.content_changes, - ); - state.vfs.write().0.set_file_contents(path, Some(text.into_bytes())); + ) + .into_bytes(); + if *data != new_contents { + *data = new_contents.clone(); + state.vfs.write().0.set_file_contents(path, Some(new_contents)); + } } Ok(()) } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs index 13544558c50c..22c7e9b0503c 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs @@ -103,7 +103,6 @@ pub(crate) fn handle_analyzer_status( .collect::>() ); } - format_to!(buf, "\nVfs memory usage: {}\n", profile::Bytes::new(snap.vfs_memory_usage() as _)); buf.push_str("\nAnalysis:\n"); buf.push_str( &snap diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/utils.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/utils.rs index a4417e4d4a14..fa5ea5b57db0 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/utils.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/utils.rs @@ -168,7 +168,7 @@ impl GlobalState { pub(crate) fn apply_document_changes( encoding: PositionEncoding, - file_contents: impl FnOnce() -> String, + file_contents: &str, mut content_changes: Vec, ) -> String { // If at least one of the changes is a full document change, use the last @@ -179,7 +179,7 @@ pub(crate) fn apply_document_changes( let text = mem::take(&mut content_changes[idx].text); (text, &content_changes[idx + 1..]) } - None => (file_contents(), &content_changes[..]), + None => (file_contents.to_owned(), &content_changes[..]), }; if content_changes.is_empty() { return text; @@ -276,11 +276,11 @@ mod tests { } let encoding = PositionEncoding::Wide(WideEncoding::Utf16); - let text = apply_document_changes(encoding, || String::new(), vec![]); + let text = apply_document_changes(encoding, "", vec![]); assert_eq!(text, ""); let text = apply_document_changes( encoding, - || text, + &text, vec![TextDocumentContentChangeEvent { range: None, range_length: None, @@ -288,49 +288,46 @@ mod tests { }], ); assert_eq!(text, "the"); - let text = apply_document_changes(encoding, || text, c![0, 3; 0, 3 => " quick"]); + let text = apply_document_changes(encoding, &text, c![0, 3; 0, 3 => " quick"]); assert_eq!(text, "the quick"); let text = - apply_document_changes(encoding, || text, c![0, 0; 0, 4 => "", 0, 5; 0, 5 => " foxes"]); + apply_document_changes(encoding, &text, c![0, 0; 0, 4 => "", 0, 5; 0, 5 => " foxes"]); assert_eq!(text, "quick foxes"); - let text = apply_document_changes(encoding, || text, c![0, 11; 0, 11 => "\ndream"]); + let text = apply_document_changes(encoding, &text, c![0, 11; 0, 11 => "\ndream"]); assert_eq!(text, "quick foxes\ndream"); - let text = apply_document_changes(encoding, || text, c![1, 0; 1, 0 => "have "]); + let text = apply_document_changes(encoding, &text, c![1, 0; 1, 0 => "have "]); assert_eq!(text, "quick foxes\nhave dream"); let text = apply_document_changes( encoding, - || text, + &text, c![0, 0; 0, 0 => "the ", 1, 4; 1, 4 => " quiet", 1, 16; 1, 16 => "s\n"], ); assert_eq!(text, "the quick foxes\nhave quiet dreams\n"); - let text = apply_document_changes( - encoding, - || text, - c![0, 15; 0, 15 => "\n", 2, 17; 2, 17 => "\n"], - ); + let text = + apply_document_changes(encoding, &text, c![0, 15; 0, 15 => "\n", 2, 17; 2, 17 => "\n"]); assert_eq!(text, "the quick foxes\n\nhave quiet dreams\n\n"); let text = apply_document_changes( encoding, - || text, + &text, c![1, 0; 1, 0 => "DREAM", 2, 0; 2, 0 => "they ", 3, 0; 3, 0 => "DON'T THEY?"], ); assert_eq!(text, "the quick foxes\nDREAM\nthey have quiet dreams\nDON'T THEY?\n"); let text = - apply_document_changes(encoding, || text, c![0, 10; 1, 5 => "", 2, 0; 2, 12 => ""]); + apply_document_changes(encoding, &text, c![0, 10; 1, 5 => "", 2, 0; 2, 12 => ""]); assert_eq!(text, "the quick \nthey have quiet dreams\n"); let text = String::from("❤️"); - let text = apply_document_changes(encoding, || text, c![0, 0; 0, 0 => "a"]); + let text = apply_document_changes(encoding, &text, c![0, 0; 0, 0 => "a"]); assert_eq!(text, "a❤️"); let text = String::from("a\nb"); let text = - apply_document_changes(encoding, || text, c![0, 1; 1, 0 => "\nțc", 0, 1; 1, 1 => "d"]); + apply_document_changes(encoding, &text, c![0, 1; 1, 0 => "\nțc", 0, 1; 1, 1 => "d"]); assert_eq!(text, "adcb"); let text = String::from("a\nb"); let text = - apply_document_changes(encoding, || text, c![0, 1; 1, 0 => "ț\nc", 0, 2; 0, 2 => "c"]); + apply_document_changes(encoding, &text, c![0, 1; 1, 0 => "ț\nc", 0, 2; 0, 2 => "c"]); assert_eq!(text, "ațc\ncb"); } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs index cdf41c955d26..ca7893faf5dd 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs @@ -571,13 +571,18 @@ impl GlobalState { } fn handle_vfs_msg(&mut self, message: vfs::loader::Message) { + let is_changed = matches!(message, vfs::loader::Message::Changed { .. }); match message { - vfs::loader::Message::Loaded { files } => { + vfs::loader::Message::Changed { files } | vfs::loader::Message::Loaded { files } => { let vfs = &mut self.vfs.write().0; for (path, contents) in files { let path = VfsPath::from(path); + // if the file is in mem docs, it's managed by the client via notifications + // so only set it if its not in there if !self.mem_docs.contains(&path) { - vfs.set_file_contents(path, contents); + if is_changed || vfs.file_id(&path).is_none() { + vfs.set_file_contents(path, contents); + } } } } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/mem_docs.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/mem_docs.rs index 45a1dab9772f..6a93a0ebb4ce 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/mem_docs.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/mem_docs.rs @@ -62,10 +62,11 @@ impl MemDocs { #[derive(Debug, Clone)] pub(crate) struct DocumentData { pub(crate) version: i32, + pub(crate) data: Vec, } impl DocumentData { - pub(crate) fn new(version: i32) -> Self { - DocumentData { version } + pub(crate) fn new(version: i32, data: Vec) -> Self { + DocumentData { version, data } } } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs index 91dc6c2e4b41..8e3fa7fa4dac 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs @@ -503,10 +503,9 @@ impl GlobalState { match vfs.file_id(&vfs_path) { Some(file_id) => Some(file_id), None => { - if !self.mem_docs.contains(&vfs_path) { - let contents = loader.handle.load_sync(path); - vfs.set_file_contents(vfs_path.clone(), contents); - } + // FIXME: Consider not loading this here? + let contents = loader.handle.load_sync(path); + vfs.set_file_contents(vfs_path.clone(), contents); vfs.file_id(&vfs_path) } } diff --git a/src/tools/rust-analyzer/crates/rustc-dependencies/Cargo.toml b/src/tools/rust-analyzer/crates/rustc-dependencies/Cargo.toml deleted file mode 100644 index 0bf04301df16..000000000000 --- a/src/tools/rust-analyzer/crates/rustc-dependencies/Cargo.toml +++ /dev/null @@ -1,23 +0,0 @@ -[package] -name = "rustc-dependencies" -version = "0.0.0" -description = "TBD" - -rust-version.workspace = true -edition.workspace = true -license.workspace = true -authors.workspace = true - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -ra-ap-rustc_lexer = { version = "0.21.0" } -ra-ap-rustc_parse_format = { version = "0.21.0", default-features = false } -ra-ap-rustc_index = { version = "0.21.0", default-features = false } -ra-ap-rustc_abi = { version = "0.21.0", default-features = false } - -[features] -in-rust-tree = [] - -[lints] -workspace = true \ No newline at end of file diff --git a/src/tools/rust-analyzer/crates/rustc-dependencies/src/lib.rs b/src/tools/rust-analyzer/crates/rustc-dependencies/src/lib.rs deleted file mode 100644 index 13fcbc491937..000000000000 --- a/src/tools/rust-analyzer/crates/rustc-dependencies/src/lib.rs +++ /dev/null @@ -1,48 +0,0 @@ -//! A wrapper around rustc internal crates, which enables switching between compiler provided -//! ones and stable ones published in crates.io - -#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] - -#[cfg(feature = "in-rust-tree")] -extern crate rustc_lexer; - -pub mod lexer { - #[cfg(not(feature = "in-rust-tree"))] - pub use ::ra_ap_rustc_lexer::*; - - #[cfg(feature = "in-rust-tree")] - pub use ::rustc_lexer::*; -} - -#[cfg(feature = "in-rust-tree")] -extern crate rustc_parse_format; - -pub mod parse_format { - #[cfg(not(feature = "in-rust-tree"))] - pub use ::ra_ap_rustc_parse_format::*; - - #[cfg(feature = "in-rust-tree")] - pub use ::rustc_parse_format::*; -} - -#[cfg(feature = "in-rust-tree")] -extern crate rustc_abi; - -pub mod abi { - #[cfg(not(feature = "in-rust-tree"))] - pub use ::ra_ap_rustc_abi::*; - - #[cfg(feature = "in-rust-tree")] - pub use ::rustc_abi::*; -} - -#[cfg(feature = "in-rust-tree")] -extern crate rustc_index; - -pub mod index { - #[cfg(not(feature = "in-rust-tree"))] - pub use ::ra_ap_rustc_index::*; - - #[cfg(feature = "in-rust-tree")] - pub use ::rustc_index::*; -} diff --git a/src/tools/rust-analyzer/crates/syntax/Cargo.toml b/src/tools/rust-analyzer/crates/syntax/Cargo.toml index 40a93fec2cec..9f78614bba66 100644 --- a/src/tools/rust-analyzer/crates/syntax/Cargo.toml +++ b/src/tools/rust-analyzer/crates/syntax/Cargo.toml @@ -23,7 +23,7 @@ indexmap.workspace = true smol_str.workspace = true triomphe.workspace = true -rustc-dependencies.workspace = true +ra-ap-rustc_lexer.workspace = true parser.workspace = true profile.workspace = true @@ -41,7 +41,7 @@ test-utils.workspace = true sourcegen.workspace = true [features] -in-rust-tree = ["rustc-dependencies/in-rust-tree"] +in-rust-tree = [] [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs index 8618018c0b6a..1c6157de5595 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs @@ -285,14 +285,16 @@ impl ast::Path { self.first_qualifier_or_self().segment() } - // FIXME: Check usages of Self::segments, they might be wrong because of the logic of the bloew function - pub fn segments_of_this_path_only_rev(&self) -> impl Iterator + Clone { - self.qualifiers_and_self().filter_map(|it| it.segment()) - } - pub fn segments(&self) -> impl Iterator + Clone { - successors(self.first_segment(), |p| { - p.parent_path().parent_path().and_then(|p| p.segment()) + let path_range = self.syntax().text_range(); + successors(self.first_segment(), move |p| { + p.parent_path().parent_path().and_then(|p| { + if path_range.contains_range(p.syntax().text_range()) { + p.segment() + } else { + None + } + }) }) } @@ -300,10 +302,6 @@ impl ast::Path { successors(self.qualifier(), |p| p.qualifier()) } - pub fn qualifiers_and_self(&self) -> impl Iterator + Clone { - successors(Some(self.clone()), |p| p.qualifier()) - } - pub fn top_path(&self) -> ast::Path { let mut this = self.clone(); while let Some(path) = this.parent_path() { diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs index d5d565a015a0..ede392fc62a2 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs @@ -2,8 +2,6 @@ use std::borrow::Cow; -use rustc_dependencies::lexer as rustc_lexer; - use rustc_lexer::unescape::{ unescape_byte, unescape_c_string, unescape_char, unescape_literal, CStrUnit, Mode, }; diff --git a/src/tools/rust-analyzer/crates/syntax/src/lib.rs b/src/tools/rust-analyzer/crates/syntax/src/lib.rs index d600698040dc..1b41596a5f27 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/lib.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/lib.rs @@ -22,6 +22,11 @@ #![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] #![warn(rust_2018_idioms, unused_lifetimes)] +#[cfg(not(feature = "in-rust-tree"))] +extern crate ra_ap_rustc_lexer as rustc_lexer; +#[cfg(feature = "in-rust-tree")] +extern crate rustc_lexer; + #[allow(unused)] macro_rules! eprintln { ($($tt:tt)*) => { stdx::eprintln!($($tt)*) }; diff --git a/src/tools/rust-analyzer/crates/syntax/src/validation.rs b/src/tools/rust-analyzer/crates/syntax/src/validation.rs index eabbda2c3983..69dffbf79f19 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/validation.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/validation.rs @@ -5,7 +5,7 @@ mod block; use rowan::Direction; -use rustc_dependencies::lexer::unescape::{self, unescape_literal, Mode}; +use rustc_lexer::unescape::{self, unescape_literal, Mode}; use crate::{ algo, @@ -106,6 +106,9 @@ fn rustc_unescape_error_to_string(err: unescape::EscapeError) -> (&'static str, EE::NonAsciiCharInByte => { "Byte literals must not contain non-ASCII characters" } + EE::NulInCStr => { + "C strings literals must not contain null characters" + } EE::UnskippedWhitespaceWarning => "Whitespace after this escape is not skipped", EE::MultipleSkippedLinesWarning => "Multiple lines are skipped by this escape", diff --git a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs index 1f3136404c61..140bb0804278 100644 --- a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs +++ b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs @@ -25,6 +25,7 @@ //! derive: //! discriminant: //! drop: +//! env: option //! eq: sized //! error: fmt //! fmt: result, transmute, coerce_unsized @@ -1450,6 +1451,15 @@ mod macros { #[macro_export] macro_rules! concat {} // endregion:concat + + // region:env + #[rustc_builtin_macro] + #[macro_export] + macro_rules! env {} + #[rustc_builtin_macro] + #[macro_export] + macro_rules! option_env {} + // endregion:env } // region:non_zero diff --git a/src/tools/rust-analyzer/crates/vfs-notify/src/lib.rs b/src/tools/rust-analyzer/crates/vfs-notify/src/lib.rs index 030650437146..19b34ffe6b9d 100644 --- a/src/tools/rust-analyzer/crates/vfs-notify/src/lib.rs +++ b/src/tools/rust-analyzer/crates/vfs-notify/src/lib.rs @@ -160,7 +160,7 @@ impl NotifyActor { Some((path, contents)) }) .collect(); - self.send(loader::Message::Loaded { files }); + self.send(loader::Message::Changed { files }); } } } diff --git a/src/tools/rust-analyzer/crates/vfs/src/lib.rs b/src/tools/rust-analyzer/crates/vfs/src/lib.rs index ef5b10ee9db2..34a85818eb84 100644 --- a/src/tools/rust-analyzer/crates/vfs/src/lib.rs +++ b/src/tools/rust-analyzer/crates/vfs/src/lib.rs @@ -1,8 +1,8 @@ //! # Virtual File System //! -//! VFS stores all files read by rust-analyzer. Reading file contents from VFS -//! always returns the same contents, unless VFS was explicitly modified with -//! [`set_file_contents`]. All changes to VFS are logged, and can be retrieved via +//! VFS records all file changes pushed to it via [`set_file_contents`]. +//! As such it only ever stores changes, not the actual content of a file at any given moment. +//! All file changes are logged, and can be retrieved via //! [`take_changes`] method. The pack of changes is then pushed to `salsa` and //! triggers incremental recomputation. //! @@ -84,40 +84,65 @@ impl FileId { /// safe because `FileId` is a newtype of `u32` impl nohash_hasher::IsEnabled for FileId {} -/// Storage for all files read by rust-analyzer. +/// Storage for all file changes and the file id to path mapping. /// /// For more information see the [crate-level](crate) documentation. #[derive(Default)] pub struct Vfs { interner: PathInterner, - data: Vec>>, + data: Vec, changes: Vec, } +#[derive(Copy, PartialEq, PartialOrd, Clone)] +pub enum FileState { + Exists, + Deleted, +} + /// Changed file in the [`Vfs`]. #[derive(Debug)] pub struct ChangedFile { /// Id of the changed file pub file_id: FileId, /// Kind of change - pub change_kind: ChangeKind, + pub change: Change, } impl ChangedFile { /// Returns `true` if the change is not [`Delete`](ChangeKind::Delete). pub fn exists(&self) -> bool { - self.change_kind != ChangeKind::Delete + !matches!(self.change, Change::Delete) } /// Returns `true` if the change is [`Create`](ChangeKind::Create) or - /// [`Delete`](ChangeKind::Delete). + /// [`Delete`](Change::Delete). pub fn is_created_or_deleted(&self) -> bool { - matches!(self.change_kind, ChangeKind::Create | ChangeKind::Delete) + matches!(self.change, Change::Create(_) | Change::Delete) + } + + pub fn kind(&self) -> ChangeKind { + match self.change { + Change::Create(_) => ChangeKind::Create, + Change::Modify(_) => ChangeKind::Modify, + Change::Delete => ChangeKind::Delete, + } } } /// Kind of [file change](ChangedFile). -#[derive(Eq, PartialEq, Copy, Clone, Debug)] +#[derive(Eq, PartialEq, Debug)] +pub enum Change { + /// The file was (re-)created + Create(Vec), + /// The file was modified + Modify(Vec), + /// The file was deleted + Delete, +} + +/// Kind of [file change](ChangedFile). +#[derive(Eq, PartialEq, Debug)] pub enum ChangeKind { /// The file was (re-)created Create, @@ -130,7 +155,7 @@ pub enum ChangeKind { impl Vfs { /// Id of the given path if it exists in the `Vfs` and is not deleted. pub fn file_id(&self, path: &VfsPath) -> Option { - self.interner.get(path).filter(|&it| self.get(it).is_some()) + self.interner.get(path).filter(|&it| matches!(self.get(it), FileState::Exists)) } /// File path corresponding to the given `file_id`. @@ -142,28 +167,13 @@ impl Vfs { self.interner.lookup(file_id).clone() } - /// File content corresponding to the given `file_id`. - /// - /// # Panics - /// - /// Panics if the id is not present in the `Vfs`, or if the corresponding file is - /// deleted. - pub fn file_contents(&self, file_id: FileId) -> &[u8] { - self.get(file_id).as_deref().unwrap() - } - - /// Returns the overall memory usage for the stored files. - pub fn memory_usage(&self) -> usize { - self.data.iter().flatten().map(|d| d.capacity()).sum() - } - /// Returns an iterator over the stored ids and their corresponding paths. /// /// This will skip deleted files. pub fn iter(&self) -> impl Iterator + '_ { (0..self.data.len()) .map(|it| FileId(it as u32)) - .filter(move |&file_id| self.get(file_id).is_some()) + .filter(move |&file_id| matches!(self.get(file_id), FileState::Exists)) .map(move |file_id| { let path = self.interner.lookup(file_id); (file_id, path) @@ -176,28 +186,21 @@ impl Vfs { /// /// If the path does not currently exists in the `Vfs`, allocates a new /// [`FileId`] for it. - pub fn set_file_contents(&mut self, path: VfsPath, mut contents: Option>) -> bool { + pub fn set_file_contents(&mut self, path: VfsPath, contents: Option>) -> bool { let file_id = self.alloc_file_id(path); - let change_kind = match (self.get(file_id), &contents) { - (None, None) => return false, - (Some(old), Some(new)) if old == new => return false, - (None, Some(_)) => ChangeKind::Create, - (Some(_), None) => ChangeKind::Delete, - (Some(_), Some(_)) => ChangeKind::Modify, + let change_kind = match (self.get(file_id), contents) { + (FileState::Deleted, None) => return false, + (FileState::Deleted, Some(v)) => Change::Create(v), + (FileState::Exists, None) => Change::Delete, + (FileState::Exists, Some(v)) => Change::Modify(v), }; - if let Some(contents) = &mut contents { - contents.shrink_to_fit(); - } - *self.get_mut(file_id) = contents; - self.changes.push(ChangedFile { file_id, change_kind }); + let changed_file = ChangedFile { file_id, change: change_kind }; + self.data[file_id.0 as usize] = + if changed_file.exists() { FileState::Exists } else { FileState::Deleted }; + self.changes.push(changed_file); true } - /// Returns `true` if the `Vfs` contains [changes](ChangedFile). - pub fn has_changes(&self) -> bool { - !self.changes.is_empty() - } - /// Drain and returns all the changes in the `Vfs`. pub fn take_changes(&mut self) -> Vec { mem::take(&mut self.changes) @@ -205,7 +208,7 @@ impl Vfs { /// Provides a panic-less way to verify file_id validity. pub fn exists(&self, file_id: FileId) -> bool { - self.get(file_id).is_some() + matches!(self.get(file_id), FileState::Exists) } /// Returns the id associated with `path` @@ -219,26 +222,17 @@ impl Vfs { let file_id = self.interner.intern(path); let idx = file_id.0 as usize; let len = self.data.len().max(idx + 1); - self.data.resize_with(len, || None); + self.data.resize(len, FileState::Deleted); file_id } - /// Returns the content associated with the given `file_id`. + /// Returns the status of the file associated with the given `file_id`. /// /// # Panics /// /// Panics if no file is associated to that id. - fn get(&self, file_id: FileId) -> &Option> { - &self.data[file_id.0 as usize] - } - - /// Mutably returns the content associated with the given `file_id`. - /// - /// # Panics - /// - /// Panics if no file is associated to that id. - fn get_mut(&mut self, file_id: FileId) -> &mut Option> { - &mut self.data[file_id.0 as usize] + fn get(&self, file_id: FileId) -> FileState { + self.data[file_id.0 as usize] } } diff --git a/src/tools/rust-analyzer/crates/vfs/src/loader.rs b/src/tools/rust-analyzer/crates/vfs/src/loader.rs index e2d74782ae52..89a544c81d8c 100644 --- a/src/tools/rust-analyzer/crates/vfs/src/loader.rs +++ b/src/tools/rust-analyzer/crates/vfs/src/loader.rs @@ -51,6 +51,8 @@ pub enum Message { Progress { n_total: usize, n_done: usize, config_version: u32 }, /// The handle loaded the following files' content. Loaded { files: Vec<(AbsPathBuf, Option>)> }, + /// The handle loaded the following files' content. + Changed { files: Vec<(AbsPathBuf, Option>)> }, } /// Type that will receive [`Messages`](Message) from a [`Handle`]. @@ -199,6 +201,9 @@ impl fmt::Debug for Message { Message::Loaded { files } => { f.debug_struct("Loaded").field("n_files", &files.len()).finish() } + Message::Changed { files } => { + f.debug_struct("Changed").field("n_files", &files.len()).finish() + } Message::Progress { n_total, n_done, config_version } => f .debug_struct("Progress") .field("n_total", n_total) diff --git a/src/tools/rust-analyzer/docs/dev/syntax.md b/src/tools/rust-analyzer/docs/dev/syntax.md index 97e376787c82..fd6f220f4fa9 100644 --- a/src/tools/rust-analyzer/docs/dev/syntax.md +++ b/src/tools/rust-analyzer/docs/dev/syntax.md @@ -41,7 +41,6 @@ Syntax trees are a semi-transient data structure. In general, frontend does not keep syntax trees for all files in memory. Instead, it *lowers* syntax trees to more compact and rigid representation, which is not full-fidelity, but which can be mapped back to a syntax tree if so desired. - ### GreenNode GreenNode is a purely-functional tree with arbitrary arity. Conceptually, it is equivalent to the following run of the mill struct: @@ -500,7 +499,7 @@ Specifically, `TreeSink` constructs the tree in lockstep with draining the origi In the process, it records which tokens of the tree correspond to which tokens of the input, by using text ranges to identify syntax tokens. The end result is that parsing an expanded code yields a syntax tree and a mapping of text-ranges of the tree to original tokens. -To deal with precedence in cases like `$expr * 1`, we use special invisible parenthesis, which are explicitly handled by the parser +To deal with precedence in cases like `$expr * 1`, we use special invisible parenthesis, which are explicitly handled by the parser. ### Whitespace & Comments diff --git a/src/tools/rust-analyzer/editors/code/package-lock.json b/src/tools/rust-analyzer/editors/code/package-lock.json index 8b9d5d4a7461..291cef926f82 100644 --- a/src/tools/rust-analyzer/editors/code/package-lock.json +++ b/src/tools/rust-analyzer/editors/code/package-lock.json @@ -2290,9 +2290,9 @@ "dev": true }, "node_modules/follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "version": "1.15.4", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz", + "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==", "dev": true, "funding": [ { diff --git a/src/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs index 0fa6edaa5d78..7f5762794320 100644 --- a/src/tools/rustfmt/src/patterns.rs +++ b/src/tools/rustfmt/src/patterns.rs @@ -40,9 +40,11 @@ pub(crate) fn is_short_pattern(pat: &ast::Pat, pat_str: &str) -> bool { fn is_short_pattern_inner(pat: &ast::Pat) -> bool { match pat.kind { - ast::PatKind::Rest | ast::PatKind::Never | ast::PatKind::Wild | ast::PatKind::Lit(_) => { - true - } + ast::PatKind::Rest + | ast::PatKind::Never + | ast::PatKind::Wild + | ast::PatKind::Err(_) + | ast::PatKind::Lit(_) => true, ast::PatKind::Ident(_, _, ref pat) => pat.is_none(), ast::PatKind::Struct(..) | ast::PatKind::MacCall(..) @@ -274,6 +276,7 @@ impl Rewrite for Pat { PatKind::Paren(ref pat) => pat .rewrite(context, shape.offset_left(1)?.sub_width(1)?) .map(|inner_pat| format!("({})", inner_pat)), + PatKind::Err(_) => None, } } } diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index c198c116282b..b03811e5efda 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -359,7 +359,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "tracing-tree", "twox-hash", "type-map", - "typed-arena", "typenum", "unic-langid", "unic-langid-impl", diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index 8e791a7dc69c..d673ce7a736d 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -15,7 +15,7 @@ use std::ffi::OsStr; use std::fmt; use std::fs; use std::num::NonZeroU32; -use std::path::Path; +use std::path::{Path, PathBuf}; use regex::Regex; @@ -52,6 +52,8 @@ pub struct Feature { pub since: Option, pub has_gate_test: bool, pub tracking_issue: Option, + pub file: PathBuf, + pub line: usize, } impl Feature { fn tracking_issue_display(&self) -> impl fmt::Display { @@ -184,23 +186,25 @@ pub fn check( .chain(lib_features.iter().map(|feat| (feat, "lib"))); for ((feature_name, feature), kind) in all_features_iter { let since = if let Some(since) = feature.since { since } else { continue }; + let file = feature.file.display(); + let line = feature.line; if since > version && since != Version::CurrentPlaceholder { tidy_error!( bad, - "The stabilization version {since} of {kind} feature `{feature_name}` is newer than the current {version}" + "{file}:{line}: The stabilization version {since} of {kind} feature `{feature_name}` is newer than the current {version}" ); } if channel == "nightly" && since == version { tidy_error!( bad, - "The stabilization version {since} of {kind} feature `{feature_name}` is written out but should be {}", + "{file}:{line}: The stabilization version {since} of {kind} feature `{feature_name}` is written out but should be {}", version::VERSION_PLACEHOLDER ); } if channel != "nightly" && since == Version::CurrentPlaceholder { tidy_error!( bad, - "The placeholder use of {kind} feature `{feature_name}` is not allowed on the {channel} channel", + "{file}:{line}: The placeholder use of {kind} feature `{feature_name}` is not allowed on the {channel} channel", ); } } @@ -433,7 +437,14 @@ fn collect_lang_features_in(features: &mut Features, base: &Path, file: &str, ba ); } Entry::Vacant(e) => { - e.insert(Feature { level, since, has_gate_test: false, tracking_issue }); + e.insert(Feature { + level, + since, + has_gate_test: false, + tracking_issue, + file: path.to_path_buf(), + line: line_number, + }); } } } @@ -559,6 +570,8 @@ fn map_lib_features( since: None, has_gate_test: false, tracking_issue: find_attr_val(line, "issue").and_then(handle_issue_none), + file: file.to_path_buf(), + line: i + 1, }; mf(Ok((feature_name, feature)), file, i + 1); continue; @@ -588,7 +601,14 @@ fn map_lib_features( }; let tracking_issue = find_attr_val(line, "issue").and_then(handle_issue_none); - let feature = Feature { level, since, has_gate_test: false, tracking_issue }; + let feature = Feature { + level, + since, + has_gate_test: false, + tracking_issue, + file: file.to_path_buf(), + line: i + 1, + }; if line.contains(']') { mf(Ok((feature_name, feature)), file, i + 1); } else { diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index eb0a2fda290d..951499870334 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -70,6 +70,7 @@ pub mod pal; pub mod rustdoc_css_themes; pub mod rustdoc_gui_tests; pub mod style; +pub mod target_policy; pub mod target_specific_tests; pub mod tests_placement; pub mod ui_tests; diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index 9f92b8995b79..a9340c40f443 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -109,6 +109,7 @@ fn main() { // Checks that only make sense for the compiler. check!(error_codes, &root_path, &[&compiler_path, &librustdoc_path], verbose); check!(fluent_alphabetical, &compiler_path, bless); + check!(target_policy, &root_path); // Checks that only make sense for the std libs. check!(pal, &library_path); diff --git a/src/tools/tidy/src/target_policy.rs b/src/tools/tidy/src/target_policy.rs new file mode 100644 index 000000000000..ca6590d1502a --- /dev/null +++ b/src/tools/tidy/src/target_policy.rs @@ -0,0 +1,52 @@ +//! Tests for target tier policy compliance. +//! +//! As of writing, only checks that sanity-check assembly test for targets doesn't miss any targets. + +use crate::walk::{filter_not_rust, walk}; +use std::{collections::HashSet, path::Path}; + +const TARGET_DEFINITIONS_PATH: &str = "compiler/rustc_target/src/spec/targets/"; +const ASSEMBLY_TEST_PATH: &str = "tests/assembly/targets/"; +const REVISION_LINE_START: &str = "// revisions: "; +const EXCEPTIONS: &[&str] = &[ + // FIXME: disabled since it fails on CI saying the csky component is missing + "csky_unknown_linux_gnuabiv2", + "csky_unknown_linux_gnuabiv2hf", +]; + +pub fn check(root_path: &Path, bad: &mut bool) { + let mut targets_to_find = HashSet::new(); + + let definitions_path = root_path.join(TARGET_DEFINITIONS_PATH); + for defn in ignore::WalkBuilder::new(&definitions_path) + .max_depth(Some(1)) + .filter_entry(|e| !filter_not_rust(e.path())) + .build() + { + let defn = defn.unwrap(); + // Skip directory itself. + if defn.path() == definitions_path { + continue; + } + + let path = defn.path(); + let target_name = path.file_stem().unwrap().to_string_lossy().into_owned(); + let _ = targets_to_find.insert(target_name); + } + + walk(&root_path.join(ASSEMBLY_TEST_PATH), |_, _| false, &mut |_, contents| { + for line in contents.lines() { + let Some(_) = line.find(REVISION_LINE_START) else { + continue; + }; + let (_, target_name) = line.split_at(REVISION_LINE_START.len()); + targets_to_find.remove(target_name); + } + }); + + for target in targets_to_find { + if !EXCEPTIONS.contains(&target.as_str()) { + tidy_error!(bad, "{ASSEMBLY_TEST_PATH}: missing assembly test for {target}") + } + } +} diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs new file mode 100644 index 000000000000..72a35f38ecad --- /dev/null +++ b/tests/assembly/targets/targets-elf.rs @@ -0,0 +1,633 @@ +// assembly-output: emit-asm +// ignore-tidy-linelength +// revisions: aarch64_apple_darwin +// [aarch64_apple_darwin] compile-flags: --target aarch64-apple-darwin +// [aarch64_apple_darwin] needs-llvm-components: aarch64 +// revisions: aarch64_apple_ios +// [aarch64_apple_ios] compile-flags: --target aarch64-apple-ios +// [aarch64_apple_ios] needs-llvm-components: aarch64 +// revisions: aarch64_apple_ios_macabi +// [aarch64_apple_ios_macabi] compile-flags: --target aarch64-apple-ios-macabi +// [aarch64_apple_ios_macabi] needs-llvm-components: aarch64 +// revisions: aarch64_apple_ios_sim +// [aarch64_apple_ios_sim] compile-flags: --target aarch64-apple-ios-sim +// [aarch64_apple_ios_sim] needs-llvm-components: aarch64 +// revisions: aarch64_apple_tvos +// [aarch64_apple_tvos] compile-flags: --target aarch64-apple-tvos +// [aarch64_apple_tvos] needs-llvm-components: aarch64 +// revisions: aarch64_apple_tvos_sim +// [aarch64_apple_tvos_sim] compile-flags: --target aarch64-apple-tvos-sim +// [aarch64_apple_tvos_sim] needs-llvm-components: aarch64 +// revisions: aarch64_apple_watchos +// [aarch64_apple_watchos] compile-flags: --target aarch64-apple-watchos +// [aarch64_apple_watchos] needs-llvm-components: aarch64 +// revisions: aarch64_apple_watchos_sim +// [aarch64_apple_watchos_sim] compile-flags: --target aarch64-apple-watchos-sim +// [aarch64_apple_watchos_sim] needs-llvm-components: aarch64 +// revisions: aarch64_be_unknown_linux_gnu +// [aarch64_be_unknown_linux_gnu] compile-flags: --target aarch64_be-unknown-linux-gnu +// [aarch64_be_unknown_linux_gnu] needs-llvm-components: aarch64 +// revisions: aarch64_be_unknown_linux_gnu_ilp32 +// [aarch64_be_unknown_linux_gnu_ilp32] compile-flags: --target aarch64_be-unknown-linux-gnu_ilp32 +// [aarch64_be_unknown_linux_gnu_ilp32] needs-llvm-components: aarch64 +// revisions: aarch64_be_unknown_netbsd +// [aarch64_be_unknown_netbsd] compile-flags: --target aarch64_be-unknown-netbsd +// [aarch64_be_unknown_netbsd] needs-llvm-components: aarch64 +// revisions: aarch64_fuchsia +// [aarch64_fuchsia] compile-flags: --target aarch64-fuchsia +// [aarch64_fuchsia] needs-llvm-components: aarch64 +// revisions: aarch64_kmc_solid_asp3 +// [aarch64_kmc_solid_asp3] compile-flags: --target aarch64-kmc-solid_asp3 +// [aarch64_kmc_solid_asp3] needs-llvm-components: aarch64 +// revisions: aarch64_linux_android +// [aarch64_linux_android] compile-flags: --target aarch64-linux-android +// [aarch64_linux_android] needs-llvm-components: aarch64 +// revisions: aarch64_nintendo_switch_freestanding +// [aarch64_nintendo_switch_freestanding] compile-flags: --target aarch64-nintendo-switch-freestanding +// [aarch64_nintendo_switch_freestanding] needs-llvm-components: aarch64 +// revisions: aarch64_unknown_freebsd +// [aarch64_unknown_freebsd] compile-flags: --target aarch64-unknown-freebsd +// [aarch64_unknown_freebsd] needs-llvm-components: aarch64 +// revisions: aarch64_unknown_fuchsia +// [aarch64_unknown_fuchsia] compile-flags: --target aarch64-unknown-fuchsia +// [aarch64_unknown_fuchsia] needs-llvm-components: aarch64 +// revisions: aarch64_unknown_hermit +// [aarch64_unknown_hermit] compile-flags: --target aarch64-unknown-hermit +// [aarch64_unknown_hermit] needs-llvm-components: aarch64 +// revisions: aarch64_unknown_illumos +// [aarch64_unknown_illumos] compile-flags: --target aarch64-unknown-illumos +// [aarch64_unknown_illumos] needs-llvm-components: aarch64 +// revisions: aarch64_unknown_linux_gnu +// [aarch64_unknown_linux_gnu] compile-flags: --target aarch64-unknown-linux-gnu +// [aarch64_unknown_linux_gnu] needs-llvm-components: aarch64 +// revisions: aarch64_unknown_linux_gnu_ilp32 +// [aarch64_unknown_linux_gnu_ilp32] compile-flags: --target aarch64-unknown-linux-gnu_ilp32 +// [aarch64_unknown_linux_gnu_ilp32] needs-llvm-components: aarch64 +// revisions: aarch64_unknown_linux_musl +// [aarch64_unknown_linux_musl] compile-flags: --target aarch64-unknown-linux-musl +// [aarch64_unknown_linux_musl] needs-llvm-components: aarch64 +// revisions: aarch64_unknown_linux_ohos +// [aarch64_unknown_linux_ohos] compile-flags: --target aarch64-unknown-linux-ohos +// [aarch64_unknown_linux_ohos] needs-llvm-components: aarch64 +// revisions: aarch64_unknown_netbsd +// [aarch64_unknown_netbsd] compile-flags: --target aarch64-unknown-netbsd +// [aarch64_unknown_netbsd] needs-llvm-components: aarch64 +// revisions: aarch64_unknown_none +// [aarch64_unknown_none] compile-flags: --target aarch64-unknown-none +// [aarch64_unknown_none] needs-llvm-components: aarch64 +// revisions: aarch64_unknown_none_softfloat +// [aarch64_unknown_none_softfloat] compile-flags: --target aarch64-unknown-none-softfloat +// [aarch64_unknown_none_softfloat] needs-llvm-components: aarch64 +// revisions: aarch64_unknown_nto_qnx_710 +// [aarch64_unknown_nto_qnx_710] compile-flags: --target aarch64-unknown-nto-qnx710 +// [aarch64_unknown_nto_qnx_710] needs-llvm-components: aarch64 +// revisions: aarch64_unknown_openbsd +// [aarch64_unknown_openbsd] compile-flags: --target aarch64-unknown-openbsd +// [aarch64_unknown_openbsd] needs-llvm-components: aarch64 +// revisions: aarch64_unknown_redox +// [aarch64_unknown_redox] compile-flags: --target aarch64-unknown-redox +// [aarch64_unknown_redox] needs-llvm-components: aarch64 +// revisions: aarch64_unknown_teeos +// [aarch64_unknown_teeos] compile-flags: --target aarch64-unknown-teeos +// [aarch64_unknown_teeos] needs-llvm-components: aarch64 +// revisions: aarch64_wrs_vxworks +// [aarch64_wrs_vxworks] compile-flags: --target aarch64-wrs-vxworks +// [aarch64_wrs_vxworks] needs-llvm-components: aarch64 +// revisions: arm64_32_apple_watchos +// [arm64_32_apple_watchos] compile-flags: --target arm64_32-apple-watchos +// [arm64_32_apple_watchos] needs-llvm-components: aarch64 +// revisions: arm64e_apple_darwin +// [arm64e_apple_darwin] compile-flags: --target arm64e-apple-darwin +// [arm64e_apple_darwin] needs-llvm-components: aarch64 +// revisions: arm64e_apple_ios +// [arm64e_apple_ios] compile-flags: --target arm64e-apple-ios +// [arm64e_apple_ios] needs-llvm-components: aarch64 +// revisions: arm_linux_androideabi +// [arm_linux_androideabi] compile-flags: --target arm-linux-androideabi +// [arm_linux_androideabi] needs-llvm-components: arm +// revisions: arm_unknown_linux_gnueabi +// [arm_unknown_linux_gnueabi] compile-flags: --target arm-unknown-linux-gnueabi +// [arm_unknown_linux_gnueabi] needs-llvm-components: arm +// revisions: arm_unknown_linux_gnueabihf +// [arm_unknown_linux_gnueabihf] compile-flags: --target arm-unknown-linux-gnueabihf +// [arm_unknown_linux_gnueabihf] needs-llvm-components: arm +// revisions: arm_unknown_linux_musleabi +// [arm_unknown_linux_musleabi] compile-flags: --target arm-unknown-linux-musleabi +// [arm_unknown_linux_musleabi] needs-llvm-components: arm +// revisions: arm_unknown_linux_musleabihf +// [arm_unknown_linux_musleabihf] compile-flags: --target arm-unknown-linux-musleabihf +// [arm_unknown_linux_musleabihf] needs-llvm-components: arm +// revisions: armeb_unknown_linux_gnueabi +// [armeb_unknown_linux_gnueabi] compile-flags: --target armeb-unknown-linux-gnueabi +// [armeb_unknown_linux_gnueabi] needs-llvm-components: arm +// revisions: armebv7r_none_eabi +// [armebv7r_none_eabi] compile-flags: --target armebv7r-none-eabi +// [armebv7r_none_eabi] needs-llvm-components: arm +// revisions: armebv7r_none_eabihf +// [armebv7r_none_eabihf] compile-flags: --target armebv7r-none-eabihf +// [armebv7r_none_eabihf] needs-llvm-components: arm +// revisions: armv4t_none_eabi +// [armv4t_none_eabi] compile-flags: --target armv4t-none-eabi +// [armv4t_none_eabi] needs-llvm-components: arm +// revisions: armv4t_unknown_linux_gnueabi +// [armv4t_unknown_linux_gnueabi] compile-flags: --target armv4t-unknown-linux-gnueabi +// [armv4t_unknown_linux_gnueabi] needs-llvm-components: arm +// revisions: armv5te_none_eabi +// [armv5te_none_eabi] compile-flags: --target armv5te-none-eabi +// [armv5te_none_eabi] needs-llvm-components: arm +// revisions: armv5te_unknown_linux_gnueabi +// [armv5te_unknown_linux_gnueabi] compile-flags: --target armv5te-unknown-linux-gnueabi +// [armv5te_unknown_linux_gnueabi] needs-llvm-components: arm +// revisions: armv5te_unknown_linux_musleabi +// [armv5te_unknown_linux_musleabi] compile-flags: --target armv5te-unknown-linux-musleabi +// [armv5te_unknown_linux_musleabi] needs-llvm-components: arm +// revisions: armv5te_unknown_linux_uclibceabi +// [armv5te_unknown_linux_uclibceabi] compile-flags: --target armv5te-unknown-linux-uclibceabi +// [armv5te_unknown_linux_uclibceabi] needs-llvm-components: arm +// revisions: armv6_unknown_freebsd +// [armv6_unknown_freebsd] compile-flags: --target armv6-unknown-freebsd +// [armv6_unknown_freebsd] needs-llvm-components: arm +// revisions: armv6_unknown_netbsd_eabihf +// [armv6_unknown_netbsd_eabihf] compile-flags: --target armv6-unknown-netbsd-eabihf +// [armv6_unknown_netbsd_eabihf] needs-llvm-components: arm +// revisions: armv6k_nintendo_3ds +// [armv6k_nintendo_3ds] compile-flags: --target armv6k-nintendo-3ds +// [armv6k_nintendo_3ds] needs-llvm-components: arm +// revisions: armv7_linux_androideabi +// [armv7_linux_androideabi] compile-flags: --target armv7-linux-androideabi +// [armv7_linux_androideabi] needs-llvm-components: arm +// revisions: armv7_sony_vita_newlibeabihf +// [armv7_sony_vita_newlibeabihf] compile-flags: --target armv7-sony-vita-newlibeabihf +// [armv7_sony_vita_newlibeabihf] needs-llvm-components: arm +// revisions: armv7_unknown_freebsd +// [armv7_unknown_freebsd] compile-flags: --target armv7-unknown-freebsd +// [armv7_unknown_freebsd] needs-llvm-components: arm +// revisions: armv7_unknown_linux_gnueabi +// [armv7_unknown_linux_gnueabi] compile-flags: --target armv7-unknown-linux-gnueabi +// [armv7_unknown_linux_gnueabi] needs-llvm-components: arm +// revisions: armv7_unknown_linux_gnueabihf +// [armv7_unknown_linux_gnueabihf] compile-flags: --target armv7-unknown-linux-gnueabihf +// [armv7_unknown_linux_gnueabihf] needs-llvm-components: arm +// revisions: armv7_unknown_linux_musleabi +// [armv7_unknown_linux_musleabi] compile-flags: --target armv7-unknown-linux-musleabi +// [armv7_unknown_linux_musleabi] needs-llvm-components: arm +// revisions: armv7_unknown_linux_musleabihf +// [armv7_unknown_linux_musleabihf] compile-flags: --target armv7-unknown-linux-musleabihf +// [armv7_unknown_linux_musleabihf] needs-llvm-components: arm +// revisions: armv7_unknown_linux_ohos +// [armv7_unknown_linux_ohos] compile-flags: --target armv7-unknown-linux-ohos +// [armv7_unknown_linux_ohos] needs-llvm-components: arm +// revisions: armv7_unknown_linux_uclibceabi +// [armv7_unknown_linux_uclibceabi] compile-flags: --target armv7-unknown-linux-uclibceabi +// [armv7_unknown_linux_uclibceabi] needs-llvm-components: arm +// revisions: armv7_unknown_linux_uclibceabihf +// [armv7_unknown_linux_uclibceabihf] compile-flags: --target armv7-unknown-linux-uclibceabihf +// [armv7_unknown_linux_uclibceabihf] needs-llvm-components: arm +// revisions: armv7_unknown_netbsd_eabihf +// [armv7_unknown_netbsd_eabihf] compile-flags: --target armv7-unknown-netbsd-eabihf +// [armv7_unknown_netbsd_eabihf] needs-llvm-components: arm +// revisions: armv7_wrs_vxworks_eabihf +// [armv7_wrs_vxworks_eabihf] compile-flags: --target armv7-wrs-vxworks-eabihf +// [armv7_wrs_vxworks_eabihf] needs-llvm-components: arm +// revisions: armv7a_kmc_solid_asp3_eabi +// [armv7a_kmc_solid_asp3_eabi] compile-flags: --target armv7a-kmc-solid_asp3-eabi +// [armv7a_kmc_solid_asp3_eabi] needs-llvm-components: arm +// revisions: armv7a_kmc_solid_asp3_eabihf +// [armv7a_kmc_solid_asp3_eabihf] compile-flags: --target armv7a-kmc-solid_asp3-eabihf +// [armv7a_kmc_solid_asp3_eabihf] needs-llvm-components: arm +// revisions: armv7a_none_eabi +// [armv7a_none_eabi] compile-flags: --target armv7a-none-eabi +// [armv7a_none_eabi] needs-llvm-components: arm +// revisions: armv7a_none_eabihf +// [armv7a_none_eabihf] compile-flags: --target armv7a-none-eabihf +// [armv7a_none_eabihf] needs-llvm-components: arm +// revisions: armv7k_apple_watchos +// [armv7k_apple_watchos] compile-flags: --target armv7k-apple-watchos +// [armv7k_apple_watchos] needs-llvm-components: arm +// revisions: armv7r_none_eabi +// [armv7r_none_eabi] compile-flags: --target armv7r-none-eabi +// [armv7r_none_eabi] needs-llvm-components: arm +// revisions: armv7r_none_eabihf +// [armv7r_none_eabihf] compile-flags: --target armv7r-none-eabihf +// [armv7r_none_eabihf] needs-llvm-components: arm +// revisions: armv7s_apple_ios +// [armv7s_apple_ios] compile-flags: --target armv7s-apple-ios +// [armv7s_apple_ios] needs-llvm-components: arm +// FIXME: disabled since it fails on CI saying the csky component is missing +/* + revisions: csky_unknown_linux_gnuabiv2 + [csky_unknown_linux_gnuabiv2] compile-flags: --target csky-unknown-linux-gnuabiv2 + [csky_unknown_linux_gnuabiv2] needs-llvm-components: csky + revisions: csky_unknown_linux_gnuabiv2hf + [csky_unknown_linux_gnuabiv2hf] compile-flags: --target csky-unknown-linux-gnuabiv2hf + [csky_unknown_linux_gnuabiv2hf] needs-llvm-components: csky +*/ +// revisions: hexagon_unknown_linux_musl +// [hexagon_unknown_linux_musl] compile-flags: --target hexagon-unknown-linux-musl +// [hexagon_unknown_linux_musl] needs-llvm-components: hexagon +// revisions: hexagon_unknown_none_elf +// [hexagon_unknown_none_elf] compile-flags: --target hexagon-unknown-none-elf +// [hexagon_unknown_none_elf] needs-llvm-components: hexagon +// revisions: i386_apple_ios +// [i386_apple_ios] compile-flags: --target i386-apple-ios +// [i386_apple_ios] needs-llvm-components: x86 +// revisions: i586_pc_nto_qnx700 +// [i586_pc_nto_qnx700] compile-flags: --target i586-pc-nto-qnx700 +// [i586_pc_nto_qnx700] needs-llvm-components: x86 +// revisions: i586_unknown_linux_gnu +// [i586_unknown_linux_gnu] compile-flags: --target i586-unknown-linux-gnu +// [i586_unknown_linux_gnu] needs-llvm-components: x86 +// revisions: i586_unknown_linux_musl +// [i586_unknown_linux_musl] compile-flags: --target i586-unknown-linux-musl +// [i586_unknown_linux_musl] needs-llvm-components: x86 +// revisions: i586_unknown_netbsd +// [i586_unknown_netbsd] compile-flags: --target i586-unknown-netbsd +// [i586_unknown_netbsd] needs-llvm-components: x86 +// revisions: i686_apple_darwin +// [i686_apple_darwin] compile-flags: --target i686-apple-darwin +// [i686_apple_darwin] needs-llvm-components: x86 +// revisions: i686_linux_android +// [i686_linux_android] compile-flags: --target i686-linux-android +// [i686_linux_android] needs-llvm-components: x86 +// revisions: i686_unknown_freebsd +// [i686_unknown_freebsd] compile-flags: --target i686-unknown-freebsd +// [i686_unknown_freebsd] needs-llvm-components: x86 +// revisions: i686_unknown_haiku +// [i686_unknown_haiku] compile-flags: --target i686-unknown-haiku +// [i686_unknown_haiku] needs-llvm-components: x86 +// revisions: i686_unknown_hurd_gnu +// [i686_unknown_hurd_gnu] compile-flags: --target i686-unknown-hurd-gnu +// [i686_unknown_hurd_gnu] needs-llvm-components: x86 +// revisions: i686_unknown_linux_gnu +// [i686_unknown_linux_gnu] compile-flags: --target i686-unknown-linux-gnu +// [i686_unknown_linux_gnu] needs-llvm-components: x86 +// revisions: i686_unknown_linux_musl +// [i686_unknown_linux_musl] compile-flags: --target i686-unknown-linux-musl +// [i686_unknown_linux_musl] needs-llvm-components: x86 +// revisions: i686_unknown_netbsd +// [i686_unknown_netbsd] compile-flags: --target i686-unknown-netbsd +// [i686_unknown_netbsd] needs-llvm-components: x86 +// revisions: i686_unknown_openbsd +// [i686_unknown_openbsd] compile-flags: --target i686-unknown-openbsd +// [i686_unknown_openbsd] needs-llvm-components: x86 +// revisions: i686_wrs_vxworks +// [i686_wrs_vxworks] compile-flags: --target i686-wrs-vxworks +// [i686_wrs_vxworks] needs-llvm-components: x86 +// revisions: loongarch64_unknown_linux_gnu +// [loongarch64_unknown_linux_gnu] compile-flags: --target loongarch64-unknown-linux-gnu +// [loongarch64_unknown_linux_gnu] needs-llvm-components: loongarch +// revisions: loongarch64_unknown_none +// [loongarch64_unknown_none] compile-flags: --target loongarch64-unknown-none +// [loongarch64_unknown_none] needs-llvm-components: loongarch +// revisions: loongarch64_unknown_none_softfloat +// [loongarch64_unknown_none_softfloat] compile-flags: --target loongarch64-unknown-none-softfloat +// [loongarch64_unknown_none_softfloat] needs-llvm-components: loongarch +// revisions: m68k_unknown_linux_gnu +// [m68k_unknown_linux_gnu] compile-flags: --target m68k-unknown-linux-gnu +// [m68k_unknown_linux_gnu] needs-llvm-components: m68k +// revisions: mips64_openwrt_linux_musl +// [mips64_openwrt_linux_musl] compile-flags: --target mips64-openwrt-linux-musl +// [mips64_openwrt_linux_musl] needs-llvm-components: mips +// revisions: mips64_unknown_linux_gnuabi64 +// [mips64_unknown_linux_gnuabi64] compile-flags: --target mips64-unknown-linux-gnuabi64 +// [mips64_unknown_linux_gnuabi64] needs-llvm-components: mips +// revisions: mips64_unknown_linux_muslabi64 +// [mips64_unknown_linux_muslabi64] compile-flags: --target mips64-unknown-linux-muslabi64 +// [mips64_unknown_linux_muslabi64] needs-llvm-components: mips +// revisions: mips64el_unknown_linux_gnuabi64 +// [mips64el_unknown_linux_gnuabi64] compile-flags: --target mips64el-unknown-linux-gnuabi64 +// [mips64el_unknown_linux_gnuabi64] needs-llvm-components: mips +// revisions: mips64el_unknown_linux_muslabi64 +// [mips64el_unknown_linux_muslabi64] compile-flags: --target mips64el-unknown-linux-muslabi64 +// [mips64el_unknown_linux_muslabi64] needs-llvm-components: mips +// revisions: mips_unknown_linux_gnu +// [mips_unknown_linux_gnu] compile-flags: --target mips-unknown-linux-gnu +// [mips_unknown_linux_gnu] needs-llvm-components: mips +// revisions: mips_unknown_linux_musl +// [mips_unknown_linux_musl] compile-flags: --target mips-unknown-linux-musl +// [mips_unknown_linux_musl] needs-llvm-components: mips +// revisions: mips_unknown_linux_uclibc +// [mips_unknown_linux_uclibc] compile-flags: --target mips-unknown-linux-uclibc +// [mips_unknown_linux_uclibc] needs-llvm-components: mips +// revisions: mipsel_sony_psp +// [mipsel_sony_psp] compile-flags: --target mipsel-sony-psp +// [mipsel_sony_psp] needs-llvm-components: mips +// revisions: mipsel_sony_psx +// [mipsel_sony_psx] compile-flags: --target mipsel-sony-psx +// [mipsel_sony_psx] needs-llvm-components: mips +// revisions: mipsel_unknown_linux_gnu +// [mipsel_unknown_linux_gnu] compile-flags: --target mipsel-unknown-linux-gnu +// [mipsel_unknown_linux_gnu] needs-llvm-components: mips +// revisions: mipsel_unknown_linux_musl +// [mipsel_unknown_linux_musl] compile-flags: --target mipsel-unknown-linux-musl +// [mipsel_unknown_linux_musl] needs-llvm-components: mips +// revisions: mipsel_unknown_linux_uclibc +// [mipsel_unknown_linux_uclibc] compile-flags: --target mipsel-unknown-linux-uclibc +// [mipsel_unknown_linux_uclibc] needs-llvm-components: mips +// revisions: mipsel_unknown_netbsd +// [mipsel_unknown_netbsd] compile-flags: --target mipsel-unknown-netbsd +// [mipsel_unknown_netbsd] needs-llvm-components: mips +// revisions: mipsel_unknown_none +// [mipsel_unknown_none] compile-flags: --target mipsel-unknown-none +// [mipsel_unknown_none] needs-llvm-components: mips +// revisions: mipsisa32r6_unknown_linux_gnu +// [mipsisa32r6_unknown_linux_gnu] compile-flags: --target mipsisa32r6-unknown-linux-gnu +// [mipsisa32r6_unknown_linux_gnu] needs-llvm-components: mips +// revisions: mipsisa32r6el_unknown_linux_gnu +// [mipsisa32r6el_unknown_linux_gnu] compile-flags: --target mipsisa32r6el-unknown-linux-gnu +// [mipsisa32r6el_unknown_linux_gnu] needs-llvm-components: mips +// revisions: mipsisa64r6_unknown_linux_gnuabi64 +// [mipsisa64r6_unknown_linux_gnuabi64] compile-flags: --target mipsisa64r6-unknown-linux-gnuabi64 +// [mipsisa64r6_unknown_linux_gnuabi64] needs-llvm-components: mips +// revisions: mipsisa64r6el_unknown_linux_gnuabi64 +// [mipsisa64r6el_unknown_linux_gnuabi64] compile-flags: --target mipsisa64r6el-unknown-linux-gnuabi64 +// [mipsisa64r6el_unknown_linux_gnuabi64] needs-llvm-components: mips +// revisions: msp430_none_elf +// [msp430_none_elf] compile-flags: --target msp430-none-elf +// [msp430_none_elf] needs-llvm-components: msp430 +// revisions: powerpc64_unknown_freebsd +// [powerpc64_unknown_freebsd] compile-flags: --target powerpc64-unknown-freebsd +// [powerpc64_unknown_freebsd] needs-llvm-components: powerpc +// revisions: powerpc64_unknown_linux_gnu +// [powerpc64_unknown_linux_gnu] compile-flags: --target powerpc64-unknown-linux-gnu +// [powerpc64_unknown_linux_gnu] needs-llvm-components: powerpc +// revisions: powerpc64_unknown_linux_musl +// [powerpc64_unknown_linux_musl] compile-flags: --target powerpc64-unknown-linux-musl +// [powerpc64_unknown_linux_musl] needs-llvm-components: powerpc +// revisions: powerpc64_unknown_openbsd +// [powerpc64_unknown_openbsd] compile-flags: --target powerpc64-unknown-openbsd +// [powerpc64_unknown_openbsd] needs-llvm-components: powerpc +// revisions: powerpc64_wrs_vxworks +// [powerpc64_wrs_vxworks] compile-flags: --target powerpc64-wrs-vxworks +// [powerpc64_wrs_vxworks] needs-llvm-components: powerpc +// revisions: powerpc64le_unknown_freebsd +// [powerpc64le_unknown_freebsd] compile-flags: --target powerpc64le-unknown-freebsd +// [powerpc64le_unknown_freebsd] needs-llvm-components: powerpc +// revisions: powerpc64le_unknown_linux_gnu +// [powerpc64le_unknown_linux_gnu] compile-flags: --target powerpc64le-unknown-linux-gnu +// [powerpc64le_unknown_linux_gnu] needs-llvm-components: powerpc +// revisions: powerpc64le_unknown_linux_musl +// [powerpc64le_unknown_linux_musl] compile-flags: --target powerpc64le-unknown-linux-musl +// [powerpc64le_unknown_linux_musl] needs-llvm-components: powerpc +// revisions: powerpc_unknown_freebsd +// [powerpc_unknown_freebsd] compile-flags: --target powerpc-unknown-freebsd +// [powerpc_unknown_freebsd] needs-llvm-components: powerpc +// revisions: powerpc_unknown_linux_gnu +// [powerpc_unknown_linux_gnu] compile-flags: --target powerpc-unknown-linux-gnu +// [powerpc_unknown_linux_gnu] needs-llvm-components: powerpc +// revisions: powerpc_unknown_linux_gnuspe +// [powerpc_unknown_linux_gnuspe] compile-flags: --target powerpc-unknown-linux-gnuspe +// [powerpc_unknown_linux_gnuspe] needs-llvm-components: powerpc +// revisions: powerpc_unknown_linux_musl +// [powerpc_unknown_linux_musl] compile-flags: --target powerpc-unknown-linux-musl +// [powerpc_unknown_linux_musl] needs-llvm-components: powerpc +// revisions: powerpc_unknown_netbsd +// [powerpc_unknown_netbsd] compile-flags: --target powerpc-unknown-netbsd +// [powerpc_unknown_netbsd] needs-llvm-components: powerpc +// revisions: powerpc_unknown_openbsd +// [powerpc_unknown_openbsd] compile-flags: --target powerpc-unknown-openbsd +// [powerpc_unknown_openbsd] needs-llvm-components: powerpc +// revisions: powerpc_wrs_vxworks +// [powerpc_wrs_vxworks] compile-flags: --target powerpc-wrs-vxworks +// [powerpc_wrs_vxworks] needs-llvm-components: powerpc +// revisions: powerpc_wrs_vxworks_spe +// [powerpc_wrs_vxworks_spe] compile-flags: --target powerpc-wrs-vxworks-spe +// [powerpc_wrs_vxworks_spe] needs-llvm-components: powerpc +// revisions: riscv32gc_unknown_linux_gnu +// [riscv32gc_unknown_linux_gnu] compile-flags: --target riscv32gc-unknown-linux-gnu +// [riscv32gc_unknown_linux_gnu] needs-llvm-components: riscv +// revisions: riscv32gc_unknown_linux_musl +// [riscv32gc_unknown_linux_musl] compile-flags: --target riscv32gc-unknown-linux-musl +// [riscv32gc_unknown_linux_musl] needs-llvm-components: riscv +// revisions: riscv32i_unknown_none_elf +// [riscv32i_unknown_none_elf] compile-flags: --target riscv32i-unknown-none-elf +// [riscv32i_unknown_none_elf] needs-llvm-components: riscv +// revisions: riscv32im_unknown_none_elf +// [riscv32im_unknown_none_elf] compile-flags: --target riscv32im-unknown-none-elf +// [riscv32im_unknown_none_elf] needs-llvm-components: riscv +// revisions: riscv32imac_esp_espidf +// [riscv32imac_esp_espidf] compile-flags: --target riscv32imac-esp-espidf +// [riscv32imac_esp_espidf] needs-llvm-components: riscv +// revisions: riscv32imac_unknown_none_elf +// [riscv32imac_unknown_none_elf] compile-flags: --target riscv32imac-unknown-none-elf +// [riscv32imac_unknown_none_elf] needs-llvm-components: riscv +// revisions: riscv32imac_unknown_xous_elf +// [riscv32imac_unknown_xous_elf] compile-flags: --target riscv32imac-unknown-xous-elf +// [riscv32imac_unknown_xous_elf] needs-llvm-components: riscv +// revisions: riscv32imafc_unknown_none_elf +// [riscv32imafc_unknown_none_elf] compile-flags: --target riscv32imafc-unknown-none-elf +// [riscv32imafc_unknown_none_elf] needs-llvm-components: riscv +// revisions: riscv32imafc_esp_espidf +// [riscv32imafc_esp_espidf] compile-flags: --target riscv32imafc-esp-espidf +// [riscv32imafc_esp_espidf] needs-llvm-components: riscv +// revisions: riscv32imc_esp_espidf +// [riscv32imc_esp_espidf] compile-flags: --target riscv32imc-esp-espidf +// [riscv32imc_esp_espidf] needs-llvm-components: riscv +// revisions: riscv32imc_unknown_none_elf +// [riscv32imc_unknown_none_elf] compile-flags: --target riscv32imc-unknown-none-elf +// [riscv32imc_unknown_none_elf] needs-llvm-components: riscv +// revisions: riscv64_linux_android +// [riscv64_linux_android] compile-flags: --target riscv64-linux-android +// [riscv64_linux_android] needs-llvm-components: riscv +// revisions: riscv64gc_unknown_freebsd +// [riscv64gc_unknown_freebsd] compile-flags: --target riscv64gc-unknown-freebsd +// [riscv64gc_unknown_freebsd] needs-llvm-components: riscv +// revisions: riscv64gc_unknown_fuchsia +// [riscv64gc_unknown_fuchsia] compile-flags: --target riscv64gc-unknown-fuchsia +// [riscv64gc_unknown_fuchsia] needs-llvm-components: riscv +// revisions: riscv64gc_unknown_hermit +// [riscv64gc_unknown_hermit] compile-flags: --target riscv64gc-unknown-hermit +// [riscv64gc_unknown_hermit] needs-llvm-components: riscv +// revisions: riscv64gc_unknown_linux_gnu +// [riscv64gc_unknown_linux_gnu] compile-flags: --target riscv64gc-unknown-linux-gnu +// [riscv64gc_unknown_linux_gnu] needs-llvm-components: riscv +// revisions: riscv64gc_unknown_linux_musl +// [riscv64gc_unknown_linux_musl] compile-flags: --target riscv64gc-unknown-linux-musl +// [riscv64gc_unknown_linux_musl] needs-llvm-components: riscv +// revisions: riscv64gc_unknown_netbsd +// [riscv64gc_unknown_netbsd] compile-flags: --target riscv64gc-unknown-netbsd +// [riscv64gc_unknown_netbsd] needs-llvm-components: riscv +// revisions: riscv64gc_unknown_none_elf +// [riscv64gc_unknown_none_elf] compile-flags: --target riscv64gc-unknown-none-elf +// [riscv64gc_unknown_none_elf] needs-llvm-components: riscv +// revisions: riscv64gc_unknown_openbsd +// [riscv64gc_unknown_openbsd] compile-flags: --target riscv64gc-unknown-openbsd +// [riscv64gc_unknown_openbsd] needs-llvm-components: riscv +// revisions: riscv64imac_unknown_none_elf +// [riscv64imac_unknown_none_elf] compile-flags: --target riscv64imac-unknown-none-elf +// [riscv64imac_unknown_none_elf] needs-llvm-components: riscv +// revisions: s390x_unknown_linux_gnu +// [s390x_unknown_linux_gnu] compile-flags: --target s390x-unknown-linux-gnu +// [s390x_unknown_linux_gnu] needs-llvm-components: systemz +// revisions: s390x_unknown_linux_musl +// [s390x_unknown_linux_musl] compile-flags: --target s390x-unknown-linux-musl +// [s390x_unknown_linux_musl] needs-llvm-components: systemz +// revisions: sparc64_unknown_linux_gnu +// [sparc64_unknown_linux_gnu] compile-flags: --target sparc64-unknown-linux-gnu +// [sparc64_unknown_linux_gnu] needs-llvm-components: sparc +// revisions: sparc64_unknown_netbsd +// [sparc64_unknown_netbsd] compile-flags: --target sparc64-unknown-netbsd +// [sparc64_unknown_netbsd] needs-llvm-components: sparc +// revisions: sparc64_unknown_openbsd +// [sparc64_unknown_openbsd] compile-flags: --target sparc64-unknown-openbsd +// [sparc64_unknown_openbsd] needs-llvm-components: sparc +// revisions: sparc_unknown_linux_gnu +// [sparc_unknown_linux_gnu] compile-flags: --target sparc-unknown-linux-gnu +// [sparc_unknown_linux_gnu] needs-llvm-components: sparc +// revisions: sparc_unknown_none_elf +// [sparc_unknown_none_elf] compile-flags: --target sparc-unknown-none-elf +// [sparc_unknown_none_elf] needs-llvm-components: sparc +// revisions: sparcv9_sun_solaris +// [sparcv9_sun_solaris] compile-flags: --target sparcv9-sun-solaris +// [sparcv9_sun_solaris] needs-llvm-components: sparc +// revisions: thumbv4t_none_eabi +// [thumbv4t_none_eabi] compile-flags: --target thumbv4t-none-eabi +// [thumbv4t_none_eabi] needs-llvm-components: arm +// revisions: thumbv5te_none_eabi +// [thumbv5te_none_eabi] compile-flags: --target thumbv5te-none-eabi +// [thumbv5te_none_eabi] needs-llvm-components: arm +// revisions: thumbv6m_none_eabi +// [thumbv6m_none_eabi] compile-flags: --target thumbv6m-none-eabi +// [thumbv6m_none_eabi] needs-llvm-components: arm +// revisions: thumbv7em_none_eabi +// [thumbv7em_none_eabi] compile-flags: --target thumbv7em-none-eabi +// [thumbv7em_none_eabi] needs-llvm-components: arm +// revisions: thumbv7em_none_eabihf +// [thumbv7em_none_eabihf] compile-flags: --target thumbv7em-none-eabihf +// [thumbv7em_none_eabihf] needs-llvm-components: arm +// revisions: thumbv7m_none_eabi +// [thumbv7m_none_eabi] compile-flags: --target thumbv7m-none-eabi +// [thumbv7m_none_eabi] needs-llvm-components: arm +// revisions: thumbv7neon_linux_androideabi +// [thumbv7neon_linux_androideabi] compile-flags: --target thumbv7neon-linux-androideabi +// [thumbv7neon_linux_androideabi] needs-llvm-components: arm +// revisions: thumbv7neon_unknown_linux_gnueabihf +// [thumbv7neon_unknown_linux_gnueabihf] compile-flags: --target thumbv7neon-unknown-linux-gnueabihf +// [thumbv7neon_unknown_linux_gnueabihf] needs-llvm-components: arm +// revisions: thumbv7neon_unknown_linux_musleabihf +// [thumbv7neon_unknown_linux_musleabihf] compile-flags: --target thumbv7neon-unknown-linux-musleabihf +// [thumbv7neon_unknown_linux_musleabihf] needs-llvm-components: arm +// revisions: thumbv8m_base_none_eabi +// [thumbv8m_base_none_eabi] compile-flags: --target thumbv8m.base-none-eabi +// [thumbv8m_base_none_eabi] needs-llvm-components: arm +// revisions: thumbv8m_main_none_eabi +// [thumbv8m_main_none_eabi] compile-flags: --target thumbv8m.main-none-eabi +// [thumbv8m_main_none_eabi] needs-llvm-components: arm +// revisions: thumbv8m_main_none_eabihf +// [thumbv8m_main_none_eabihf] compile-flags: --target thumbv8m.main-none-eabihf +// [thumbv8m_main_none_eabihf] needs-llvm-components: arm +// revisions: wasm32_unknown_emscripten +// [wasm32_unknown_emscripten] compile-flags: --target wasm32-unknown-emscripten +// [wasm32_unknown_emscripten] needs-llvm-components: webassembly +// revisions: wasm32_unknown_unknown +// [wasm32_unknown_unknown] compile-flags: --target wasm32-unknown-unknown +// [wasm32_unknown_unknown] needs-llvm-components: webassembly +// revisions: wasm32_wasi +// [wasm32_wasi] compile-flags: --target wasm32-wasi +// [wasm32_wasi] needs-llvm-components: webassembly +// revisions: wasm32_wasi_preview1_threads +// [wasm32_wasi_preview1_threads] compile-flags: --target wasm32-wasi-preview1-threads +// [wasm32_wasi_preview1_threads] needs-llvm-components: webassembly +// revisions: wasm64_unknown_unknown +// [wasm64_unknown_unknown] compile-flags: --target wasm64-unknown-unknown +// [wasm64_unknown_unknown] needs-llvm-components: webassembly +// revisions: x86_64_apple_darwin +// [x86_64_apple_darwin] compile-flags: --target x86_64-apple-darwin +// [x86_64_apple_darwin] needs-llvm-components: x86 +// revisions: x86_64_apple_ios +// [x86_64_apple_ios] compile-flags: --target x86_64-apple-ios +// [x86_64_apple_ios] needs-llvm-components: x86 +// revisions: x86_64_apple_ios_macabi +// [x86_64_apple_ios_macabi] compile-flags: --target x86_64-apple-ios-macabi +// [x86_64_apple_ios_macabi] needs-llvm-components: x86 +// revisions: x86_64_apple_tvos +// [x86_64_apple_tvos] compile-flags: --target x86_64-apple-tvos +// [x86_64_apple_tvos] needs-llvm-components: x86 +// revisions: x86_64_apple_watchos_sim +// [x86_64_apple_watchos_sim] compile-flags: --target x86_64-apple-watchos-sim +// [x86_64_apple_watchos_sim] needs-llvm-components: x86 +// revisions: x86_64_fortanix_unknown_sgx +// [x86_64_fortanix_unknown_sgx] compile-flags: --target x86_64-fortanix-unknown-sgx +// [x86_64_fortanix_unknown_sgx] needs-llvm-components: x86 +// revisions: x86_64_fuchsia +// [x86_64_fuchsia] compile-flags: --target x86_64-fuchsia +// [x86_64_fuchsia] needs-llvm-components: x86 +// revisions: x86_64_linux_android +// [x86_64_linux_android] compile-flags: --target x86_64-linux-android +// [x86_64_linux_android] needs-llvm-components: x86 +// revisions: x86_64_pc_nto_qnx710 +// [x86_64_pc_nto_qnx710] compile-flags: --target x86_64-pc-nto-qnx710 +// [x86_64_pc_nto_qnx710] needs-llvm-components: x86 +// revisions: x86_64_pc_solaris +// [x86_64_pc_solaris] compile-flags: --target x86_64-pc-solaris +// [x86_64_pc_solaris] needs-llvm-components: x86 +// revisions: x86_64_unikraft_linux_musl +// [x86_64_unikraft_linux_musl] compile-flags: --target x86_64-unikraft-linux-musl +// [x86_64_unikraft_linux_musl] needs-llvm-components: x86 +// revisions: x86_64_unknown_dragonfly +// [x86_64_unknown_dragonfly] compile-flags: --target x86_64-unknown-dragonfly +// [x86_64_unknown_dragonfly] needs-llvm-components: x86 +// revisions: x86_64_unknown_freebsd +// [x86_64_unknown_freebsd] compile-flags: --target x86_64-unknown-freebsd +// [x86_64_unknown_freebsd] needs-llvm-components: x86 +// revisions: x86_64_unknown_fuchsia +// [x86_64_unknown_fuchsia] compile-flags: --target x86_64-unknown-fuchsia +// [x86_64_unknown_fuchsia] needs-llvm-components: x86 +// revisions: x86_64_unknown_haiku +// [x86_64_unknown_haiku] compile-flags: --target x86_64-unknown-haiku +// [x86_64_unknown_haiku] needs-llvm-components: x86 +// revisions: x86_64_unknown_hermit +// [x86_64_unknown_hermit] compile-flags: --target x86_64-unknown-hermit +// [x86_64_unknown_hermit] needs-llvm-components: x86 +// revisions: x86_64_unknown_illumos +// [x86_64_unknown_illumos] compile-flags: --target x86_64-unknown-illumos +// [x86_64_unknown_illumos] needs-llvm-components: x86 +// revisions: x86_64_unknown_l4re_uclibc +// [x86_64_unknown_l4re_uclibc] compile-flags: --target x86_64-unknown-l4re-uclibc +// [x86_64_unknown_l4re_uclibc] needs-llvm-components: x86 +// revisions: x86_64_unknown_linux_gnu +// [x86_64_unknown_linux_gnu] compile-flags: --target x86_64-unknown-linux-gnu +// [x86_64_unknown_linux_gnu] needs-llvm-components: x86 +// revisions: x86_64_unknown_linux_gnux32 +// [x86_64_unknown_linux_gnux32] compile-flags: --target x86_64-unknown-linux-gnux32 +// [x86_64_unknown_linux_gnux32] needs-llvm-components: x86 +// revisions: x86_64_unknown_linux_musl +// [x86_64_unknown_linux_musl] compile-flags: --target x86_64-unknown-linux-musl +// [x86_64_unknown_linux_musl] needs-llvm-components: x86 +// revisions: x86_64_unknown_linux_ohos +// [x86_64_unknown_linux_ohos] compile-flags: --target x86_64-unknown-linux-ohos +// [x86_64_unknown_linux_ohos] needs-llvm-components: x86 +// revisions: x86_64_unknown_netbsd +// [x86_64_unknown_netbsd] compile-flags: --target x86_64-unknown-netbsd +// [x86_64_unknown_netbsd] needs-llvm-components: x86 +// revisions: x86_64_unknown_none +// [x86_64_unknown_none] compile-flags: --target x86_64-unknown-none +// [x86_64_unknown_none] needs-llvm-components: x86 +// revisions: x86_64_unknown_openbsd +// [x86_64_unknown_openbsd] compile-flags: --target x86_64-unknown-openbsd +// [x86_64_unknown_openbsd] needs-llvm-components: x86 +// revisions: x86_64_unknown_redox +// [x86_64_unknown_redox] compile-flags: --target x86_64-unknown-redox +// [x86_64_unknown_redox] needs-llvm-components: x86 +// revisions: x86_64_wrs_vxworks +// [x86_64_wrs_vxworks] compile-flags: --target x86_64-wrs-vxworks +// [x86_64_wrs_vxworks] needs-llvm-components: x86 +// revisions: x86_64h_apple_darwin +// [x86_64h_apple_darwin] compile-flags: --target x86_64h-apple-darwin +// [x86_64h_apple_darwin] needs-llvm-components: x86 + +// Sanity-check that each target can produce assembly code. + +#![feature(no_core, lang_items)] +#![no_std] +#![no_core] +#![crate_type = "lib"] + +#[lang = "sized"] +trait Sized {} + +pub fn test() -> u8 { + 42 +} + +// CHECK: .section diff --git a/tests/assembly/targets/targets-nvptx.rs b/tests/assembly/targets/targets-nvptx.rs new file mode 100644 index 000000000000..063342304000 --- /dev/null +++ b/tests/assembly/targets/targets-nvptx.rs @@ -0,0 +1,21 @@ +// assembly-output: emit-asm +// ignore-tidy-linelength +// revisions: nvptx64_nvidia_cuda +// [nvptx64_nvidia_cuda] compile-flags: --target nvptx64-nvidia-cuda +// [nvptx64_nvidia_cuda] needs-llvm-components: nvptx + +// Sanity-check that each target can produce assembly code. + +#![feature(no_core, lang_items)] +#![no_std] +#![no_core] +#![crate_type = "lib"] + +#[lang = "sized"] +trait Sized {} + +pub fn test() -> u8 { + 42 +} + +// CHECK: .version diff --git a/tests/assembly/targets/targets-pe.rs b/tests/assembly/targets/targets-pe.rs new file mode 100644 index 000000000000..7398d7ef7900 --- /dev/null +++ b/tests/assembly/targets/targets-pe.rs @@ -0,0 +1,93 @@ +// assembly-output: emit-asm +// ignore-tidy-linelength +// revisions: aarch64_pc_windows_msvc +// [aarch64_pc_windows_msvc] compile-flags: --target aarch64-pc-windows-msvc +// [aarch64_pc_windows_msvc] needs-llvm-components: aarch64 +// revisions: aarch64_pc_windows_gnullvm +// [aarch64_pc_windows_gnullvm] compile-flags: --target aarch64-pc-windows-gnullvm +// [aarch64_pc_windows_gnullvm] needs-llvm-components: aarch64 +// revisions: aarch64_unknown_uefi +// [aarch64_unknown_uefi] compile-flags: --target aarch64-unknown-uefi +// [aarch64_unknown_uefi] needs-llvm-components: aarch64 +// revisions: aarch64_uwp_windows_msvc +// [aarch64_uwp_windows_msvc] compile-flags: --target aarch64-uwp-windows-msvc +// [aarch64_uwp_windows_msvc] needs-llvm-components: aarch64 +// revisions: avr_unknown_gnu_atmega328 +// [avr_unknown_gnu_atmega328] compile-flags: --target avr-unknown-gnu-atmega328 +// [avr_unknown_gnu_atmega328] needs-llvm-components: avr +// revisions: bpfeb_unknown_none +// [bpfeb_unknown_none] compile-flags: --target bpfeb-unknown-none +// [bpfeb_unknown_none] needs-llvm-components: bpf +// revisions: bpfel_unknown_none +// [bpfel_unknown_none] compile-flags: --target bpfel-unknown-none +// [bpfel_unknown_none] needs-llvm-components: bpf +// revisions: i586_pc_windows_msvc +// [i586_pc_windows_msvc] compile-flags: --target i586-pc-windows-msvc +// [i586_pc_windows_msvc] needs-llvm-components: x86 +// revisions: i686_pc_windows_gnu +// [i686_pc_windows_gnu] compile-flags: --target i686-pc-windows-gnu +// [i686_pc_windows_gnu] needs-llvm-components: x86 +// revisions: i686_pc_windows_msvc +// [i686_pc_windows_msvc] compile-flags: --target i686-pc-windows-msvc +// [i686_pc_windows_msvc] needs-llvm-components: x86 +// revisions: i686_pc_windows_gnullvm +// [i686_pc_windows_gnullvm] compile-flags: --target i686-pc-windows-gnullvm +// [i686_pc_windows_gnullvm] needs-llvm-components: x86 +// revisions: i686_uwp_windows_gnu +// [i686_uwp_windows_gnu] compile-flags: --target i686-uwp-windows-gnu +// [i686_uwp_windows_gnu] needs-llvm-components: x86 +// revisions: i686_unknown_uefi +// [i686_unknown_uefi] compile-flags: --target i686-unknown-uefi +// [i686_unknown_uefi] needs-llvm-components: x86 +// revisions: i686_uwp_windows_msvc +// [i686_uwp_windows_msvc] compile-flags: --target i686-uwp-windows-msvc +// [i686_uwp_windows_msvc] needs-llvm-components: x86 +// revisions: i686_win7_windows_msvc +// [i686_win7_windows_msvc] compile-flags: --target i686-win7-windows-msvc +// [i686_win7_windows_msvc] needs-llvm-components: x86 +// revisions: powerpc64_ibm_aix +// [powerpc64_ibm_aix] compile-flags: --target powerpc64-ibm-aix +// [powerpc64_ibm_aix] needs-llvm-components: powerpc +// revisions: thumbv7a_uwp_windows_msvc +// [thumbv7a_uwp_windows_msvc] compile-flags: --target thumbv7a-uwp-windows-msvc +// [thumbv7a_uwp_windows_msvc] needs-llvm-components: arm +// revisions: thumbv7a_pc_windows_msvc +// [thumbv7a_pc_windows_msvc] compile-flags: --target thumbv7a-pc-windows-msvc +// [thumbv7a_pc_windows_msvc] needs-llvm-components: arm +// revisions: x86_64_pc_windows_gnu +// [x86_64_pc_windows_gnu] compile-flags: --target x86_64-pc-windows-gnu +// [x86_64_pc_windows_gnu] needs-llvm-components: x86 +// revisions: x86_64_pc_windows_gnullvm +// [x86_64_pc_windows_gnullvm] compile-flags: --target x86_64-pc-windows-gnullvm +// [x86_64_pc_windows_gnullvm] needs-llvm-components: x86 +// revisions: x86_64_pc_windows_msvc +// [x86_64_pc_windows_msvc] compile-flags: --target x86_64-pc-windows-msvc +// [x86_64_pc_windows_msvc] needs-llvm-components: x86 +// revisions: x86_64_unknown_uefi +// [x86_64_unknown_uefi] compile-flags: --target x86_64-unknown-uefi +// [x86_64_unknown_uefi] needs-llvm-components: x86 +// revisions: x86_64_uwp_windows_gnu +// [x86_64_uwp_windows_gnu] compile-flags: --target x86_64-uwp-windows-gnu +// [x86_64_uwp_windows_gnu] needs-llvm-components: x86 +// revisions: x86_64_uwp_windows_msvc +// [x86_64_uwp_windows_msvc] compile-flags: --target x86_64-uwp-windows-msvc +// [x86_64_uwp_windows_msvc] needs-llvm-components: x86 +// revisions: x86_64_win7_windows_msvc +// [x86_64_win7_windows_msvc] compile-flags: --target x86_64-win7-windows-msvc +// [x86_64_win7_windows_msvc] needs-llvm-components: x86 + +// Sanity-check that each target can produce assembly code. + +#![feature(no_core, lang_items)] +#![no_std] +#![no_core] +#![crate_type = "lib"] + +#[lang = "sized"] +trait Sized {} + +pub fn test() -> u8 { + 42 +} + +// CHECK: .file diff --git a/tests/codegen/debuginfo-inline-callsite-location.rs b/tests/codegen/debuginfo-inline-callsite-location.rs index b1475ee79316..d529f9ccead5 100644 --- a/tests/codegen/debuginfo-inline-callsite-location.rs +++ b/tests/codegen/debuginfo-inline-callsite-location.rs @@ -4,9 +4,9 @@ // can correctly merge the debug info if it merges the inlined code (e.g., for merging of tail // calls to panic. -// CHECK: tail call void @_ZN4core9panicking5panic17h{{([0-9a-z]{16})}}E +// CHECK: tail call void @_ZN4core6option13unwrap_failed17h{{([0-9a-z]{16})}}E // CHECK-SAME: !dbg ![[#first_dbg:]] -// CHECK: tail call void @_ZN4core9panicking5panic17h{{([0-9a-z]{16})}}E +// CHECK: tail call void @_ZN4core6option13unwrap_failed17h{{([0-9a-z]{16})}}E // CHECK-SAME: !dbg ![[#second_dbg:]] // CHECK-DAG: ![[#func_dbg:]] = distinct !DISubprogram(name: "unwrap" diff --git a/tests/codegen/i128-x86-align.rs b/tests/codegen/i128-x86-align.rs new file mode 100644 index 000000000000..aaf5785dc9ff --- /dev/null +++ b/tests/codegen/i128-x86-align.rs @@ -0,0 +1,103 @@ +// only-x86_64 +// compile-flags: -O -C no-prepopulate-passes --crate-type=lib + +// On LLVM 17 and earlier LLVM's own data layout specifies that i128 has 8 byte alignment, +// while rustc wants it to have 16 byte alignment. This test checks that we handle this +// correctly. + +// CHECK: %ScalarPair = type { i32, [3 x i32], i128 } +// CHECK: %Struct = type { i32, i32, [2 x i32], i128 } + +#![feature(core_intrinsics)] + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct ScalarPair { + a: i32, + b: i128, +} + +#[no_mangle] +pub fn load(x: &ScalarPair) -> ScalarPair { + // CHECK-LABEL: @load( + // CHECK-SAME: align 16 dereferenceable(32) %x + // CHECK: [[A:%.*]] = load i32, ptr %x, align 16 + // CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr %x, i64 16 + // CHECK-NEXT: [[B:%.*]] = load i128, ptr [[GEP]], align 16 + // CHECK-NEXT: [[IV1:%.*]] = insertvalue { i32, i128 } poison, i32 [[A]], 0 + // CHECK-NEXT: [[IV2:%.*]] = insertvalue { i32, i128 } [[IV1]], i128 [[B]], 1 + // CHECK-NEXT: ret { i32, i128 } [[IV2]] + *x +} + +#[no_mangle] +pub fn store(x: &mut ScalarPair) { + // CHECK-LABEL: @store( + // CHECK-SAME: align 16 dereferenceable(32) %x + // CHECK: store i32 1, ptr %x, align 16 + // CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr %x, i64 16 + // CHECK-NEXT: store i128 2, ptr [[GEP]], align 16 + *x = ScalarPair { a: 1, b: 2 }; +} + +#[no_mangle] +pub fn alloca() { + // CHECK-LABEL: @alloca( + // CHECK: [[X:%.*]] = alloca %ScalarPair, align 16 + // CHECK: store i32 1, ptr %x, align 16 + // CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr %x, i64 16 + // CHECK-NEXT: store i128 2, ptr [[GEP]], align 16 + let mut x = ScalarPair { a: 1, b: 2 }; + store(&mut x); +} + +#[no_mangle] +pub fn load_volatile(x: &ScalarPair) -> ScalarPair { + // CHECK-LABEL: @load_volatile( + // CHECK-SAME: align 16 dereferenceable(32) %x + // CHECK: [[TMP:%.*]] = alloca %ScalarPair, align 16 + // CHECK: [[LOAD:%.*]] = load volatile %ScalarPair, ptr %x, align 16 + // CHECK-NEXT: store %ScalarPair [[LOAD]], ptr [[TMP]], align 16 + // CHECK-NEXT: [[A:%.*]] = load i32, ptr [[TMP]], align 16 + // CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[TMP]], i64 16 + // CHECK-NEXT: [[B:%.*]] = load i128, ptr [[GEP]], align 16 + unsafe { std::intrinsics::volatile_load(x) } +} + +#[no_mangle] +pub fn transmute(x: ScalarPair) -> (std::mem::MaybeUninit, i128) { + // CHECK-LABEL: define { i128, i128 } @transmute(i32 noundef %x.0, i128 noundef %x.1) + // CHECK: [[TMP:%.*]] = alloca { i128, i128 }, align 16 + // CHECK-NEXT: store i32 %x.0, ptr [[TMP]], align 16 + // CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[TMP]], i64 16 + // CHECK-NEXT: store i128 %x.1, ptr [[GEP]], align 16 + // CHECK-NEXT: [[LOAD1:%.*]] = load i128, ptr %_0, align 16 + // CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds i8, ptr [[TMP]], i64 16 + // CHECK-NEXT: [[LOAD2:%.*]] = load i128, ptr [[GEP2]], align 16 + // CHECK-NEXT: [[IV1:%.*]] = insertvalue { i128, i128 } poison, i128 [[LOAD1]], 0 + // CHECK-NEXT: [[IV2:%.*]] = insertvalue { i128, i128 } [[IV1]], i128 [[LOAD2]], 1 + // CHECK-NEXT: ret { i128, i128 } [[IV2]] + unsafe { std::mem::transmute(x) } +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct Struct { + a: i32, + b: i32, + c: i128, +} + +#[no_mangle] +pub fn store_struct(x: &mut Struct) { + // CHECK-LABEL: @store_struct( + // CHECK-SAME: align 16 dereferenceable(32) %x + // CHECK: [[TMP:%.*]] = alloca %Struct, align 16 + // CHECK: store i32 1, ptr [[TMP]], align 16 + // CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds %Struct, ptr [[TMP]], i32 0, i32 1 + // CHECK-NEXT: store i32 2, ptr [[GEP1]], align 4 + // CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds %Struct, ptr [[TMP]], i32 0, i32 3 + // CHECK-NEXT: store i128 3, ptr [[GEP2]], align 16 + // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 %x, ptr align 16 [[TMP]], i64 32, i1 false) + *x = Struct { a: 1, b: 2, c: 3 }; +} diff --git a/tests/codegen/infallible-unwrap-in-opt-z.rs b/tests/codegen/infallible-unwrap-in-opt-z.rs new file mode 100644 index 000000000000..5c57b41532fb --- /dev/null +++ b/tests/codegen/infallible-unwrap-in-opt-z.rs @@ -0,0 +1,26 @@ +// compile-flags: -C opt-level=z --edition=2021 +// ignore-debug + +#![crate_type = "lib"] + +// From + +// CHECK-LABEL: @read_up_to_8( +#[no_mangle] +pub fn read_up_to_8(buf: &[u8]) -> u64 { + // CHECK-NOT: unwrap_failed + if buf.len() < 4 { + // actual instance has more code. + return 0; + } + let lo = u32::from_le_bytes(buf[..4].try_into().unwrap()) as u64; + let hi = u32::from_le_bytes(buf[buf.len() - 4..][..4].try_into().unwrap()) as u64; + lo | (hi << 8 * (buf.len() as u64 - 4)) +} + +// CHECK-LABEL: @checking_unwrap_expectation( +#[no_mangle] +pub fn checking_unwrap_expectation(buf: &[u8]) -> &[u8; 4] { + // CHECK: call void @_ZN4core6result13unwrap_failed17h + buf.try_into().unwrap() +} diff --git a/tests/codegen/swap-small-types.rs b/tests/codegen/swap-small-types.rs index 27bc00bc3abb..2c6751744798 100644 --- a/tests/codegen/swap-small-types.rs +++ b/tests/codegen/swap-small-types.rs @@ -26,12 +26,15 @@ pub fn swap_rgb48_manually(x: &mut RGB48, y: &mut RGB48) { // CHECK-LABEL: @swap_rgb48 #[no_mangle] pub fn swap_rgb48(x: &mut RGB48, y: &mut RGB48) { - // FIXME: See #115212 for why this has an alloca again + // CHECK-NOT: alloca - // CHECK: alloca [3 x i16], align 2 - // CHECK: call void @llvm.memcpy.p0.p0.i64({{.+}}, i64 6, i1 false) - // CHECK: call void @llvm.memcpy.p0.p0.i64({{.+}}, i64 6, i1 false) - // CHECK: call void @llvm.memcpy.p0.p0.i64({{.+}}, i64 6, i1 false) + // Whether `i8` is the best for this is unclear, but + // might as well record what's actually happening right now. + + // CHECK: load i8 + // CHECK: load i8 + // CHECK: store i8 + // CHECK: store i8 swap(x, y) } @@ -41,10 +44,39 @@ type RGBA64 = [u16; 4]; #[no_mangle] pub fn swap_rgba64(x: &mut RGBA64, y: &mut RGBA64) { // CHECK-NOT: alloca - // CHECK-DAG: %[[XVAL:.+]] = load <4 x i16>, ptr %x, align 2 - // CHECK-DAG: %[[YVAL:.+]] = load <4 x i16>, ptr %y, align 2 - // CHECK-DAG: store <4 x i16> %[[YVAL]], ptr %x, align 2 - // CHECK-DAG: store <4 x i16> %[[XVAL]], ptr %y, align 2 + // CHECK-DAG: %[[XVAL:.+]] = load i64, ptr %x, align 2 + // CHECK-DAG: %[[YVAL:.+]] = load i64, ptr %y, align 2 + // CHECK-DAG: store i64 %[[YVAL]], ptr %x, align 2 + // CHECK-DAG: store i64 %[[XVAL]], ptr %y, align 2 + swap(x, y) +} + +// CHECK-LABEL: @swap_vecs +#[no_mangle] +pub fn swap_vecs(x: &mut Vec, y: &mut Vec) { + // CHECK-NOT: alloca + // There are plenty more loads and stores than just these, + // but at least one sure better be 64-bit (for size or capacity). + // CHECK: load i64 + // CHECK: load i64 + // CHECK: store i64 + // CHECK: store i64 + // CHECK: ret void + swap(x, y) +} + +// CHECK-LABEL: @swap_slices +#[no_mangle] +pub fn swap_slices<'a>(x: &mut &'a [u32], y: &mut &'a [u32]) { + // CHECK-NOT: alloca + // CHECK: load ptr + // CHECK: load i64 + // CHECK: load ptr + // CHECK: load i64 + // CHECK: store ptr + // CHECK: store i64 + // CHECK: store ptr + // CHECK: store i64 swap(x, y) } @@ -55,9 +87,9 @@ type RGB24 = [u8; 3]; // CHECK-LABEL: @swap_rgb24_slices #[no_mangle] pub fn swap_rgb24_slices(x: &mut [RGB24], y: &mut [RGB24]) { -// CHECK-NOT: alloca -// CHECK: load <{{[0-9]+}} x i8> -// CHECK: store <{{[0-9]+}} x i8> + // CHECK-NOT: alloca + // CHECK: load <{{[0-9]+}} x i8> + // CHECK: store <{{[0-9]+}} x i8> if x.len() == y.len() { x.swap_with_slice(y); } @@ -69,9 +101,9 @@ type RGBA32 = [u8; 4]; // CHECK-LABEL: @swap_rgba32_slices #[no_mangle] pub fn swap_rgba32_slices(x: &mut [RGBA32], y: &mut [RGBA32]) { -// CHECK-NOT: alloca -// CHECK: load <{{[0-9]+}} x i32> -// CHECK: store <{{[0-9]+}} x i32> + // CHECK-NOT: alloca + // CHECK: load <{{[0-9]+}} x i32> + // CHECK: store <{{[0-9]+}} x i32> if x.len() == y.len() { x.swap_with_slice(y); } @@ -84,10 +116,24 @@ const _: () = assert!(!std::mem::size_of::().is_power_of_two()); // CHECK-LABEL: @swap_string_slices #[no_mangle] pub fn swap_string_slices(x: &mut [String], y: &mut [String]) { -// CHECK-NOT: alloca -// CHECK: load <{{[0-9]+}} x i64> -// CHECK: store <{{[0-9]+}} x i64> + // CHECK-NOT: alloca + // CHECK: load <{{[0-9]+}} x i64> + // CHECK: store <{{[0-9]+}} x i64> if x.len() == y.len() { x.swap_with_slice(y); } } + +#[repr(C, packed)] +pub struct Packed { + pub first: bool, + pub second: usize, +} + +// CHECK-LABEL: @swap_packed_structs +#[no_mangle] +pub fn swap_packed_structs(x: &mut Packed, y: &mut Packed) { + // CHECK-NOT: alloca + // CHECK: ret void + swap(x, y) +} diff --git a/tests/coverage/abort.cov-map b/tests/coverage/abort.cov-map index 45d3795eff8f..1c36f2871dd1 100644 --- a/tests/coverage/abort.cov-map +++ b/tests/coverage/abort.cov-map @@ -1,5 +1,5 @@ Function name: abort::main -Raw bytes (105): 0x[01, 01, 12, 01, 47, 05, 09, 03, 0d, 42, 11, 03, 0d, 11, 3e, 42, 11, 03, 0d, 3b, 15, 11, 3e, 42, 11, 03, 0d, 15, 36, 3b, 15, 11, 3e, 42, 11, 03, 0d, 05, 09, 0d, 01, 0d, 01, 01, 1b, 03, 02, 0b, 00, 18, 42, 01, 0c, 00, 19, 11, 00, 1a, 02, 0a, 3e, 02, 0a, 00, 0b, 3b, 02, 0c, 00, 19, 15, 00, 1a, 00, 31, 36, 00, 31, 00, 32, 33, 04, 0c, 00, 19, 05, 00, 1a, 00, 31, 09, 00, 31, 00, 32, 47, 01, 09, 00, 17, 0d, 02, 05, 01, 02] +Raw bytes (105): 0x[01, 01, 12, 01, 47, 05, 09, 03, 0d, 42, 11, 03, 0d, 11, 3e, 42, 11, 03, 0d, 3b, 15, 11, 3e, 42, 11, 03, 0d, 15, 36, 3b, 15, 11, 3e, 42, 11, 03, 0d, 05, 09, 0d, 01, 0e, 01, 01, 1b, 03, 02, 0b, 00, 18, 42, 01, 0c, 00, 19, 11, 00, 1a, 02, 0a, 3e, 02, 0a, 00, 0b, 3b, 02, 0c, 00, 19, 15, 00, 1a, 00, 31, 36, 00, 31, 00, 32, 33, 04, 0c, 00, 19, 05, 00, 1a, 00, 31, 09, 00, 31, 00, 32, 47, 01, 09, 00, 17, 0d, 02, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 18 @@ -22,7 +22,7 @@ Number of expressions: 18 - expression 16 operands: lhs = Expression(0, Add), rhs = Counter(3) - expression 17 operands: lhs = Counter(1), rhs = Counter(2) Number of file 0 mappings: 13 -- Code(Counter(0)) at (prev + 13, 1) to (start + 1, 27) +- Code(Counter(0)) at (prev + 14, 1) to (start + 1, 27) - Code(Expression(0, Add)) at (prev + 2, 11) to (start + 0, 24) = (c0 + (c1 + c2)) - Code(Expression(16, Sub)) at (prev + 1, 12) to (start + 0, 25) diff --git a/tests/coverage/abort.coverage b/tests/coverage/abort.coverage index ceef63867807..b658a6562591 100644 --- a/tests/coverage/abort.coverage +++ b/tests/coverage/abort.coverage @@ -10,6 +10,7 @@ LL| 12| } LL| 12|} LL| | + LL| |#[rustfmt::skip] LL| 1|fn main() -> Result<(), u8> { LL| 1| let mut countdown = 10; LL| 11| while countdown > 0 { diff --git a/tests/coverage/abort.rs b/tests/coverage/abort.rs index 98264bdc1afe..649e8e52a490 100644 --- a/tests/coverage/abort.rs +++ b/tests/coverage/abort.rs @@ -10,6 +10,7 @@ extern "C" fn might_abort(should_abort: bool) { } } +#[rustfmt::skip] fn main() -> Result<(), u8> { let mut countdown = 10; while countdown > 0 { diff --git a/tests/coverage/async.cov-map b/tests/coverage/async.cov-map index 6bdcca40ed66..e06d1676358f 100644 --- a/tests/coverage/async.cov-map +++ b/tests/coverage/async.cov-map @@ -1,20 +1,20 @@ Function name: async::c -Raw bytes (9): 0x[01, 01, 00, 01, 01, 07, 01, 00, 19] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 09, 01, 00, 19] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 7, 1) to (start + 0, 25) +- Code(Counter(0)) at (prev + 9, 1) to (start + 0, 25) Function name: async::c::{closure#0} -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 07, 19, 01, 0e, 05, 02, 09, 00, 0a, 02, 02, 09, 00, 0a, 07, 02, 01, 00, 02] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 09, 19, 01, 0e, 05, 02, 09, 00, 0a, 02, 02, 09, 00, 0a, 07, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 7, 25) to (start + 1, 14) +- Code(Counter(0)) at (prev + 9, 25) to (start + 1, 14) - Code(Counter(1)) at (prev + 2, 9) to (start + 0, 10) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 10) = (c0 - c1) @@ -22,84 +22,84 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: async::d -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0f, 01, 00, 14] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 11, 01, 00, 14] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 15, 1) to (start + 0, 20) +- Code(Counter(0)) at (prev + 17, 1) to (start + 0, 20) Function name: async::d::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0f, 14, 00, 19] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 11, 14, 00, 19] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 15, 20) to (start + 0, 25) +- Code(Counter(0)) at (prev + 17, 20) to (start + 0, 25) Function name: async::e (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 11, 01, 00, 14] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 13, 01, 00, 14] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 17, 1) to (start + 0, 20) +- Code(Zero) at (prev + 19, 1) to (start + 0, 20) Function name: async::e::{closure#0} (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 11, 14, 00, 19] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 13, 14, 00, 19] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 17, 20) to (start + 0, 25) +- Code(Zero) at (prev + 19, 20) to (start + 0, 25) Function name: async::f -Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 01, 00, 14] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 15, 01, 00, 14] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 19, 1) to (start + 0, 20) +- Code(Counter(0)) at (prev + 21, 1) to (start + 0, 20) Function name: async::f::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 14, 00, 19] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 15, 14, 00, 19] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 19, 20) to (start + 0, 25) +- Code(Counter(0)) at (prev + 21, 20) to (start + 0, 25) Function name: async::foo (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 15, 01, 00, 1e] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 17, 01, 00, 1e] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 21, 1) to (start + 0, 30) +- Code(Zero) at (prev + 23, 1) to (start + 0, 30) Function name: async::foo::{closure#0} (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 15, 1e, 00, 2d] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 17, 1e, 00, 2d] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 21, 30) to (start + 0, 45) +- Code(Zero) at (prev + 23, 30) to (start + 0, 45) Function name: async::g -Raw bytes (9): 0x[01, 01, 00, 01, 01, 17, 01, 00, 17] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 19, 01, 00, 17] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 23, 1) to (start + 0, 23) +- Code(Counter(0)) at (prev + 25, 1) to (start + 0, 23) Function name: async::g::{closure#0} (unused) -Raw bytes (69): 0x[01, 01, 00, 0d, 00, 17, 17, 01, 0c, 00, 02, 09, 00, 0a, 00, 00, 0e, 00, 11, 00, 00, 12, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 09, 00, 0a, 00, 00, 0e, 00, 11, 00, 00, 12, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] +Raw bytes (69): 0x[01, 01, 00, 0d, 00, 19, 17, 01, 0c, 00, 02, 09, 00, 0a, 00, 00, 0e, 00, 11, 00, 00, 12, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 09, 00, 0a, 00, 00, 0e, 00, 11, 00, 00, 12, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 13 -- Code(Zero) at (prev + 23, 23) to (start + 1, 12) +- Code(Zero) at (prev + 25, 23) to (start + 1, 12) - Code(Zero) at (prev + 2, 9) to (start + 0, 10) - Code(Zero) at (prev + 0, 14) to (start + 0, 17) - Code(Zero) at (prev + 0, 18) to (start + 0, 23) @@ -114,20 +114,20 @@ Number of file 0 mappings: 13 - Code(Zero) at (prev + 2, 1) to (start + 0, 2) Function name: async::h -Raw bytes (9): 0x[01, 01, 00, 01, 01, 1f, 01, 00, 16] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 21, 01, 00, 16] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 31, 1) to (start + 0, 22) +- Code(Counter(0)) at (prev + 33, 1) to (start + 0, 22) Function name: async::h::{closure#0} (unused) -Raw bytes (44): 0x[01, 01, 00, 08, 00, 1f, 16, 03, 0c, 00, 04, 09, 00, 0a, 00, 00, 0e, 00, 13, 00, 00, 14, 00, 19, 00, 00, 1a, 00, 1b, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] +Raw bytes (44): 0x[01, 01, 00, 08, 00, 21, 16, 03, 0c, 00, 04, 09, 00, 0a, 00, 00, 0e, 00, 13, 00, 00, 14, 00, 19, 00, 00, 1a, 00, 1b, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 8 -- Code(Zero) at (prev + 31, 22) to (start + 3, 12) +- Code(Zero) at (prev + 33, 22) to (start + 3, 12) - Code(Zero) at (prev + 4, 9) to (start + 0, 10) - Code(Zero) at (prev + 0, 14) to (start + 0, 19) - Code(Zero) at (prev + 0, 20) to (start + 0, 25) @@ -137,22 +137,22 @@ Number of file 0 mappings: 8 - Code(Zero) at (prev + 2, 1) to (start + 0, 2) Function name: async::i -Raw bytes (9): 0x[01, 01, 00, 01, 01, 28, 01, 00, 13] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 2a, 01, 00, 13] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 40, 1) to (start + 0, 19) +- Code(Counter(0)) at (prev + 42, 1) to (start + 0, 19) Function name: async::i::{closure#0} -Raw bytes (78): 0x[01, 01, 02, 07, 21, 19, 1d, 0e, 01, 28, 13, 04, 0c, 0d, 05, 09, 00, 0a, 01, 00, 0e, 00, 12, 05, 00, 13, 00, 18, 09, 00, 1c, 00, 21, 0d, 00, 27, 00, 2a, 15, 00, 2b, 00, 30, 1d, 01, 09, 00, 0a, 11, 00, 0e, 00, 11, 25, 00, 12, 00, 17, 29, 00, 1b, 00, 20, 1d, 00, 24, 00, 26, 21, 01, 0e, 00, 10, 03, 02, 01, 00, 02] +Raw bytes (78): 0x[01, 01, 02, 07, 21, 19, 1d, 0e, 01, 2a, 13, 04, 0c, 0d, 05, 09, 00, 0a, 01, 00, 0e, 00, 12, 05, 00, 13, 00, 18, 09, 00, 1c, 00, 21, 0d, 00, 27, 00, 2a, 15, 00, 2b, 00, 30, 1d, 01, 09, 00, 0a, 11, 00, 0e, 00, 11, 25, 00, 12, 00, 17, 29, 00, 1b, 00, 20, 1d, 00, 24, 00, 26, 21, 01, 0e, 00, 10, 03, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Expression(1, Add), rhs = Counter(8) - expression 1 operands: lhs = Counter(6), rhs = Counter(7) Number of file 0 mappings: 14 -- Code(Counter(0)) at (prev + 40, 19) to (start + 4, 12) +- Code(Counter(0)) at (prev + 42, 19) to (start + 4, 12) - Code(Counter(3)) at (prev + 5, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 14) to (start + 0, 18) - Code(Counter(1)) at (prev + 0, 19) to (start + 0, 24) @@ -169,14 +169,14 @@ Number of file 0 mappings: 14 = ((c6 + c7) + c8) Function name: async::j -Raw bytes (53): 0x[01, 01, 02, 07, 0d, 05, 09, 09, 01, 33, 01, 13, 0c, 05, 14, 09, 00, 0a, 01, 00, 0e, 00, 1b, 05, 00, 1f, 00, 27, 09, 01, 09, 00, 0a, 11, 00, 0e, 00, 1a, 09, 00, 1e, 00, 20, 0d, 01, 0e, 00, 10, 03, 02, 01, 00, 02] +Raw bytes (53): 0x[01, 01, 02, 07, 0d, 05, 09, 09, 01, 35, 01, 13, 0c, 05, 14, 09, 00, 0a, 01, 00, 0e, 00, 1b, 05, 00, 1f, 00, 27, 09, 01, 09, 00, 0a, 11, 00, 0e, 00, 1a, 09, 00, 1e, 00, 20, 0d, 01, 0e, 00, 10, 03, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Expression(1, Add), rhs = Counter(3) - expression 1 operands: lhs = Counter(1), rhs = Counter(2) Number of file 0 mappings: 9 -- Code(Counter(0)) at (prev + 51, 1) to (start + 19, 12) +- Code(Counter(0)) at (prev + 53, 1) to (start + 19, 12) - Code(Counter(1)) at (prev + 20, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 14) to (start + 0, 27) - Code(Counter(1)) at (prev + 0, 31) to (start + 0, 39) @@ -188,14 +188,14 @@ Number of file 0 mappings: 9 = ((c1 + c2) + c3) Function name: async::j::c -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 35, 05, 01, 12, 05, 02, 0d, 00, 0e, 02, 0a, 0d, 00, 0e, 07, 02, 05, 00, 06] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 37, 05, 01, 12, 05, 02, 0d, 00, 0e, 02, 0a, 0d, 00, 0e, 07, 02, 05, 00, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 53, 5) to (start + 1, 18) +- Code(Counter(0)) at (prev + 55, 5) to (start + 1, 18) - Code(Counter(1)) at (prev + 2, 13) to (start + 0, 14) - Code(Expression(0, Sub)) at (prev + 10, 13) to (start + 0, 14) = (c0 - c1) @@ -203,35 +203,35 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: async::j::d -Raw bytes (9): 0x[01, 01, 00, 01, 01, 44, 05, 00, 17] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 46, 05, 00, 17] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 68, 5) to (start + 0, 23) +- Code(Counter(0)) at (prev + 70, 5) to (start + 0, 23) Function name: async::j::f -Raw bytes (9): 0x[01, 01, 00, 01, 01, 45, 05, 00, 17] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 47, 05, 00, 17] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 69, 5) to (start + 0, 23) +- Code(Counter(0)) at (prev + 71, 5) to (start + 0, 23) Function name: async::k (unused) -Raw bytes (29): 0x[01, 01, 00, 05, 00, 4d, 01, 01, 0c, 00, 02, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] +Raw bytes (29): 0x[01, 01, 00, 05, 00, 4f, 01, 01, 0c, 00, 02, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 5 -- Code(Zero) at (prev + 77, 1) to (start + 1, 12) +- Code(Zero) at (prev + 79, 1) to (start + 1, 12) - Code(Zero) at (prev + 2, 14) to (start + 0, 16) - Code(Zero) at (prev + 1, 14) to (start + 0, 16) - Code(Zero) at (prev + 1, 14) to (start + 0, 16) - Code(Zero) at (prev + 2, 1) to (start + 0, 2) Function name: async::l -Raw bytes (37): 0x[01, 01, 04, 01, 07, 05, 09, 0f, 02, 09, 05, 05, 01, 55, 01, 01, 0c, 02, 02, 0e, 00, 10, 05, 01, 0e, 00, 10, 09, 01, 0e, 00, 10, 0b, 02, 01, 00, 02] +Raw bytes (37): 0x[01, 01, 04, 01, 07, 05, 09, 0f, 02, 09, 05, 05, 01, 57, 01, 01, 0c, 02, 02, 0e, 00, 10, 05, 01, 0e, 00, 10, 09, 01, 0e, 00, 10, 0b, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 @@ -240,7 +240,7 @@ Number of expressions: 4 - expression 2 operands: lhs = Expression(3, Add), rhs = Expression(0, Sub) - expression 3 operands: lhs = Counter(2), rhs = Counter(1) Number of file 0 mappings: 5 -- Code(Counter(0)) at (prev + 85, 1) to (start + 1, 12) +- Code(Counter(0)) at (prev + 87, 1) to (start + 1, 12) - Code(Expression(0, Sub)) at (prev + 2, 14) to (start + 0, 16) = (c0 - (c1 + c2)) - Code(Counter(1)) at (prev + 1, 14) to (start + 0, 16) @@ -249,26 +249,26 @@ Number of file 0 mappings: 5 = ((c2 + c1) + (c0 - (c1 + c2))) Function name: async::m -Raw bytes (9): 0x[01, 01, 00, 01, 01, 5d, 01, 00, 19] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 5f, 01, 00, 19] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 93, 1) to (start + 0, 25) +- Code(Counter(0)) at (prev + 95, 1) to (start + 0, 25) Function name: async::m::{closure#0} (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 5d, 19, 00, 22] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 5f, 19, 00, 22] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 93, 25) to (start + 0, 34) +- Code(Zero) at (prev + 95, 25) to (start + 0, 34) Function name: async::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 5f, 01, 08, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 61, 01, 08, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 95, 1) to (start + 8, 2) +- Code(Counter(0)) at (prev + 97, 1) to (start + 8, 2) diff --git a/tests/coverage/async.coverage b/tests/coverage/async.coverage index 015e03d5165f..b4f6fc3a8a21 100644 --- a/tests/coverage/async.coverage +++ b/tests/coverage/async.coverage @@ -1,6 +1,8 @@ LL| |#![feature(coverage_attribute)] + LL| |#![feature(custom_inner_attributes)] // for #![rustfmt::skip] LL| |#![feature(noop_waker)] LL| |#![allow(unused_assignments, dead_code)] + LL| |#![rustfmt::skip] LL| |// edition: 2018 LL| |// compile-flags: -Copt-level=1 LL| | @@ -117,8 +119,7 @@ LL| | #[coverage(off)] LL| | pub fn block_on(mut future: F) -> F::Output { LL| | let mut future = pin!(future); - LL| | let waker = Waker::noop(); - LL| | let mut context = Context::from_waker(&waker); + LL| | let mut context = Context::from_waker(Waker::noop()); LL| | LL| | loop { LL| | if let Poll::Ready(val) = future.as_mut().poll(&mut context) { diff --git a/tests/coverage/async.rs b/tests/coverage/async.rs index abc9e5f7f646..6047cb79fb1b 100644 --- a/tests/coverage/async.rs +++ b/tests/coverage/async.rs @@ -1,6 +1,8 @@ #![feature(coverage_attribute)] +#![feature(custom_inner_attributes)] // for #![rustfmt::skip] #![feature(noop_waker)] #![allow(unused_assignments, dead_code)] +#![rustfmt::skip] // edition: 2018 // compile-flags: -Copt-level=1 @@ -110,8 +112,7 @@ mod executor { #[coverage(off)] pub fn block_on(mut future: F) -> F::Output { let mut future = pin!(future); - let waker = Waker::noop(); - let mut context = Context::from_waker(&waker); + let mut context = Context::from_waker(Waker::noop()); loop { if let Poll::Ready(val) = future.as_mut().poll(&mut context) { diff --git a/tests/coverage/async2.coverage b/tests/coverage/async2.coverage index acd83de94934..a69eefe72cbc 100644 --- a/tests/coverage/async2.coverage +++ b/tests/coverage/async2.coverage @@ -41,8 +41,7 @@ LL| | #[coverage(off)] LL| | pub fn block_on(mut future: F) -> F::Output { LL| | let mut future = pin!(future); - LL| | let waker = Waker::noop(); - LL| | let mut context = Context::from_waker(&waker); + LL| | let mut context = Context::from_waker(Waker::noop()); LL| | LL| | loop { LL| | if let Poll::Ready(val) = future.as_mut().poll(&mut context) { diff --git a/tests/coverage/async2.rs b/tests/coverage/async2.rs index 393573f7dc95..ae83f0103e64 100644 --- a/tests/coverage/async2.rs +++ b/tests/coverage/async2.rs @@ -39,8 +39,7 @@ mod executor { #[coverage(off)] pub fn block_on(mut future: F) -> F::Output { let mut future = pin!(future); - let waker = Waker::noop(); - let mut context = Context::from_waker(&waker); + let mut context = Context::from_waker(Waker::noop()); loop { if let Poll::Ready(val) = future.as_mut().poll(&mut context) { diff --git a/tests/coverage/async_block.coverage b/tests/coverage/async_block.coverage index 297397ca26c8..0e24b80124f4 100644 --- a/tests/coverage/async_block.coverage +++ b/tests/coverage/async_block.coverage @@ -24,8 +24,7 @@ LL| | #[coverage(off)] LL| | pub fn block_on(mut future: F) -> F::Output { LL| | let mut future = pin!(future); - LL| | let waker = Waker::noop(); - LL| | let mut context = Context::from_waker(&waker); + LL| | let mut context = Context::from_waker(Waker::noop()); LL| | LL| | loop { LL| | if let Poll::Ready(val) = future.as_mut().poll(&mut context) { diff --git a/tests/coverage/async_block.rs b/tests/coverage/async_block.rs index 9d8647bf1f20..f94bcfe31937 100644 --- a/tests/coverage/async_block.rs +++ b/tests/coverage/async_block.rs @@ -23,8 +23,7 @@ mod executor { #[coverage(off)] pub fn block_on(mut future: F) -> F::Output { let mut future = pin!(future); - let waker = Waker::noop(); - let mut context = Context::from_waker(&waker); + let mut context = Context::from_waker(Waker::noop()); loop { if let Poll::Ready(val) = future.as_mut().poll(&mut context) { diff --git a/tests/coverage/bench.cov-map b/tests/coverage/bench.cov-map new file mode 100644 index 000000000000..aa702a486818 --- /dev/null +++ b/tests/coverage/bench.cov-map @@ -0,0 +1,8 @@ +Function name: bench::my_bench +Raw bytes (9): 0x[01, 01, 00, 01, 01, 08, 01, 00, 27] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 8, 1) to (start + 0, 39) + diff --git a/tests/coverage/bench.coverage b/tests/coverage/bench.coverage new file mode 100644 index 000000000000..64945dc64150 --- /dev/null +++ b/tests/coverage/bench.coverage @@ -0,0 +1,9 @@ + LL| |#![feature(test)] + LL| |// edition: 2021 + LL| |// compile-flags: --test + LL| | + LL| |extern crate test; + LL| | + LL| |#[bench] + LL| 1|fn my_bench(_b: &mut test::Bencher) {} + diff --git a/tests/coverage/bench.rs b/tests/coverage/bench.rs new file mode 100644 index 000000000000..2dcd7355b2f7 --- /dev/null +++ b/tests/coverage/bench.rs @@ -0,0 +1,8 @@ +#![feature(test)] +// edition: 2021 +// compile-flags: --test + +extern crate test; + +#[bench] +fn my_bench(_b: &mut test::Bencher) {} diff --git a/tests/coverage/closure.cov-map b/tests/coverage/closure.cov-map index c5ac17600cd2..921ca6cf4e1a 100644 --- a/tests/coverage/closure.cov-map +++ b/tests/coverage/closure.cov-map @@ -1,12 +1,12 @@ Function name: closure::main -Raw bytes (128): 0x[01, 01, 02, 01, 05, 05, 02, 18, 01, 08, 01, 0f, 0d, 01, 16, 0e, 06, 0a, 01, 10, 05, 13, 0d, 01, 1a, 0e, 06, 0a, 01, 10, 05, 0c, 16, 01, 16, 05, 0d, 18, 01, 19, 09, 01, 1e, 01, 04, 09, 00, 29, 01, 01, 09, 00, 2d, 01, 01, 09, 00, 24, 01, 05, 09, 00, 24, 01, 02, 09, 00, 21, 01, 04, 09, 00, 21, 01, 04, 09, 00, 28, 01, 09, 09, 00, 32, 01, 04, 09, 00, 33, 01, 07, 09, 00, 4b, 01, 08, 09, 00, 48, 01, 0a, 09, 00, 47, 01, 08, 09, 00, 44, 01, 0a, 08, 00, 10, 05, 00, 11, 04, 06, 02, 04, 06, 00, 07, 07, 01, 05, 03, 02] +Raw bytes (128): 0x[01, 01, 02, 01, 05, 05, 02, 18, 01, 09, 01, 0f, 0d, 01, 16, 0e, 06, 0a, 01, 10, 05, 13, 0d, 01, 1a, 0e, 06, 0a, 01, 10, 05, 0c, 16, 01, 16, 05, 0d, 18, 01, 19, 09, 01, 1e, 01, 04, 09, 00, 29, 01, 01, 09, 00, 2d, 01, 01, 09, 00, 24, 01, 05, 09, 00, 24, 01, 02, 09, 00, 21, 01, 04, 09, 00, 21, 01, 04, 09, 00, 28, 01, 09, 09, 00, 32, 01, 04, 09, 00, 33, 01, 07, 09, 00, 4b, 01, 08, 09, 00, 48, 01, 0a, 09, 00, 47, 01, 08, 09, 00, 44, 01, 0a, 08, 00, 10, 05, 00, 11, 04, 06, 02, 04, 06, 00, 07, 07, 01, 05, 03, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 24 -- Code(Counter(0)) at (prev + 8, 1) to (start + 15, 13) +- Code(Counter(0)) at (prev + 9, 1) to (start + 15, 13) - Code(Counter(0)) at (prev + 22, 14) to (start + 6, 10) - Code(Counter(0)) at (prev + 16, 5) to (start + 19, 13) - Code(Counter(0)) at (prev + 26, 14) to (start + 6, 10) @@ -34,14 +34,14 @@ Number of file 0 mappings: 24 = (c1 + (c0 - c1)) Function name: closure::main::{closure#0} -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 27, 05, 02, 14, 05, 02, 15, 02, 0a, 02, 02, 0a, 00, 0b, 07, 01, 09, 01, 06] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 28, 05, 02, 14, 05, 02, 15, 02, 0a, 02, 02, 0a, 00, 0b, 07, 01, 09, 01, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 39, 5) to (start + 2, 20) +- Code(Counter(0)) at (prev + 40, 5) to (start + 2, 20) - Code(Counter(1)) at (prev + 2, 21) to (start + 2, 10) - Code(Expression(0, Sub)) at (prev + 2, 10) to (start + 0, 11) = (c0 - c1) @@ -49,46 +49,46 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: closure::main::{closure#10} (unused) -Raw bytes (10): 0x[01, 01, 00, 01, 00, 9a, 01, 07, 00, 21] +Raw bytes (10): 0x[01, 01, 00, 01, 00, 9b, 01, 07, 00, 21] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 154, 7) to (start + 0, 33) +- Code(Zero) at (prev + 155, 7) to (start + 0, 33) Function name: closure::main::{closure#11} (unused) -Raw bytes (10): 0x[01, 01, 00, 01, 00, 9e, 01, 07, 00, 21] +Raw bytes (10): 0x[01, 01, 00, 01, 00, 9f, 01, 07, 00, 21] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 158, 7) to (start + 0, 33) +- Code(Zero) at (prev + 159, 7) to (start + 0, 33) Function name: closure::main::{closure#12} (unused) -Raw bytes (10): 0x[01, 01, 00, 01, 00, a6, 01, 01, 00, 17] +Raw bytes (10): 0x[01, 01, 00, 01, 00, a7, 01, 01, 00, 17] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 166, 1) to (start + 0, 23) +- Code(Zero) at (prev + 167, 1) to (start + 0, 23) Function name: closure::main::{closure#13} (unused) -Raw bytes (10): 0x[01, 01, 00, 01, 00, ab, 01, 0d, 02, 0e] +Raw bytes (10): 0x[01, 01, 00, 01, 00, ac, 01, 0d, 02, 0e] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 171, 13) to (start + 2, 14) +- Code(Zero) at (prev + 172, 13) to (start + 2, 14) Function name: closure::main::{closure#14} -Raw bytes (29): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, b2, 01, 0d, 02, 1b, 05, 02, 1e, 00, 25, 02, 00, 2f, 00, 33, 07, 01, 0d, 00, 0e] +Raw bytes (29): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, b3, 01, 0d, 02, 1b, 05, 02, 1e, 00, 25, 02, 00, 2f, 00, 33, 07, 01, 0d, 00, 0e] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 178, 13) to (start + 2, 27) +- Code(Counter(0)) at (prev + 179, 13) to (start + 2, 27) - Code(Counter(1)) at (prev + 2, 30) to (start + 0, 37) - Code(Expression(0, Sub)) at (prev + 0, 47) to (start + 0, 51) = (c0 - c1) @@ -96,7 +96,7 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: closure::main::{closure#15} -Raw bytes (41): 0x[01, 01, 03, 05, 0a, 01, 05, 01, 05, 06, 01, ba, 01, 09, 00, 0a, 03, 01, 0d, 00, 15, 01, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 0a, 00, 2f, 00, 33, 03, 02, 09, 00, 0a] +Raw bytes (41): 0x[01, 01, 03, 05, 0a, 01, 05, 01, 05, 06, 01, bb, 01, 09, 00, 0a, 03, 01, 0d, 00, 15, 01, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 0a, 00, 2f, 00, 33, 03, 02, 09, 00, 0a] Number of files: 1 - file 0 => global file 1 Number of expressions: 3 @@ -104,7 +104,7 @@ Number of expressions: 3 - expression 1 operands: lhs = Counter(0), rhs = Counter(1) - expression 2 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 186, 9) to (start + 0, 10) +- Code(Counter(0)) at (prev + 187, 9) to (start + 0, 10) - Code(Expression(0, Add)) at (prev + 1, 13) to (start + 0, 21) = (c1 + (c0 - c1)) - Code(Counter(0)) at (prev + 1, 17) to (start + 1, 27) @@ -115,14 +115,14 @@ Number of file 0 mappings: 6 = (c1 + (c0 - c1)) Function name: closure::main::{closure#16} -Raw bytes (29): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, c4, 01, 0d, 02, 1b, 05, 02, 1e, 00, 25, 02, 00, 2f, 00, 33, 07, 01, 0d, 00, 0e] +Raw bytes (29): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, c5, 01, 0d, 02, 1b, 05, 02, 1e, 00, 25, 02, 00, 2f, 00, 33, 07, 01, 0d, 00, 0e] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 196, 13) to (start + 2, 27) +- Code(Counter(0)) at (prev + 197, 13) to (start + 2, 27) - Code(Counter(1)) at (prev + 2, 30) to (start + 0, 37) - Code(Expression(0, Sub)) at (prev + 0, 47) to (start + 0, 51) = (c0 - c1) @@ -130,7 +130,7 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: closure::main::{closure#17} -Raw bytes (41): 0x[01, 01, 03, 05, 0a, 01, 05, 01, 05, 06, 01, cc, 01, 09, 00, 0a, 03, 01, 0d, 00, 15, 01, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 0a, 00, 2f, 00, 33, 03, 02, 09, 00, 0a] +Raw bytes (41): 0x[01, 01, 03, 05, 0a, 01, 05, 01, 05, 06, 01, cd, 01, 09, 00, 0a, 03, 01, 0d, 00, 15, 01, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 0a, 00, 2f, 00, 33, 03, 02, 09, 00, 0a] Number of files: 1 - file 0 => global file 1 Number of expressions: 3 @@ -138,7 +138,7 @@ Number of expressions: 3 - expression 1 operands: lhs = Counter(0), rhs = Counter(1) - expression 2 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 204, 9) to (start + 0, 10) +- Code(Counter(0)) at (prev + 205, 9) to (start + 0, 10) - Code(Expression(0, Add)) at (prev + 1, 13) to (start + 0, 21) = (c1 + (c0 - c1)) - Code(Counter(0)) at (prev + 1, 17) to (start + 1, 27) @@ -149,14 +149,14 @@ Number of file 0 mappings: 6 = (c1 + (c0 - c1)) Function name: closure::main::{closure#18} -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 18, 0d, 02, 1c, 05, 02, 1d, 02, 12, 02, 02, 12, 00, 13, 07, 01, 11, 01, 0e] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 19, 0d, 02, 1c, 05, 02, 1d, 02, 12, 02, 02, 12, 00, 13, 07, 01, 11, 01, 0e] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 24, 13) to (start + 2, 28) +- Code(Counter(0)) at (prev + 25, 13) to (start + 2, 28) - Code(Counter(1)) at (prev + 2, 29) to (start + 2, 18) - Code(Expression(0, Sub)) at (prev + 2, 18) to (start + 0, 19) = (c0 - c1) @@ -164,14 +164,14 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: closure::main::{closure#19} -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 42, 0d, 02, 1c, 05, 02, 1d, 02, 12, 02, 02, 12, 00, 13, 07, 01, 11, 01, 0e] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 43, 0d, 02, 1c, 05, 02, 1d, 02, 12, 02, 02, 12, 00, 13, 07, 01, 11, 01, 0e] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 66, 13) to (start + 2, 28) +- Code(Counter(0)) at (prev + 67, 13) to (start + 2, 28) - Code(Counter(1)) at (prev + 2, 29) to (start + 2, 18) - Code(Expression(0, Sub)) at (prev + 2, 18) to (start + 0, 19) = (c0 - c1) @@ -179,14 +179,14 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: closure::main::{closure#1} -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 51, 05, 02, 14, 05, 02, 15, 02, 0a, 02, 02, 0a, 00, 0b, 07, 01, 09, 01, 06] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 52, 05, 02, 14, 05, 02, 15, 02, 0a, 02, 02, 0a, 00, 0b, 07, 01, 09, 01, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 81, 5) to (start + 2, 20) +- Code(Counter(0)) at (prev + 82, 5) to (start + 2, 20) - Code(Counter(1)) at (prev + 2, 21) to (start + 2, 10) - Code(Expression(0, Sub)) at (prev + 2, 10) to (start + 0, 11) = (c0 - c1) @@ -194,14 +194,14 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: closure::main::{closure#2} -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 67, 05, 02, 14, 05, 02, 15, 02, 0a, 02, 02, 0a, 00, 0b, 07, 01, 09, 01, 06] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 68, 05, 02, 14, 05, 02, 15, 02, 0a, 02, 02, 0a, 00, 0b, 07, 01, 09, 01, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 103, 5) to (start + 2, 20) +- Code(Counter(0)) at (prev + 104, 5) to (start + 2, 20) - Code(Counter(1)) at (prev + 2, 21) to (start + 2, 10) - Code(Expression(0, Sub)) at (prev + 2, 10) to (start + 0, 11) = (c0 - c1) @@ -209,61 +209,61 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: closure::main::{closure#3} (unused) -Raw bytes (25): 0x[01, 01, 00, 04, 00, 80, 01, 05, 01, 14, 00, 01, 15, 02, 0a, 00, 02, 0a, 00, 0b, 00, 01, 09, 01, 06] +Raw bytes (25): 0x[01, 01, 00, 04, 00, 81, 01, 05, 01, 14, 00, 01, 15, 02, 0a, 00, 02, 0a, 00, 0b, 00, 01, 09, 01, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 4 -- Code(Zero) at (prev + 128, 5) to (start + 1, 20) +- Code(Zero) at (prev + 129, 5) to (start + 1, 20) - Code(Zero) at (prev + 1, 21) to (start + 2, 10) - Code(Zero) at (prev + 2, 10) to (start + 0, 11) - Code(Zero) at (prev + 1, 9) to (start + 1, 6) Function name: closure::main::{closure#4} (unused) -Raw bytes (10): 0x[01, 01, 00, 01, 00, 88, 01, 35, 00, 43] +Raw bytes (10): 0x[01, 01, 00, 01, 00, 89, 01, 35, 00, 43] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 136, 53) to (start + 0, 67) +- Code(Zero) at (prev + 137, 53) to (start + 0, 67) Function name: closure::main::{closure#5} -Raw bytes (10): 0x[01, 01, 00, 01, 01, 8b, 01, 3d, 00, 4f] +Raw bytes (10): 0x[01, 01, 00, 01, 01, 8c, 01, 3d, 00, 4f] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 139, 61) to (start + 0, 79) +- Code(Counter(0)) at (prev + 140, 61) to (start + 0, 79) Function name: closure::main::{closure#6} -Raw bytes (10): 0x[01, 01, 00, 01, 01, 8c, 01, 41, 00, 57] +Raw bytes (10): 0x[01, 01, 00, 01, 01, 8d, 01, 41, 00, 57] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 140, 65) to (start + 0, 87) +- Code(Counter(0)) at (prev + 141, 65) to (start + 0, 87) Function name: closure::main::{closure#7} (unused) -Raw bytes (10): 0x[01, 01, 00, 01, 00, 8d, 01, 3b, 00, 51] +Raw bytes (10): 0x[01, 01, 00, 01, 00, 8e, 01, 3b, 00, 51] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 141, 59) to (start + 0, 81) +- Code(Zero) at (prev + 142, 59) to (start + 0, 81) Function name: closure::main::{closure#8} (unused) -Raw bytes (10): 0x[01, 01, 00, 01, 00, 92, 01, 3b, 00, 55] +Raw bytes (10): 0x[01, 01, 00, 01, 00, 93, 01, 3b, 00, 55] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 146, 59) to (start + 0, 85) +- Code(Zero) at (prev + 147, 59) to (start + 0, 85) Function name: closure::main::{closure#9} (unused) -Raw bytes (10): 0x[01, 01, 00, 01, 00, 94, 01, 38, 02, 06] +Raw bytes (10): 0x[01, 01, 00, 01, 00, 95, 01, 38, 02, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 148, 56) to (start + 2, 6) +- Code(Zero) at (prev + 149, 56) to (start + 2, 6) diff --git a/tests/coverage/closure.coverage b/tests/coverage/closure.coverage index 67014f792c81..58224eeaf626 100644 --- a/tests/coverage/closure.coverage +++ b/tests/coverage/closure.coverage @@ -5,6 +5,7 @@ LL| |// `rustc_middle/mir/mono.rs`, but those hacks were later cleaned up by LL| |// . LL| | + LL| |#[rustfmt::skip] LL| 1|fn main() { LL| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure LL| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from diff --git a/tests/coverage/closure.rs b/tests/coverage/closure.rs index 16a2c4e33bd4..4be78062f3f5 100644 --- a/tests/coverage/closure.rs +++ b/tests/coverage/closure.rs @@ -5,6 +5,7 @@ // `rustc_middle/mir/mono.rs`, but those hacks were later cleaned up by // . +#[rustfmt::skip] fn main() { // Initialize test constants in a way that cannot be determined at compile time, to ensure // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from diff --git a/tests/coverage/closure_bug.cov-map b/tests/coverage/closure_bug.cov-map index 90eeb1a6686f..160b348bd632 100644 --- a/tests/coverage/closure_bug.cov-map +++ b/tests/coverage/closure_bug.cov-map @@ -1,5 +1,5 @@ Function name: closure_bug::main -Raw bytes (201): 0x[01, 01, 26, 01, 05, 05, 02, 05, 02, 97, 01, 09, 05, 02, 09, 92, 01, 97, 01, 09, 05, 02, 09, 92, 01, 97, 01, 09, 05, 02, 8f, 01, 0d, 09, 92, 01, 97, 01, 09, 05, 02, 0d, 8a, 01, 8f, 01, 0d, 09, 92, 01, 97, 01, 09, 05, 02, 0d, 8a, 01, 8f, 01, 0d, 09, 92, 01, 97, 01, 09, 05, 02, 87, 01, 11, 0d, 8a, 01, 8f, 01, 0d, 09, 92, 01, 97, 01, 09, 05, 02, 11, 82, 01, 87, 01, 11, 0d, 8a, 01, 8f, 01, 0d, 09, 92, 01, 97, 01, 09, 05, 02, 11, 01, 06, 01, 03, 0a, 01, 09, 05, 01, 0e, 05, 01, 0f, 00, 17, 02, 00, 17, 00, 18, 97, 01, 02, 09, 00, 0a, 97, 01, 06, 05, 01, 0e, 09, 01, 0f, 00, 17, 92, 01, 00, 17, 00, 18, 8f, 01, 02, 09, 00, 0a, 8f, 01, 06, 05, 01, 0e, 0d, 01, 0f, 00, 17, 8a, 01, 00, 17, 00, 18, 87, 01, 02, 09, 00, 0a, 87, 01, 06, 05, 01, 0e, 11, 01, 0f, 00, 17, 82, 01, 00, 17, 00, 18, 7f, 01, 01, 00, 02] +Raw bytes (201): 0x[01, 01, 26, 01, 05, 05, 02, 05, 02, 97, 01, 09, 05, 02, 09, 92, 01, 97, 01, 09, 05, 02, 09, 92, 01, 97, 01, 09, 05, 02, 8f, 01, 0d, 09, 92, 01, 97, 01, 09, 05, 02, 0d, 8a, 01, 8f, 01, 0d, 09, 92, 01, 97, 01, 09, 05, 02, 0d, 8a, 01, 8f, 01, 0d, 09, 92, 01, 97, 01, 09, 05, 02, 87, 01, 11, 0d, 8a, 01, 8f, 01, 0d, 09, 92, 01, 97, 01, 09, 05, 02, 11, 82, 01, 87, 01, 11, 0d, 8a, 01, 8f, 01, 0d, 09, 92, 01, 97, 01, 09, 05, 02, 11, 01, 07, 01, 03, 0a, 01, 09, 05, 01, 0e, 05, 01, 0f, 00, 17, 02, 00, 17, 00, 18, 97, 01, 02, 09, 00, 0a, 97, 01, 06, 05, 01, 0e, 09, 01, 0f, 00, 17, 92, 01, 00, 17, 00, 18, 8f, 01, 02, 09, 00, 0a, 8f, 01, 06, 05, 01, 0e, 0d, 01, 0f, 00, 17, 8a, 01, 00, 17, 00, 18, 87, 01, 02, 09, 00, 0a, 87, 01, 06, 05, 01, 0e, 11, 01, 0f, 00, 17, 82, 01, 00, 17, 00, 18, 7f, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 38 @@ -42,7 +42,7 @@ Number of expressions: 38 - expression 36 operands: lhs = Expression(37, Add), rhs = Counter(2) - expression 37 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 17 -- Code(Counter(0)) at (prev + 6, 1) to (start + 3, 10) +- Code(Counter(0)) at (prev + 7, 1) to (start + 3, 10) - Code(Counter(0)) at (prev + 9, 5) to (start + 1, 14) - Code(Counter(1)) at (prev + 1, 15) to (start + 0, 23) - Code(Expression(0, Sub)) at (prev + 0, 23) to (start + 0, 24) @@ -72,14 +72,14 @@ Number of file 0 mappings: 17 = (c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) Function name: closure_bug::main::{closure#0} -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 0d, 09, 00, 12, 05, 00, 15, 00, 19, 02, 00, 23, 00, 28, 07, 00, 29, 00, 2a] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 0e, 09, 00, 12, 05, 00, 15, 00, 19, 02, 00, 23, 00, 28, 07, 00, 29, 00, 2a] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 13, 9) to (start + 0, 18) +- Code(Counter(0)) at (prev + 14, 9) to (start + 0, 18) - Code(Counter(1)) at (prev + 0, 21) to (start + 0, 25) - Code(Expression(0, Sub)) at (prev + 0, 35) to (start + 0, 40) = (c0 - c1) @@ -87,14 +87,14 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: closure_bug::main::{closure#1} -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 16, 09, 00, 12, 05, 00, 15, 00, 19, 02, 00, 23, 00, 28, 07, 00, 29, 00, 2a] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 17, 09, 00, 12, 05, 00, 15, 00, 19, 02, 00, 23, 00, 28, 07, 00, 29, 00, 2a] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 22, 9) to (start + 0, 18) +- Code(Counter(0)) at (prev + 23, 9) to (start + 0, 18) - Code(Counter(1)) at (prev + 0, 21) to (start + 0, 25) - Code(Expression(0, Sub)) at (prev + 0, 35) to (start + 0, 40) = (c0 - c1) @@ -102,14 +102,14 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: closure_bug::main::{closure#2} -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 1f, 09, 00, 12, 05, 00, 15, 00, 19, 02, 00, 23, 00, 28, 07, 00, 29, 00, 2a] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 20, 09, 00, 12, 05, 00, 15, 00, 19, 02, 00, 23, 00, 28, 07, 00, 29, 00, 2a] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 31, 9) to (start + 0, 18) +- Code(Counter(0)) at (prev + 32, 9) to (start + 0, 18) - Code(Counter(1)) at (prev + 0, 21) to (start + 0, 25) - Code(Expression(0, Sub)) at (prev + 0, 35) to (start + 0, 40) = (c0 - c1) @@ -117,14 +117,14 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: closure_bug::main::{closure#3} -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 28, 09, 00, 12, 05, 00, 15, 00, 19, 02, 00, 23, 00, 28, 07, 00, 29, 00, 2a] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 29, 09, 00, 12, 05, 00, 15, 00, 19, 02, 00, 23, 00, 28, 07, 00, 29, 00, 2a] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 40, 9) to (start + 0, 18) +- Code(Counter(0)) at (prev + 41, 9) to (start + 0, 18) - Code(Counter(1)) at (prev + 0, 21) to (start + 0, 25) - Code(Expression(0, Sub)) at (prev + 0, 35) to (start + 0, 40) = (c0 - c1) diff --git a/tests/coverage/closure_bug.coverage b/tests/coverage/closure_bug.coverage index f3299834bce1..3bf19f28072f 100644 --- a/tests/coverage/closure_bug.coverage +++ b/tests/coverage/closure_bug.coverage @@ -3,6 +3,7 @@ LL| |// the coverage report. However, an unstable sort was causing them to be treated LL| |// inconsistently when preparing coverage spans. LL| | + LL| |#[rustfmt::skip] LL| 1|fn main() { LL| 1| let truthy = std::env::args().len() == 1; LL| 1| diff --git a/tests/coverage/closure_bug.rs b/tests/coverage/closure_bug.rs index 739bc5f0b51c..6c94b90c656e 100644 --- a/tests/coverage/closure_bug.rs +++ b/tests/coverage/closure_bug.rs @@ -3,6 +3,7 @@ // the coverage report. However, an unstable sort was causing them to be treated // inconsistently when preparing coverage spans. +#[rustfmt::skip] fn main() { let truthy = std::env::args().len() == 1; diff --git a/tests/coverage/closure_macro.cov-map b/tests/coverage/closure_macro.cov-map index b02c7e2e4c66..323d6e3c8aa5 100644 --- a/tests/coverage/closure_macro.cov-map +++ b/tests/coverage/closure_macro.cov-map @@ -1,20 +1,20 @@ Function name: closure_macro::load_configuration_files -Raw bytes (9): 0x[01, 01, 00, 01, 01, 1d, 01, 02, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 1e, 01, 02, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 29, 1) to (start + 2, 2) +- Code(Counter(0)) at (prev + 30, 1) to (start + 2, 2) Function name: closure_macro::main -Raw bytes (43): 0x[01, 01, 02, 01, 05, 05, 02, 07, 01, 21, 01, 01, 21, 02, 02, 09, 00, 0f, 05, 00, 12, 00, 13, 02, 00, 12, 00, 13, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 07, 03, 01, 00, 02] +Raw bytes (43): 0x[01, 01, 02, 01, 05, 05, 02, 07, 01, 22, 01, 01, 21, 02, 02, 09, 00, 0f, 05, 00, 12, 00, 13, 02, 00, 12, 00, 13, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 07, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 7 -- Code(Counter(0)) at (prev + 33, 1) to (start + 1, 33) +- Code(Counter(0)) at (prev + 34, 1) to (start + 1, 33) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15) = (c0 - c1) - Code(Counter(1)) at (prev + 0, 18) to (start + 0, 19) @@ -27,10 +27,10 @@ Number of file 0 mappings: 7 = (c1 + (c0 - c1)) Function name: closure_macro::main::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 23, 12, 00, 54] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 24, 12, 00, 54] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 35, 18) to (start + 0, 84) +- Code(Counter(0)) at (prev + 36, 18) to (start + 0, 84) diff --git a/tests/coverage/closure_macro.coverage b/tests/coverage/closure_macro.coverage index 0f2c917e0900..a6eeb79a71c8 100644 --- a/tests/coverage/closure_macro.coverage +++ b/tests/coverage/closure_macro.coverage @@ -14,7 +14,8 @@ LL| | LL| |macro_rules! on_error { LL| | ($value:expr, $error_message:expr) => { - LL| | $value.or_else(|e| { // FIXME(85000): no coverage in closure macros + LL| | $value.or_else(|e| { + LL| | // FIXME(85000): no coverage in closure macros LL| | let message = format!($error_message, e); LL| | if message.len() > 0 { LL| | println!("{}", message); diff --git a/tests/coverage/closure_macro.rs b/tests/coverage/closure_macro.rs index 9b289141c2e5..c3ef91678809 100644 --- a/tests/coverage/closure_macro.rs +++ b/tests/coverage/closure_macro.rs @@ -14,7 +14,8 @@ macro_rules! bail { macro_rules! on_error { ($value:expr, $error_message:expr) => { - $value.or_else(|e| { // FIXME(85000): no coverage in closure macros + $value.or_else(|e| { + // FIXME(85000): no coverage in closure macros let message = format!($error_message, e); if message.len() > 0 { println!("{}", message); diff --git a/tests/coverage/closure_macro_async.cov-map b/tests/coverage/closure_macro_async.cov-map index 14b1525ca0e6..5f5e06442789 100644 --- a/tests/coverage/closure_macro_async.cov-map +++ b/tests/coverage/closure_macro_async.cov-map @@ -1,28 +1,28 @@ Function name: closure_macro_async::load_configuration_files -Raw bytes (9): 0x[01, 01, 00, 01, 01, 1e, 01, 02, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 1f, 01, 02, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 30, 1) to (start + 2, 2) +- Code(Counter(0)) at (prev + 31, 1) to (start + 2, 2) Function name: closure_macro_async::test -Raw bytes (9): 0x[01, 01, 00, 01, 01, 22, 01, 00, 2b] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 23, 01, 00, 2b] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 34, 1) to (start + 0, 43) +- Code(Counter(0)) at (prev + 35, 1) to (start + 0, 43) Function name: closure_macro_async::test::{closure#0} -Raw bytes (43): 0x[01, 01, 02, 01, 05, 05, 02, 07, 01, 22, 2b, 01, 21, 02, 02, 09, 00, 0f, 05, 00, 12, 00, 13, 02, 00, 12, 00, 13, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 07, 03, 01, 00, 02] +Raw bytes (43): 0x[01, 01, 02, 01, 05, 05, 02, 07, 01, 23, 2b, 01, 21, 02, 02, 09, 00, 0f, 05, 00, 12, 00, 13, 02, 00, 12, 00, 13, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 07, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 7 -- Code(Counter(0)) at (prev + 34, 43) to (start + 1, 33) +- Code(Counter(0)) at (prev + 35, 43) to (start + 1, 33) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15) = (c0 - c1) - Code(Counter(1)) at (prev + 0, 18) to (start + 0, 19) @@ -35,10 +35,10 @@ Number of file 0 mappings: 7 = (c1 + (c0 - c1)) Function name: closure_macro_async::test::{closure#0}::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 24, 12, 00, 54] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 25, 12, 00, 54] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 36, 18) to (start + 0, 84) +- Code(Counter(0)) at (prev + 37, 18) to (start + 0, 84) diff --git a/tests/coverage/closure_macro_async.coverage b/tests/coverage/closure_macro_async.coverage index 2c9bd4ac97a1..d67c2ed524b3 100644 --- a/tests/coverage/closure_macro_async.coverage +++ b/tests/coverage/closure_macro_async.coverage @@ -15,7 +15,8 @@ LL| | LL| |macro_rules! on_error { LL| | ($value:expr, $error_message:expr) => { - LL| | $value.or_else(|e| { // FIXME(85000): no coverage in closure macros + LL| | $value.or_else(|e| { + LL| | // FIXME(85000): no coverage in closure macros LL| | let message = format!($error_message, e); LL| | if message.len() > 0 { LL| | println!("{}", message); @@ -54,8 +55,7 @@ LL| | #[coverage(off)] LL| | pub fn block_on(mut future: F) -> F::Output { LL| | let mut future = pin!(future); - LL| | let waker = Waker::noop(); - LL| | let mut context = Context::from_waker(&waker); + LL| | let mut context = Context::from_waker(Waker::noop()); LL| | LL| | loop { LL| | if let Poll::Ready(val) = future.as_mut().poll(&mut context) { diff --git a/tests/coverage/closure_macro_async.rs b/tests/coverage/closure_macro_async.rs index a7f0cabb4c23..116cb72b0f37 100644 --- a/tests/coverage/closure_macro_async.rs +++ b/tests/coverage/closure_macro_async.rs @@ -15,7 +15,8 @@ macro_rules! bail { macro_rules! on_error { ($value:expr, $error_message:expr) => { - $value.or_else(|e| { // FIXME(85000): no coverage in closure macros + $value.or_else(|e| { + // FIXME(85000): no coverage in closure macros let message = format!($error_message, e); if message.len() > 0 { println!("{}", message); @@ -53,8 +54,7 @@ mod executor { #[coverage(off)] pub fn block_on(mut future: F) -> F::Output { let mut future = pin!(future); - let waker = Waker::noop(); - let mut context = Context::from_waker(&waker); + let mut context = Context::from_waker(Waker::noop()); loop { if let Poll::Ready(val) = future.as_mut().poll(&mut context) { diff --git a/tests/coverage/conditions.cov-map b/tests/coverage/conditions.cov-map index cfee55ed31a4..a6a427aca007 100644 --- a/tests/coverage/conditions.cov-map +++ b/tests/coverage/conditions.cov-map @@ -1,5 +1,5 @@ Function name: conditions::main -Raw bytes (784): 0x[01, 01, 8e, 01, 09, 33, 37, 41, 3b, 3d, 35, 39, 05, 00, b7, 04, 09, 05, 00, 0d, 35, 26, 39, 0d, 35, 3b, 3d, 35, 39, 37, 41, 3b, 3d, 35, 39, b2, 04, 0d, b7, 04, 09, 05, 00, 45, 00, 83, 01, 49, 45, 00, 7e, 31, 83, 01, 49, 45, 00, 7a, 4d, 7e, 31, 83, 01, 49, 45, 00, 76, 51, 7a, 4d, 7e, 31, 83, 01, 49, 45, 00, a7, 01, 55, 4d, 51, a3, 01, 59, a7, 01, 55, 4d, 51, 49, 9f, 01, a3, 01, 59, a7, 01, 55, 4d, 51, 61, 00, e3, 01, 65, 61, 00, de, 01, 2d, e3, 01, 65, 61, 00, da, 01, 69, de, 01, 2d, e3, 01, 65, 61, 00, d6, 01, 6d, da, 01, 69, de, 01, 2d, e3, 01, 65, 61, 00, 8b, 02, 71, 69, 6d, 87, 02, 75, 8b, 02, 71, 69, 6d, ff, 01, 00, 65, 83, 02, 87, 02, 75, 8b, 02, 71, 69, 6d, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, 79, 00, d7, 02, 7d, 79, 00, d2, 02, 29, d7, 02, 7d, 79, 00, ce, 02, 81, 01, d2, 02, 29, d7, 02, 7d, 79, 00, ca, 02, 85, 01, ce, 02, 81, 01, d2, 02, 29, d7, 02, 7d, 79, 00, f3, 03, 89, 01, 81, 01, 85, 01, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, 11, 93, 04, 97, 04, 21, 9b, 04, 1d, 15, 19, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, e7, 03, 11, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, e2, 03, 25, e7, 03, 11, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, de, 03, 15, e2, 03, 25, e7, 03, 11, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, da, 03, 19, de, 03, 15, e2, 03, 25, e7, 03, 11, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, 9b, 04, 1d, 15, 19, 97, 04, 21, 9b, 04, 1d, 15, 19, 8f, 04, 9f, 04, 11, 93, 04, 97, 04, 21, 9b, 04, 1d, 15, 19, a3, 04, ae, 04, a7, 04, 31, ab, 04, 2d, 25, 29, b2, 04, 0d, b7, 04, 09, 05, 00, 44, 01, 03, 01, 02, 0c, 05, 02, 0d, 02, 06, 00, 02, 06, 00, 07, 03, 03, 09, 00, 0a, b7, 04, 00, 10, 00, 1d, 09, 01, 09, 01, 0a, b2, 04, 02, 0f, 00, 1c, 0d, 01, 0c, 00, 19, 26, 00, 1d, 00, 2a, 22, 00, 2e, 00, 3c, 37, 00, 3d, 02, 0a, 41, 02, 0a, 00, 0b, 33, 01, 09, 01, 12, ae, 04, 03, 09, 00, 0f, 03, 03, 09, 01, 0c, 45, 01, 0d, 02, 06, 00, 02, 06, 00, 07, 83, 01, 02, 08, 00, 15, 49, 00, 16, 02, 06, 7e, 02, 0f, 00, 1c, 7a, 01, 0c, 00, 19, 76, 00, 1d, 00, 2a, 72, 00, 2e, 00, 3c, a3, 01, 00, 3d, 02, 0a, 59, 02, 0a, 00, 0b, 9f, 01, 01, 09, 00, 17, 31, 02, 09, 00, 0f, 9b, 01, 03, 08, 00, 0c, 5d, 01, 0d, 01, 10, 61, 01, 11, 02, 0a, 00, 02, 0a, 00, 0b, e3, 01, 02, 0c, 00, 19, 65, 00, 1a, 02, 0a, de, 01, 03, 11, 00, 1e, da, 01, 01, 10, 00, 1d, d6, 01, 00, 21, 00, 2e, d2, 01, 00, 32, 00, 40, 87, 02, 00, 41, 02, 0e, 75, 02, 0e, 00, 0f, 83, 02, 01, 0d, 00, 1b, 2d, 02, 0d, 00, 13, 00, 02, 06, 00, 07, fb, 01, 02, 09, 01, 0c, 79, 01, 0d, 02, 06, 00, 02, 06, 00, 07, e7, 03, 02, 09, 00, 0a, d7, 02, 00, 10, 00, 1d, 7d, 00, 1e, 02, 06, d2, 02, 02, 0f, 00, 1c, ce, 02, 01, 0c, 00, 19, ca, 02, 00, 1d, 00, 2a, c6, 02, 00, 2e, 00, 3c, ef, 03, 00, 3d, 02, 0a, 8d, 01, 02, 0a, 00, 0b, eb, 03, 01, 09, 00, 17, 29, 02, 0d, 02, 0f, 8f, 04, 05, 09, 00, 0a, e7, 03, 00, 10, 00, 1d, 11, 00, 1e, 02, 06, e2, 03, 02, 0f, 00, 1c, de, 03, 01, 0c, 00, 19, da, 03, 00, 1d, 00, 2a, d6, 03, 00, 2e, 00, 3c, 97, 04, 00, 3d, 02, 0a, 21, 02, 0a, 00, 0b, 93, 04, 01, 09, 00, 17, 25, 02, 09, 00, 0f, 8b, 04, 02, 01, 00, 02] +Raw bytes (784): 0x[01, 01, 8e, 01, 09, 33, 37, 41, 3b, 3d, 35, 39, 05, 00, b7, 04, 09, 05, 00, 0d, 35, 26, 39, 0d, 35, 3b, 3d, 35, 39, 37, 41, 3b, 3d, 35, 39, b2, 04, 0d, b7, 04, 09, 05, 00, 45, 00, 83, 01, 49, 45, 00, 7e, 31, 83, 01, 49, 45, 00, 7a, 4d, 7e, 31, 83, 01, 49, 45, 00, 76, 51, 7a, 4d, 7e, 31, 83, 01, 49, 45, 00, a7, 01, 55, 4d, 51, a3, 01, 59, a7, 01, 55, 4d, 51, 49, 9f, 01, a3, 01, 59, a7, 01, 55, 4d, 51, 61, 00, e3, 01, 65, 61, 00, de, 01, 2d, e3, 01, 65, 61, 00, da, 01, 69, de, 01, 2d, e3, 01, 65, 61, 00, d6, 01, 6d, da, 01, 69, de, 01, 2d, e3, 01, 65, 61, 00, 8b, 02, 71, 69, 6d, 87, 02, 75, 8b, 02, 71, 69, 6d, ff, 01, 00, 65, 83, 02, 87, 02, 75, 8b, 02, 71, 69, 6d, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, 79, 00, d7, 02, 7d, 79, 00, d2, 02, 29, d7, 02, 7d, 79, 00, ce, 02, 81, 01, d2, 02, 29, d7, 02, 7d, 79, 00, ca, 02, 85, 01, ce, 02, 81, 01, d2, 02, 29, d7, 02, 7d, 79, 00, f3, 03, 89, 01, 81, 01, 85, 01, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, 11, 93, 04, 97, 04, 21, 9b, 04, 1d, 15, 19, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, e7, 03, 11, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, e2, 03, 25, e7, 03, 11, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, de, 03, 15, e2, 03, 25, e7, 03, 11, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, da, 03, 19, de, 03, 15, e2, 03, 25, e7, 03, 11, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, 9b, 04, 1d, 15, 19, 97, 04, 21, 9b, 04, 1d, 15, 19, 8f, 04, 9f, 04, 11, 93, 04, 97, 04, 21, 9b, 04, 1d, 15, 19, a3, 04, ae, 04, a7, 04, 31, ab, 04, 2d, 25, 29, b2, 04, 0d, b7, 04, 09, 05, 00, 44, 01, 03, 01, 02, 0c, 05, 02, 0d, 02, 06, 00, 02, 06, 00, 07, 03, 03, 09, 00, 0a, b7, 04, 00, 10, 00, 1d, 09, 01, 09, 01, 0a, b2, 04, 02, 0f, 00, 1c, 0d, 01, 0c, 00, 19, 26, 00, 1d, 00, 2a, 22, 00, 2e, 00, 3c, 37, 00, 3d, 02, 0a, 41, 02, 0a, 00, 0b, 33, 01, 09, 01, 12, ae, 04, 03, 09, 00, 0f, 03, 03, 09, 01, 0c, 45, 01, 0d, 02, 06, 00, 02, 06, 00, 07, 83, 01, 02, 08, 00, 15, 49, 00, 16, 02, 06, 7e, 02, 0f, 00, 1c, 7a, 01, 0c, 00, 19, 76, 00, 1d, 00, 2a, 72, 00, 2e, 00, 3c, a3, 01, 00, 3d, 02, 0a, 59, 02, 0a, 00, 0b, 9f, 01, 01, 09, 00, 17, 31, 02, 09, 00, 0f, 9b, 01, 03, 08, 00, 0c, 5d, 01, 0d, 01, 10, 61, 01, 11, 02, 0a, 00, 02, 0a, 00, 0b, e3, 01, 02, 0c, 00, 19, 65, 00, 1a, 02, 0a, de, 01, 04, 11, 00, 1e, da, 01, 01, 10, 00, 1d, d6, 01, 00, 21, 00, 2e, d2, 01, 00, 32, 00, 40, 87, 02, 00, 41, 02, 0e, 75, 02, 0e, 00, 0f, 83, 02, 01, 0d, 00, 1b, 2d, 02, 0d, 00, 13, 00, 02, 06, 00, 07, fb, 01, 02, 09, 01, 0c, 79, 01, 0d, 02, 06, 00, 02, 06, 00, 07, e7, 03, 02, 09, 00, 0a, d7, 02, 00, 10, 00, 1d, 7d, 00, 1e, 02, 06, d2, 02, 02, 0f, 00, 1c, ce, 02, 01, 0c, 00, 19, ca, 02, 00, 1d, 00, 2a, c6, 02, 00, 2e, 00, 3c, ef, 03, 00, 3d, 02, 0a, 8d, 01, 02, 0a, 00, 0b, eb, 03, 01, 09, 00, 17, 29, 02, 0d, 02, 0f, 8f, 04, 05, 09, 00, 0a, e7, 03, 00, 10, 00, 1d, 11, 00, 1e, 02, 06, e2, 03, 02, 0f, 00, 1c, de, 03, 01, 0c, 00, 19, da, 03, 00, 1d, 00, 2a, d6, 03, 00, 2e, 00, 3c, 97, 04, 00, 3d, 02, 0a, 21, 02, 0a, 00, 0b, 93, 04, 01, 09, 00, 17, 25, 02, 09, 00, 0f, 8b, 04, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 142 @@ -197,7 +197,7 @@ Number of file 0 mappings: 68 - Code(Expression(56, Add)) at (prev + 2, 12) to (start + 0, 25) = (c24 + Zero) - Code(Counter(25)) at (prev + 0, 26) to (start + 2, 10) -- Code(Expression(55, Sub)) at (prev + 3, 17) to (start + 0, 30) +- Code(Expression(55, Sub)) at (prev + 4, 17) to (start + 0, 30) = ((c24 + Zero) - c25) - Code(Expression(54, Sub)) at (prev + 1, 16) to (start + 0, 29) = (((c24 + Zero) - c25) - c11) diff --git a/tests/coverage/conditions.coverage b/tests/coverage/conditions.coverage index 473335ff641a..48516217592e 100644 --- a/tests/coverage/conditions.coverage +++ b/tests/coverage/conditions.coverage @@ -49,6 +49,7 @@ LL| 1| if countdown > 7 { LL| 1| countdown -= 4; LL| 1| } + LL| | // LL| 0| else if countdown > 2 { LL| 0| if countdown < 1 || countdown > 5 || countdown != 9 { LL| 0| countdown = 0; diff --git a/tests/coverage/conditions.rs b/tests/coverage/conditions.rs index fa7f2a116c21..e18e7191e612 100644 --- a/tests/coverage/conditions.rs +++ b/tests/coverage/conditions.rs @@ -45,6 +45,7 @@ fn main() { if countdown > 7 { countdown -= 4; } + // else if countdown > 2 { if countdown < 1 || countdown > 5 || countdown != 9 { countdown = 0; diff --git a/tests/coverage/coroutine.cov-map b/tests/coverage/coroutine.cov-map index 8dd03acc2f4d..ef9faab590b3 100644 --- a/tests/coverage/coroutine.cov-map +++ b/tests/coverage/coroutine.cov-map @@ -1,5 +1,5 @@ Function name: coroutine::get_u32 -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 0b, 01, 01, 0b, 05, 01, 0e, 00, 13, 02, 00, 1d, 00, 3c, 07, 01, 01, 00, 02] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 0b, 01, 01, 0b, 05, 02, 09, 00, 0e, 02, 02, 09, 00, 28, 07, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 @@ -7,14 +7,14 @@ Number of expressions: 2 - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 11, 1) to (start + 1, 11) -- Code(Counter(1)) at (prev + 1, 14) to (start + 0, 19) -- Code(Expression(0, Sub)) at (prev + 0, 29) to (start + 0, 60) +- Code(Counter(1)) at (prev + 2, 9) to (start + 0, 14) +- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 40) = (c0 - c1) -- Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) +- Code(Expression(1, Add)) at (prev + 2, 1) to (start + 0, 2) = (c1 + (c0 - c1)) Function name: coroutine::main -Raw bytes (65): 0x[01, 01, 08, 07, 0d, 05, 09, 11, 15, 1e, 19, 11, 15, 15, 19, 1e, 19, 11, 15, 09, 01, 0f, 01, 02, 16, 01, 07, 0b, 00, 2e, 11, 01, 2b, 00, 2d, 03, 01, 0e, 00, 35, 11, 02, 0b, 00, 2e, 1e, 01, 22, 00, 27, 1a, 00, 2c, 00, 2e, 17, 01, 0e, 00, 35, 1a, 02, 01, 00, 02] +Raw bytes (65): 0x[01, 01, 08, 07, 0d, 05, 09, 11, 15, 1e, 19, 11, 15, 15, 19, 1e, 19, 11, 15, 09, 01, 13, 01, 02, 16, 01, 07, 0b, 00, 2e, 11, 01, 2b, 00, 2d, 03, 01, 0e, 00, 35, 11, 02, 0b, 00, 2e, 1e, 01, 22, 00, 27, 1a, 00, 2c, 00, 2e, 17, 01, 0e, 00, 35, 1a, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 8 @@ -27,7 +27,7 @@ Number of expressions: 8 - expression 6 operands: lhs = Expression(7, Sub), rhs = Counter(6) - expression 7 operands: lhs = Counter(4), rhs = Counter(5) Number of file 0 mappings: 9 -- Code(Counter(0)) at (prev + 15, 1) to (start + 2, 22) +- Code(Counter(0)) at (prev + 19, 1) to (start + 2, 22) - Code(Counter(0)) at (prev + 7, 11) to (start + 0, 46) - Code(Counter(4)) at (prev + 1, 43) to (start + 0, 45) - Code(Expression(0, Add)) at (prev + 1, 14) to (start + 0, 53) @@ -43,11 +43,11 @@ Number of file 0 mappings: 9 = ((c4 - c5) - c6) Function name: coroutine::main::{closure#0} -Raw bytes (14): 0x[01, 01, 00, 02, 01, 11, 1c, 01, 1f, 05, 02, 10, 01, 06] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 15, 1c, 01, 1f, 05, 02, 10, 01, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 17, 28) to (start + 1, 31) +- Code(Counter(0)) at (prev + 21, 28) to (start + 1, 31) - Code(Counter(1)) at (prev + 2, 16) to (start + 1, 6) diff --git a/tests/coverage/coroutine.coverage b/tests/coverage/coroutine.coverage index 3a9791a0dbd8..bd3d4e468801 100644 --- a/tests/coverage/coroutine.coverage +++ b/tests/coverage/coroutine.coverage @@ -9,8 +9,11 @@ LL| |// drop all `Counter` `Coverage` statements from a MIR. `simplify.rs` has logic LL| |// to handle this condition, and still report dead block coverage. LL| 1|fn get_u32(val: bool) -> Result { - LL| 1| if val { Ok(1) } else { Err(String::from("some error")) } - ^0 + LL| 1| if val { + LL| 1| Ok(1) + LL| | } else { + LL| 0| Err(String::from("some error")) + LL| | } LL| 1|} LL| | LL| 1|fn main() { diff --git a/tests/coverage/coroutine.rs b/tests/coverage/coroutine.rs index 86d19af6f4f0..2aa689466fc3 100644 --- a/tests/coverage/coroutine.rs +++ b/tests/coverage/coroutine.rs @@ -9,7 +9,11 @@ use std::pin::Pin; // drop all `Counter` `Coverage` statements from a MIR. `simplify.rs` has logic // to handle this condition, and still report dead block coverage. fn get_u32(val: bool) -> Result { - if val { Ok(1) } else { Err(String::from("some error")) } + if val { + Ok(1) + } else { + Err(String::from("some error")) + } } fn main() { diff --git a/tests/coverage/fn_sig_into_try.cov-map b/tests/coverage/fn_sig_into_try.cov-map index 6e26c61aac9f..c3969f8ce999 100644 --- a/tests/coverage/fn_sig_into_try.cov-map +++ b/tests/coverage/fn_sig_into_try.cov-map @@ -1,53 +1,53 @@ Function name: fn_sig_into_try::a -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0a, 01, 04, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 0a, 01, 05, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 10, 1) to (start + 4, 2) +- Code(Counter(0)) at (prev + 10, 1) to (start + 5, 2) Function name: fn_sig_into_try::b -Raw bytes (28): 0x[01, 01, 02, 01, 00, 00, 02, 04, 01, 10, 01, 02, 0f, 00, 02, 0f, 00, 10, 02, 01, 05, 00, 0c, 07, 01, 01, 00, 02] +Raw bytes (28): 0x[01, 01, 02, 01, 00, 00, 02, 04, 01, 11, 01, 03, 0f, 00, 03, 0f, 00, 10, 02, 01, 05, 00, 0c, 07, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Zero - expression 1 operands: lhs = Zero, rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 16, 1) to (start + 2, 15) -- Code(Zero) at (prev + 2, 15) to (start + 0, 16) -- Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 12) - = (c0 - Zero) -- Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) - = (Zero + (c0 - Zero)) - -Function name: fn_sig_into_try::c -Raw bytes (28): 0x[01, 01, 02, 01, 00, 00, 02, 04, 01, 16, 01, 02, 17, 00, 02, 17, 00, 18, 02, 01, 05, 00, 0c, 07, 01, 01, 00, 02] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 2 -- expression 0 operands: lhs = Counter(0), rhs = Zero -- expression 1 operands: lhs = Zero, rhs = Expression(0, Sub) -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 22, 1) to (start + 2, 23) -- Code(Zero) at (prev + 2, 23) to (start + 0, 24) -- Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 12) - = (c0 - Zero) -- Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) - = (Zero + (c0 - Zero)) - -Function name: fn_sig_into_try::d -Raw bytes (28): 0x[01, 01, 02, 01, 00, 00, 02, 04, 01, 1c, 01, 03, 0f, 00, 03, 0f, 00, 10, 02, 01, 05, 00, 0c, 07, 01, 01, 00, 02] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 2 -- expression 0 operands: lhs = Counter(0), rhs = Zero -- expression 1 operands: lhs = Zero, rhs = Expression(0, Sub) -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 28, 1) to (start + 3, 15) +- Code(Counter(0)) at (prev + 17, 1) to (start + 3, 15) - Code(Zero) at (prev + 3, 15) to (start + 0, 16) - Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 12) = (c0 - Zero) - Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) = (Zero + (c0 - Zero)) +Function name: fn_sig_into_try::c +Raw bytes (28): 0x[01, 01, 02, 01, 00, 00, 02, 04, 01, 18, 01, 03, 17, 00, 03, 17, 00, 18, 02, 01, 05, 00, 0c, 07, 01, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 2 +- expression 0 operands: lhs = Counter(0), rhs = Zero +- expression 1 operands: lhs = Zero, rhs = Expression(0, Sub) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 24, 1) to (start + 3, 23) +- Code(Zero) at (prev + 3, 23) to (start + 0, 24) +- Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 12) + = (c0 - Zero) +- Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) + = (Zero + (c0 - Zero)) + +Function name: fn_sig_into_try::d +Raw bytes (28): 0x[01, 01, 02, 01, 00, 00, 02, 04, 01, 1f, 01, 04, 0f, 00, 04, 0f, 00, 10, 02, 01, 05, 00, 0c, 07, 01, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 2 +- expression 0 operands: lhs = Counter(0), rhs = Zero +- expression 1 operands: lhs = Zero, rhs = Expression(0, Sub) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 31, 1) to (start + 4, 15) +- Code(Zero) at (prev + 4, 15) to (start + 0, 16) +- Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 12) + = (c0 - Zero) +- Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) + = (Zero + (c0 - Zero)) + diff --git a/tests/coverage/fn_sig_into_try.coverage b/tests/coverage/fn_sig_into_try.coverage index f1ddb1da7802..71e15fc11eb8 100644 --- a/tests/coverage/fn_sig_into_try.coverage +++ b/tests/coverage/fn_sig_into_try.coverage @@ -8,12 +8,14 @@ LL| |// signature should be handled in the same way. LL| | LL| 1|fn a() -> Option + LL| 1|// LL| 1|{ LL| 1| Some(7i32); LL| 1| Some(0) LL| 1|} LL| | LL| 1|fn b() -> Option + LL| 1|// LL| 1|{ LL| 1| Some(7i32)?; ^0 @@ -21,6 +23,7 @@ LL| 1|} LL| | LL| 1|fn c() -> Option + LL| 1|// LL| 1|{ LL| 1| let _ = Some(7i32)?; ^0 @@ -28,6 +31,7 @@ LL| 1|} LL| | LL| 1|fn d() -> Option + LL| 1|// LL| 1|{ LL| 1| let _: () = (); LL| 1| Some(7i32)?; diff --git a/tests/coverage/fn_sig_into_try.rs b/tests/coverage/fn_sig_into_try.rs index 92850c8a188f..1f4cc67af838 100644 --- a/tests/coverage/fn_sig_into_try.rs +++ b/tests/coverage/fn_sig_into_try.rs @@ -8,24 +8,28 @@ // signature should be handled in the same way. fn a() -> Option +// { Some(7i32); Some(0) } fn b() -> Option +// { Some(7i32)?; Some(0) } fn c() -> Option +// { let _ = Some(7i32)?; Some(0) } fn d() -> Option +// { let _: () = (); Some(7i32)?; diff --git a/tests/coverage/generics.coverage b/tests/coverage/generics.coverage index 098391835663..c68c0be80b15 100644 --- a/tests/coverage/generics.coverage +++ b/tests/coverage/generics.coverage @@ -1,11 +1,11 @@ LL| |#![allow(unused_assignments)] LL| |// failure-status: 1 LL| | - LL| |struct Firework where T: Copy + std::fmt::Display { + LL| |struct Firework { LL| | strength: T, LL| |} LL| | - LL| |impl Firework where T: Copy + std::fmt::Display { + LL| |impl Firework { LL| | #[inline(always)] LL| 3| fn set_strength(&mut self, new_strength: T) { LL| 3| self.strength = new_strength; @@ -23,7 +23,7 @@ ------------------ LL| |} LL| | - LL| |impl Drop for Firework where T: Copy + std::fmt::Display { + LL| |impl Drop for Firework { LL| | #[inline(always)] LL| 2| fn drop(&mut self) { LL| 2| println!("BOOM times {}!!!", self.strength); diff --git a/tests/coverage/generics.rs b/tests/coverage/generics.rs index bf4c2d8d6853..fd3811b6937b 100644 --- a/tests/coverage/generics.rs +++ b/tests/coverage/generics.rs @@ -1,18 +1,18 @@ #![allow(unused_assignments)] // failure-status: 1 -struct Firework where T: Copy + std::fmt::Display { +struct Firework { strength: T, } -impl Firework where T: Copy + std::fmt::Display { +impl Firework { #[inline(always)] fn set_strength(&mut self, new_strength: T) { self.strength = new_strength; } } -impl Drop for Firework where T: Copy + std::fmt::Display { +impl Drop for Firework { #[inline(always)] fn drop(&mut self) { println!("BOOM times {}!!!", self.strength); diff --git a/tests/coverage/if.cov-map b/tests/coverage/if.cov-map index 391a69e0e821..d7122f4b1a03 100644 --- a/tests/coverage/if.cov-map +++ b/tests/coverage/if.cov-map @@ -1,12 +1,12 @@ Function name: if::main -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 03, 01, 12, 10, 05, 13, 05, 05, 06, 02, 05, 06, 00, 07, 07, 01, 01, 00, 02] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 04, 01, 12, 10, 05, 13, 05, 05, 06, 02, 05, 06, 00, 07, 07, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 3, 1) to (start + 18, 16) +- Code(Counter(0)) at (prev + 4, 1) to (start + 18, 16) - Code(Counter(1)) at (prev + 19, 5) to (start + 5, 6) - Code(Expression(0, Sub)) at (prev + 5, 6) to (start + 0, 7) = (c0 - c1) diff --git a/tests/coverage/if.coverage b/tests/coverage/if.coverage index 2e6845190aab..77db24ef51bf 100644 --- a/tests/coverage/if.coverage +++ b/tests/coverage/if.coverage @@ -1,5 +1,6 @@ LL| |#![allow(unused_assignments, unused_variables)] LL| | + LL| |#[rustfmt::skip] LL| 1|fn main() { LL| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure LL| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from diff --git a/tests/coverage/if.rs b/tests/coverage/if.rs index 8ad5042ff7ba..e8c0e7a7a225 100644 --- a/tests/coverage/if.rs +++ b/tests/coverage/if.rs @@ -1,5 +1,6 @@ #![allow(unused_assignments, unused_variables)] +#[rustfmt::skip] fn main() { // Initialize test constants in a way that cannot be determined at compile time, to ensure // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from diff --git a/tests/coverage/if_else.cov-map b/tests/coverage/if_else.cov-map index da692ca3aa2a..7163681d3a04 100644 --- a/tests/coverage/if_else.cov-map +++ b/tests/coverage/if_else.cov-map @@ -1,5 +1,5 @@ Function name: if_else::main -Raw bytes (53): 0x[01, 01, 07, 01, 05, 05, 02, 1b, 09, 05, 02, 09, 16, 1b, 09, 05, 02, 07, 01, 03, 01, 08, 10, 05, 09, 05, 05, 06, 02, 08, 09, 02, 10, 1b, 06, 09, 00, 10, 09, 01, 05, 05, 06, 16, 07, 05, 05, 06, 13, 06, 01, 00, 02] +Raw bytes (53): 0x[01, 01, 07, 01, 05, 05, 02, 1b, 09, 05, 02, 09, 16, 1b, 09, 05, 02, 07, 01, 04, 01, 08, 10, 05, 09, 05, 05, 06, 02, 08, 09, 02, 10, 1b, 06, 09, 00, 10, 09, 01, 05, 05, 06, 16, 07, 05, 05, 06, 13, 06, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 7 @@ -11,7 +11,7 @@ Number of expressions: 7 - expression 5 operands: lhs = Expression(6, Add), rhs = Counter(2) - expression 6 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 7 -- Code(Counter(0)) at (prev + 3, 1) to (start + 8, 16) +- Code(Counter(0)) at (prev + 4, 1) to (start + 8, 16) - Code(Counter(1)) at (prev + 9, 5) to (start + 5, 6) - Code(Expression(0, Sub)) at (prev + 8, 9) to (start + 2, 16) = (c0 - c1) diff --git a/tests/coverage/if_else.coverage b/tests/coverage/if_else.coverage index 0274401f0047..2bf93487cec2 100644 --- a/tests/coverage/if_else.coverage +++ b/tests/coverage/if_else.coverage @@ -1,5 +1,6 @@ LL| |#![allow(unused_assignments, unused_variables)] LL| | + LL| |#[rustfmt::skip] LL| 1|fn main() { LL| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure LL| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from diff --git a/tests/coverage/if_else.rs b/tests/coverage/if_else.rs index 3244e1e3afd2..a0687925d636 100644 --- a/tests/coverage/if_else.rs +++ b/tests/coverage/if_else.rs @@ -1,5 +1,6 @@ #![allow(unused_assignments, unused_variables)] +#[rustfmt::skip] fn main() { // Initialize test constants in a way that cannot be determined at compile time, to ensure // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from diff --git a/tests/coverage/if_not.cov-map b/tests/coverage/if_not.cov-map index fb893e379606..3c660551dea1 100644 --- a/tests/coverage/if_not.cov-map +++ b/tests/coverage/if_not.cov-map @@ -1,5 +1,5 @@ Function name: if_not::if_not -Raw bytes (86): 0x[01, 01, 10, 01, 05, 05, 02, 3f, 09, 05, 02, 09, 3a, 3f, 09, 05, 02, 37, 0d, 09, 3a, 3f, 09, 05, 02, 0d, 32, 37, 0d, 09, 3a, 3f, 09, 05, 02, 0a, 01, 04, 01, 03, 0d, 02, 04, 05, 02, 06, 05, 02, 06, 00, 07, 3f, 03, 09, 01, 0d, 3a, 02, 05, 02, 06, 09, 02, 06, 00, 07, 37, 03, 09, 01, 0d, 32, 02, 05, 02, 06, 0d, 02, 0c, 02, 06, 2f, 03, 01, 00, 02] +Raw bytes (86): 0x[01, 01, 10, 01, 05, 05, 02, 3f, 09, 05, 02, 09, 3a, 3f, 09, 05, 02, 37, 0d, 09, 3a, 3f, 09, 05, 02, 0d, 32, 37, 0d, 09, 3a, 3f, 09, 05, 02, 0a, 01, 05, 01, 03, 0d, 02, 04, 05, 02, 06, 05, 02, 06, 00, 07, 3f, 03, 09, 01, 0d, 3a, 02, 05, 02, 06, 09, 02, 06, 00, 07, 37, 03, 09, 01, 0d, 32, 02, 05, 02, 06, 0d, 02, 0c, 02, 06, 2f, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 16 @@ -20,7 +20,7 @@ Number of expressions: 16 - expression 14 operands: lhs = Expression(15, Add), rhs = Counter(2) - expression 15 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 10 -- Code(Counter(0)) at (prev + 4, 1) to (start + 3, 13) +- Code(Counter(0)) at (prev + 5, 1) to (start + 3, 13) - Code(Expression(0, Sub)) at (prev + 4, 5) to (start + 2, 6) = (c0 - c1) - Code(Counter(1)) at (prev + 2, 6) to (start + 0, 7) diff --git a/tests/coverage/if_not.coverage b/tests/coverage/if_not.coverage index 41838b8513f6..86ff7fc4f07d 100644 --- a/tests/coverage/if_not.coverage +++ b/tests/coverage/if_not.coverage @@ -1,6 +1,7 @@ LL| |#![feature(coverage_attribute)] LL| |// edition: 2021 LL| | + LL| |#[rustfmt::skip] LL| 12|fn if_not(cond: bool) { LL| 12| if LL| 12| ! diff --git a/tests/coverage/if_not.rs b/tests/coverage/if_not.rs index 4f45ae0b3d44..7b166662b5d0 100644 --- a/tests/coverage/if_not.rs +++ b/tests/coverage/if_not.rs @@ -1,6 +1,7 @@ #![feature(coverage_attribute)] // edition: 2021 +#[rustfmt::skip] fn if_not(cond: bool) { if ! diff --git a/tests/coverage/inline-dead.cov-map b/tests/coverage/inline-dead.cov-map index ab04e746b916..c669b7245ead 100644 --- a/tests/coverage/inline-dead.cov-map +++ b/tests/coverage/inline-dead.cov-map @@ -1,20 +1,20 @@ Function name: inline_dead::dead (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 19, 01, 02, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 17, 01, 02, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 25, 1) to (start + 2, 2) +- Code(Zero) at (prev + 23, 1) to (start + 2, 2) Function name: inline_dead::live:: -Raw bytes (28): 0x[01, 01, 02, 01, 00, 00, 02, 04, 01, 10, 01, 01, 09, 00, 02, 09, 00, 0f, 02, 02, 09, 00, 0a, 07, 02, 01, 00, 02] +Raw bytes (28): 0x[01, 01, 02, 01, 00, 00, 02, 04, 01, 0e, 01, 01, 09, 00, 02, 09, 00, 0f, 02, 02, 09, 00, 0a, 07, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Zero - expression 1 operands: lhs = Zero, rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 16, 1) to (start + 1, 9) +- Code(Counter(0)) at (prev + 14, 1) to (start + 1, 9) - Code(Zero) at (prev + 2, 9) to (start + 0, 15) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 10) = (c0 - Zero) @@ -22,16 +22,16 @@ Number of file 0 mappings: 4 = (Zero + (c0 - Zero)) Function name: inline_dead::main -Raw bytes (14): 0x[01, 01, 00, 02, 01, 04, 01, 03, 0d, 01, 07, 06, 02, 02] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 04, 01, 03, 0d, 01, 05, 06, 02, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 4, 1) to (start + 3, 13) -- Code(Counter(0)) at (prev + 7, 6) to (start + 2, 2) +- Code(Counter(0)) at (prev + 5, 6) to (start + 2, 2) Function name: inline_dead::main::{closure#0} -Raw bytes (23): 0x[01, 01, 02, 00, 06, 01, 00, 03, 01, 07, 17, 01, 16, 00, 02, 0d, 00, 0e, 03, 02, 05, 00, 06] +Raw bytes (23): 0x[01, 01, 02, 00, 06, 01, 00, 03, 01, 07, 17, 01, 16, 00, 01, 17, 00, 18, 03, 01, 05, 00, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 @@ -39,7 +39,7 @@ Number of expressions: 2 - expression 1 operands: lhs = Counter(0), rhs = Zero Number of file 0 mappings: 3 - Code(Counter(0)) at (prev + 7, 23) to (start + 1, 22) -- Code(Zero) at (prev + 2, 13) to (start + 0, 14) -- Code(Expression(0, Add)) at (prev + 2, 5) to (start + 0, 6) +- Code(Zero) at (prev + 1, 23) to (start + 0, 24) +- Code(Expression(0, Add)) at (prev + 1, 5) to (start + 0, 6) = (Zero + (c0 - Zero)) diff --git a/tests/coverage/inline-dead.coverage b/tests/coverage/inline-dead.coverage index 7c201f482db3..a643332bce1f 100644 --- a/tests/coverage/inline-dead.coverage +++ b/tests/coverage/inline-dead.coverage @@ -5,9 +5,8 @@ LL| 1| println!("{}", live::()); LL| 1| LL| 1| let f = |x: bool| { - LL| 1| debug_assert!( - LL| 0| x - LL| | ); + LL| 1| debug_assert!(x); + ^0 LL| 1| }; LL| 1| f(false); LL| 1|} diff --git a/tests/coverage/inline-dead.rs b/tests/coverage/inline-dead.rs index 854fa0629675..a854c17f6d59 100644 --- a/tests/coverage/inline-dead.rs +++ b/tests/coverage/inline-dead.rs @@ -5,9 +5,7 @@ fn main() { println!("{}", live::()); let f = |x: bool| { - debug_assert!( - x - ); + debug_assert!(x); }; f(false); } diff --git a/tests/coverage/issue-84561.cov-map b/tests/coverage/issue-84561.cov-map index 82582b309bfc..6d577b3d4851 100644 --- a/tests/coverage/issue-84561.cov-map +++ b/tests/coverage/issue-84561.cov-map @@ -7,14 +7,14 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 4, 10) to (start + 0, 19) Function name: ::fmt -Raw bytes (29): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 88, 01, 05, 01, 25, 05, 01, 25, 00, 26, 02, 01, 09, 00, 0f, 07, 01, 05, 00, 06] +Raw bytes (29): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 8a, 01, 05, 01, 25, 05, 01, 25, 00, 26, 02, 01, 09, 00, 0f, 07, 01, 05, 00, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 136, 5) to (start + 1, 37) +- Code(Counter(0)) at (prev + 138, 5) to (start + 1, 37) - Code(Counter(1)) at (prev + 1, 37) to (start + 0, 38) - Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 15) = (c0 - c1) @@ -22,15 +22,15 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: issue_84561::main -Raw bytes (10): 0x[01, 01, 00, 01, 01, b2, 01, 01, 04, 02] +Raw bytes (10): 0x[01, 01, 00, 01, 01, b4, 01, 01, 04, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 178, 1) to (start + 4, 2) +- Code(Counter(0)) at (prev + 180, 1) to (start + 4, 2) Function name: issue_84561::test1 -Raw bytes (78): 0x[01, 01, 0e, 05, 06, 01, 05, 09, 36, 03, 09, 0d, 2e, 33, 0d, 09, 36, 03, 09, 11, 26, 2b, 11, 0d, 2e, 33, 0d, 09, 36, 03, 09, 09, 01, 98, 01, 01, 01, 0b, 05, 01, 0c, 00, 1e, 03, 01, 05, 00, 0b, 09, 00, 0c, 00, 1e, 33, 01, 0d, 01, 0b, 0d, 01, 0c, 00, 1e, 2b, 01, 05, 03, 0b, 11, 03, 0c, 00, 1e, 23, 01, 01, 00, 02] +Raw bytes (78): 0x[01, 01, 0e, 05, 06, 01, 05, 09, 36, 03, 09, 0d, 2e, 33, 0d, 09, 36, 03, 09, 11, 26, 2b, 11, 0d, 2e, 33, 0d, 09, 36, 03, 09, 09, 01, 9a, 01, 01, 01, 0b, 05, 01, 0c, 00, 1e, 03, 01, 05, 00, 0b, 09, 00, 0c, 00, 1e, 33, 01, 0d, 01, 0b, 0d, 01, 0c, 00, 1e, 2b, 01, 05, 03, 0b, 11, 03, 0c, 00, 1e, 23, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 14 @@ -49,7 +49,7 @@ Number of expressions: 14 - expression 12 operands: lhs = Counter(2), rhs = Expression(13, Sub) - expression 13 operands: lhs = Expression(0, Add), rhs = Counter(2) Number of file 0 mappings: 9 -- Code(Counter(0)) at (prev + 152, 1) to (start + 1, 11) +- Code(Counter(0)) at (prev + 154, 1) to (start + 1, 11) - Code(Counter(1)) at (prev + 1, 12) to (start + 0, 30) - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 0, 11) = (c1 + (c0 - c1)) @@ -64,28 +64,28 @@ Number of file 0 mappings: 9 = (c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) Function name: issue_84561::test2 -Raw bytes (24): 0x[01, 01, 02, 05, 06, 01, 05, 03, 01, ae, 01, 01, 01, 10, 05, 01, 11, 00, 23, 03, 01, 01, 00, 02] +Raw bytes (24): 0x[01, 01, 02, 05, 06, 01, 05, 03, 01, b0, 01, 01, 01, 10, 05, 01, 11, 00, 23, 03, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(1), rhs = Expression(1, Sub) - expression 1 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 3 -- Code(Counter(0)) at (prev + 174, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 176, 1) to (start + 1, 16) - Code(Counter(1)) at (prev + 1, 17) to (start + 0, 35) - Code(Expression(0, Add)) at (prev + 1, 1) to (start + 0, 2) = (c1 + (c0 - c1)) Function name: issue_84561::test2::call_print -Raw bytes (10): 0x[01, 01, 00, 01, 01, a5, 01, 09, 02, 0a] +Raw bytes (10): 0x[01, 01, 00, 01, 01, a7, 01, 09, 02, 0a] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 165, 9) to (start + 2, 10) +- Code(Counter(0)) at (prev + 167, 9) to (start + 2, 10) Function name: issue_84561::test3 -Raw bytes (436): 0x[01, 01, 41, 05, 09, 0d, 00, 15, 19, 12, 00, 15, 19, 21, 00, 1e, 00, 21, 00, 31, 00, 3d, 41, 2e, 45, 3d, 41, 42, 49, 45, 00, 3f, 51, 42, 49, 45, 00, 5d, 8a, 01, 8f, 01, 5d, 92, 01, 55, 51, 00, 92, 01, 55, 51, 00, 8f, 01, 5d, 92, 01, 55, 51, 00, 87, 01, 61, 5d, 8a, 01, 8f, 01, 5d, 92, 01, 55, 51, 00, 82, 01, 65, 87, 01, 61, 5d, 8a, 01, 8f, 01, 5d, 92, 01, 55, 51, 00, 75, f6, 01, fb, 01, 79, 71, fe, 01, 82, 02, 71, 69, 6d, 71, fe, 01, 82, 02, 71, 69, 6d, 69, 6d, 82, 02, 71, 69, 6d, fb, 01, 79, 71, fe, 01, 82, 02, 71, 69, 6d, f3, 01, 7d, 75, f6, 01, fb, 01, 79, 71, fe, 01, 82, 02, 71, 69, 6d, ee, 01, 00, f3, 01, 7d, 75, f6, 01, fb, 01, 79, 71, fe, 01, 82, 02, 71, 69, 6d, 33, 01, 06, 01, 03, 1c, 05, 04, 09, 01, 1c, 02, 02, 05, 04, 1f, 0d, 05, 05, 00, 1f, 06, 01, 05, 00, 1f, 15, 01, 09, 01, 1c, 12, 02, 05, 00, 1f, 0e, 01, 05, 00, 0f, 00, 00, 20, 00, 30, 21, 01, 05, 03, 0f, 00, 03, 20, 00, 30, 00, 00, 33, 00, 41, 00, 00, 4b, 00, 5a, 1e, 01, 05, 00, 0f, 00, 05, 09, 03, 10, 00, 05, 0d, 00, 1b, 00, 02, 0d, 00, 1c, 1a, 04, 09, 05, 06, 31, 06, 05, 03, 06, 22, 04, 05, 03, 06, 3d, 04, 09, 04, 06, 2e, 05, 08, 00, 0f, 45, 01, 09, 03, 0a, 2a, 05, 09, 03, 0a, 3f, 05, 08, 00, 0f, 51, 01, 09, 00, 13, 00, 03, 0d, 00, 1d, 3a, 03, 09, 00, 13, 00, 03, 0d, 00, 1d, 87, 01, 03, 05, 00, 0f, 8f, 01, 01, 0c, 00, 13, 5d, 01, 0d, 00, 13, 8a, 01, 02, 0d, 00, 13, 82, 01, 04, 05, 02, 13, 65, 03, 0d, 00, 13, 7e, 02, 0d, 00, 13, f3, 01, 03, 05, 00, 0f, 69, 01, 0c, 00, 13, 6d, 01, 0d, 03, 0e, 75, 04, 0d, 00, 13, fb, 01, 02, 0d, 00, 17, 82, 02, 01, 14, 00, 1b, 71, 01, 15, 00, 1b, fe, 01, 02, 15, 00, 1b, f6, 01, 04, 0d, 00, 13, 7d, 03, 09, 00, 19, ee, 01, 02, 05, 00, 0f, ea, 01, 03, 09, 00, 22, 00, 02, 05, 00, 0f, 00, 03, 09, 00, 2c, 00, 02, 01, 00, 02] +Raw bytes (436): 0x[01, 01, 41, 05, 09, 0d, 00, 15, 19, 12, 00, 15, 19, 21, 00, 1e, 00, 21, 00, 31, 00, 3d, 41, 2e, 45, 3d, 41, 42, 49, 45, 00, 3f, 51, 42, 49, 45, 00, 5d, 8a, 01, 8f, 01, 5d, 92, 01, 55, 51, 00, 92, 01, 55, 51, 00, 8f, 01, 5d, 92, 01, 55, 51, 00, 87, 01, 61, 5d, 8a, 01, 8f, 01, 5d, 92, 01, 55, 51, 00, 82, 01, 65, 87, 01, 61, 5d, 8a, 01, 8f, 01, 5d, 92, 01, 55, 51, 00, 75, f6, 01, fb, 01, 79, 71, fe, 01, 82, 02, 71, 69, 6d, 71, fe, 01, 82, 02, 71, 69, 6d, 69, 6d, 82, 02, 71, 69, 6d, fb, 01, 79, 71, fe, 01, 82, 02, 71, 69, 6d, f3, 01, 7d, 75, f6, 01, fb, 01, 79, 71, fe, 01, 82, 02, 71, 69, 6d, ee, 01, 00, f3, 01, 7d, 75, f6, 01, fb, 01, 79, 71, fe, 01, 82, 02, 71, 69, 6d, 33, 01, 08, 01, 03, 1c, 05, 04, 09, 01, 1c, 02, 02, 05, 04, 1f, 0d, 05, 05, 00, 1f, 06, 01, 05, 00, 1f, 15, 01, 09, 01, 1c, 12, 02, 05, 00, 1f, 0e, 01, 05, 00, 0f, 00, 00, 20, 00, 30, 21, 01, 05, 03, 0f, 00, 03, 20, 00, 30, 00, 00, 33, 00, 41, 00, 00, 4b, 00, 5a, 1e, 01, 05, 00, 0f, 00, 05, 09, 03, 10, 00, 05, 0d, 00, 1b, 00, 02, 0d, 00, 1c, 1a, 04, 09, 05, 06, 31, 06, 05, 03, 06, 22, 04, 05, 03, 06, 3d, 04, 09, 04, 06, 2e, 05, 08, 00, 0f, 45, 01, 09, 03, 0a, 2a, 05, 09, 03, 0a, 3f, 05, 08, 00, 0f, 51, 01, 09, 00, 13, 00, 03, 0d, 00, 1d, 3a, 03, 09, 00, 13, 00, 03, 0d, 00, 1d, 87, 01, 03, 05, 00, 0f, 8f, 01, 01, 0c, 00, 13, 5d, 01, 0d, 00, 13, 8a, 01, 02, 0d, 00, 13, 82, 01, 04, 05, 02, 13, 65, 03, 0d, 00, 13, 7e, 02, 0d, 00, 13, f3, 01, 03, 05, 00, 0f, 69, 01, 0c, 00, 13, 6d, 01, 0d, 03, 0e, 75, 04, 0d, 00, 13, fb, 01, 02, 0d, 00, 17, 82, 02, 01, 14, 00, 1b, 71, 01, 15, 00, 1b, fe, 01, 02, 15, 00, 1b, f6, 01, 04, 0d, 00, 13, 7d, 03, 09, 00, 19, ee, 01, 02, 05, 00, 0f, ea, 01, 03, 09, 00, 22, 00, 02, 05, 00, 0f, 00, 03, 09, 00, 2c, 00, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 65 @@ -155,7 +155,7 @@ Number of expressions: 65 - expression 63 operands: lhs = Expression(64, Sub), rhs = Counter(28) - expression 64 operands: lhs = Counter(26), rhs = Counter(27) Number of file 0 mappings: 51 -- Code(Counter(0)) at (prev + 6, 1) to (start + 3, 28) +- Code(Counter(0)) at (prev + 8, 1) to (start + 3, 28) - Code(Counter(1)) at (prev + 4, 9) to (start + 1, 28) - Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 4, 31) = (c1 - c2) diff --git a/tests/coverage/issue-84561.coverage b/tests/coverage/issue-84561.coverage index e693866e2776..9080d95eff5f 100644 --- a/tests/coverage/issue-84561.coverage +++ b/tests/coverage/issue-84561.coverage @@ -3,6 +3,8 @@ LL| |// failure-status: 101 LL| 21|#[derive(PartialEq, Eq)] LL| |struct Foo(u32); + LL| | + LL| |#[rustfmt::skip] LL| 1|fn test3() { LL| 1| let is_true = std::env::args().len() == 1; LL| 1| let bar = Foo(1); diff --git a/tests/coverage/issue-84561.rs b/tests/coverage/issue-84561.rs index facf5b5b4cfb..9c218a37e6c4 100644 --- a/tests/coverage/issue-84561.rs +++ b/tests/coverage/issue-84561.rs @@ -3,6 +3,8 @@ // failure-status: 101 #[derive(PartialEq, Eq)] struct Foo(u32); + +#[rustfmt::skip] fn test3() { let is_true = std::env::args().len() == 1; let bar = Foo(1); diff --git a/tests/coverage/lazy_boolean.cov-map b/tests/coverage/lazy_boolean.cov-map index 2d1ff24e62d5..03dbb59d26b5 100644 --- a/tests/coverage/lazy_boolean.cov-map +++ b/tests/coverage/lazy_boolean.cov-map @@ -1,5 +1,5 @@ Function name: lazy_boolean::main -Raw bytes (636): 0x[01, 01, a4, 01, 01, 05, 09, 8a, 05, 8f, 05, 09, 05, 02, 05, 02, 8f, 05, 09, 05, 02, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 09, 8a, 05, 8f, 05, 09, 05, 02, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, d7, 04, 25, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 25, d2, 04, d7, 04, 25, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 1c, 01, 03, 01, 07, 0f, 05, 07, 10, 04, 06, 02, 04, 06, 00, 07, 87, 05, 02, 09, 00, 11, 8f, 05, 02, 0d, 00, 12, 8a, 05, 02, 0d, 00, 12, ff, 04, 03, 09, 00, 11, 87, 05, 02, 0d, 00, 12, 82, 05, 02, 0d, 00, 12, f7, 04, 02, 09, 00, 11, ff, 04, 00, 14, 00, 19, 11, 00, 1d, 00, 22, ef, 04, 01, 09, 00, 11, f7, 04, 00, 14, 00, 19, 15, 00, 1d, 00, 22, ef, 04, 03, 09, 01, 10, ea, 04, 02, 05, 03, 06, 19, 03, 06, 00, 07, e7, 04, 03, 09, 00, 10, 1d, 01, 05, 03, 06, e2, 04, 05, 05, 03, 06, df, 04, 05, 08, 00, 10, da, 04, 00, 11, 02, 06, 21, 02, 06, 00, 07, d7, 04, 02, 08, 00, 0f, 25, 00, 10, 02, 06, d2, 04, 02, 0c, 02, 06, cf, 04, 03, 01, 00, 02] +Raw bytes (636): 0x[01, 01, a4, 01, 01, 05, 09, 8a, 05, 8f, 05, 09, 05, 02, 05, 02, 8f, 05, 09, 05, 02, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 09, 8a, 05, 8f, 05, 09, 05, 02, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, d7, 04, 25, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 25, d2, 04, d7, 04, 25, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 1c, 01, 04, 01, 07, 0f, 05, 07, 10, 04, 06, 02, 04, 06, 00, 07, 87, 05, 02, 09, 00, 11, 8f, 05, 02, 0d, 00, 12, 8a, 05, 02, 0d, 00, 12, ff, 04, 03, 09, 00, 11, 87, 05, 02, 0d, 00, 12, 82, 05, 02, 0d, 00, 12, f7, 04, 02, 09, 00, 11, ff, 04, 00, 14, 00, 19, 11, 00, 1d, 00, 22, ef, 04, 01, 09, 00, 11, f7, 04, 00, 14, 00, 19, 15, 00, 1d, 00, 22, ef, 04, 03, 09, 01, 10, ea, 04, 02, 05, 03, 06, 19, 03, 06, 00, 07, e7, 04, 03, 09, 00, 10, 1d, 01, 05, 03, 06, e2, 04, 05, 05, 03, 06, df, 04, 05, 08, 00, 10, da, 04, 00, 11, 02, 06, 21, 02, 06, 00, 07, d7, 04, 02, 08, 00, 0f, 25, 00, 10, 02, 06, d2, 04, 02, 0c, 02, 06, cf, 04, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 164 @@ -168,7 +168,7 @@ Number of expressions: 164 - expression 162 operands: lhs = Expression(163, Add), rhs = Counter(2) - expression 163 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 28 -- Code(Counter(0)) at (prev + 3, 1) to (start + 7, 15) +- Code(Counter(0)) at (prev + 4, 1) to (start + 7, 15) - Code(Counter(1)) at (prev + 7, 16) to (start + 4, 6) - Code(Expression(0, Sub)) at (prev + 4, 6) to (start + 0, 7) = (c0 - c1) diff --git a/tests/coverage/lazy_boolean.coverage b/tests/coverage/lazy_boolean.coverage index 2d927a083560..f058be839008 100644 --- a/tests/coverage/lazy_boolean.coverage +++ b/tests/coverage/lazy_boolean.coverage @@ -1,5 +1,6 @@ LL| |#![allow(unused_assignments, unused_variables)] LL| | + LL| |#[rustfmt::skip] LL| 1|fn main() { LL| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure LL| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from diff --git a/tests/coverage/lazy_boolean.rs b/tests/coverage/lazy_boolean.rs index bb6219e851c8..47bfb1164490 100644 --- a/tests/coverage/lazy_boolean.rs +++ b/tests/coverage/lazy_boolean.rs @@ -1,5 +1,6 @@ #![allow(unused_assignments, unused_variables)] +#[rustfmt::skip] fn main() { // Initialize test constants in a way that cannot be determined at compile time, to ensure // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from diff --git a/tests/coverage/loop_break_value.cov-map b/tests/coverage/loop_break_value.cov-map index 75018442d075..d8dca8a85c38 100644 --- a/tests/coverage/loop_break_value.cov-map +++ b/tests/coverage/loop_break_value.cov-map @@ -1,8 +1,8 @@ Function name: loop_break_value::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 03, 01, 0a, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 04, 01, 0a, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 3, 1) to (start + 10, 2) +- Code(Counter(0)) at (prev + 4, 1) to (start + 10, 2) diff --git a/tests/coverage/loop_break_value.coverage b/tests/coverage/loop_break_value.coverage index 1f0630636ddf..7d4533987594 100644 --- a/tests/coverage/loop_break_value.coverage +++ b/tests/coverage/loop_break_value.coverage @@ -1,5 +1,6 @@ LL| |#![allow(unused_assignments, unused_variables)] LL| | + LL| |#[rustfmt::skip] LL| 1|fn main() { LL| 1| let result LL| 1| = diff --git a/tests/coverage/loop_break_value.rs b/tests/coverage/loop_break_value.rs index dbc4fad7a231..015365c2b3e1 100644 --- a/tests/coverage/loop_break_value.rs +++ b/tests/coverage/loop_break_value.rs @@ -1,5 +1,6 @@ #![allow(unused_assignments, unused_variables)] +#[rustfmt::skip] fn main() { let result = diff --git a/tests/coverage/partial_eq.cov-map b/tests/coverage/partial_eq.cov-map index 3a803e3c18fb..5e4aae0260b5 100644 --- a/tests/coverage/partial_eq.cov-map +++ b/tests/coverage/partial_eq.cov-map @@ -55,10 +55,10 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 12, 5) to (start + 6, 6) Function name: partial_eq::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 15, 01, 05, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 15, 01, 0a, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 21, 1) to (start + 5, 2) +- Code(Counter(0)) at (prev + 21, 1) to (start + 10, 2) diff --git a/tests/coverage/partial_eq.coverage b/tests/coverage/partial_eq.coverage index c6d9ad6cf27e..6e3696386a77 100644 --- a/tests/coverage/partial_eq.coverage +++ b/tests/coverage/partial_eq.coverage @@ -23,7 +23,12 @@ LL| 1| let version_3_2_1 = Version::new(3, 2, 1); LL| 1| let version_3_3_0 = Version::new(3, 3, 0); LL| 1| - LL| 1| println!("{:?} < {:?} = {}", version_3_2_1, version_3_3_0, version_3_2_1 < version_3_3_0); + LL| 1| println!( + LL| 1| "{:?} < {:?} = {}", + LL| 1| version_3_2_1, + LL| 1| version_3_3_0, + LL| 1| version_3_2_1 < version_3_3_0 + LL| 1| ); LL| 1|} LL| | LL| |/* diff --git a/tests/coverage/partial_eq.rs b/tests/coverage/partial_eq.rs index dd8b42c18cea..825e266f111f 100644 --- a/tests/coverage/partial_eq.rs +++ b/tests/coverage/partial_eq.rs @@ -22,7 +22,12 @@ fn main() { let version_3_2_1 = Version::new(3, 2, 1); let version_3_3_0 = Version::new(3, 3, 0); - println!("{:?} < {:?} = {}", version_3_2_1, version_3_3_0, version_3_2_1 < version_3_3_0); + println!( + "{:?} < {:?} = {}", + version_3_2_1, + version_3_3_0, + version_3_2_1 < version_3_3_0 + ); } /* diff --git a/tests/coverage/simple_loop.cov-map b/tests/coverage/simple_loop.cov-map index f1691ffc5e6a..0a342cb3673a 100644 --- a/tests/coverage/simple_loop.cov-map +++ b/tests/coverage/simple_loop.cov-map @@ -1,5 +1,5 @@ Function name: simple_loop::main -Raw bytes (57): 0x[01, 01, 09, 01, 05, 23, 09, 05, 02, 1f, 09, 23, 09, 05, 02, 1f, 09, 23, 09, 05, 02, 07, 01, 03, 01, 09, 10, 05, 0a, 05, 05, 06, 02, 05, 06, 00, 07, 1f, 05, 0d, 02, 0e, 1a, 04, 0d, 00, 12, 09, 02, 0a, 03, 0a, 1a, 06, 01, 00, 02] +Raw bytes (57): 0x[01, 01, 09, 01, 05, 23, 09, 05, 02, 1f, 09, 23, 09, 05, 02, 1f, 09, 23, 09, 05, 02, 07, 01, 04, 01, 09, 10, 05, 0a, 05, 05, 06, 02, 05, 06, 00, 07, 1f, 05, 0d, 02, 0e, 1a, 04, 0d, 00, 12, 09, 02, 0a, 03, 0a, 1a, 06, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 9 @@ -13,7 +13,7 @@ Number of expressions: 9 - expression 7 operands: lhs = Expression(8, Add), rhs = Counter(2) - expression 8 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 7 -- Code(Counter(0)) at (prev + 3, 1) to (start + 9, 16) +- Code(Counter(0)) at (prev + 4, 1) to (start + 9, 16) - Code(Counter(1)) at (prev + 10, 5) to (start + 5, 6) - Code(Expression(0, Sub)) at (prev + 5, 6) to (start + 0, 7) = (c0 - c1) diff --git a/tests/coverage/simple_loop.coverage b/tests/coverage/simple_loop.coverage index 691c6cd1e7dd..b6552c62ff90 100644 --- a/tests/coverage/simple_loop.coverage +++ b/tests/coverage/simple_loop.coverage @@ -1,5 +1,6 @@ LL| |#![allow(unused_assignments)] LL| | + LL| |#[rustfmt::skip] LL| 1|fn main() { LL| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure LL| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from diff --git a/tests/coverage/simple_loop.rs b/tests/coverage/simple_loop.rs index 6f7f23475b82..6776911563df 100644 --- a/tests/coverage/simple_loop.rs +++ b/tests/coverage/simple_loop.rs @@ -1,5 +1,6 @@ #![allow(unused_assignments)] +#[rustfmt::skip] fn main() { // Initialize test constants in a way that cannot be determined at compile time, to ensure // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from diff --git a/tests/coverage/simple_match.cov-map b/tests/coverage/simple_match.cov-map index 4a32745d2929..7c242e2c328d 100644 --- a/tests/coverage/simple_match.cov-map +++ b/tests/coverage/simple_match.cov-map @@ -1,5 +1,5 @@ Function name: simple_match::main -Raw bytes (78): 0x[01, 01, 0c, 01, 05, 2b, 2f, 05, 02, 09, 0d, 27, 11, 2b, 2f, 05, 02, 09, 0d, 27, 11, 2b, 2f, 05, 02, 09, 0d, 0a, 01, 03, 01, 07, 0f, 05, 07, 10, 02, 06, 02, 02, 06, 00, 07, 27, 05, 09, 00, 0d, 22, 05, 0d, 00, 16, 09, 02, 0d, 00, 0e, 22, 02, 11, 02, 12, 09, 04, 0d, 07, 0e, 0d, 0a, 0d, 00, 0f, 11, 03, 01, 00, 02] +Raw bytes (78): 0x[01, 01, 0c, 01, 05, 2b, 2f, 05, 02, 09, 0d, 27, 11, 2b, 2f, 05, 02, 09, 0d, 27, 11, 2b, 2f, 05, 02, 09, 0d, 0a, 01, 04, 01, 07, 0f, 05, 07, 10, 02, 06, 02, 02, 06, 00, 07, 27, 05, 09, 00, 0d, 22, 05, 0d, 00, 16, 09, 02, 0d, 00, 0e, 22, 02, 11, 02, 12, 09, 04, 0d, 07, 0e, 0d, 0a, 0d, 00, 0f, 11, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 12 @@ -16,7 +16,7 @@ Number of expressions: 12 - expression 10 operands: lhs = Counter(1), rhs = Expression(0, Sub) - expression 11 operands: lhs = Counter(2), rhs = Counter(3) Number of file 0 mappings: 10 -- Code(Counter(0)) at (prev + 3, 1) to (start + 7, 15) +- Code(Counter(0)) at (prev + 4, 1) to (start + 7, 15) - Code(Counter(1)) at (prev + 7, 16) to (start + 2, 6) - Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) = (c0 - c1) diff --git a/tests/coverage/simple_match.coverage b/tests/coverage/simple_match.coverage index 7f5dd3bb6463..3a4fc6743f5e 100644 --- a/tests/coverage/simple_match.coverage +++ b/tests/coverage/simple_match.coverage @@ -1,5 +1,6 @@ LL| |#![allow(unused_assignments, unused_variables)] LL| | + LL| |#[rustfmt::skip] LL| 1|fn main() { LL| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure LL| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from diff --git a/tests/coverage/simple_match.rs b/tests/coverage/simple_match.rs index be99e59a8268..2ad4e55b4edc 100644 --- a/tests/coverage/simple_match.rs +++ b/tests/coverage/simple_match.rs @@ -1,5 +1,6 @@ #![allow(unused_assignments, unused_variables)] +#[rustfmt::skip] fn main() { // Initialize test constants in a way that cannot be determined at compile time, to ensure // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from diff --git a/tests/coverage/test_harness.cov-map b/tests/coverage/test_harness.cov-map index 6940d2e28243..f75328b11c9a 100644 --- a/tests/coverage/test_harness.cov-map +++ b/tests/coverage/test_harness.cov-map @@ -6,14 +6,6 @@ Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 10, 1) to (start + 0, 16) -Function name: test_harness::my_test::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 09, 01, 00, 08] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 9, 1) to (start + 0, 8) - Function name: test_harness::unused (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 07, 01, 00, 0f] Number of files: 1 diff --git a/tests/coverage/test_harness.coverage b/tests/coverage/test_harness.coverage index ff6009f6fce4..c3f660506fbd 100644 --- a/tests/coverage/test_harness.coverage +++ b/tests/coverage/test_harness.coverage @@ -6,6 +6,6 @@ LL| |#[allow(dead_code)] LL| 0|fn unused() {} LL| | - LL| 1|#[test] + LL| |#[test] LL| 1|fn my_test() {} diff --git a/tests/coverage/thin-lto.cov-map b/tests/coverage/thin-lto.cov-map index 7e84e398f845..1f61b805f622 100644 --- a/tests/coverage/thin-lto.cov-map +++ b/tests/coverage/thin-lto.cov-map @@ -1,8 +1,8 @@ Function name: thin_lto::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 03, 01, 01, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 03, 01, 00, 11] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 3, 1) to (start + 1, 2) +- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 17) diff --git a/tests/coverage/thin-lto.coverage b/tests/coverage/thin-lto.coverage index 21abb5dce04e..7ece467217ac 100644 --- a/tests/coverage/thin-lto.coverage +++ b/tests/coverage/thin-lto.coverage @@ -1,5 +1,4 @@ LL| |// compile-flags: -O -C lto=thin -C prefer-dynamic=no LL| | - LL| 1|pub fn main() { - LL| 1|} + LL| 1|pub fn main() {} diff --git a/tests/coverage/thin-lto.rs b/tests/coverage/thin-lto.rs index 050aac263197..04e9cd0e8088 100644 --- a/tests/coverage/thin-lto.rs +++ b/tests/coverage/thin-lto.rs @@ -1,4 +1,3 @@ // compile-flags: -O -C lto=thin -C prefer-dynamic=no -pub fn main() { -} +pub fn main() {} diff --git a/tests/coverage/try_error_result.cov-map b/tests/coverage/try_error_result.cov-map index a9a18a180ddd..5cfb40ce5289 100644 --- a/tests/coverage/try_error_result.cov-map +++ b/tests/coverage/try_error_result.cov-map @@ -1,12 +1,12 @@ Function name: ::get_thing_2 -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 28, 05, 01, 18, 05, 02, 0d, 00, 14, 02, 02, 0d, 00, 1a, 07, 02, 05, 00, 06] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 29, 05, 01, 18, 05, 02, 0d, 00, 14, 02, 02, 0d, 00, 1a, 07, 02, 05, 00, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 40, 5) to (start + 1, 24) +- Code(Counter(0)) at (prev + 41, 5) to (start + 1, 24) - Code(Counter(1)) at (prev + 2, 13) to (start + 0, 20) - Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 26) = (c0 - c1) @@ -14,14 +14,14 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: ::call -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 33, 05, 01, 18, 05, 02, 0d, 00, 14, 02, 02, 0d, 00, 13, 07, 02, 05, 00, 06] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 34, 05, 01, 18, 05, 02, 0d, 00, 14, 02, 02, 0d, 00, 13, 07, 02, 05, 00, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 51, 5) to (start + 1, 24) +- Code(Counter(0)) at (prev + 52, 5) to (start + 1, 24) - Code(Counter(1)) at (prev + 2, 13) to (start + 0, 20) - Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 19) = (c0 - c1) @@ -44,14 +44,14 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: try_error_result::main -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 70, 01, 02, 0c, 05, 03, 05, 00, 06, 02, 02, 05, 00, 0b, 07, 01, 01, 00, 02] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 73, 01, 02, 0c, 05, 03, 05, 00, 06, 02, 02, 05, 00, 0b, 07, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 112, 1) to (start + 2, 12) +- Code(Counter(0)) at (prev + 115, 1) to (start + 2, 12) - Code(Counter(1)) at (prev + 3, 5) to (start + 0, 6) - Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 11) = (c0 - c1) @@ -59,7 +59,7 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: try_error_result::test1 -Raw bytes (77): 0x[01, 01, 09, 01, 07, 05, 09, 03, 0d, 1d, 11, 16, 1d, 03, 0d, 1f, 0d, 23, 19, 11, 15, 0b, 01, 0c, 01, 02, 17, 03, 07, 09, 00, 0e, 16, 02, 09, 04, 1a, 1d, 06, 0d, 00, 29, 11, 00, 29, 00, 2a, 0e, 01, 0d, 00, 2a, 15, 00, 2a, 00, 2b, 12, 04, 0d, 00, 2a, 19, 00, 2a, 00, 2b, 0d, 03, 05, 00, 0b, 1b, 01, 01, 00, 02] +Raw bytes (77): 0x[01, 01, 09, 01, 07, 05, 09, 03, 0d, 1d, 11, 16, 1d, 03, 0d, 1f, 0d, 23, 19, 11, 15, 0b, 01, 0d, 01, 02, 17, 03, 07, 09, 00, 0e, 16, 02, 09, 04, 1a, 1d, 06, 0d, 00, 29, 11, 00, 29, 00, 2a, 0e, 01, 0d, 00, 2a, 15, 00, 2a, 00, 2b, 12, 04, 0d, 00, 2a, 19, 00, 2a, 00, 2b, 0d, 03, 05, 00, 0b, 1b, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 9 @@ -73,7 +73,7 @@ Number of expressions: 9 - expression 7 operands: lhs = Expression(8, Add), rhs = Counter(6) - expression 8 operands: lhs = Counter(4), rhs = Counter(5) Number of file 0 mappings: 11 -- Code(Counter(0)) at (prev + 12, 1) to (start + 2, 23) +- Code(Counter(0)) at (prev + 13, 1) to (start + 2, 23) - Code(Expression(0, Add)) at (prev + 7, 9) to (start + 0, 14) = (c0 + (c1 + c2)) - Code(Expression(5, Sub)) at (prev + 2, 9) to (start + 4, 26) @@ -91,7 +91,7 @@ Number of file 0 mappings: 11 = (((c4 + c5) + c6) + c3) Function name: try_error_result::test2 -Raw bytes (358): 0x[01, 01, 3b, 01, 07, 05, 09, 03, 0d, 41, 11, 4a, 15, 41, 11, 42, 1d, 46, 19, 4a, 15, 41, 11, 4a, 15, 41, 11, 46, 19, 4a, 15, 41, 11, 42, 1d, 46, 19, 4a, 15, 41, 11, 5e, 25, 49, 21, 49, 21, 5e, 25, 49, 21, 8a, 01, 2d, 8e, 01, 29, 92, 01, 41, 03, 0d, 92, 01, 41, 03, 0d, 8e, 01, 29, 92, 01, 41, 03, 0d, 8a, 01, 2d, 8e, 01, 29, 92, 01, 41, 03, 0d, a6, 01, 35, 45, 31, 45, 31, a6, 01, 35, 45, 31, ba, 01, 3d, 4d, 39, 4d, 39, ba, 01, 3d, 4d, 39, c3, 01, 0d, c7, 01, db, 01, cb, 01, cf, 01, 11, 15, d3, 01, d7, 01, 19, 1d, 21, 25, df, 01, e3, 01, 29, 2d, e7, 01, eb, 01, 31, 35, 39, 3d, 28, 01, 3c, 01, 03, 17, 03, 08, 09, 00, 0e, 92, 01, 02, 09, 04, 1a, 41, 06, 0d, 00, 2f, 11, 00, 2f, 00, 30, 4a, 00, 31, 03, 35, 15, 04, 11, 00, 12, 46, 02, 11, 04, 12, 3e, 05, 11, 00, 14, 46, 00, 17, 00, 41, 19, 00, 41, 00, 42, 42, 00, 43, 00, 5f, 1d, 00, 5f, 00, 60, 3e, 01, 0d, 00, 20, 5a, 01, 11, 00, 14, 49, 00, 17, 00, 41, 21, 00, 41, 00, 42, 5e, 00, 43, 00, 60, 25, 00, 60, 00, 61, 5a, 01, 0d, 00, 20, 86, 01, 04, 11, 00, 14, 8e, 01, 00, 17, 00, 42, 29, 00, 42, 00, 43, 8a, 01, 00, 44, 00, 61, 2d, 00, 61, 00, 62, 86, 01, 01, 0d, 00, 20, a2, 01, 01, 11, 00, 14, 45, 00, 17, 01, 36, 31, 01, 36, 00, 37, a6, 01, 01, 12, 00, 2f, 35, 00, 2f, 00, 30, a2, 01, 01, 0d, 00, 20, b6, 01, 01, 11, 00, 14, 4d, 00, 17, 01, 36, 39, 02, 11, 00, 12, ba, 01, 01, 12, 00, 2f, 3d, 01, 11, 00, 12, b6, 01, 02, 0d, 00, 20, 0d, 03, 05, 00, 0b, bf, 01, 01, 01, 00, 02] +Raw bytes (358): 0x[01, 01, 3b, 01, 07, 05, 09, 03, 0d, 41, 11, 4a, 15, 41, 11, 42, 1d, 46, 19, 4a, 15, 41, 11, 4a, 15, 41, 11, 46, 19, 4a, 15, 41, 11, 42, 1d, 46, 19, 4a, 15, 41, 11, 5e, 25, 49, 21, 49, 21, 5e, 25, 49, 21, 8a, 01, 2d, 8e, 01, 29, 92, 01, 41, 03, 0d, 92, 01, 41, 03, 0d, 8e, 01, 29, 92, 01, 41, 03, 0d, 8a, 01, 2d, 8e, 01, 29, 92, 01, 41, 03, 0d, a6, 01, 35, 45, 31, 45, 31, a6, 01, 35, 45, 31, ba, 01, 3d, 4d, 39, 4d, 39, ba, 01, 3d, 4d, 39, c3, 01, 0d, c7, 01, db, 01, cb, 01, cf, 01, 11, 15, d3, 01, d7, 01, 19, 1d, 21, 25, df, 01, e3, 01, 29, 2d, e7, 01, eb, 01, 31, 35, 39, 3d, 28, 01, 3e, 01, 03, 17, 03, 08, 09, 00, 0e, 92, 01, 02, 09, 04, 1a, 41, 06, 0d, 00, 2f, 11, 00, 2f, 00, 30, 4a, 00, 31, 03, 35, 15, 04, 11, 00, 12, 46, 02, 11, 04, 12, 3e, 05, 11, 00, 14, 46, 00, 17, 00, 41, 19, 00, 41, 00, 42, 42, 00, 43, 00, 5f, 1d, 00, 5f, 00, 60, 3e, 01, 0d, 00, 20, 5a, 01, 11, 00, 14, 49, 00, 17, 00, 41, 21, 00, 41, 00, 42, 5e, 00, 43, 00, 60, 25, 00, 60, 00, 61, 5a, 01, 0d, 00, 20, 86, 01, 04, 11, 00, 14, 8e, 01, 00, 17, 00, 42, 29, 00, 42, 00, 43, 8a, 01, 00, 44, 00, 61, 2d, 00, 61, 00, 62, 86, 01, 01, 0d, 00, 20, a2, 01, 01, 11, 00, 14, 45, 00, 17, 01, 36, 31, 01, 36, 00, 37, a6, 01, 01, 12, 00, 2f, 35, 00, 2f, 00, 30, a2, 01, 01, 0d, 00, 20, b6, 01, 01, 11, 00, 14, 4d, 00, 17, 01, 36, 39, 02, 11, 00, 12, ba, 01, 01, 12, 00, 2f, 3d, 01, 11, 00, 12, b6, 01, 02, 0d, 00, 20, 0d, 03, 05, 00, 0b, bf, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 59 @@ -155,7 +155,7 @@ Number of expressions: 59 - expression 57 operands: lhs = Counter(12), rhs = Counter(13) - expression 58 operands: lhs = Counter(14), rhs = Counter(15) Number of file 0 mappings: 40 -- Code(Counter(0)) at (prev + 60, 1) to (start + 3, 23) +- Code(Counter(0)) at (prev + 62, 1) to (start + 3, 23) - Code(Expression(0, Add)) at (prev + 8, 9) to (start + 0, 14) = (c0 + (c1 + c2)) - Code(Expression(36, Sub)) at (prev + 2, 9) to (start + 4, 26) diff --git a/tests/coverage/try_error_result.coverage b/tests/coverage/try_error_result.coverage index 5d48cbd62f20..418efa7fcb5c 100644 --- a/tests/coverage/try_error_result.coverage +++ b/tests/coverage/try_error_result.coverage @@ -9,6 +9,7 @@ LL| | } LL| 6|} LL| | + LL| |#[rustfmt::skip] LL| 1|fn test1() -> Result<(), ()> { LL| 1| let mut LL| 1| countdown = 10 @@ -58,6 +59,7 @@ LL| 17| } LL| |} LL| | + LL| |#[rustfmt::skip] LL| 1|fn test2() -> Result<(), ()> { LL| 1| let thing1 = Thing1{}; LL| 1| let mut @@ -115,6 +117,7 @@ LL| 0| Ok(()) LL| 1|} LL| | + LL| |#[rustfmt::skip] LL| 1|fn main() -> Result<(), ()> { LL| 1| test1().expect_err("test1 should fail"); LL| 1| test2() diff --git a/tests/coverage/try_error_result.rs b/tests/coverage/try_error_result.rs index 557cbf22bfad..1acc26169123 100644 --- a/tests/coverage/try_error_result.rs +++ b/tests/coverage/try_error_result.rs @@ -9,6 +9,7 @@ fn call(return_error: bool) -> Result<(), ()> { } } +#[rustfmt::skip] fn test1() -> Result<(), ()> { let mut countdown = 10 @@ -57,6 +58,7 @@ impl Thing2 { } } +#[rustfmt::skip] fn test2() -> Result<(), ()> { let thing1 = Thing1{}; let mut @@ -109,6 +111,7 @@ fn test2() -> Result<(), ()> { Ok(()) } +#[rustfmt::skip] fn main() -> Result<(), ()> { test1().expect_err("test1 should fail"); test2() diff --git a/tests/coverage/while.cov-map b/tests/coverage/while.cov-map index af250f3fb710..c6557b48e27d 100644 --- a/tests/coverage/while.cov-map +++ b/tests/coverage/while.cov-map @@ -1,5 +1,5 @@ Function name: while::main -Raw bytes (28): 0x[01, 01, 02, 01, 00, 03, 00, 04, 01, 01, 01, 01, 10, 03, 02, 0b, 00, 14, 00, 00, 15, 01, 06, 06, 02, 01, 00, 02] +Raw bytes (28): 0x[01, 01, 02, 01, 00, 03, 00, 04, 01, 01, 01, 01, 10, 03, 02, 0b, 00, 14, 00, 00, 15, 02, 06, 06, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 @@ -9,7 +9,7 @@ Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 1, 1) to (start + 1, 16) - Code(Expression(0, Add)) at (prev + 2, 11) to (start + 0, 20) = (c0 + Zero) -- Code(Zero) at (prev + 0, 21) to (start + 1, 6) -- Code(Expression(1, Sub)) at (prev + 2, 1) to (start + 0, 2) +- Code(Zero) at (prev + 0, 21) to (start + 2, 6) +- Code(Expression(1, Sub)) at (prev + 3, 1) to (start + 0, 2) = ((c0 + Zero) - Zero) diff --git a/tests/coverage/while.coverage b/tests/coverage/while.coverage index c9d497651c9f..90c16288d668 100644 --- a/tests/coverage/while.coverage +++ b/tests/coverage/while.coverage @@ -1,6 +1,7 @@ LL| 1|fn main() { LL| 1| let num = 9; LL| 1| while num >= 10 { + LL| 0| // loop body LL| 0| } LL| 1|} diff --git a/tests/coverage/while.rs b/tests/coverage/while.rs index 781b90b35663..d60916a97981 100644 --- a/tests/coverage/while.rs +++ b/tests/coverage/while.rs @@ -1,5 +1,6 @@ fn main() { let num = 9; while num >= 10 { + // loop body } } diff --git a/tests/coverage/while_early_ret.cov-map b/tests/coverage/while_early_ret.cov-map index 369ebe891f12..c883eb4baf20 100644 --- a/tests/coverage/while_early_ret.cov-map +++ b/tests/coverage/while_early_ret.cov-map @@ -1,5 +1,5 @@ Function name: while_early_ret::main -Raw bytes (61): 0x[01, 01, 06, 01, 05, 03, 09, 0e, 05, 03, 09, 17, 09, 0d, 11, 09, 01, 04, 01, 01, 1b, 03, 03, 09, 02, 0a, 0e, 05, 0d, 02, 0e, 0a, 06, 15, 02, 16, 0d, 04, 15, 00, 1b, 11, 04, 15, 00, 1b, 05, 03, 0a, 03, 0a, 09, 06, 05, 00, 0b, 13, 01, 01, 00, 02] +Raw bytes (61): 0x[01, 01, 06, 01, 05, 03, 09, 0e, 05, 03, 09, 17, 09, 0d, 11, 09, 01, 05, 01, 01, 1b, 03, 03, 09, 02, 0a, 0e, 05, 0d, 02, 0e, 0a, 06, 15, 02, 16, 0d, 04, 15, 00, 1b, 11, 04, 15, 00, 1b, 05, 03, 0a, 03, 0a, 09, 06, 05, 00, 0b, 13, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 6 @@ -10,7 +10,7 @@ Number of expressions: 6 - expression 4 operands: lhs = Expression(5, Add), rhs = Counter(2) - expression 5 operands: lhs = Counter(3), rhs = Counter(4) Number of file 0 mappings: 9 -- Code(Counter(0)) at (prev + 4, 1) to (start + 1, 27) +- Code(Counter(0)) at (prev + 5, 1) to (start + 1, 27) - Code(Expression(0, Add)) at (prev + 3, 9) to (start + 2, 10) = (c0 + c1) - Code(Expression(3, Sub)) at (prev + 5, 13) to (start + 2, 14) diff --git a/tests/coverage/while_early_ret.coverage b/tests/coverage/while_early_ret.coverage index 49d39d366038..f4372ad282e3 100644 --- a/tests/coverage/while_early_ret.coverage +++ b/tests/coverage/while_early_ret.coverage @@ -1,6 +1,7 @@ LL| |#![allow(unused_assignments)] LL| |// failure-status: 1 LL| | + LL| |#[rustfmt::skip] LL| 1|fn main() -> Result<(), u8> { LL| 1| let mut countdown = 10; LL| | while diff --git a/tests/coverage/while_early_ret.rs b/tests/coverage/while_early_ret.rs index b2f0eee2cc0f..a6421e797f61 100644 --- a/tests/coverage/while_early_ret.rs +++ b/tests/coverage/while_early_ret.rs @@ -1,6 +1,7 @@ #![allow(unused_assignments)] // failure-status: 1 +#[rustfmt::skip] fn main() -> Result<(), u8> { let mut countdown = 10; while diff --git a/tests/debuginfo/collapse-debuginfo-external-attr.rs b/tests/debuginfo/collapse-debuginfo-external-attr.rs new file mode 100644 index 000000000000..f36b0833ad51 --- /dev/null +++ b/tests/debuginfo/collapse-debuginfo-external-attr.rs @@ -0,0 +1,31 @@ +// ignore-lldb +#![feature(collapse_debuginfo)] + +// Test that local macro debug info is not collapsed with #[collapse_debuginfo(external)] + +// compile-flags:-g + +// === GDB TESTS =================================================================================== + +// gdb-command:run +// gdb-command:next +// gdb-command:frame +// gdb-check:[...]#one_callsite[...] +// gdb-command:continue + +fn one() { + println!("one"); +} + +#[collapse_debuginfo(external)] +macro_rules! outer { + () => { + one(); // #one_callsite + }; +} + +fn main() { + let ret = 0; // #break + outer!(); + std::process::exit(ret); +} diff --git a/tests/debuginfo/collapse-debuginfo-external-flag-overriden-by-attr.rs b/tests/debuginfo/collapse-debuginfo-external-flag-overriden-by-attr.rs new file mode 100644 index 000000000000..e5cbc1a685d0 --- /dev/null +++ b/tests/debuginfo/collapse-debuginfo-external-flag-overriden-by-attr.rs @@ -0,0 +1,34 @@ +// ignore-lldb +#![feature(collapse_debuginfo)] + +// Test that macro attribute #[collapse_debuginfo(no)] +// overrides "collapse_macro_debuginfo=external" flag + +// compile-flags:-g -Z collapse_macro_debuginfo=external + +// === GDB TESTS =================================================================================== + +// gdb-command:run +// gdb-command:next +// gdb-command:frame +// gdb-check:[...]#one_callsite[...] +// gdb-command:next +// gdb-command:frame +// gdb-command:continue + +fn one() { + println!("one"); +} + +#[collapse_debuginfo(no)] +macro_rules! outer { + () => { + one(); // #one_callsite + }; +} + +fn main() { + let ret = 0; // #break + outer!(); + std::process::exit(ret); +} diff --git a/tests/debuginfo/collapse-debuginfo-external-flag.rs b/tests/debuginfo/collapse-debuginfo-external-flag.rs new file mode 100644 index 000000000000..9a0aef38ea6c --- /dev/null +++ b/tests/debuginfo/collapse-debuginfo-external-flag.rs @@ -0,0 +1,26 @@ +// ignore-lldb +#![feature(collapse_debuginfo)] + +// Test that println macro debug info is collapsed with "collapse_macro_debuginfo=external" flag + +// compile-flags:-g -Z collapse_macro_debuginfo=external + +// === GDB TESTS =================================================================================== + +// gdb-command:run +// gdb-command:next +// gdb-command:frame +// gdb-check:[...]#println_callsite[...] +// gdb-command:continue + +macro_rules! outer { + () => { + println!("one"); // #println_callsite + }; +} + +fn main() { + let ret = 0; // #break + outer!(); + std::process::exit(ret); +} diff --git a/tests/debuginfo/collapse-debuginfo-no-attr.rs b/tests/debuginfo/collapse-debuginfo-no-attr.rs index 230c8795be36..d156c381a150 100644 --- a/tests/debuginfo/collapse-debuginfo-no-attr.rs +++ b/tests/debuginfo/collapse-debuginfo-no-attr.rs @@ -4,7 +4,7 @@ // Test that line numbers are not replaced with those of the outermost expansion site when the // `collapse_debuginfo` feature is active and the attribute is not provided. -// compile-flags:-g +// compile-flags:-g -Z collapse_macro_debuginfo=no // === GDB TESTS =================================================================================== diff --git a/tests/debuginfo/collapse-debuginfo-with-yes-flag.rs b/tests/debuginfo/collapse-debuginfo-with-yes-flag.rs new file mode 100644 index 000000000000..76a97a325d7e --- /dev/null +++ b/tests/debuginfo/collapse-debuginfo-with-yes-flag.rs @@ -0,0 +1,57 @@ +// ignore-lldb +#![feature(collapse_debuginfo)] + +// Test that line numbers are replaced with those of the outermost expansion site when the +// `collapse_debuginfo` feature is active and the command line flag is provided. + +// compile-flags:-g -Z collapse_macro_debuginfo=yes + +// === GDB TESTS =================================================================================== + +// gdb-command:run +// gdb-command:next +// gdb-command:frame +// gdb-check:[...]#loc1[...] +// gdb-command:next +// gdb-command:frame +// gdb-check:[...]#loc2[...] +// gdb-command:next +// gdb-command:frame +// gdb-check:[...]#loc3[...] +// gdb-command:continue + +fn one() { + println!("one"); +} +fn two() { + println!("two"); +} +fn three() { + println!("three"); +} +fn four() { + println!("four"); +} + +macro_rules! outer { + ($b:block) => { + one(); + inner!(); + $b + }; +} + +macro_rules! inner { + () => { + two(); + }; +} + +fn main() { + let ret = 0; // #break + outer!({ // #loc1 + three(); // #loc2 + four(); // #loc3 + }); + std::process::exit(ret); +} diff --git a/tests/incremental/dirty_clean.rs b/tests/incremental/dirty_clean.rs index 11d999ab3285..87a8696b1899 100644 --- a/tests/incremental/dirty_clean.rs +++ b/tests/incremental/dirty_clean.rs @@ -26,12 +26,11 @@ mod y { use x; #[rustc_clean( - except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig", + except="hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig", cfg="cfail2", )] pub fn y() { - //[cfail2]~^ ERROR `hir_owner(y)` should be dirty but is not - //[cfail2]~| ERROR `hir_owner_nodes(y)` should be dirty but is not + //[cfail2]~^ ERROR `hir_owner_nodes(y)` should be dirty but is not //[cfail2]~| ERROR `generics_of(y)` should be dirty but is not //[cfail2]~| ERROR `predicates_of(y)` should be dirty but is not //[cfail2]~| ERROR `type_of(y)` should be dirty but is not diff --git a/tests/incremental/hash-module-order.rs b/tests/incremental/hash-module-order.rs index fe9af9eeb370..f9244d8adbf3 100644 --- a/tests/incremental/hash-module-order.rs +++ b/tests/incremental/hash-module-order.rs @@ -12,14 +12,14 @@ #![feature(rustc_attrs)] #[cfg(rpass1)] -#[rustc_clean(cfg="rpass1",except="hir_owner")] +#[rustc_clean(cfg="rpass1",except="hir_owner_nodes")] mod foo { struct First; struct Second; } #[cfg(rpass2)] -#[rustc_clean(cfg="rpass2",except="hir_owner")] +#[rustc_clean(cfg="rpass2",except="hir_owner_nodes")] mod foo { struct Second; struct First; diff --git a/tests/incremental/hashes/consts.rs b/tests/incremental/hashes/consts.rs index eaef63386ffd..7cba3c159e60 100644 --- a/tests/incremental/hashes/consts.rs +++ b/tests/incremental/hashes/consts.rs @@ -19,7 +19,7 @@ const CONST_VISIBILITY: u8 = 0; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] pub const CONST_VISIBILITY: u8 = 0; @@ -29,7 +29,7 @@ pub const CONST_VISIBILITY: u8 = 0; const CONST_CHANGE_TYPE_1: i32 = 0; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_TYPE_1: u32 = 0; @@ -39,7 +39,7 @@ const CONST_CHANGE_TYPE_1: u32 = 0; const CONST_CHANGE_TYPE_2: Option = None; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_TYPE_2: Option = None; @@ -99,11 +99,11 @@ mod const_change_type_indirectly { #[cfg(not(cfail1))] use super::ReferencedType2 as Type; - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_TYPE_INDIRECTLY_1: Type = Type; - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_TYPE_INDIRECTLY_2: Option = None; } diff --git a/tests/incremental/hashes/enum_constructors.rs b/tests/incremental/hashes/enum_constructors.rs index f685fe46d70d..0a88dd4e1553 100644 --- a/tests/incremental/hashes/enum_constructors.rs +++ b/tests/incremental/hashes/enum_constructors.rs @@ -148,17 +148,9 @@ pub mod change_constructor_path_indirectly_struct_like { #[cfg(not(any(cfail1,cfail4)))] use super::Enum2 as TheEnum; - #[rustc_clean( - cfg="cfail2", - except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,\ - typeck" - )] + #[rustc_clean(cfg="cfail2", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean( - cfg="cfail5", - except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,\ - typeck" - )] + #[rustc_clean(cfg="cfail5", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn function() -> TheEnum { TheEnum::Struct { @@ -261,17 +253,9 @@ pub mod change_constructor_path_indirectly_tuple_like { #[cfg(not(any(cfail1,cfail4)))] use super::Enum2 as TheEnum; - #[rustc_clean( - cfg="cfail2", - except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,\ - typeck" - )] + #[rustc_clean(cfg="cfail2", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean( - cfg="cfail5", - except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,\ - typeck" - )] + #[rustc_clean(cfg="cfail5", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn function() -> TheEnum { TheEnum::Tuple(0, 1, 2) @@ -350,17 +334,9 @@ pub mod change_constructor_path_indirectly_c_like { #[cfg(not(any(cfail1,cfail4)))] use super::Clike2 as TheEnum; - #[rustc_clean( - cfg="cfail2", - except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,\ - typeck" - )] + #[rustc_clean(cfg="cfail2", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean( - cfg="cfail5", - except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,\ - typeck" - )] + #[rustc_clean(cfg="cfail5", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn function() -> TheEnum { TheEnum::B diff --git a/tests/incremental/hashes/enum_defs.rs b/tests/incremental/hashes/enum_defs.rs index bc83723a908f..cb7a4e61e4f5 100644 --- a/tests/incremental/hashes/enum_defs.rs +++ b/tests/incremental/hashes/enum_defs.rs @@ -31,7 +31,7 @@ enum EnumVisibility { A } #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub enum EnumVisibility { A } @@ -45,9 +45,9 @@ enum EnumChangeNameCStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumChangeNameCStyleVariant { Variant1, @@ -64,9 +64,9 @@ enum EnumChangeNameTupleStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumChangeNameTupleStyleVariant { Variant1, @@ -83,9 +83,9 @@ enum EnumChangeNameStructStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumChangeNameStructStyleVariant { Variant1, @@ -118,9 +118,9 @@ enum EnumChangeValueCStyleVariant1 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumChangeValueCStyleVariant1 { Variant1, @@ -136,9 +136,9 @@ enum EnumAddCStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddCStyleVariant { Variant1, @@ -155,9 +155,9 @@ enum EnumRemoveCStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumRemoveCStyleVariant { Variant1, @@ -172,9 +172,9 @@ enum EnumAddTupleStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddTupleStyleVariant { Variant1, @@ -191,9 +191,9 @@ enum EnumRemoveTupleStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumRemoveTupleStyleVariant { Variant1, @@ -208,9 +208,9 @@ enum EnumAddStructStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddStructStyleVariant { Variant1, @@ -227,9 +227,9 @@ enum EnumRemoveStructStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumRemoveStructStyleVariant { Variant1, @@ -244,9 +244,9 @@ enum EnumChangeFieldTypeTupleStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] enum EnumChangeFieldTypeTupleStyleVariant { Variant1(u32, @@ -263,9 +263,9 @@ enum EnumChangeFieldTypeStructStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] enum EnumChangeFieldTypeStructStyleVariant { Variant1, @@ -284,9 +284,9 @@ enum EnumChangeFieldNameStructStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumChangeFieldNameStructStyleVariant { Variant1 { a: u32, c: u32 }, @@ -301,9 +301,9 @@ enum EnumChangeOrderTupleStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] enum EnumChangeOrderTupleStyleVariant { Variant1( @@ -320,9 +320,9 @@ enum EnumChangeFieldOrderStructStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumChangeFieldOrderStructStyleVariant { Variant1 { b: f32, a: u32 }, @@ -337,9 +337,9 @@ enum EnumAddFieldTupleStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddFieldTupleStyleVariant { Variant1(u32, u32, u32), @@ -354,9 +354,9 @@ enum EnumAddFieldStructStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddFieldStructStyleVariant { Variant1 { a: u32, b: u32, c: u32 }, @@ -411,9 +411,9 @@ enum EnumChangeNameOfTypeParameter { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumChangeNameOfTypeParameter { Variant1(T), @@ -429,9 +429,9 @@ enum EnumAddTypeParameter { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddTypeParameter { Variant1(S), @@ -447,9 +447,9 @@ enum EnumChangeNameOfLifetimeParameter<'a> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,generics_of,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,generics_of,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumChangeNameOfLifetimeParameter<'b> { Variant1(&'b u32), @@ -465,9 +465,9 @@ enum EnumAddLifetimeParameter<'a> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,generics_of,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,generics_of,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddLifetimeParameter<'a, 'b> { Variant1(&'a u32), @@ -484,9 +484,9 @@ enum EnumAddLifetimeParameterBound<'a, 'b> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddLifetimeParameterBound<'a, 'b: 'a> { Variant1(&'a u32), @@ -501,9 +501,9 @@ enum EnumAddLifetimeBoundToParameter<'a, T> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddLifetimeBoundToParameter<'a, T: 'a> { Variant1(T), @@ -519,9 +519,9 @@ enum EnumAddTraitBound { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddTraitBound { Variant1(T), @@ -537,9 +537,9 @@ enum EnumAddLifetimeParameterBoundWhere<'a, 'b> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddLifetimeParameterBoundWhere<'a, 'b> where 'b: 'a { Variant1(&'a u32), @@ -556,9 +556,9 @@ enum EnumAddLifetimeBoundToParameterWhere<'a, T> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddLifetimeBoundToParameterWhere<'a, T> where T: 'a { Variant1(T), @@ -574,9 +574,9 @@ enum EnumAddTraitBoundWhere { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddTraitBoundWhere where T: Sync { Variant1(T), @@ -592,9 +592,9 @@ enum EnumSwapUsageTypeParameters { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] enum EnumSwapUsageTypeParameters { Variant1 { @@ -615,9 +615,9 @@ enum EnumSwapUsageLifetimeParameters<'a, 'b> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] enum EnumSwapUsageLifetimeParameters<'a, 'b> { Variant1 { @@ -642,9 +642,9 @@ mod change_field_type_indirectly_tuple_style { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedType2 as FieldType; - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] + #[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] enum TupleStyle { Variant1( @@ -662,9 +662,9 @@ mod change_field_type_indirectly_struct_style { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedType2 as FieldType; - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] + #[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] enum StructStyle { Variant1 { @@ -687,9 +687,9 @@ mod change_trait_bound_indirectly { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")] + #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail6")] enum Enum { Variant1(T) @@ -705,9 +705,9 @@ mod change_trait_bound_indirectly_where { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")] + #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail6")] enum Enum where T: Trait { Variant1(T) diff --git a/tests/incremental/hashes/extern_mods.rs b/tests/incremental/hashes/extern_mods.rs index 1906843c7a24..93a8fcfea321 100644 --- a/tests/incremental/hashes/extern_mods.rs +++ b/tests/incremental/hashes/extern_mods.rs @@ -24,9 +24,9 @@ extern "C" { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes")] #[rustc_clean(cfg = "cfail6")] extern "C" { pub fn change_function_name2(c: i64) -> i32; @@ -129,9 +129,9 @@ extern "C" { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes")] #[rustc_clean(cfg = "cfail6")] extern "rust-call" { pub fn change_calling_convention(c: (i32,)); @@ -159,9 +159,9 @@ extern "C" { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes")] #[rustc_clean(cfg = "cfail6")] extern "C" { pub fn add_function1(c: i32); diff --git a/tests/incremental/hashes/function_interfaces.rs b/tests/incremental/hashes/function_interfaces.rs index 23b81705f9aa..2aaaf94492c2 100644 --- a/tests/incremental/hashes/function_interfaces.rs +++ b/tests/incremental/hashes/function_interfaces.rs @@ -25,12 +25,12 @@ pub fn add_parameter() {} #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail6")] pub fn add_parameter(p: i32) {} @@ -41,9 +41,9 @@ pub fn add_parameter(p: i32) {} pub fn add_return_type() {} #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg = "cfail6")] pub fn add_return_type() -> () {} @@ -55,12 +55,12 @@ pub fn type_of_parameter(p: i32) {} #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail6")] pub fn type_of_parameter(p: i64) {} @@ -73,12 +73,12 @@ pub fn type_of_parameter_ref(p: &i32) {} #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail6")] pub fn type_of_parameter_ref(p: &mut i32) {} @@ -91,12 +91,12 @@ pub fn order_of_parameters(p1: i32, p2: i64) {} #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail6")] pub fn order_of_parameters(p2: i64, p1: i32) {} @@ -109,12 +109,12 @@ pub fn make_unsafe() {} #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail6")] pub unsafe fn make_unsafe() {} @@ -125,9 +125,9 @@ pub unsafe fn make_unsafe() {} pub fn make_extern() {} #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, typeck, fn_sig")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, typeck, fn_sig")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, typeck, fn_sig")] +#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, typeck, fn_sig")] #[rustc_clean(cfg = "cfail6")] pub extern "C" fn make_extern() {} @@ -139,12 +139,12 @@ pub fn type_parameter () {} #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of" + except = "hir_owner_nodes, generics_of, type_of, predicates_of" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of" + except = "hir_owner_nodes, generics_of, type_of, predicates_of" )] #[rustc_clean(cfg = "cfail6")] pub fn type_parameter() {} @@ -155,9 +155,9 @@ pub fn type_parameter() {} pub fn lifetime_parameter () {} #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, generics_of,fn_sig")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, generics_of,fn_sig")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, generics_of,fn_sig")] +#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, generics_of,fn_sig")] #[rustc_clean(cfg = "cfail6")] pub fn lifetime_parameter<'a>() {} @@ -167,7 +167,7 @@ pub fn lifetime_parameter<'a>() {} pub fn trait_bound() {} #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] pub fn trait_bound() {} @@ -177,9 +177,9 @@ pub fn trait_bound() {} pub fn builtin_bound() {} #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, predicates_of")] +#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail6")] pub fn builtin_bound() {} @@ -191,12 +191,12 @@ pub fn lifetime_bound<'a, T>() {} #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig" + except = "hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig,optimized_mir" + except = "hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig,optimized_mir" )] #[rustc_clean(cfg = "cfail6")] pub fn lifetime_bound<'a, T: 'a>() {} @@ -207,7 +207,7 @@ pub fn lifetime_bound<'a, T: 'a>() {} pub fn second_trait_bound() {} #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] pub fn second_trait_bound() {} @@ -217,9 +217,9 @@ pub fn second_trait_bound() {} pub fn second_builtin_bound() {} #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, predicates_of")] +#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail6")] pub fn second_builtin_bound() {} @@ -231,12 +231,12 @@ pub fn second_lifetime_bound<'a, 'b, T: 'a >() {} #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig" + except = "hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig" + except = "hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig" )] #[rustc_clean(cfg = "cfail6")] pub fn second_lifetime_bound<'a, 'b, T: 'a + 'b>() {} @@ -302,9 +302,9 @@ pub fn return_impl_trait() -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, typeck, fn_sig")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, typeck, fn_sig")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, typeck, fn_sig, optimized_mir")] +#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, typeck, fn_sig, optimized_mir")] #[rustc_clean(cfg = "cfail6")] pub fn return_impl_trait() -> impl Clone { 0 @@ -339,12 +339,12 @@ pub mod change_return_type_indirectly { #[rustc_clean( cfg = "cfail2", - except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail6")] pub fn indirect_return_type() -> ReturnType { @@ -362,12 +362,12 @@ pub mod change_parameter_type_indirectly { #[rustc_clean( cfg = "cfail2", - except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail6")] pub fn indirect_parameter_type(p: ParameterType) {} @@ -384,9 +384,9 @@ pub mod change_trait_bound_indirectly { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")] + #[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] - #[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, predicates_of")] + #[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail6")] pub fn indirect_trait_bound(p: T) {} } @@ -399,9 +399,9 @@ pub mod change_trait_bound_indirectly_in_where_clause { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")] + #[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] - #[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, predicates_of")] + #[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail6")] pub fn indirect_trait_bound_where(p: T) where diff --git a/tests/incremental/hashes/if_expressions.rs b/tests/incremental/hashes/if_expressions.rs index 937fd3ac879a..cd80f8aa00a5 100644 --- a/tests/incremental/hashes/if_expressions.rs +++ b/tests/incremental/hashes/if_expressions.rs @@ -27,9 +27,9 @@ pub fn change_condition(x: bool) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_condition(x: bool) -> u32 { if !x { @@ -103,9 +103,9 @@ pub fn add_else_branch(x: bool) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_else_branch(x: bool) -> u32 { let mut ret = 1; @@ -156,9 +156,9 @@ pub fn change_then_branch_if_let(x: Option) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_then_branch_if_let(x: Option) -> u32 { if let Some(x) = x { @@ -209,9 +209,9 @@ pub fn add_else_branch_if_let(x: Option) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn add_else_branch_if_let(x: Option) -> u32 { let mut ret = 1; diff --git a/tests/incremental/hashes/indexing_expressions.rs b/tests/incremental/hashes/indexing_expressions.rs index b1ac6f6fa6c2..4bccec61a7ce 100644 --- a/tests/incremental/hashes/indexing_expressions.rs +++ b/tests/incremental/hashes/indexing_expressions.rs @@ -74,9 +74,9 @@ fn add_lower_bound(slice: &[u32]) -> &[u32] { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,typeck", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,typeck", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn add_lower_bound(slice: &[u32]) -> &[u32] { &slice[3..4] @@ -91,9 +91,9 @@ fn add_upper_bound(slice: &[u32]) -> &[u32] { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,typeck", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,typeck", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn add_upper_bound(slice: &[u32]) -> &[u32] { &slice[3..7] @@ -125,9 +125,9 @@ fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,typeck", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,typeck", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] { &slice[3..=7] diff --git a/tests/incremental/hashes/inherent_impls.rs b/tests/incremental/hashes/inherent_impls.rs index 285f857c9cbc..853fbc79fc87 100644 --- a/tests/incremental/hashes/inherent_impls.rs +++ b/tests/incremental/hashes/inherent_impls.rs @@ -26,9 +26,9 @@ impl Foo { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,associated_item_def_ids")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,associated_item_def_ids")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,associated_item_def_ids")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,associated_item_def_ids")] #[rustc_clean(cfg="cfail6")] impl Foo { #[rustc_clean(cfg="cfail3")] @@ -115,7 +115,7 @@ impl Foo { impl Foo { //-------------------------- //-------------------------- - //-------------------------------------------------------------- + //---------------------------------------------------- //-------------------------- pub fn method_privacy() { } } @@ -128,7 +128,7 @@ impl Foo { impl Foo { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] + #[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] fn method_privacy() { } } @@ -138,31 +138,31 @@ impl Foo { impl Foo { //------------ //--------------- - //--------------------------------------------------------------------------------------------- + //----------------------------------------------------------------------------------- // //-------------------------- //------------ //--------------- - //--------------------------------------------------------------------------------------------- + //----------------------------------------------------------------------------------- // //-------------------------- pub fn method_selfness() { } } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] impl Foo { #[rustc_clean( cfg="cfail2", - except="hir_owner,hir_owner_nodes,fn_sig,generics_of,typeck,associated_item,optimized_mir", + except="hir_owner_nodes,fn_sig,generics_of,typeck,associated_item,optimized_mir", )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( cfg="cfail5", - except="hir_owner,hir_owner_nodes,fn_sig,generics_of,typeck,associated_item,optimized_mir", + except="hir_owner_nodes,fn_sig,generics_of,typeck,associated_item,optimized_mir", )] #[rustc_clean(cfg="cfail6")] pub fn method_selfness(&self) { } @@ -171,9 +171,9 @@ impl Foo { // Change Method Selfmutness --------------------------------------------------- #[cfg(any(cfail1,cfail4))] impl Foo { - //------------------------------------------------------------------------------------------ + //-------------------------------------------------------------------------------- //-------------------------- - //------------------------------------------------------------------------------------------ + //-------------------------------------------------------------------------------- //-------------------------- pub fn method_selfmutness(& self) { } } @@ -184,9 +184,9 @@ impl Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,fn_sig,typeck,optimized_mir")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")] + #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,fn_sig,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn method_selfmutness(&mut self) { } } @@ -200,9 +200,9 @@ impl Foo { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,associated_item_def_ids")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,associated_item_def_ids")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,associated_item_def_ids")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,associated_item_def_ids")] #[rustc_clean(cfg="cfail6")] impl Foo { #[rustc_clean(cfg="cfail2")] @@ -221,9 +221,9 @@ impl Foo { // Add Method Parameter -------------------------------------------------------- #[cfg(any(cfail1,cfail4))] impl Foo { - //------------------------------------------------------------------------------------------ + //-------------------------------------------------------------------------------- //-------------------------- - //------------------------------------------------------------------------------------------ + //-------------------------------------------------------------------------------- //-------------------------- pub fn add_method_parameter(&self ) { } } @@ -234,9 +234,9 @@ impl Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,fn_sig,typeck,optimized_mir")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")] + #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,fn_sig,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn add_method_parameter(&self, _: i32) { } } @@ -271,9 +271,9 @@ impl Foo { // Change Method Return Type --------------------------------------------------- #[cfg(any(cfail1,cfail4))] impl Foo { - //------------------------------------------------------------------------------------------ + //-------------------------------------------------------------------------------- //-------------------------- - //------------------------------------------------------------------------------------------ + //-------------------------------------------------------------------------------- //-------------------------- pub fn change_method_return_type(&self) -> u16 { 0 } } @@ -284,9 +284,9 @@ impl Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,fn_sig,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,fn_sig,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_method_return_type(&self) -> u32 { 0 } } @@ -348,9 +348,9 @@ impl Foo { // Make method unsafe ---------------------------------------------------------- #[cfg(any(cfail1,cfail4))] impl Foo { - //------------------------------------------------------------------------------------------ + //-------------------------------------------------------------------------------- //-------------------------- - //------------------------------------------------------------------------------------------ + //-------------------------------------------------------------------------------- //-------------------------- pub fn make_method_unsafe(&self) { } } @@ -361,9 +361,9 @@ impl Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,fn_sig,typeck,optimized_mir")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")] + #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,fn_sig,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub unsafe fn make_method_unsafe(&self) { } } @@ -373,9 +373,9 @@ impl Foo { // Make method extern ---------------------------------------------------------- #[cfg(any(cfail1,cfail4))] impl Foo { - //---------------------------------------------------------------------------- + //------------------------------------------------------------------ //-------------------------- - //---------------------------------------------------------------------------- + //------------------------------------------------------------------ //-------------------------- pub fn make_method_extern(&self) { } } @@ -386,9 +386,9 @@ impl Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,fn_sig,typeck")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,typeck")] + #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,fn_sig,typeck")] #[rustc_clean(cfg="cfail6")] pub extern "C" fn make_method_extern(&self) { } } @@ -398,9 +398,9 @@ impl Foo { // Change method calling convention -------------------------------------------- #[cfg(any(cfail1,cfail4))] impl Foo { - //---------------------------------------------------------------------------- + //------------------------------------------------------------------ //-------------------------- - //---------------------------------------------------------------------------- + //------------------------------------------------------------------ //-------------------------- pub extern "C" fn change_method_calling_convention(&self) { } } @@ -411,9 +411,9 @@ impl Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,fn_sig,typeck")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,typeck")] + #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,fn_sig,typeck")] #[rustc_clean(cfg="cfail6")] pub extern "system" fn change_method_calling_convention(&self) { } } @@ -432,9 +432,9 @@ impl Foo { // ---------------------------------------------------------- // ----------------------------------------------------------- // ---------------------------------------------------------- - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- - // -------------------------------------------------------------------------------- + // ---------------------------------------------------------------------- // ------------------------- pub fn add_lifetime_parameter_to_method (&self) { } } @@ -454,9 +454,9 @@ impl Foo { // if we lower generics before the body, then the `HirId` for // things in the body will be affected. So if you start to see // `typeck` appear dirty, that might be the cause. -nmatsakis - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,fn_sig")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,generics_of")] + #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,fn_sig,generics_of")] #[rustc_clean(cfg="cfail6")] pub fn add_lifetime_parameter_to_method<'a>(&self) { } } @@ -477,12 +477,12 @@ impl Foo { // ------------------------------------------------- // ----------- // -------------- - // ---------------------------------------------------------------------- + // ------------------------------------------------------------ // // ------------------------- // ----------- // -------------- - // ---------------------------------------------------------------------- + // ------------------------------------------------------------ // // ------------------------- pub fn add_type_parameter_to_method (&self) { } @@ -505,12 +505,12 @@ impl Foo { // appear dirty, that might be the cause. -nmatsakis #[rustc_clean( cfg="cfail2", - except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of", + except="hir_owner_nodes,generics_of,predicates_of,type_of", )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( cfg="cfail5", - except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of", + except="hir_owner_nodes,generics_of,predicates_of,type_of", )] #[rustc_clean(cfg="cfail6")] pub fn add_type_parameter_to_method(&self) { } @@ -523,12 +523,12 @@ impl Foo { impl Foo { //------------ //--------------- - //----------------------------------------------------------------------------- + //------------------------------------------------------------------- // //-------------------------- //------------ //--------------- - //----------------------------------------------------------------------------- + //------------------------------------------------------------------- // //-------------------------- pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b >(&self) { } @@ -542,12 +542,12 @@ impl Foo { impl Foo { #[rustc_clean( cfg="cfail2", - except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" + except="hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( cfg="cfail5", - except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" + except="hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" )] #[rustc_clean(cfg="cfail6")] pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b: 'a>(&self) { } @@ -569,12 +569,12 @@ impl Foo { // ------------------------------------------------- // ----------- // -------------- - // ---------------------------------------------------------------------------- + // ------------------------------------------------------------------ // // ------------------------- // ----------- // -------------- - // ---------------------------------------------------------------------------- + // ------------------------------------------------------------------ // // ------------------------- pub fn add_lifetime_bound_to_type_param_of_method<'a, T >(&self) { } @@ -597,12 +597,12 @@ impl Foo { // appear dirty, that might be the cause. -nmatsakis #[rustc_clean( cfg="cfail2", - except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" + except="hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( cfg="cfail5", - except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" + except="hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" )] #[rustc_clean(cfg="cfail6")] pub fn add_lifetime_bound_to_type_param_of_method<'a, T: 'a>(&self) { } @@ -622,9 +622,9 @@ impl Foo { // ------------------------------------------------------------ // ------------------------------------------------------ // ------------------------------------------------- - // --------------------------------------------------------------------------- + // ----------------------------------------------------------------- // ------------------------- - // --------------------------------------------------------------------------- + // ----------------------------------------------------------------- // ------------------------- pub fn add_trait_bound_to_type_param_of_method(&self) { } } @@ -644,9 +644,9 @@ impl Foo { // generics before the body, then the `HirId` for things in the // body will be affected. So if you start to see `typeck` // appear dirty, that might be the cause. -nmatsakis - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")] + #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail6")] pub fn add_trait_bound_to_type_param_of_method(&self) { } } @@ -689,9 +689,9 @@ impl Bar { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,generics_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,generics_of")] #[rustc_clean(cfg="cfail6")] impl Bar { #[rustc_clean( @@ -716,9 +716,9 @@ impl Bar { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] impl Bar { #[rustc_clean(cfg="cfail2", except="fn_sig,optimized_mir,typeck")] @@ -737,9 +737,9 @@ impl Bar { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] impl Bar { #[rustc_clean(cfg="cfail2")] @@ -758,9 +758,9 @@ impl Bar { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] impl Bar { #[rustc_clean(cfg="cfail2")] diff --git a/tests/incremental/hashes/match_expressions.rs b/tests/incremental/hashes/match_expressions.rs index ecb19480d654..ebcf1708a7aa 100644 --- a/tests/incremental/hashes/match_expressions.rs +++ b/tests/incremental/hashes/match_expressions.rs @@ -28,9 +28,9 @@ pub fn add_arm(x: u32) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_arm(x: u32) -> u32 { match x { @@ -79,9 +79,9 @@ pub fn add_guard_clause(x: u32, y: bool) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_guard_clause(x: u32, y: bool) -> u32 { match x { @@ -104,9 +104,9 @@ pub fn change_guard_clause(x: u32, y: bool) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_guard_clause(x: u32, y: bool) -> u32 { match x { @@ -129,9 +129,9 @@ pub fn add_at_binding(x: u32) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_at_binding(x: u32) -> u32 { match x { @@ -178,9 +178,9 @@ pub fn change_simple_name_to_pattern(x: u32) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_simple_name_to_pattern(x: u32) -> u32 { match (x, x & 1) { @@ -273,9 +273,9 @@ pub fn add_amp_to_binding_in_pattern(x: u32) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_amp_to_binding_in_pattern(x: u32) -> u32 { match (&x, x & 1) { @@ -322,9 +322,9 @@ pub fn add_alternative_to_arm(x: u32) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_alternative_to_arm(x: u32) -> u32 { match x { diff --git a/tests/incremental/hashes/statics.rs b/tests/incremental/hashes/statics.rs index bb83f8300d06..2adf05390bc4 100644 --- a/tests/incremental/hashes/statics.rs +++ b/tests/incremental/hashes/statics.rs @@ -26,7 +26,7 @@ static STATIC_VISIBILITY: u8 = 0; #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub static STATIC_VISIBILITY: u8 = 0; @@ -36,9 +36,9 @@ pub static STATIC_VISIBILITY: u8 = 0; static STATIC_MUTABILITY: u8 = 0; #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] static mut STATIC_MUTABILITY: u8 = 0; @@ -87,9 +87,9 @@ static STATIC_THREAD_LOCAL: u8 = 0; static STATIC_CHANGE_TYPE_1: i16 = 0; #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] static STATIC_CHANGE_TYPE_1: u64 = 0; @@ -99,9 +99,9 @@ static STATIC_CHANGE_TYPE_1: u64 = 0; static STATIC_CHANGE_TYPE_2: Option = None; #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] static STATIC_CHANGE_TYPE_2: Option = None; @@ -169,15 +169,15 @@ mod static_change_type_indirectly { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedType2 as Type; - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] + #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] static STATIC_CHANGE_TYPE_INDIRECTLY_1: Type = Type; - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] + #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] static STATIC_CHANGE_TYPE_INDIRECTLY_2: Option = None; } diff --git a/tests/incremental/hashes/struct_constructors.rs b/tests/incremental/hashes/struct_constructors.rs index e50e5674c661..eabb8683e029 100644 --- a/tests/incremental/hashes/struct_constructors.rs +++ b/tests/incremental/hashes/struct_constructors.rs @@ -90,9 +90,9 @@ pub fn add_field_regular_struct() -> RegularStruct { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_field_regular_struct() -> RegularStruct { let struct1 = RegularStruct { @@ -185,15 +185,9 @@ pub mod change_constructor_path_indirectly_regular_struct { #[cfg(not(any(cfail1,cfail4)))] use super::RegularStruct2 as Struct; - #[rustc_clean( - cfg="cfail2", - except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,typeck" - )] + #[rustc_clean(cfg="cfail2", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean( - cfg="cfail5", - except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,typeck" - )] + #[rustc_clean(cfg="cfail5", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn function() -> Struct { Struct { @@ -251,15 +245,9 @@ pub mod change_constructor_path_indirectly_tuple_struct { #[cfg(not(any(cfail1,cfail4)))] use super::TupleStruct2 as Struct; - #[rustc_clean( - cfg="cfail5", - except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,typeck" - )] + #[rustc_clean(cfg="cfail5", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] - #[rustc_clean( - cfg="cfail2", - except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,typeck" - )] + #[rustc_clean(cfg="cfail2", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] pub fn function() -> Struct { Struct(0, 1, 2) diff --git a/tests/incremental/hashes/struct_defs.rs b/tests/incremental/hashes/struct_defs.rs index 4a2706b4f010..6ea4d890e4d5 100644 --- a/tests/incremental/hashes/struct_defs.rs +++ b/tests/incremental/hashes/struct_defs.rs @@ -51,9 +51,9 @@ struct LayoutC; struct TupleStructFieldType(i32); #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] // Note that changing the type of a field does not change the type of the struct or enum, but // adding/removing fields or changing a fields name or visibility does. @@ -68,9 +68,9 @@ struct TupleStructFieldType( struct TupleStructAddField(i32); #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,type_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,type_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct TupleStructAddField( i32, @@ -86,7 +86,7 @@ struct TupleStructFieldVisibility( char); #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] struct TupleStructFieldVisibility(pub char); @@ -97,9 +97,9 @@ struct TupleStructFieldVisibility(pub char); struct RecordStructFieldType { x: f32 } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] // Note that changing the type of a field does not change the type of the struct or enum, but // adding/removing fields or changing a fields name or visibility does. @@ -114,9 +114,9 @@ struct RecordStructFieldType { struct RecordStructFieldName { x: f32 } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,type_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,type_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct RecordStructFieldName { y: f32 } @@ -127,9 +127,9 @@ struct RecordStructFieldName { y: f32 } struct RecordStructAddField { x: f32 } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,type_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,type_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct RecordStructAddField { x: f32, @@ -144,7 +144,7 @@ struct RecordStructFieldVisibility { x: f32 } #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] struct RecordStructFieldVisibility { pub x: f32 } @@ -155,9 +155,9 @@ struct RecordStructFieldVisibility { pub x: f32 } struct AddLifetimeParameter<'a>(&'a f32, &'a f64); #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of,generics_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,type_of,generics_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of,generics_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,type_of,generics_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct AddLifetimeParameter<'a, 'b>(&'a f32, &'b f64); @@ -168,9 +168,9 @@ struct AddLifetimeParameter<'a, 'b>(&'a f32, &'b f64); struct AddLifetimeParameterBound<'a, 'b>(&'a f32, &'b f64); #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct AddLifetimeParameterBound<'a, 'b: 'a>( &'a f32, @@ -181,9 +181,9 @@ struct AddLifetimeParameterBound<'a, 'b: 'a>( struct AddLifetimeParameterBoundWhereClause<'a, 'b>(&'a f32, &'b f64); #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct AddLifetimeParameterBoundWhereClause<'a, 'b>( &'a f32, @@ -197,9 +197,9 @@ struct AddLifetimeParameterBoundWhereClause<'a, 'b>( struct AddTypeParameter(T1, T1); #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of,generics_of,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,type_of,generics_of,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of,generics_of,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,type_of,generics_of,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct AddTypeParameter( // The field contains the parent's Generics, so it's dirty even though its @@ -215,9 +215,9 @@ struct AddTypeParameter( struct AddTypeParameterBound(T); #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct AddTypeParameterBound( T @@ -228,9 +228,9 @@ struct AddTypeParameterBound( struct AddTypeParameterBoundWhereClause(T); #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct AddTypeParameterBoundWhereClause( T @@ -257,7 +257,7 @@ struct Visibility; #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub struct Visibility; @@ -271,9 +271,9 @@ mod tuple_struct_change_field_type_indirectly { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedType2 as FieldType; - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct TupleStruct( FieldType @@ -288,9 +288,9 @@ mod record_struct_change_field_type_indirectly { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedType2 as FieldType; - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct RecordStruct { _x: FieldType @@ -310,9 +310,9 @@ mod change_trait_bound_indirectly { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct Struct(T); } @@ -324,9 +324,9 @@ mod change_trait_bound_indirectly_in_where_clause { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct Struct(T) where T : Trait; } diff --git a/tests/incremental/hashes/trait_defs.rs b/tests/incremental/hashes/trait_defs.rs index 7b8c6245d2d4..0a5eba739772 100644 --- a/tests/incremental/hashes/trait_defs.rs +++ b/tests/incremental/hashes/trait_defs.rs @@ -30,7 +30,7 @@ trait TraitVisibility { } #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub trait TraitVisibility { } @@ -41,9 +41,9 @@ pub trait TraitVisibility { } trait TraitUnsafety { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] unsafe trait TraitUnsafety { } @@ -55,9 +55,9 @@ trait TraitAddMethod { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub trait TraitAddMethod { fn method(); @@ -72,9 +72,9 @@ trait TraitChangeMethodName { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeMethodName { fn methodChanged(); @@ -85,9 +85,9 @@ trait TraitChangeMethodName { // Add return type to method #[cfg(any(cfail1,cfail4))] trait TraitAddReturnType { - //--------------------------------------------------------------------- + //----------------------------------------------------------- //-------------------------- - //--------------------------------------------------------------------- + //----------------------------------------------------------- //-------------------------- fn method() ; } @@ -98,9 +98,9 @@ trait TraitAddReturnType { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddReturnType { - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method() -> u32; } @@ -110,9 +110,9 @@ trait TraitAddReturnType { // Change return type of method #[cfg(any(cfail1,cfail4))] trait TraitChangeReturnType { - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- fn method() -> u32; } @@ -123,9 +123,9 @@ trait TraitChangeReturnType { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeReturnType { - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method() -> u64; } @@ -135,9 +135,9 @@ trait TraitChangeReturnType { // Add parameter to method #[cfg(any(cfail1,cfail4))] trait TraitAddParameterToMethod { - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- fn method( ); } @@ -148,9 +148,9 @@ trait TraitAddParameterToMethod { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddParameterToMethod { - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(a: u32); } @@ -161,9 +161,9 @@ trait TraitAddParameterToMethod { #[cfg(any(cfail1,cfail4))] trait TraitChangeMethodParameterName { //------------------------------------------------------ - //-------------------------------------------------------------- + //---------------------------------------------------- //-------------------------- - //-------------------------------------------------------------- + //---------------------------------------------------- //-------------------------- fn method(a: u32); @@ -181,9 +181,9 @@ trait TraitChangeMethodParameterName { #[rustc_clean(cfg="cfail6")] trait TraitChangeMethodParameterName { // FIXME(#38501) This should preferably always be clean. - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(b: u32); @@ -199,9 +199,9 @@ trait TraitChangeMethodParameterName { // Change type of method parameter (i32 => i64) #[cfg(any(cfail1,cfail4))] trait TraitChangeMethodParameterType { - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- fn method(a: i32); } @@ -212,9 +212,9 @@ trait TraitChangeMethodParameterType { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeMethodParameterType { - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(a: i64); } @@ -224,9 +224,9 @@ trait TraitChangeMethodParameterType { // Change type of method parameter (&i32 => &mut i32) #[cfg(any(cfail1,cfail4))] trait TraitChangeMethodParameterTypeRef { - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- fn method(a: & i32); } @@ -237,9 +237,9 @@ trait TraitChangeMethodParameterTypeRef { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeMethodParameterTypeRef { - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(a: &mut i32); } @@ -249,9 +249,9 @@ trait TraitChangeMethodParameterTypeRef { // Change order of method parameters #[cfg(any(cfail1,cfail4))] trait TraitChangeMethodParametersOrder { - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- fn method(a: i32, b: i64); } @@ -262,9 +262,9 @@ trait TraitChangeMethodParametersOrder { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeMethodParametersOrder { - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(b: i64, a: i32); } @@ -274,22 +274,22 @@ trait TraitChangeMethodParametersOrder { // Add default implementation to method #[cfg(any(cfail1,cfail4))] trait TraitAddMethodAutoImplementation { - // ------------------------------------------------------------- + // --------------------------------------------------- // ------------------------- - // ------------------------------------------------------------- + // --------------------------------------------------- // ------------------------- fn method() ; } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddMethodAutoImplementation { - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method() {} } @@ -304,9 +304,9 @@ trait TraitChangeOrderOfMethods { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeOrderOfMethods { fn method1(); @@ -318,9 +318,9 @@ trait TraitChangeOrderOfMethods { // Change mode of self parameter #[cfg(any(cfail1,cfail4))] trait TraitChangeModeSelfRefToMut { - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- fn method(& self); } @@ -331,9 +331,9 @@ trait TraitChangeModeSelfRefToMut { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeModeSelfRefToMut { - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(&mut self); } @@ -342,9 +342,9 @@ trait TraitChangeModeSelfRefToMut { #[cfg(any(cfail1,cfail4))] trait TraitChangeModeSelfOwnToMut: Sized { - // ---------------------------------------------------------------------------------- + // ------------------------------------------------------------------------ // ------------------------- - // ---------------------------------------------------------------------------------- + // ------------------------------------------------------------------------ // ------------------------- fn method( self) {} } @@ -355,9 +355,9 @@ trait TraitChangeModeSelfOwnToMut: Sized { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeModeSelfOwnToMut: Sized { - #[rustc_clean(except="hir_owner,hir_owner_nodes,typeck,optimized_mir", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,typeck,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,typeck,optimized_mir", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,typeck,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(mut self) {} } @@ -366,9 +366,9 @@ trait TraitChangeModeSelfOwnToMut: Sized { #[cfg(any(cfail1,cfail4))] trait TraitChangeModeSelfOwnToRef { - // -------------------------------------------------------------------------------- + // ---------------------------------------------------------------------- // ------------------------- - // -------------------------------------------------------------------------------- + // ---------------------------------------------------------------------- // ------------------------- fn method( self); } @@ -379,9 +379,9 @@ trait TraitChangeModeSelfOwnToRef { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeModeSelfOwnToRef { - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,generics_of", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,fn_sig,generics_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,generics_of", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,fn_sig,generics_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(&self); } @@ -391,22 +391,22 @@ trait TraitChangeModeSelfOwnToRef { // Add unsafe modifier to method #[cfg(any(cfail1,cfail4))] trait TraitAddUnsafeModifier { - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- - fn method() ; + fn method(); } #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner", cfg="cfail5")] +#[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddUnsafeModifier { - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] unsafe fn method(); } @@ -416,9 +416,9 @@ trait TraitAddUnsafeModifier { // Add extern modifier to method #[cfg(any(cfail1,cfail4))] trait TraitAddExternModifier { - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- fn method(); } @@ -429,9 +429,9 @@ trait TraitAddExternModifier { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddExternModifier { - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] extern "C" fn method(); } @@ -441,9 +441,9 @@ trait TraitAddExternModifier { // Change extern "C" to extern "stdcall" #[cfg(any(cfail1,cfail4))] trait TraitChangeExternCToRustIntrinsic { - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- - // -------------------------------------------------------------------- + // ---------------------------------------------------------- // ------------------------- extern "C" fn method(); } @@ -454,9 +454,9 @@ trait TraitChangeExternCToRustIntrinsic { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeExternCToRustIntrinsic { - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] extern "stdcall" fn method(); } @@ -466,10 +466,10 @@ trait TraitChangeExternCToRustIntrinsic { // Add type parameter to method #[cfg(any(cfail1,cfail4))] trait TraitAddTypeParameterToMethod { - // -------------------------------------------------------------------------------- + // ---------------------------------------------------------------------- // --------------- // ------------------------- - // -------------------------------------------------------------------------------- + // ---------------------------------------------------------------------- // --------------- // ------------------------- fn method (); @@ -481,10 +481,10 @@ trait TraitAddTypeParameterToMethod { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddTypeParameterToMethod { - #[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of", + #[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of,type_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of", + #[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of,type_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(); @@ -495,9 +495,9 @@ trait TraitAddTypeParameterToMethod { // Add lifetime parameter to method #[cfg(any(cfail1,cfail4))] trait TraitAddLifetimeParameterToMethod { - // -------------------------------------------------------------------------------- + // ---------------------------------------------------------------------- // ------------------------- - // -------------------------------------------------------------------------------- + // ---------------------------------------------------------------------- // ------------------------- fn method (); } @@ -508,9 +508,9 @@ trait TraitAddLifetimeParameterToMethod { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeParameterToMethod { - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,generics_of", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,fn_sig,generics_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,generics_of", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,fn_sig,generics_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method<'a>(); } @@ -524,9 +524,9 @@ trait ReferencedTrait1 { } // Add trait bound to method type parameter #[cfg(any(cfail1,cfail4))] trait TraitAddTraitBoundToMethodTypeParameter { - // --------------------------------------------------------------------------- + // ----------------------------------------------------------------- // ------------------------- - // --------------------------------------------------------------------------- + // ----------------------------------------------------------------- // ------------------------- fn method(); } @@ -537,9 +537,9 @@ trait TraitAddTraitBoundToMethodTypeParameter { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddTraitBoundToMethodTypeParameter { - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(); } @@ -549,9 +549,9 @@ trait TraitAddTraitBoundToMethodTypeParameter { // Add builtin bound to method type parameter #[cfg(any(cfail1,cfail4))] trait TraitAddBuiltinBoundToMethodTypeParameter { - // --------------------------------------------------------------------------- + // ----------------------------------------------------------------- // ------------------------- - // --------------------------------------------------------------------------- + // ----------------------------------------------------------------- // ------------------------- fn method(); } @@ -562,9 +562,9 @@ trait TraitAddBuiltinBoundToMethodTypeParameter { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddBuiltinBoundToMethodTypeParameter { - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(); } @@ -575,12 +575,12 @@ trait TraitAddBuiltinBoundToMethodTypeParameter { #[cfg(any(cfail1,cfail4))] trait TraitAddLifetimeBoundToMethodLifetimeParameter { // ----------- - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------- // -------------- // // ------------------------- // ----------- - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------- // -------------- // // ------------------------- @@ -594,12 +594,12 @@ trait TraitAddLifetimeBoundToMethodLifetimeParameter { #[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeBoundToMethodLifetimeParameter { #[rustc_clean( - except="hir_owner,hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", + except="hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", cfg="cfail2", )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( - except="hir_owner,hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", + except="hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", cfg="cfail5", )] #[rustc_clean(cfg="cfail6")] @@ -611,9 +611,9 @@ trait TraitAddLifetimeBoundToMethodLifetimeParameter { // Add second trait bound to method type parameter #[cfg(any(cfail1,cfail4))] trait TraitAddSecondTraitBoundToMethodTypeParameter { - // --------------------------------------------------------------------------- + // ----------------------------------------------------------------- // ------------------------- - // --------------------------------------------------------------------------- + // ----------------------------------------------------------------- // ------------------------- fn method(); } @@ -624,9 +624,9 @@ trait TraitAddSecondTraitBoundToMethodTypeParameter { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondTraitBoundToMethodTypeParameter { - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(); } @@ -636,9 +636,9 @@ trait TraitAddSecondTraitBoundToMethodTypeParameter { // Add second builtin bound to method type parameter #[cfg(any(cfail1,cfail4))] trait TraitAddSecondBuiltinBoundToMethodTypeParameter { - // --------------------------------------------------------------------------- + // ----------------------------------------------------------------- // ------------------------- - // --------------------------------------------------------------------------- + // ----------------------------------------------------------------- // ------------------------- fn method(); } @@ -649,9 +649,9 @@ trait TraitAddSecondBuiltinBoundToMethodTypeParameter { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondBuiltinBoundToMethodTypeParameter { - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(); } @@ -662,12 +662,12 @@ trait TraitAddSecondBuiltinBoundToMethodTypeParameter { #[cfg(any(cfail1,cfail4))] trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter { // ----------- - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------- // -------------- // // ------------------------- // ----------- - // ----------------------------------------------------------------------------- + // ------------------------------------------------------------------- // -------------- // // ------------------------- @@ -681,12 +681,12 @@ trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter { #[rustc_clean(cfg="cfail6")] trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter { #[rustc_clean( - except="hir_owner,hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", + except="hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", cfg="cfail2", )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( - except="hir_owner,hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", + except="hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", cfg="cfail5", )] #[rustc_clean(cfg="cfail6")] @@ -710,9 +710,9 @@ trait TraitAddAssociatedType { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddAssociatedType { #[rustc_clean(cfg="cfail3")] @@ -731,9 +731,9 @@ trait TraitAddAssociatedType { // Add trait bound to associated type #[cfg(any(cfail1,cfail4))] trait TraitAddTraitBoundToAssociatedType { - // ------------------------------------------------------------- + // --------------------------------------------------- // ------------------------- - // ------------------------------------------------------------- + // --------------------------------------------------- // ------------------------- type Associated ; @@ -749,9 +749,9 @@ trait TraitAddTraitBoundToAssociatedType { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddTraitBoundToAssociatedType { - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] type Associated: ReferencedTrait0; @@ -763,9 +763,9 @@ trait TraitAddTraitBoundToAssociatedType { // Add lifetime bound to associated type #[cfg(any(cfail1,cfail4))] trait TraitAddLifetimeBoundToAssociatedType<'a> { - // ------------------------------------------------------------- + // --------------------------------------------------- // ------------------------- - // ------------------------------------------------------------- + // --------------------------------------------------- // ------------------------- type Associated ; @@ -778,9 +778,9 @@ trait TraitAddLifetimeBoundToAssociatedType<'a> { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeBoundToAssociatedType<'a> { - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] type Associated: 'a; @@ -792,9 +792,9 @@ trait TraitAddLifetimeBoundToAssociatedType<'a> { // Add default to associated type #[cfg(any(cfail1,cfail4))] trait TraitAddDefaultToAssociatedType { - //-------------------------------------------------------------- + //---------------------------------------------------- //-------------------------- - //-------------------------------------------------------------- + //---------------------------------------------------- //-------------------------- type Associated ; @@ -802,14 +802,14 @@ trait TraitAddDefaultToAssociatedType { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddDefaultToAssociatedType { - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] type Associated = ReferenceType0; @@ -825,9 +825,9 @@ trait TraitAddAssociatedConstant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddAssociatedConstant { const Value: u32; @@ -840,9 +840,9 @@ trait TraitAddAssociatedConstant { // Add initializer to associated constant #[cfg(any(cfail1,cfail4))] trait TraitAddInitializerToAssociatedConstant { - //-------------------------------------------------------------- + //---------------------------------------------------- //-------------------------- - //-------------------------------------------------------------- + //---------------------------------------------------- //-------------------------- const Value: u32 ; @@ -854,14 +854,14 @@ trait TraitAddInitializerToAssociatedConstant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddInitializerToAssociatedConstant { - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] const Value: u32 = 1; @@ -877,9 +877,9 @@ trait TraitAddInitializerToAssociatedConstant { // Change type of associated constant #[cfg(any(cfail1,cfail4))] trait TraitChangeTypeOfAssociatedConstant { - // --------------------------------------------------------------------- + // ----------------------------------------------------------- // ------------------------- - // --------------------------------------------------------------------- + // ----------------------------------------------------------- // ------------------------- const Value: u32; @@ -896,9 +896,9 @@ trait TraitChangeTypeOfAssociatedConstant { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeTypeOfAssociatedConstant { - #[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,type_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,type_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] const Value: f64; @@ -916,9 +916,9 @@ trait TraitChangeTypeOfAssociatedConstant { trait TraitAddSuperTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSuperTrait : ReferencedTrait0 { } @@ -929,9 +929,9 @@ trait TraitAddSuperTrait : ReferencedTrait0 { } trait TraitAddBuiltiBound { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddBuiltiBound : Send { } @@ -942,9 +942,9 @@ trait TraitAddBuiltiBound : Send { } trait TraitAddStaticLifetimeBound { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddStaticLifetimeBound : 'static { } @@ -955,9 +955,9 @@ trait TraitAddStaticLifetimeBound : 'static { } trait TraitAddTraitAsSecondBound : ReferencedTrait0 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddTraitAsSecondBound : ReferencedTrait0 + ReferencedTrait1 { } @@ -965,9 +965,9 @@ trait TraitAddTraitAsSecondBound : ReferencedTrait0 + ReferencedTrait1 { } trait TraitAddTraitAsSecondBoundFromBuiltin : Send { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddTraitAsSecondBoundFromBuiltin : Send + ReferencedTrait0 { } @@ -978,9 +978,9 @@ trait TraitAddTraitAsSecondBoundFromBuiltin : Send + ReferencedTrait0 { } trait TraitAddBuiltinBoundAsSecondBound : ReferencedTrait0 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddBuiltinBoundAsSecondBound : ReferencedTrait0 + Send { } @@ -988,9 +988,9 @@ trait TraitAddBuiltinBoundAsSecondBound : ReferencedTrait0 + Send { } trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin : Send { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin: Send + Copy { } @@ -1001,9 +1001,9 @@ trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin: Send + Copy { } trait TraitAddStaticBoundAsSecondBound : ReferencedTrait0 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddStaticBoundAsSecondBound : ReferencedTrait0 + 'static { } @@ -1011,9 +1011,9 @@ trait TraitAddStaticBoundAsSecondBound : ReferencedTrait0 + 'static { } trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send + 'static { } @@ -1024,9 +1024,9 @@ trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send + 'static { } trait TraitAddTypeParameterToTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddTypeParameterToTrait { } @@ -1037,9 +1037,9 @@ trait TraitAddTypeParameterToTrait { } trait TraitAddLifetimeParameterToTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeParameterToTrait<'a> { } @@ -1050,9 +1050,9 @@ trait TraitAddLifetimeParameterToTrait<'a> { } trait TraitAddTraitBoundToTypeParameterOfTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddTraitBoundToTypeParameterOfTrait { } @@ -1063,9 +1063,9 @@ trait TraitAddTraitBoundToTypeParameterOfTrait { } trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T: 'a> { } @@ -1076,9 +1076,9 @@ trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T: 'a> { } trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a, 'b> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b> { } @@ -1089,9 +1089,9 @@ trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b> { } trait TraitAddBuiltinBoundToTypeParameterOfTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddBuiltinBoundToTypeParameterOfTrait { } @@ -1102,9 +1102,9 @@ trait TraitAddBuiltinBoundToTypeParameterOfTrait { } trait TraitAddSecondTypeParameterToTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondTypeParameterToTrait { } @@ -1115,9 +1115,9 @@ trait TraitAddSecondTypeParameterToTrait { } trait TraitAddSecondLifetimeParameterToTrait<'a> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondLifetimeParameterToTrait<'a, 'b> { } @@ -1128,9 +1128,9 @@ trait TraitAddSecondLifetimeParameterToTrait<'a, 'b> { } trait TraitAddSecondTraitBoundToTypeParameterOfTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondTraitBoundToTypeParameterOfTrait { } @@ -1141,9 +1141,9 @@ trait TraitAddSecondTraitBoundToTypeParameterOfTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondLifetimeBoundToTypeParameterOfTrait<'a, 'b, T: 'a + 'b> { } @@ -1154,9 +1154,9 @@ trait TraitAddSecondLifetimeBoundToTypeParameterOfTrait<'a, 'b, T: 'a + 'b> { } trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b, 'c> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b + 'c, 'b, 'c> { } @@ -1167,9 +1167,9 @@ trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b + 'c, 'b, 'c> trait TraitAddSecondBuiltinBoundToTypeParameterOfTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondBuiltinBoundToTypeParameterOfTrait { } @@ -1185,9 +1185,9 @@ struct ReferenceType1 {} trait TraitAddTraitBoundToTypeParameterOfTraitWhere { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddTraitBoundToTypeParameterOfTraitWhere where T: ReferencedTrait0 { } @@ -1198,9 +1198,9 @@ trait TraitAddTraitBoundToTypeParameterOfTraitWhere where T: ReferencedTrait0 trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> where T: 'a { } @@ -1211,9 +1211,9 @@ trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> where T: 'a { } trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> where 'a: 'b { } @@ -1224,9 +1224,9 @@ trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> where 'a: 'b trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere where T: Send { } @@ -1237,9 +1237,9 @@ trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere where T: Send { } trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere where T: ReferencedTrait0 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere where T: ReferencedTrait0 + ReferencedTrait1 { } @@ -1251,9 +1251,9 @@ trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: 'a { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: 'a + 'b { } @@ -1264,9 +1264,9 @@ trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> where 'a: 'b { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> where 'a: 'b + 'c { } @@ -1277,9 +1277,9 @@ trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> whe trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere where T: Send { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere where T: Send + Sync { } @@ -1296,9 +1296,9 @@ mod change_return_type_of_method_indirectly_use { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeReturnType { - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method() -> ReturnType; } @@ -1318,9 +1318,9 @@ mod change_method_parameter_type_indirectly_by_use { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeArgType { - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(a: ArgType); } @@ -1340,9 +1340,9 @@ mod change_method_parameter_type_bound_indirectly_by_use { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeBoundOfMethodTypeParameter { - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(a: T); } @@ -1363,9 +1363,9 @@ mod change_method_parameter_type_bound_indirectly_by_use_where { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeBoundOfMethodTypeParameterWhere { - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(a: T) where T: Bound; } @@ -1380,9 +1380,9 @@ mod change_method_type_parameter_bound_indirectly { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait1 as Bound; - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeTraitBound { fn method(a: T); @@ -1399,9 +1399,9 @@ mod change_method_type_parameter_bound_indirectly_where { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait1 as Bound; - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeTraitBoundWhere where T: Bound { fn method(a: T); diff --git a/tests/incremental/hashes/trait_impls.rs b/tests/incremental/hashes/trait_impls.rs index 3b2e18d17a96..028598244de7 100644 --- a/tests/incremental/hashes/trait_impls.rs +++ b/tests/incremental/hashes/trait_impls.rs @@ -32,9 +32,9 @@ impl ChangeMethodNameTrait for Foo { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub trait ChangeMethodNameTrait { #[rustc_clean(cfg="cfail3")] @@ -43,9 +43,9 @@ pub trait ChangeMethodNameTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl ChangeMethodNameTrait for Foo { #[rustc_clean(cfg="cfail3")] @@ -141,18 +141,18 @@ pub trait ChangeMethodSelfnessTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl ChangeMethodSelfnessTrait for Foo { #[rustc_clean( - except="hir_owner,hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", + except="hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", cfg="cfail2", )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( - except="hir_owner,hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", + except="hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", cfg="cfail5", )] #[rustc_clean(cfg="cfail6")] @@ -179,18 +179,18 @@ pub trait RemoveMethodSelfnessTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl RemoveMethodSelfnessTrait for Foo { #[rustc_clean( - except="hir_owner,hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", + except="hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", cfg="cfail2", )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( - except="hir_owner,hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", + except="hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", cfg="cfail5", )] #[rustc_clean(cfg="cfail6")] @@ -206,9 +206,9 @@ pub trait ChangeMethodSelfmutnessTrait { #[cfg(any(cfail1,cfail4))] impl ChangeMethodSelfmutnessTrait for Foo { - // ----------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------- // ------------------------- - // ----------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------- // ------------------------- fn method_name(& self) {} } @@ -224,9 +224,9 @@ pub trait ChangeMethodSelfmutnessTrait { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl ChangeMethodSelfmutnessTrait for Foo { - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method_name(&mut self) {} } @@ -249,9 +249,9 @@ pub trait ChangeItemKindTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl ChangeItemKindTrait for Foo { type name = (); @@ -277,9 +277,9 @@ pub trait RemoveItemTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl RemoveItemTrait for Foo { type TypeName = (); @@ -304,9 +304,9 @@ pub trait AddItemTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl AddItemTrait for Foo { type TypeName = (); @@ -317,9 +317,9 @@ impl AddItemTrait for Foo { #[cfg(any(cfail1,cfail4))] pub trait ChangeHasValueTrait { - //-------------------------------------------------------------- + //---------------------------------------------------- //-------------------------- - //-------------------------------------------------------------- + //---------------------------------------------------- //-------------------------- fn method_name() ; } @@ -330,14 +330,14 @@ impl ChangeHasValueTrait for Foo { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub trait ChangeHasValueTrait { - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method_name() { } } @@ -359,9 +359,9 @@ pub trait AddDefaultTrait { #[cfg(any(cfail1,cfail4))] impl AddDefaultTrait for Foo { - // ------------------------------------------------------------- + // --------------------------------------------------- // ------------------------- - // ------------------------------------------------------------- + // --------------------------------------------------- // ------------------------- fn method_name() { } } @@ -372,9 +372,9 @@ impl AddDefaultTrait for Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl AddDefaultTrait for Foo { - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] default fn method_name() { } } @@ -388,9 +388,9 @@ pub trait AddArgumentTrait { #[cfg(any(cfail1,cfail4))] impl AddArgumentTrait for Foo { - // ----------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------- // ------------------------- - // ----------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------- // ------------------------- fn method_name(&self ) { } } @@ -406,9 +406,9 @@ pub trait AddArgumentTrait { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl AddArgumentTrait for Foo { - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method_name(&self, _x: u32) { } } @@ -422,9 +422,9 @@ pub trait ChangeArgumentTypeTrait { #[cfg(any(cfail1,cfail4))] impl ChangeArgumentTypeTrait for Foo { - // ----------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------- // ------------------------- - // ----------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------- // ------------------------- fn method_name(&self, _x: u32 ) { } } @@ -440,9 +440,9 @@ pub trait ChangeArgumentTypeTrait { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl ChangeArgumentTypeTrait for Foo { - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")] + #[rustc_clean(except="hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")] + #[rustc_clean(except="hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method_name(&self, _x: char) { } } @@ -462,18 +462,18 @@ impl AddTypeParameterToImpl for Bar { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,impl_trait_ref", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,generics_of,impl_trait_ref", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,impl_trait_ref", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,generics_of,impl_trait_ref", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl AddTypeParameterToImpl for Bar { #[rustc_clean( - except="hir_owner,hir_owner_nodes,generics_of,fn_sig,type_of,typeck,optimized_mir", + except="hir_owner_nodes,generics_of,fn_sig,type_of,typeck,optimized_mir", cfg="cfail2", )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( - except="hir_owner,hir_owner_nodes,generics_of,fn_sig,type_of,typeck,optimized_mir", + except="hir_owner_nodes,generics_of,fn_sig,type_of,typeck,optimized_mir", cfg="cfail5", )] #[rustc_clean(cfg="cfail6")] @@ -493,9 +493,9 @@ impl ChangeSelfTypeOfImpl for u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,impl_trait_ref", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes,impl_trait_ref", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,impl_trait_ref", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes,impl_trait_ref", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl ChangeSelfTypeOfImpl for u64 { #[rustc_clean(except="fn_sig,typeck,optimized_mir", cfg="cfail2")] @@ -518,9 +518,9 @@ impl AddLifetimeBoundToImplParameter for T { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl AddLifetimeBoundToImplParameter for T { #[rustc_clean(cfg="cfail2")] @@ -543,9 +543,9 @@ impl AddTraitBoundToImplParameter for T { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl AddTraitBoundToImplParameter for T { #[rustc_clean(cfg="cfail2")] diff --git a/tests/incremental/hashes/type_defs.rs b/tests/incremental/hashes/type_defs.rs index 79398eb07fe4..206c0595d546 100644 --- a/tests/incremental/hashes/type_defs.rs +++ b/tests/incremental/hashes/type_defs.rs @@ -24,7 +24,7 @@ type ChangePrimitiveType = i32; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangePrimitiveType = i64; @@ -35,7 +35,7 @@ type ChangePrimitiveType = i64; type ChangeMutability = &'static i32; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeMutability = &'static mut i32; @@ -46,7 +46,7 @@ type ChangeMutability = &'static mut i32; type ChangeLifetime<'a> = (&'static i32, &'a i32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeLifetime<'a> = (&'a i32, &'a i32); @@ -60,7 +60,7 @@ struct Struct2; type ChangeTypeStruct = Struct1; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeTypeStruct = Struct2; @@ -71,7 +71,7 @@ type ChangeTypeStruct = Struct2; type ChangeTypeTuple = (u32, u64); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeTypeTuple = (u32, i64); @@ -91,7 +91,7 @@ enum Enum2 { type ChangeTypeEnum = Enum1; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeTypeEnum = Enum2; @@ -102,7 +102,7 @@ type ChangeTypeEnum = Enum2; type AddTupleField = (i32, i64); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type AddTupleField = (i32, i64, i16); @@ -113,7 +113,7 @@ type AddTupleField = (i32, i64, i16); type ChangeNestedTupleField = (i32, (i64, i16)); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeNestedTupleField = (i32, (i64, i8)); @@ -124,7 +124,7 @@ type ChangeNestedTupleField = (i32, (i64, i8)); type AddTypeParam = (T1, T1); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type AddTypeParam = (T1, T2); @@ -135,7 +135,7 @@ type AddTypeParam = (T1, T2); type AddTypeParamBound = (T1, u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type AddTypeParamBound = (T1, u32); @@ -146,7 +146,7 @@ type AddTypeParamBound = (T1, u32); type AddTypeParamBoundWhereClause where T1: Clone = (T1, u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type AddTypeParamBoundWhereClause where T1: Clone+Copy = (T1, u32); @@ -157,7 +157,7 @@ type AddTypeParamBoundWhereClause where T1: Clone+Copy = (T1, u32); type AddLifetimeParam<'a> = (&'a u32, &'a u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type AddLifetimeParam<'a, 'b> = (&'a u32, &'b u32); @@ -168,7 +168,7 @@ type AddLifetimeParam<'a, 'b> = (&'a u32, &'b u32); type AddLifetimeParamBound<'a, 'b> = (&'a u32, &'b u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type AddLifetimeParamBound<'a, 'b: 'a> = (&'a u32, &'b u32); @@ -181,7 +181,7 @@ where 'b: 'a = (&'a u32, &'b u32, &'c u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type AddLifetimeParamBoundWhereClause<'a, 'b, 'c> where 'b: 'a, @@ -200,7 +200,7 @@ mod change_trait_bound_indirectly { #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeTraitBoundIndirectly = (T, u32); } @@ -214,7 +214,7 @@ mod change_trait_bound_indirectly_in_where_clause { #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeTraitBoundIndirectly where T : Trait = (T, u32); } diff --git a/tests/mir-opt/const_allocation.main.GVN.after.32bit.mir b/tests/mir-opt/const_allocation.main.GVN.after.32bit.mir index f089c6741fe8..10d99a134633 100644 --- a/tests/mir-opt/const_allocation.main.GVN.after.32bit.mir +++ b/tests/mir-opt/const_allocation.main.GVN.after.32bit.mir @@ -7,10 +7,10 @@ fn main() -> () { bb0: { StorageLive(_1); - nop; + StorageLive(_2); _2 = const {ALLOC9: &&[(Option, &[&str])]}; _1 = (*_2); - nop; + StorageDead(_2); StorageDead(_1); _0 = const (); return; diff --git a/tests/mir-opt/const_allocation.main.GVN.after.64bit.mir b/tests/mir-opt/const_allocation.main.GVN.after.64bit.mir index 9cbbaf302bef..2f23dbe9ee4f 100644 --- a/tests/mir-opt/const_allocation.main.GVN.after.64bit.mir +++ b/tests/mir-opt/const_allocation.main.GVN.after.64bit.mir @@ -7,10 +7,10 @@ fn main() -> () { bb0: { StorageLive(_1); - nop; + StorageLive(_2); _2 = const {ALLOC9: &&[(Option, &[&str])]}; _1 = (*_2); - nop; + StorageDead(_2); StorageDead(_1); _0 = const (); return; diff --git a/tests/mir-opt/const_allocation2.main.GVN.after.32bit.mir b/tests/mir-opt/const_allocation2.main.GVN.after.32bit.mir index dfa2d8081286..6499e3676aaa 100644 --- a/tests/mir-opt/const_allocation2.main.GVN.after.32bit.mir +++ b/tests/mir-opt/const_allocation2.main.GVN.after.32bit.mir @@ -7,10 +7,10 @@ fn main() -> () { bb0: { StorageLive(_1); - nop; + StorageLive(_2); _2 = const {ALLOC9: &&[(Option, &[&u8])]}; _1 = (*_2); - nop; + StorageDead(_2); StorageDead(_1); _0 = const (); return; diff --git a/tests/mir-opt/const_allocation2.main.GVN.after.64bit.mir b/tests/mir-opt/const_allocation2.main.GVN.after.64bit.mir index 02b669871698..02f5ebab8477 100644 --- a/tests/mir-opt/const_allocation2.main.GVN.after.64bit.mir +++ b/tests/mir-opt/const_allocation2.main.GVN.after.64bit.mir @@ -7,10 +7,10 @@ fn main() -> () { bb0: { StorageLive(_1); - nop; + StorageLive(_2); _2 = const {ALLOC9: &&[(Option, &[&u8])]}; _1 = (*_2); - nop; + StorageDead(_2); StorageDead(_1); _0 = const (); return; diff --git a/tests/mir-opt/const_allocation3.main.GVN.after.32bit.mir b/tests/mir-opt/const_allocation3.main.GVN.after.32bit.mir index 386a55ee6fa1..c95e696946a6 100644 --- a/tests/mir-opt/const_allocation3.main.GVN.after.32bit.mir +++ b/tests/mir-opt/const_allocation3.main.GVN.after.32bit.mir @@ -7,10 +7,10 @@ fn main() -> () { bb0: { StorageLive(_1); - nop; + StorageLive(_2); _2 = const {ALLOC4: &&Packed}; _1 = (*_2); - nop; + StorageDead(_2); StorageDead(_1); _0 = const (); return; diff --git a/tests/mir-opt/const_allocation3.main.GVN.after.64bit.mir b/tests/mir-opt/const_allocation3.main.GVN.after.64bit.mir index b9e98f8cd4c8..198bc8bd07ef 100644 --- a/tests/mir-opt/const_allocation3.main.GVN.after.64bit.mir +++ b/tests/mir-opt/const_allocation3.main.GVN.after.64bit.mir @@ -7,10 +7,10 @@ fn main() -> () { bb0: { StorageLive(_1); - nop; + StorageLive(_2); _2 = const {ALLOC2: &&Packed}; _1 = (*_2); - nop; + StorageDead(_2); StorageDead(_1); _0 = const (); return; diff --git a/tests/mir-opt/const_prop/address_of_pair.fn0.GVN.diff b/tests/mir-opt/const_prop/address_of_pair.fn0.GVN.diff index 2285962fad1e..a044cfc62e20 100644 --- a/tests/mir-opt/const_prop/address_of_pair.fn0.GVN.diff +++ b/tests/mir-opt/const_prop/address_of_pair.fn0.GVN.diff @@ -24,9 +24,8 @@ bb0: { StorageLive(_2); - _2 = (const 1_i32, const false); -- StorageLive(_3); + _2 = const (1_i32, false); -+ nop; + StorageLive(_3); _3 = &raw mut (_2.1: bool); - _2 = (const 1_i32, const false); + _2 = const (1_i32, false); @@ -42,9 +41,8 @@ StorageDead(_6); _0 = _5; - StorageDead(_5); -- StorageDead(_3); -+ nop; + nop; + StorageDead(_3); StorageDead(_2); return; } diff --git a/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-abort.diff index f9537661e8ca..6d00dd5b2126 100644 --- a/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-abort.diff @@ -18,11 +18,12 @@ _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; StorageLive(_3); _3 = const 2_usize; - _4 = Len(_2); +- _4 = Len(_2); - _5 = Lt(_3, _4); - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind unreachable]; -+ _5 = Lt(const 2_usize, _4); -+ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> [success: bb1, unwind unreachable]; ++ _4 = const 4_usize; ++ _5 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-unwind.diff index 07886779fead..7e2f72ab31bc 100644 --- a/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-unwind.diff @@ -18,11 +18,12 @@ _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; StorageLive(_3); _3 = const 2_usize; - _4 = Len(_2); +- _4 = Len(_2); - _5 = Lt(_3, _4); - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind continue]; -+ _5 = Lt(const 2_usize, _4); -+ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> [success: bb1, unwind continue]; ++ _4 = const 4_usize; ++ _5 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-abort.diff index f9537661e8ca..6d00dd5b2126 100644 --- a/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-abort.diff @@ -18,11 +18,12 @@ _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; StorageLive(_3); _3 = const 2_usize; - _4 = Len(_2); +- _4 = Len(_2); - _5 = Lt(_3, _4); - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind unreachable]; -+ _5 = Lt(const 2_usize, _4); -+ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> [success: bb1, unwind unreachable]; ++ _4 = const 4_usize; ++ _5 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-unwind.diff index 07886779fead..7e2f72ab31bc 100644 --- a/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-unwind.diff @@ -18,11 +18,12 @@ _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; StorageLive(_3); _3 = const 2_usize; - _4 = Len(_2); +- _4 = Len(_2); - _5 = Lt(_3, _4); - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind continue]; -+ _5 = Lt(const 2_usize, _4); -+ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> [success: bb1, unwind continue]; ++ _4 = const 4_usize; ++ _5 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-abort.diff index a42f9291324b..e1a93e314468 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-abort.diff @@ -22,18 +22,15 @@ } bb0: { -- StorageLive(_1); -+ nop; + StorageLive(_1); StorageLive(_2); -- StorageLive(_3); -+ nop; + StorageLive(_3); _9 = const _; _3 = &(*_9); _2 = &raw const (*_3); _1 = move _2 as *const [i32] (PointerCoercion(Unsize)); StorageDead(_2); -- StorageDead(_3); -+ nop; + StorageDead(_3); StorageLive(_5); StorageLive(_6); _6 = const 3_usize; @@ -50,8 +47,7 @@ StorageDead(_6); _0 = const (); StorageDead(_5); -- StorageDead(_1); -+ nop; + StorageDead(_1); return; } } diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-unwind.diff index f2d6de6621b1..91999145efb3 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-unwind.diff @@ -22,18 +22,15 @@ } bb0: { -- StorageLive(_1); -+ nop; + StorageLive(_1); StorageLive(_2); -- StorageLive(_3); -+ nop; + StorageLive(_3); _9 = const _; _3 = &(*_9); _2 = &raw const (*_3); _1 = move _2 as *const [i32] (PointerCoercion(Unsize)); StorageDead(_2); -- StorageDead(_3); -+ nop; + StorageDead(_3); StorageLive(_5); StorageLive(_6); _6 = const 3_usize; @@ -50,8 +47,7 @@ StorageDead(_6); _0 = const (); StorageDead(_5); -- StorageDead(_1); -+ nop; + StorageDead(_1); return; } } diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-abort.diff index a42f9291324b..e1a93e314468 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-abort.diff @@ -22,18 +22,15 @@ } bb0: { -- StorageLive(_1); -+ nop; + StorageLive(_1); StorageLive(_2); -- StorageLive(_3); -+ nop; + StorageLive(_3); _9 = const _; _3 = &(*_9); _2 = &raw const (*_3); _1 = move _2 as *const [i32] (PointerCoercion(Unsize)); StorageDead(_2); -- StorageDead(_3); -+ nop; + StorageDead(_3); StorageLive(_5); StorageLive(_6); _6 = const 3_usize; @@ -50,8 +47,7 @@ StorageDead(_6); _0 = const (); StorageDead(_5); -- StorageDead(_1); -+ nop; + StorageDead(_1); return; } } diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-unwind.diff index f2d6de6621b1..91999145efb3 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-unwind.diff @@ -22,18 +22,15 @@ } bb0: { -- StorageLive(_1); -+ nop; + StorageLive(_1); StorageLive(_2); -- StorageLive(_3); -+ nop; + StorageLive(_3); _9 = const _; _3 = &(*_9); _2 = &raw const (*_3); _1 = move _2 as *const [i32] (PointerCoercion(Unsize)); StorageDead(_2); -- StorageDead(_3); -+ nop; + StorageDead(_3); StorageLive(_5); StorageLive(_6); _6 = const 3_usize; @@ -50,8 +47,7 @@ StorageDead(_6); _0 = const (); StorageDead(_5); -- StorageDead(_1); -+ nop; + StorageDead(_1); return; } } diff --git a/tests/mir-opt/const_prop/boolean_identities.rs b/tests/mir-opt/const_prop/boolean_identities.rs index f6575ac8e547..3b7ea25ad46e 100644 --- a/tests/mir-opt/const_prop/boolean_identities.rs +++ b/tests/mir-opt/const_prop/boolean_identities.rs @@ -5,10 +5,9 @@ pub fn test(x: bool, y: bool) -> bool { // CHECK-LABEL: fn test( // CHECK: debug a => [[a:_.*]]; // CHECK: debug b => [[b:_.*]]; - // FIXME(cjgillot) simplify algebraic identity - // CHECK-NOT: [[a]] = const true; - // CHECK-NOT: [[b]] = const false; - // CHECK-NOT: _0 = const false; + // CHECK: [[a]] = const true; + // CHECK: [[b]] = const false; + // CHECK: _0 = const false; let a = (y | true); let b = (x & false); a & b diff --git a/tests/mir-opt/const_prop/boolean_identities.test.GVN.diff b/tests/mir-opt/const_prop/boolean_identities.test.GVN.diff index eca87af75272..0bd8413289e6 100644 --- a/tests/mir-opt/const_prop/boolean_identities.test.GVN.diff +++ b/tests/mir-opt/const_prop/boolean_identities.test.GVN.diff @@ -24,21 +24,23 @@ StorageLive(_4); _4 = _2; - _3 = BitOr(move _4, const true); -+ _3 = BitOr(_2, const true); ++ _3 = const true; StorageDead(_4); - StorageLive(_5); + nop; StorageLive(_6); _6 = _1; - _5 = BitAnd(move _6, const false); -+ _5 = BitAnd(_1, const false); ++ _5 = const false; StorageDead(_6); StorageLive(_7); - _7 = _3; +- _7 = _3; ++ _7 = const true; StorageLive(_8); - _8 = _5; +- _8 = _5; - _0 = BitAnd(move _7, move _8); -+ _0 = BitAnd(_3, _5); ++ _8 = const false; ++ _0 = const false; StorageDead(_8); StorageDead(_7); - StorageDead(_5); diff --git a/tests/mir-opt/const_prop/boxes.main.GVN.panic-abort.diff b/tests/mir-opt/const_prop/boxes.main.GVN.panic-abort.diff index b3fdaa5ee825..59ee38f5a2b9 100644 --- a/tests/mir-opt/const_prop/boxes.main.GVN.panic-abort.diff +++ b/tests/mir-opt/const_prop/boxes.main.GVN.panic-abort.diff @@ -20,7 +20,8 @@ bb0: { StorageLive(_1); - StorageLive(_2); +- StorageLive(_2); ++ nop; StorageLive(_3); - _4 = SizeOf(i32); - _5 = AlignOf(i32); @@ -39,8 +40,10 @@ StorageDead(_7); _9 = (((_3.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const i32); _2 = (*_9); - _1 = Add(move _2, const 0_i32); - StorageDead(_2); +- _1 = Add(move _2, const 0_i32); +- StorageDead(_2); ++ _1 = _2; ++ nop; drop(_3) -> [return: bb2, unwind unreachable]; } diff --git a/tests/mir-opt/const_prop/boxes.main.GVN.panic-unwind.diff b/tests/mir-opt/const_prop/boxes.main.GVN.panic-unwind.diff index d0350c97253a..9d87bd809d1f 100644 --- a/tests/mir-opt/const_prop/boxes.main.GVN.panic-unwind.diff +++ b/tests/mir-opt/const_prop/boxes.main.GVN.panic-unwind.diff @@ -20,7 +20,8 @@ bb0: { StorageLive(_1); - StorageLive(_2); +- StorageLive(_2); ++ nop; StorageLive(_3); - _4 = SizeOf(i32); - _5 = AlignOf(i32); @@ -39,8 +40,10 @@ StorageDead(_7); _9 = (((_3.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const i32); _2 = (*_9); - _1 = Add(move _2, const 0_i32); - StorageDead(_2); +- _1 = Add(move _2, const 0_i32); +- StorageDead(_2); ++ _1 = _2; ++ nop; drop(_3) -> [return: bb2, unwind: bb3]; } diff --git a/tests/mir-opt/const_prop/boxes.rs b/tests/mir-opt/const_prop/boxes.rs index 5227d7b8b8ba..d2d61f86d5eb 100644 --- a/tests/mir-opt/const_prop/boxes.rs +++ b/tests/mir-opt/const_prop/boxes.rs @@ -12,7 +12,7 @@ fn main() { // CHECK: debug x => [[x:_.*]]; // CHECK: (*{{_.*}}) = const 42_i32; // CHECK: [[tmp:_.*]] = (*{{_.*}}); - // CHECK: [[x]] = Add(move [[tmp]], const 0_i32); + // CHECK: [[x]] = [[tmp]]; let x = *(#[rustc_box] Box::new(42)) + 0; diff --git a/tests/mir-opt/const_prop/indirect_mutation.bar.GVN.diff b/tests/mir-opt/const_prop/indirect_mutation.bar.GVN.diff index 7dd80d643607..b389080c4977 100644 --- a/tests/mir-opt/const_prop/indirect_mutation.bar.GVN.diff +++ b/tests/mir-opt/const_prop/indirect_mutation.bar.GVN.diff @@ -22,12 +22,10 @@ - _1 = (const 1_i32,); + _1 = const (1_i32,); StorageLive(_2); -- StorageLive(_3); -+ nop; + StorageLive(_3); _3 = &raw mut (_1.0: i32); (*_3) = const 5_i32; -- StorageDead(_3); -+ nop; + StorageDead(_3); _2 = const (); StorageDead(_2); StorageLive(_4); diff --git a/tests/mir-opt/const_prop/indirect_mutation.foo.GVN.diff b/tests/mir-opt/const_prop/indirect_mutation.foo.GVN.diff index c4b647d9d2d2..c21869dece65 100644 --- a/tests/mir-opt/const_prop/indirect_mutation.foo.GVN.diff +++ b/tests/mir-opt/const_prop/indirect_mutation.foo.GVN.diff @@ -17,13 +17,11 @@ bb0: { StorageLive(_1); - _1 = (const 1_i32,); -- StorageLive(_2); + _1 = const (1_i32,); -+ nop; + StorageLive(_2); _2 = &mut (_1.0: i32); (*_2) = const 5_i32; -- StorageDead(_2); -+ nop; + StorageDead(_2); StorageLive(_3); StorageLive(_4); _4 = (_1.0: i32); diff --git a/tests/mir-opt/const_prop/issue_67019.main.GVN.panic-abort.diff b/tests/mir-opt/const_prop/issue_67019.main.GVN.panic-abort.diff index fc0c8afd4cfd..dfab4959516d 100644 --- a/tests/mir-opt/const_prop/issue_67019.main.GVN.panic-abort.diff +++ b/tests/mir-opt/const_prop/issue_67019.main.GVN.panic-abort.diff @@ -33,10 +33,6 @@ + } + + ALLOC1 (size: 2, align: 1) { -+ 01 02 │ .. -+ } -+ -+ ALLOC2 (size: 2, align: 1) { + 01 02 │ .. } diff --git a/tests/mir-opt/const_prop/issue_67019.main.GVN.panic-unwind.diff b/tests/mir-opt/const_prop/issue_67019.main.GVN.panic-unwind.diff index cf4089598e73..b6d697323166 100644 --- a/tests/mir-opt/const_prop/issue_67019.main.GVN.panic-unwind.diff +++ b/tests/mir-opt/const_prop/issue_67019.main.GVN.panic-unwind.diff @@ -33,10 +33,6 @@ + } + + ALLOC1 (size: 2, align: 1) { -+ 01 02 │ .. -+ } -+ -+ ALLOC2 (size: 2, align: 1) { + 01 02 │ .. } diff --git a/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-abort.diff index cf36109fdcbd..bd987c01ab16 100644 --- a/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-abort.diff @@ -18,11 +18,12 @@ _2 = [const 0_u8; 5000]; StorageLive(_3); _3 = const 2_usize; - _4 = Len(_2); +- _4 = Len(_2); - _5 = Lt(_3, _4); - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind unreachable]; -+ _5 = Lt(const 2_usize, _4); -+ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> [success: bb1, unwind unreachable]; ++ _4 = const 5000_usize; ++ _5 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-unwind.diff index 40ed96971800..e9ebef84ae04 100644 --- a/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-unwind.diff @@ -18,11 +18,12 @@ _2 = [const 0_u8; 5000]; StorageLive(_3); _3 = const 2_usize; - _4 = Len(_2); +- _4 = Len(_2); - _5 = Lt(_3, _4); - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind continue]; -+ _5 = Lt(const 2_usize, _4); -+ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> [success: bb1, unwind continue]; ++ _4 = const 5000_usize; ++ _5 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-abort.diff index cf36109fdcbd..bd987c01ab16 100644 --- a/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-abort.diff @@ -18,11 +18,12 @@ _2 = [const 0_u8; 5000]; StorageLive(_3); _3 = const 2_usize; - _4 = Len(_2); +- _4 = Len(_2); - _5 = Lt(_3, _4); - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind unreachable]; -+ _5 = Lt(const 2_usize, _4); -+ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> [success: bb1, unwind unreachable]; ++ _4 = const 5000_usize; ++ _5 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-unwind.diff index 40ed96971800..e9ebef84ae04 100644 --- a/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-unwind.diff @@ -18,11 +18,12 @@ _2 = [const 0_u8; 5000]; StorageLive(_3); _3 = const 2_usize; - _4 = Len(_2); +- _4 = Len(_2); - _5 = Lt(_3, _4); - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind continue]; -+ _5 = Lt(const 2_usize, _4); -+ assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, const 2_usize) -> [success: bb1, unwind continue]; ++ _4 = const 5000_usize; ++ _5 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/mult_by_zero.rs b/tests/mir-opt/const_prop/mult_by_zero.rs index 2fdb75c3100e..b8afaeef43fd 100644 --- a/tests/mir-opt/const_prop/mult_by_zero.rs +++ b/tests/mir-opt/const_prop/mult_by_zero.rs @@ -3,8 +3,7 @@ // EMIT_MIR mult_by_zero.test.GVN.diff fn test(x: i32) -> i32 { // CHECK: fn test( - // FIXME(cjgillot) simplify algebraic identity - // CHECK-NOT: _0 = const 0_i32; + // CHECK: _0 = const 0_i32; x * 0 } diff --git a/tests/mir-opt/const_prop/mult_by_zero.test.GVN.diff b/tests/mir-opt/const_prop/mult_by_zero.test.GVN.diff index e9fb34749c10..6c2aab45d48b 100644 --- a/tests/mir-opt/const_prop/mult_by_zero.test.GVN.diff +++ b/tests/mir-opt/const_prop/mult_by_zero.test.GVN.diff @@ -10,7 +10,7 @@ StorageLive(_2); _2 = _1; - _0 = Mul(move _2, const 0_i32); -+ _0 = Mul(_1, const 0_i32); ++ _0 = const 0_i32; StorageDead(_2); return; } diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.GVN.diff b/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.GVN.diff index bc60546cd190..4ed7c9851479 100644 --- a/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.GVN.diff +++ b/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.GVN.diff @@ -19,17 +19,15 @@ bb0: { StorageLive(_1); - _1 = (const 42_i32, const 43_i32); -- StorageLive(_2); + _1 = const (42_i32, 43_i32); -+ nop; + StorageLive(_2); _2 = &mut _1; ((*_2).1: i32) = const 99_i32; StorageLive(_3); _3 = _1; _0 = const (); StorageDead(_3); -- StorageDead(_2); -+ nop; + StorageDead(_2); StorageDead(_1); return; } diff --git a/tests/mir-opt/const_prop/mutable_variable_no_prop.main.GVN.diff b/tests/mir-opt/const_prop/mutable_variable_no_prop.main.GVN.diff index d02c392f6bd6..e113f43a56e9 100644 --- a/tests/mir-opt/const_prop/mutable_variable_no_prop.main.GVN.diff +++ b/tests/mir-opt/const_prop/mutable_variable_no_prop.main.GVN.diff @@ -22,14 +22,12 @@ _1 = const 42_u32; StorageLive(_2); StorageLive(_3); -- StorageLive(_4); -+ nop; + StorageLive(_4); _4 = const {ALLOC0: *mut u32}; _3 = (*_4); _1 = move _3; StorageDead(_3); -- StorageDead(_4); -+ nop; + StorageDead(_4); _2 = const (); StorageDead(_2); StorageLive(_5); diff --git a/tests/mir-opt/const_prop/offset_of.rs b/tests/mir-opt/const_prop/offset_of.rs index 43ecbbed186f..f15d15bfcb26 100644 --- a/tests/mir-opt/const_prop/offset_of.rs +++ b/tests/mir-opt/const_prop/offset_of.rs @@ -2,7 +2,7 @@ // unit-test: GVN // EMIT_MIR_FOR_EACH_PANIC_STRATEGY -#![feature(offset_of, offset_of_enum)] +#![feature(offset_of_enum, offset_of_nested)] use std::marker::PhantomData; use std::mem::offset_of; diff --git a/tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-abort.diff b/tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-abort.diff index 425bc3ff6c1b..4e79b3ad5992 100644 --- a/tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-abort.diff +++ b/tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-abort.diff @@ -16,14 +16,12 @@ - StorageLive(_1); + nop; StorageLive(_2); -- StorageLive(_3); -+ nop; + StorageLive(_3); _3 = const _; _2 = &raw const (*_3); _1 = move _2 as usize (PointerExposeAddress); StorageDead(_2); -- StorageDead(_3); -+ nop; + StorageDead(_3); StorageLive(_4); StorageLive(_5); _5 = _1; diff --git a/tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-unwind.diff b/tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-unwind.diff index e9360ab8d629..fdc459b457ce 100644 --- a/tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-unwind.diff +++ b/tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-unwind.diff @@ -16,14 +16,12 @@ - StorageLive(_1); + nop; StorageLive(_2); -- StorageLive(_3); -+ nop; + StorageLive(_3); _3 = const _; _2 = &raw const (*_3); _1 = move _2 as usize (PointerExposeAddress); StorageDead(_2); -- StorageDead(_3); -+ nop; + StorageDead(_3); StorageLive(_4); StorageLive(_5); _5 = _1; diff --git a/tests/mir-opt/const_prop/ref_deref.main.GVN.diff b/tests/mir-opt/const_prop/ref_deref.main.GVN.diff index 8f9aa20524d0..56cbd00025ed 100644 --- a/tests/mir-opt/const_prop/ref_deref.main.GVN.diff +++ b/tests/mir-opt/const_prop/ref_deref.main.GVN.diff @@ -13,14 +13,12 @@ bb0: { StorageLive(_1); -- StorageLive(_2); -+ nop; + StorageLive(_2); _4 = const _; _2 = &(*_4); - _1 = (*_2); -- StorageDead(_2); + _1 = const 4_i32; -+ nop; + StorageDead(_2); _0 = const (); StorageDead(_1); return; diff --git a/tests/mir-opt/const_prop/ref_deref_project.main.GVN.diff b/tests/mir-opt/const_prop/ref_deref_project.main.GVN.diff index 8d38888b7d6a..d75c0c3b286b 100644 --- a/tests/mir-opt/const_prop/ref_deref_project.main.GVN.diff +++ b/tests/mir-opt/const_prop/ref_deref_project.main.GVN.diff @@ -13,14 +13,12 @@ bb0: { StorageLive(_1); -- StorageLive(_2); -+ nop; + StorageLive(_2); _4 = const _; _2 = &((*_4).1: i32); - _1 = (*_2); -- StorageDead(_2); + _1 = const 5_i32; -+ nop; + StorageDead(_2); _0 = const (); StorageDead(_1); return; diff --git a/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-abort.diff index a52e6e35483d..71635b8e9c3e 100644 --- a/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-abort.diff @@ -20,11 +20,12 @@ _3 = [const 42_u32; 8]; StorageLive(_4); _4 = const 2_usize; - _5 = Len(_3); +- _5 = Len(_3); - _6 = Lt(_4, _5); - assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind unreachable]; -+ _6 = Lt(const 2_usize, _5); -+ assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, const 2_usize) -> [success: bb1, unwind unreachable]; ++ _5 = const 8_usize; ++ _6 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-unwind.diff index fe0acee71ebe..84205028d6d2 100644 --- a/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-unwind.diff @@ -20,11 +20,12 @@ _3 = [const 42_u32; 8]; StorageLive(_4); _4 = const 2_usize; - _5 = Len(_3); +- _5 = Len(_3); - _6 = Lt(_4, _5); - assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind continue]; -+ _6 = Lt(const 2_usize, _5); -+ assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, const 2_usize) -> [success: bb1, unwind continue]; ++ _5 = const 8_usize; ++ _6 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-abort.diff index a52e6e35483d..71635b8e9c3e 100644 --- a/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-abort.diff @@ -20,11 +20,12 @@ _3 = [const 42_u32; 8]; StorageLive(_4); _4 = const 2_usize; - _5 = Len(_3); +- _5 = Len(_3); - _6 = Lt(_4, _5); - assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind unreachable]; -+ _6 = Lt(const 2_usize, _5); -+ assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, const 2_usize) -> [success: bb1, unwind unreachable]; ++ _5 = const 8_usize; ++ _6 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-unwind.diff index fe0acee71ebe..84205028d6d2 100644 --- a/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-unwind.diff @@ -20,11 +20,12 @@ _3 = [const 42_u32; 8]; StorageLive(_4); _4 = const 2_usize; - _5 = Len(_3); +- _5 = Len(_3); - _6 = Lt(_4, _5); - assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind continue]; -+ _6 = Lt(const 2_usize, _5); -+ assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, const 2_usize) -> [success: bb1, unwind continue]; ++ _5 = const 8_usize; ++ _6 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff index 8b2411e50ab0..803be994d9ae 100644 --- a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff @@ -18,8 +18,7 @@ bb0: { StorageLive(_1); -- StorageLive(_2); -+ nop; + StorageLive(_2); StorageLive(_3); StorageLive(_4); _9 = const _; @@ -44,8 +43,7 @@ + _1 = (*_2)[1 of 2]; StorageDead(_6); StorageDead(_4); -- StorageDead(_2); -+ nop; + StorageDead(_2); _0 = const (); StorageDead(_1); return; diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff index 9b20d243f876..2a20e3eca599 100644 --- a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff @@ -18,8 +18,7 @@ bb0: { StorageLive(_1); -- StorageLive(_2); -+ nop; + StorageLive(_2); StorageLive(_3); StorageLive(_4); _9 = const _; @@ -44,8 +43,7 @@ + _1 = (*_2)[1 of 2]; StorageDead(_6); StorageDead(_4); -- StorageDead(_2); -+ nop; + StorageDead(_2); _0 = const (); StorageDead(_1); return; diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff index 8b2411e50ab0..803be994d9ae 100644 --- a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff @@ -18,8 +18,7 @@ bb0: { StorageLive(_1); -- StorageLive(_2); -+ nop; + StorageLive(_2); StorageLive(_3); StorageLive(_4); _9 = const _; @@ -44,8 +43,7 @@ + _1 = (*_2)[1 of 2]; StorageDead(_6); StorageDead(_4); -- StorageDead(_2); -+ nop; + StorageDead(_2); _0 = const (); StorageDead(_1); return; diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff index 9b20d243f876..2a20e3eca599 100644 --- a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff @@ -18,8 +18,7 @@ bb0: { StorageLive(_1); -- StorageLive(_2); -+ nop; + StorageLive(_2); StorageLive(_3); StorageLive(_4); _9 = const _; @@ -44,8 +43,7 @@ + _1 = (*_2)[1 of 2]; StorageDead(_6); StorageDead(_4); -- StorageDead(_2); -+ nop; + StorageDead(_2); _0 = const (); StorageDead(_1); return; diff --git a/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.32bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.32bit.diff index 93dfef96cf15..0ff31b1a9818 100644 --- a/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.32bit.diff +++ b/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.32bit.diff @@ -13,13 +13,12 @@ bb0: { StorageLive(_1); -- StorageLive(_2); + StorageLive(_2); - _2 = const 1_usize as &mut Never (Transmute); -+ nop; +- _1 = &mut (*_2); + _2 = const {0x1 as &mut Never}; - _1 = &mut (*_2); -- StorageDead(_2); -+ nop; ++ _1 = const {0x1 as &mut Never}; + StorageDead(_2); unreachable; } } diff --git a/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.64bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.64bit.diff index 93dfef96cf15..0ff31b1a9818 100644 --- a/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.64bit.diff +++ b/tests/mir-opt/const_prop/transmute.unreachable_mut.GVN.64bit.diff @@ -13,13 +13,12 @@ bb0: { StorageLive(_1); -- StorageLive(_2); + StorageLive(_2); - _2 = const 1_usize as &mut Never (Transmute); -+ nop; +- _1 = &mut (*_2); + _2 = const {0x1 as &mut Never}; - _1 = &mut (*_2); -- StorageDead(_2); -+ nop; ++ _1 = const {0x1 as &mut Never}; + StorageDead(_2); unreachable; } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff index 6925fdb1e704..ffbd97bb5452 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff @@ -25,20 +25,21 @@ scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; let mut _8: *const [bool; 0]; + let mut _9: *mut [bool; 0]; scope 12 { scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _6; + debug ptr => _9; scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _6; - let mut _9: *mut u8; + debug self => _9; + let mut _10: *mut u8; scope 15 { scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _9; + debug ptr => _10; scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _9; + debug self => _10; scope 18 { scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _9; + debug self => _10; } } } @@ -74,8 +75,10 @@ StorageDead(_7); StorageLive(_8); StorageLive(_9); + StorageLive(_10); _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); _5 = NonNull::<[bool; 0]> { pointer: _8 }; + StorageDead(_10); StorageDead(_9); StorageDead(_8); StorageDead(_6); diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff index 82ad842505c5..7b6dcf1972b2 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff @@ -25,20 +25,21 @@ scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; let mut _8: *const [bool; 0]; + let mut _9: *mut [bool; 0]; scope 12 { scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _6; + debug ptr => _9; scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _6; - let mut _9: *mut u8; + debug self => _9; + let mut _10: *mut u8; scope 15 { scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _9; + debug ptr => _10; scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _9; + debug self => _10; scope 18 { scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _9; + debug self => _10; } } } @@ -74,8 +75,10 @@ StorageDead(_7); StorageLive(_8); StorageLive(_9); + StorageLive(_10); _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); _5 = NonNull::<[bool; 0]> { pointer: _8 }; + StorageDead(_10); StorageDead(_9); StorageDead(_8); StorageDead(_6); diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff index 6925fdb1e704..ffbd97bb5452 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff @@ -25,20 +25,21 @@ scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; let mut _8: *const [bool; 0]; + let mut _9: *mut [bool; 0]; scope 12 { scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _6; + debug ptr => _9; scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _6; - let mut _9: *mut u8; + debug self => _9; + let mut _10: *mut u8; scope 15 { scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _9; + debug ptr => _10; scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _9; + debug self => _10; scope 18 { scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _9; + debug self => _10; } } } @@ -74,8 +75,10 @@ StorageDead(_7); StorageLive(_8); StorageLive(_9); + StorageLive(_10); _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); _5 = NonNull::<[bool; 0]> { pointer: _8 }; + StorageDead(_10); StorageDead(_9); StorageDead(_8); StorageDead(_6); diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff index 82ad842505c5..7b6dcf1972b2 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff @@ -25,20 +25,21 @@ scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; let mut _8: *const [bool; 0]; + let mut _9: *mut [bool; 0]; scope 12 { scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _6; + debug ptr => _9; scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _6; - let mut _9: *mut u8; + debug self => _9; + let mut _10: *mut u8; scope 15 { scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _9; + debug ptr => _10; scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _9; + debug self => _10; scope 18 { scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _9; + debug self => _10; } } } @@ -74,8 +75,10 @@ StorageDead(_7); StorageLive(_8); StorageLive(_9); + StorageLive(_10); _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); _5 = NonNull::<[bool; 0]> { pointer: _8 }; + StorageDead(_10); StorageDead(_9); StorageDead(_8); StorageDead(_6); diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff index 13545aa464aa..df68ce496fd8 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff @@ -25,20 +25,21 @@ scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; let mut _8: *const [bool; 0]; + let mut _9: *mut [bool; 0]; scope 12 { scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _6; + debug ptr => _9; scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _6; - let mut _9: *mut u8; + debug self => _9; + let mut _10: *mut u8; scope 15 { scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _9; + debug ptr => _10; scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _9; + debug self => _10; scope 18 { scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _9; + debug self => _10; } } } @@ -76,9 +77,11 @@ StorageDead(_7); StorageLive(_8); StorageLive(_9); + StorageLive(_10); - _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); _5 = NonNull::<[bool; 0]> { pointer: _8 }; + StorageDead(_10); StorageDead(_9); StorageDead(_8); StorageDead(_6); diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff index bf3269153814..e16ea22091ee 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff @@ -25,20 +25,21 @@ scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; let mut _8: *const [bool; 0]; + let mut _9: *mut [bool; 0]; scope 12 { scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _6; + debug ptr => _9; scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _6; - let mut _9: *mut u8; + debug self => _9; + let mut _10: *mut u8; scope 15 { scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _9; + debug ptr => _10; scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _9; + debug self => _10; scope 18 { scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _9; + debug self => _10; } } } @@ -76,9 +77,11 @@ StorageDead(_7); StorageLive(_8); StorageLive(_9); + StorageLive(_10); - _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); _5 = NonNull::<[bool; 0]> { pointer: _8 }; + StorageDead(_10); StorageDead(_9); StorageDead(_8); StorageDead(_6); diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff index 13545aa464aa..df68ce496fd8 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff @@ -25,20 +25,21 @@ scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; let mut _8: *const [bool; 0]; + let mut _9: *mut [bool; 0]; scope 12 { scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _6; + debug ptr => _9; scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _6; - let mut _9: *mut u8; + debug self => _9; + let mut _10: *mut u8; scope 15 { scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _9; + debug ptr => _10; scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _9; + debug self => _10; scope 18 { scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _9; + debug self => _10; } } } @@ -76,9 +77,11 @@ StorageDead(_7); StorageLive(_8); StorageLive(_9); + StorageLive(_10); - _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); _5 = NonNull::<[bool; 0]> { pointer: _8 }; + StorageDead(_10); StorageDead(_9); StorageDead(_8); StorageDead(_6); diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff index bf3269153814..e16ea22091ee 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff @@ -25,20 +25,21 @@ scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; let mut _8: *const [bool; 0]; + let mut _9: *mut [bool; 0]; scope 12 { scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _6; + debug ptr => _9; scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _6; - let mut _9: *mut u8; + debug self => _9; + let mut _10: *mut u8; scope 15 { scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _9; + debug ptr => _10; scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _9; + debug self => _10; scope 18 { scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _9; + debug self => _10; } } } @@ -76,9 +77,11 @@ StorageDead(_7); StorageLive(_8); StorageLive(_9); + StorageLive(_10); - _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); _5 = NonNull::<[bool; 0]> { pointer: _8 }; + StorageDead(_10); StorageDead(_9); StorageDead(_8); StorageDead(_6); diff --git a/tests/mir-opt/dataflow-const-prop/offset_of.rs b/tests/mir-opt/dataflow-const-prop/offset_of.rs index e71b3f59ecab..c1be69102580 100644 --- a/tests/mir-opt/dataflow-const-prop/offset_of.rs +++ b/tests/mir-opt/dataflow-const-prop/offset_of.rs @@ -2,7 +2,7 @@ // unit-test: DataflowConstProp // EMIT_MIR_FOR_EACH_PANIC_STRATEGY -#![feature(offset_of)] +#![feature(offset_of_nested)] use std::marker::PhantomData; use std::mem::offset_of; diff --git a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination.panic-abort.diff b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination-final.panic-abort.diff similarity index 64% rename from tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination.panic-abort.diff rename to tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination-final.panic-abort.diff index dc0f9073416f..07fb8301b9a9 100644 --- a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination.panic-abort.diff +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination-final.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `move_packed` before DeadStoreElimination -+ // MIR for `move_packed` after DeadStoreElimination +- // MIR for `move_packed` before DeadStoreElimination-final ++ // MIR for `move_packed` after DeadStoreElimination-final fn move_packed(_1: Packed) -> () { let mut _0: (); diff --git a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination.panic-unwind.diff b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination-final.panic-unwind.diff similarity index 64% rename from tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination.panic-unwind.diff rename to tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination-final.panic-unwind.diff index 86ef026ec5c8..cac3badfa673 100644 --- a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination.panic-unwind.diff +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination-final.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `move_packed` before DeadStoreElimination -+ // MIR for `move_packed` after DeadStoreElimination +- // MIR for `move_packed` before DeadStoreElimination-final ++ // MIR for `move_packed` after DeadStoreElimination-final fn move_packed(_1: Packed) -> () { let mut _0: (); diff --git a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination.panic-abort.diff b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination-final.panic-abort.diff similarity index 70% rename from tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination.panic-abort.diff rename to tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination-final.panic-abort.diff index 8f799b33f45d..f9bc9405d6a4 100644 --- a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination.panic-abort.diff +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination-final.panic-abort.diff @@ -1,12 +1,12 @@ -- // MIR for `move_simple` before DeadStoreElimination -+ // MIR for `move_simple` after DeadStoreElimination +- // MIR for `move_simple` before DeadStoreElimination-final ++ // MIR for `move_simple` after DeadStoreElimination-final fn move_simple(_1: i32) -> () { debug x => _1; let mut _0: (); let _2: (); -- let mut _3: i32; -- let mut _4: i32; + let mut _3: i32; + let mut _4: i32; bb0: { StorageLive(_2); diff --git a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination.panic-unwind.diff b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination-final.panic-unwind.diff similarity index 69% rename from tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination.panic-unwind.diff rename to tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination-final.panic-unwind.diff index 0551d663b50f..efe165422d94 100644 --- a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination.panic-unwind.diff +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_simple.DeadStoreElimination-final.panic-unwind.diff @@ -1,12 +1,12 @@ -- // MIR for `move_simple` before DeadStoreElimination -+ // MIR for `move_simple` after DeadStoreElimination +- // MIR for `move_simple` before DeadStoreElimination-final ++ // MIR for `move_simple` after DeadStoreElimination-final fn move_simple(_1: i32) -> () { debug x => _1; let mut _0: (); let _2: (); -- let mut _3: i32; -- let mut _4: i32; + let mut _3: i32; + let mut _4: i32; bb0: { StorageLive(_2); diff --git a/tests/mir-opt/dead-store-elimination/call_arg_copy.rs b/tests/mir-opt/dead-store-elimination/call_arg_copy.rs index 490a4aa502c3..37b3313f7d04 100644 --- a/tests/mir-opt/dead-store-elimination/call_arg_copy.rs +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.rs @@ -1,6 +1,5 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY -// unit-test: DeadStoreElimination +// unit-test: DeadStoreElimination-final // compile-flags: -Zmir-enable-passes=+CopyProp #![feature(core_intrinsics)] @@ -12,8 +11,10 @@ use std::intrinsics::mir::*; #[inline(never)] fn use_both(_: i32, _: i32) {} -// EMIT_MIR call_arg_copy.move_simple.DeadStoreElimination.diff +// EMIT_MIR call_arg_copy.move_simple.DeadStoreElimination-final.diff fn move_simple(x: i32) { + // CHECK-LABEL: fn move_simple( + // CHECK: = use_both(_1, move _1) use_both(x, x); } @@ -23,11 +24,14 @@ struct Packed { y: i32, } -// EMIT_MIR call_arg_copy.move_packed.DeadStoreElimination.diff +// EMIT_MIR call_arg_copy.move_packed.DeadStoreElimination-final.diff #[custom_mir(dialect = "analysis")] fn move_packed(packed: Packed) { + // CHECK-LABEL: fn move_packed( + // CHECK: = use_both(const 0_i32, (_1.1: i32)) mir!( { + // We have a packed struct, verify that the copy is not turned into a move. Call(RET = use_both(0, packed.y), ReturnTo(ret), UnwindContinue()) } ret = { diff --git a/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff b/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination-initial.diff similarity index 70% rename from tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff rename to tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination-initial.diff index cf73358dc52e..2766b6ce6a9f 100644 --- a/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff +++ b/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination-initial.diff @@ -1,10 +1,10 @@ -- // MIR for `cycle` before DeadStoreElimination -+ // MIR for `cycle` after DeadStoreElimination +- // MIR for `cycle` before DeadStoreElimination-initial ++ // MIR for `cycle` after DeadStoreElimination-initial fn cycle(_1: i32, _2: i32, _3: i32) -> () { let mut _0: (); let mut _4: bool; -- let mut _5: i32; + let mut _5: i32; bb0: { _4 = cond() -> [return: bb1, unwind continue]; @@ -19,6 +19,10 @@ - _3 = _2; - _2 = _1; - _1 = _5; ++ nop; ++ nop; ++ nop; ++ nop; _4 = cond() -> [return: bb1, unwind continue]; } diff --git a/tests/mir-opt/dead-store-elimination/cycle.rs b/tests/mir-opt/dead-store-elimination/cycle.rs index 13e5411275da..e8f566b4aa7b 100644 --- a/tests/mir-opt/dead-store-elimination/cycle.rs +++ b/tests/mir-opt/dead-store-elimination/cycle.rs @@ -1,9 +1,8 @@ -// skip-filecheck // This example is interesting because the non-transitive version of `MaybeLiveLocals` would // report that *all* of these stores are live. // // needs-unwind -// unit-test: DeadStoreElimination +// unit-test: DeadStoreElimination-initial #![feature(core_intrinsics, custom_mir)] use std::intrinsics::mir::*; @@ -13,9 +12,13 @@ fn cond() -> bool { false } -// EMIT_MIR cycle.cycle.DeadStoreElimination.diff +// EMIT_MIR cycle.cycle.DeadStoreElimination-initial.diff #[custom_mir(dialect = "runtime", phase = "post-cleanup")] fn cycle(mut x: i32, mut y: i32, mut z: i32) { + // CHECK-LABEL: fn cycle( + // CHECK-NOT: {{_.*}} = {{_.*}}; + // CHECK-NOT: {{_.*}} = move {{_.*}}; + // We use custom MIR to avoid generating debuginfo, that would force to preserve writes. mir!( let condition: bool; diff --git a/tests/mir-opt/dead-store-elimination/place_mention.main.DeadStoreElimination.diff b/tests/mir-opt/dead-store-elimination/place_mention.main.DeadStoreElimination-initial.diff similarity index 73% rename from tests/mir-opt/dead-store-elimination/place_mention.main.DeadStoreElimination.diff rename to tests/mir-opt/dead-store-elimination/place_mention.main.DeadStoreElimination-initial.diff index 2130518771a5..5a5502858712 100644 --- a/tests/mir-opt/dead-store-elimination/place_mention.main.DeadStoreElimination.diff +++ b/tests/mir-opt/dead-store-elimination/place_mention.main.DeadStoreElimination-initial.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before DeadStoreElimination -+ // MIR for `main` after DeadStoreElimination +- // MIR for `main` before DeadStoreElimination-initial ++ // MIR for `main` after DeadStoreElimination-initial fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/dead-store-elimination/place_mention.rs b/tests/mir-opt/dead-store-elimination/place_mention.rs index 4813cf7ee2bd..ae75e622ff7f 100644 --- a/tests/mir-opt/dead-store-elimination/place_mention.rs +++ b/tests/mir-opt/dead-store-elimination/place_mention.rs @@ -1,10 +1,15 @@ -// skip-filecheck -// unit-test: DeadStoreElimination +// Verify that we account for the `PlaceMention` statement as a use of the tuple, +// and don't remove it as a dead store. +// +// unit-test: DeadStoreElimination-initial // compile-flags: -Zmir-keep-place-mention -// EMIT_MIR place_mention.main.DeadStoreElimination.diff +// EMIT_MIR place_mention.main.DeadStoreElimination-initial.diff fn main() { - // Verify that we account for the `PlaceMention` statement as a use of the tuple, - // and don't remove it as a dead store. + // CHECK-LABEL: fn main( + // CHECK-NOT: PlaceMention( + // CHECK: [[tmp:_.*]] = + // CHECK-NEXT: PlaceMention([[tmp:_.*]]); + let (_, _) = ("Hello", "World"); } diff --git a/tests/mir-opt/dead-store-elimination/provenance_soundness.pointer_to_int.DeadStoreElimination.diff b/tests/mir-opt/dead-store-elimination/provenance_soundness.pointer_to_int.DeadStoreElimination-initial.diff similarity index 84% rename from tests/mir-opt/dead-store-elimination/provenance_soundness.pointer_to_int.DeadStoreElimination.diff rename to tests/mir-opt/dead-store-elimination/provenance_soundness.pointer_to_int.DeadStoreElimination-initial.diff index 31f727e5fb35..9b0dc6b6af67 100644 --- a/tests/mir-opt/dead-store-elimination/provenance_soundness.pointer_to_int.DeadStoreElimination.diff +++ b/tests/mir-opt/dead-store-elimination/provenance_soundness.pointer_to_int.DeadStoreElimination-initial.diff @@ -1,5 +1,5 @@ -- // MIR for `pointer_to_int` before DeadStoreElimination -+ // MIR for `pointer_to_int` after DeadStoreElimination +- // MIR for `pointer_to_int` before DeadStoreElimination-initial ++ // MIR for `pointer_to_int` after DeadStoreElimination-initial fn pointer_to_int(_1: *mut i32) -> () { debug p => _1; diff --git a/tests/mir-opt/dead-store-elimination/provenance_soundness.retags.DeadStoreElimination.diff b/tests/mir-opt/dead-store-elimination/provenance_soundness.retags.DeadStoreElimination-initial.diff similarity index 61% rename from tests/mir-opt/dead-store-elimination/provenance_soundness.retags.DeadStoreElimination.diff rename to tests/mir-opt/dead-store-elimination/provenance_soundness.retags.DeadStoreElimination-initial.diff index e1ebc39aacc4..ab74d2411bb1 100644 --- a/tests/mir-opt/dead-store-elimination/provenance_soundness.retags.DeadStoreElimination.diff +++ b/tests/mir-opt/dead-store-elimination/provenance_soundness.retags.DeadStoreElimination-initial.diff @@ -1,5 +1,5 @@ -- // MIR for `retags` before DeadStoreElimination -+ // MIR for `retags` after DeadStoreElimination +- // MIR for `retags` before DeadStoreElimination-initial ++ // MIR for `retags` after DeadStoreElimination-initial fn retags(_1: &mut i32) -> () { debug _r => _1; diff --git a/tests/mir-opt/dead-store-elimination/provenance_soundness.rs b/tests/mir-opt/dead-store-elimination/provenance_soundness.rs index 24ffbe980ebc..916c393b9de0 100644 --- a/tests/mir-opt/dead-store-elimination/provenance_soundness.rs +++ b/tests/mir-opt/dead-store-elimination/provenance_soundness.rs @@ -1,17 +1,21 @@ -// skip-filecheck -// unit-test: DeadStoreElimination +// Test that we don't remove pointer to int casts or retags +// unit-test: DeadStoreElimination-initial // compile-flags: -Zmir-emit-retag -// Test that we don't remove pointer to int casts or retags - -// EMIT_MIR provenance_soundness.pointer_to_int.DeadStoreElimination.diff +// EMIT_MIR provenance_soundness.pointer_to_int.DeadStoreElimination-initial.diff fn pointer_to_int(p: *mut i32) { + // CHECK-LABEL: fn pointer_to_int( + // CHECK: {{_.*}} = {{.*}} as usize (PointerExposeAddress); + // CHECK: {{_.*}} = {{.*}} as isize (PointerExposeAddress); let _x = p as usize; let _y = p as isize; } -// EMIT_MIR provenance_soundness.retags.DeadStoreElimination.diff -fn retags(_r: &mut i32) {} +// EMIT_MIR provenance_soundness.retags.DeadStoreElimination-initial.diff +fn retags(_r: &mut i32) { + // CHECK-LABEL: fn retags( + // CHECK: Retag([fn entry] _1); +} fn main() { pointer_to_int(&mut 5 as *mut _); diff --git a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff index 993e0f1d1a67..0af3faf28f07 100644 --- a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff +++ b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff @@ -5,12 +5,13 @@ let mut _0: (); let _1: main::Un; let mut _2: u32; + let mut _3: u32; scope 1 { debug un => _1; scope 2 { } scope 4 (inlined std::mem::drop::) { - debug _x => _2; + debug _x => _3; } } scope 3 (inlined val) { @@ -18,10 +19,13 @@ bb0: { StorageLive(_1); - _1 = Un { us: const 1_u32 }; StorageLive(_2); - _2 = (_1.0: u32); + _2 = const 1_u32; + _1 = Un { us: const 1_u32 }; StorageDead(_2); + StorageLive(_3); + _3 = (_1.0: u32); + StorageDead(_3); StorageDead(_1); return; } diff --git a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff index 993e0f1d1a67..0af3faf28f07 100644 --- a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff +++ b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff @@ -5,12 +5,13 @@ let mut _0: (); let _1: main::Un; let mut _2: u32; + let mut _3: u32; scope 1 { debug un => _1; scope 2 { } scope 4 (inlined std::mem::drop::) { - debug _x => _2; + debug _x => _3; } } scope 3 (inlined val) { @@ -18,10 +19,13 @@ bb0: { StorageLive(_1); - _1 = Un { us: const 1_u32 }; StorageLive(_2); - _2 = (_1.0: u32); + _2 = const 1_u32; + _1 = Un { us: const 1_u32 }; StorageDead(_2); + StorageLive(_3); + _3 = (_1.0: u32); + StorageDead(_3); StorageDead(_1); return; } diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff index 0ba1bac0a030..080478ea8841 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff @@ -73,31 +73,59 @@ } bb4: { +- StorageLive(_8); ++ nop; _8 = ((_6 as Some).0: usize); + StorageLive(_9); + _9 = _1; + StorageLive(_10); + _10 = _2; StorageLive(_11); _11 = _5; StorageLive(_12); StorageLive(_13); - _13 = _8 as u32 (IntToInt); + StorageLive(_14); + _14 = _8; +- _13 = move _14 as u32 (IntToInt); ++ _13 = _8 as u32 (IntToInt); + StorageDead(_14); _12 = Add(move _13, const 1_u32); StorageDead(_13); - _0 = float_to_exponential_common_exact::(_1, _2, move _11, move _12, _3) -> [return: bb5, unwind unreachable]; + StorageLive(_15); + _15 = _3; +- _0 = float_to_exponential_common_exact::(move _9, move _10, move _11, move _12, move _15) -> [return: bb5, unwind unreachable]; ++ _0 = float_to_exponential_common_exact::(_1, _2, move _11, move _12, _3) -> [return: bb5, unwind unreachable]; } bb5: { + StorageDead(_15); StorageDead(_12); StorageDead(_11); + StorageDead(_10); + StorageDead(_9); +- StorageDead(_8); ++ nop; goto -> bb8; } bb6: { + StorageLive(_16); + _16 = _1; + StorageLive(_17); + _17 = _2; StorageLive(_18); _18 = _5; - _0 = float_to_exponential_common_shortest::(_1, _2, move _18, _3) -> [return: bb7, unwind unreachable]; + StorageLive(_19); + _19 = _3; +- _0 = float_to_exponential_common_shortest::(move _16, move _17, move _18, move _19) -> [return: bb7, unwind unreachable]; ++ _0 = float_to_exponential_common_shortest::(_1, _2, move _18, _3) -> [return: bb7, unwind unreachable]; } bb7: { + StorageDead(_19); StorageDead(_18); + StorageDead(_17); + StorageDead(_16); goto -> bb8; } diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff index 27ea43ef12b7..ff8933fca8b2 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff @@ -73,31 +73,59 @@ } bb4: { +- StorageLive(_8); ++ nop; _8 = ((_6 as Some).0: usize); + StorageLive(_9); + _9 = _1; + StorageLive(_10); + _10 = _2; StorageLive(_11); _11 = _5; StorageLive(_12); StorageLive(_13); - _13 = _8 as u32 (IntToInt); + StorageLive(_14); + _14 = _8; +- _13 = move _14 as u32 (IntToInt); ++ _13 = _8 as u32 (IntToInt); + StorageDead(_14); _12 = Add(move _13, const 1_u32); StorageDead(_13); - _0 = float_to_exponential_common_exact::(_1, _2, move _11, move _12, _3) -> [return: bb5, unwind continue]; + StorageLive(_15); + _15 = _3; +- _0 = float_to_exponential_common_exact::(move _9, move _10, move _11, move _12, move _15) -> [return: bb5, unwind continue]; ++ _0 = float_to_exponential_common_exact::(_1, _2, move _11, move _12, _3) -> [return: bb5, unwind continue]; } bb5: { + StorageDead(_15); StorageDead(_12); StorageDead(_11); + StorageDead(_10); + StorageDead(_9); +- StorageDead(_8); ++ nop; goto -> bb8; } bb6: { + StorageLive(_16); + _16 = _1; + StorageLive(_17); + _17 = _2; StorageLive(_18); _18 = _5; - _0 = float_to_exponential_common_shortest::(_1, _2, move _18, _3) -> [return: bb7, unwind continue]; + StorageLive(_19); + _19 = _3; +- _0 = float_to_exponential_common_shortest::(move _16, move _17, move _18, move _19) -> [return: bb7, unwind continue]; ++ _0 = float_to_exponential_common_shortest::(_1, _2, move _18, _3) -> [return: bb7, unwind continue]; } bb7: { + StorageDead(_19); StorageDead(_18); + StorageDead(_17); + StorageDead(_16); goto -> bb8; } diff --git a/tests/mir-opt/gvn.arithmetic.GVN.panic-abort.diff b/tests/mir-opt/gvn.arithmetic.GVN.panic-abort.diff index d524ad242fec..84eb6c5cfe8d 100644 --- a/tests/mir-opt/gvn.arithmetic.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.arithmetic.GVN.panic-abort.diff @@ -13,13 +13,13 @@ let _8: (); let mut _9: u64; let mut _10: u64; - let _11: (); - let mut _12: u64; + let mut _11: u64; + let _12: (); let mut _13: u64; - let _14: (); - let mut _15: u64; + let mut _14: u64; + let _15: (); let mut _16: u64; - let mut _17: bool; + let mut _17: u64; let _18: (); let mut _19: u64; let mut _20: u64; @@ -51,18 +51,32 @@ let _46: (); let mut _47: u64; let mut _48: u64; - let _49: (); - let mut _50: u64; + let mut _49: bool; + let _50: (); let mut _51: u64; - let _52: (); - let mut _53: u64; + let mut _52: u64; + let _53: (); let mut _54: u64; - let _55: (); - let mut _56: u64; + let mut _55: u64; + let _56: (); let mut _57: u64; - let _58: (); - let mut _59: u64; + let mut _58: u64; + let _59: (); let mut _60: u64; + let mut _61: u64; + let _62: (); + let mut _63: u64; + let mut _64: u64; + let _65: (); + let mut _66: u64; + let mut _67: u64; + let mut _68: u64; + let _69: (); + let mut _70: u64; + let mut _71: u64; + let _72: (); + let mut _73: u64; + let mut _74: u64; bb0: { StorageLive(_2); @@ -70,9 +84,10 @@ StorageLive(_4); _4 = _1; - _3 = Add(move _4, const 0_u64); -+ _3 = Add(_1, const 0_u64); ++ _3 = _1; StorageDead(_4); - _2 = opaque::(move _3) -> [return: bb1, unwind unreachable]; +- _2 = opaque::(move _3) -> [return: bb1, unwind unreachable]; ++ _2 = opaque::(_1) -> [return: bb1, unwind unreachable]; } bb1: { @@ -83,98 +98,101 @@ StorageLive(_7); _7 = _1; - _6 = Sub(move _7, const 0_u64); -+ _6 = Sub(_1, const 0_u64); ++ _6 = _1; StorageDead(_7); - _5 = opaque::(move _6) -> [return: bb2, unwind unreachable]; +- _5 = opaque::(move _6) -> [return: bb2, unwind unreachable]; ++ _5 = opaque::(_1) -> [return: bb2, unwind unreachable]; } bb2: { StorageDead(_6); StorageDead(_5); StorageLive(_8); - StorageLive(_9); +- StorageLive(_9); ++ nop; StorageLive(_10); _10 = _1; -- _9 = Mul(move _10, const 0_u64); -+ _9 = Mul(_1, const 0_u64); + StorageLive(_11); + _11 = _1; +- _9 = Sub(move _10, move _11); ++ _9 = const 0_u64; + StorageDead(_11); StorageDead(_10); - _8 = opaque::(move _9) -> [return: bb3, unwind unreachable]; +- _8 = opaque::(move _9) -> [return: bb3, unwind unreachable]; ++ _8 = opaque::(const 0_u64) -> [return: bb3, unwind unreachable]; } bb3: { - StorageDead(_9); +- StorageDead(_9); ++ nop; StorageDead(_8); - StorageLive(_11); StorageLive(_12); StorageLive(_13); - _13 = _1; -- _12 = Mul(move _13, const 1_u64); -+ _12 = Mul(_1, const 1_u64); - StorageDead(_13); - _11 = opaque::(move _12) -> [return: bb4, unwind unreachable]; + StorageLive(_14); + _14 = _1; +- _13 = Mul(move _14, const 0_u64); ++ _13 = const 0_u64; + StorageDead(_14); +- _12 = opaque::(move _13) -> [return: bb4, unwind unreachable]; ++ _12 = opaque::(const 0_u64) -> [return: bb4, unwind unreachable]; } bb4: { + StorageDead(_13); StorageDead(_12); - StorageDead(_11); - StorageLive(_14); StorageLive(_15); StorageLive(_16); - _16 = _1; -- _17 = Eq(const 0_u64, const 0_u64); -- assert(!move _17, "attempt to divide `{}` by zero", _16) -> [success: bb5, unwind unreachable]; -+ _17 = const true; -+ assert(!const true, "attempt to divide `{}` by zero", _1) -> [success: bb5, unwind unreachable]; + StorageLive(_17); + _17 = _1; +- _16 = Mul(move _17, const 1_u64); ++ _16 = _1; + StorageDead(_17); +- _15 = opaque::(move _16) -> [return: bb5, unwind unreachable]; ++ _15 = opaque::(_1) -> [return: bb5, unwind unreachable]; } bb5: { -- _15 = Div(move _16, const 0_u64); -+ _15 = Div(_1, const 0_u64); StorageDead(_16); - _14 = opaque::(move _15) -> [return: bb6, unwind unreachable]; - } - - bb6: { StorageDead(_15); - StorageDead(_14); StorageLive(_18); StorageLive(_19); StorageLive(_20); _20 = _1; -- _21 = Eq(const 1_u64, const 0_u64); -- assert(!move _21, "attempt to divide `{}` by zero", _20) -> [success: bb7, unwind unreachable]; -+ _21 = const false; -+ assert(!const false, "attempt to divide `{}` by zero", _1) -> [success: bb7, unwind unreachable]; +- _21 = Eq(const 0_u64, const 0_u64); +- assert(!move _21, "attempt to divide `{}` by zero", _20) -> [success: bb6, unwind unreachable]; ++ _21 = const true; ++ assert(!const true, "attempt to divide `{}` by zero", _1) -> [success: bb6, unwind unreachable]; + } + + bb6: { +- _19 = Div(move _20, const 0_u64); ++ _19 = Div(_1, const 0_u64); + StorageDead(_20); + _18 = opaque::(move _19) -> [return: bb7, unwind unreachable]; } bb7: { -- _19 = Div(move _20, const 1_u64); -+ _19 = Div(_1, const 1_u64); - StorageDead(_20); - _18 = opaque::(move _19) -> [return: bb8, unwind unreachable]; - } - - bb8: { StorageDead(_19); StorageDead(_18); StorageLive(_22); StorageLive(_23); StorageLive(_24); _24 = _1; -- _25 = Eq(_24, const 0_u64); -- assert(!move _25, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb9, unwind unreachable]; -+ _25 = Eq(_1, const 0_u64); -+ assert(!_25, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb9, unwind unreachable]; +- _25 = Eq(const 1_u64, const 0_u64); +- assert(!move _25, "attempt to divide `{}` by zero", _24) -> [success: bb8, unwind unreachable]; ++ _25 = const false; ++ assert(!const false, "attempt to divide `{}` by zero", _1) -> [success: bb8, unwind unreachable]; + } + + bb8: { +- _23 = Div(move _24, const 1_u64); ++ _23 = _1; + StorageDead(_24); +- _22 = opaque::(move _23) -> [return: bb9, unwind unreachable]; ++ _22 = opaque::(_1) -> [return: bb9, unwind unreachable]; } bb9: { -- _23 = Div(const 0_u64, move _24); -+ _23 = Div(const 0_u64, _1); - StorageDead(_24); - _22 = opaque::(move _23) -> [return: bb10, unwind unreachable]; - } - - bb10: { StorageDead(_23); StorageDead(_22); StorageLive(_26); @@ -182,79 +200,81 @@ StorageLive(_28); _28 = _1; - _29 = Eq(_28, const 0_u64); -- assert(!move _29, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb11, unwind unreachable]; -+ _29 = _25; -+ assert(!_25, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb11, unwind unreachable]; +- assert(!move _29, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb10, unwind unreachable]; ++ _29 = Eq(_1, const 0_u64); ++ assert(!_29, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb10, unwind unreachable]; + } + + bb10: { +- _27 = Div(const 0_u64, move _28); ++ _27 = const 0_u64; + StorageDead(_28); +- _26 = opaque::(move _27) -> [return: bb11, unwind unreachable]; ++ _26 = opaque::(const 0_u64) -> [return: bb11, unwind unreachable]; } bb11: { -- _27 = Div(const 1_u64, move _28); -+ _27 = Div(const 1_u64, _1); - StorageDead(_28); - _26 = opaque::(move _27) -> [return: bb12, unwind unreachable]; - } - - bb12: { StorageDead(_27); StorageDead(_26); StorageLive(_30); StorageLive(_31); StorageLive(_32); _32 = _1; -- _33 = Eq(const 0_u64, const 0_u64); -- assert(!move _33, "attempt to calculate the remainder of `{}` with a divisor of zero", _32) -> [success: bb13, unwind unreachable]; -+ _33 = const true; -+ assert(!const true, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb13, unwind unreachable]; +- _33 = Eq(_32, const 0_u64); +- assert(!move _33, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb12, unwind unreachable]; ++ _33 = _29; ++ assert(!_29, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb12, unwind unreachable]; + } + + bb12: { +- _31 = Div(const 1_u64, move _32); ++ _31 = Div(const 1_u64, _1); + StorageDead(_32); + _30 = opaque::(move _31) -> [return: bb13, unwind unreachable]; } bb13: { -- _31 = Rem(move _32, const 0_u64); -+ _31 = Rem(_1, const 0_u64); - StorageDead(_32); - _30 = opaque::(move _31) -> [return: bb14, unwind unreachable]; - } - - bb14: { StorageDead(_31); StorageDead(_30); StorageLive(_34); StorageLive(_35); StorageLive(_36); _36 = _1; -- _37 = Eq(const 1_u64, const 0_u64); -- assert(!move _37, "attempt to calculate the remainder of `{}` with a divisor of zero", _36) -> [success: bb15, unwind unreachable]; -+ _37 = const false; -+ assert(!const false, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb15, unwind unreachable]; +- _37 = Eq(const 0_u64, const 0_u64); +- assert(!move _37, "attempt to calculate the remainder of `{}` with a divisor of zero", _36) -> [success: bb14, unwind unreachable]; ++ _37 = const true; ++ assert(!const true, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb14, unwind unreachable]; + } + + bb14: { +- _35 = Rem(move _36, const 0_u64); ++ _35 = Rem(_1, const 0_u64); + StorageDead(_36); + _34 = opaque::(move _35) -> [return: bb15, unwind unreachable]; } bb15: { -- _35 = Rem(move _36, const 1_u64); -+ _35 = Rem(_1, const 1_u64); - StorageDead(_36); - _34 = opaque::(move _35) -> [return: bb16, unwind unreachable]; - } - - bb16: { StorageDead(_35); StorageDead(_34); StorageLive(_38); StorageLive(_39); StorageLive(_40); _40 = _1; -- _41 = Eq(_40, const 0_u64); -- assert(!move _41, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb17, unwind unreachable]; -+ _41 = _25; -+ assert(!_25, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb17, unwind unreachable]; +- _41 = Eq(const 1_u64, const 0_u64); +- assert(!move _41, "attempt to calculate the remainder of `{}` with a divisor of zero", _40) -> [success: bb16, unwind unreachable]; ++ _41 = const false; ++ assert(!const false, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb16, unwind unreachable]; + } + + bb16: { +- _39 = Rem(move _40, const 1_u64); ++ _39 = const 0_u64; + StorageDead(_40); +- _38 = opaque::(move _39) -> [return: bb17, unwind unreachable]; ++ _38 = opaque::(const 0_u64) -> [return: bb17, unwind unreachable]; } bb17: { -- _39 = Rem(const 0_u64, move _40); -+ _39 = Rem(const 0_u64, _1); - StorageDead(_40); - _38 = opaque::(move _39) -> [return: bb18, unwind unreachable]; - } - - bb18: { StorageDead(_39); StorageDead(_38); StorageLive(_42); @@ -262,27 +282,35 @@ StorageLive(_44); _44 = _1; - _45 = Eq(_44, const 0_u64); -- assert(!move _45, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb19, unwind unreachable]; -+ _45 = _25; -+ assert(!_25, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb19, unwind unreachable]; +- assert(!move _45, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb18, unwind unreachable]; ++ _45 = _29; ++ assert(!_29, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb18, unwind unreachable]; + } + + bb18: { +- _43 = Rem(const 0_u64, move _44); ++ _43 = const 0_u64; + StorageDead(_44); +- _42 = opaque::(move _43) -> [return: bb19, unwind unreachable]; ++ _42 = opaque::(const 0_u64) -> [return: bb19, unwind unreachable]; } bb19: { -- _43 = Rem(const 1_u64, move _44); -+ _43 = Rem(const 1_u64, _1); - StorageDead(_44); - _42 = opaque::(move _43) -> [return: bb20, unwind unreachable]; - } - - bb20: { StorageDead(_43); StorageDead(_42); StorageLive(_46); StorageLive(_47); StorageLive(_48); _48 = _1; -- _47 = BitAnd(move _48, const 0_u64); -+ _47 = BitAnd(_1, const 0_u64); +- _49 = Eq(_48, const 0_u64); +- assert(!move _49, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb20, unwind unreachable]; ++ _49 = _29; ++ assert(!_29, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb20, unwind unreachable]; + } + + bb20: { +- _47 = Rem(const 1_u64, move _48); ++ _47 = Rem(const 1_u64, _1); StorageDead(_48); _46 = opaque::(move _47) -> [return: bb21, unwind unreachable]; } @@ -290,58 +318,121 @@ bb21: { StorageDead(_47); StorageDead(_46); - StorageLive(_49); StorageLive(_50); StorageLive(_51); - _51 = _1; -- _50 = BitOr(move _51, const 0_u64); -+ _50 = BitOr(_1, const 0_u64); - StorageDead(_51); - _49 = opaque::(move _50) -> [return: bb22, unwind unreachable]; + StorageLive(_52); + _52 = _1; +- _51 = BitAnd(move _52, const 0_u64); ++ _51 = const 0_u64; + StorageDead(_52); +- _50 = opaque::(move _51) -> [return: bb22, unwind unreachable]; ++ _50 = opaque::(const 0_u64) -> [return: bb22, unwind unreachable]; } bb22: { + StorageDead(_51); StorageDead(_50); - StorageDead(_49); - StorageLive(_52); StorageLive(_53); StorageLive(_54); - _54 = _1; -- _53 = BitXor(move _54, const 0_u64); -+ _53 = BitXor(_1, const 0_u64); - StorageDead(_54); - _52 = opaque::(move _53) -> [return: bb23, unwind unreachable]; + StorageLive(_55); + _55 = _1; +- _54 = BitAnd(move _55, const _); ++ _54 = _1; + StorageDead(_55); +- _53 = opaque::(move _54) -> [return: bb23, unwind unreachable]; ++ _53 = opaque::(_1) -> [return: bb23, unwind unreachable]; } bb23: { + StorageDead(_54); StorageDead(_53); - StorageDead(_52); - StorageLive(_55); StorageLive(_56); StorageLive(_57); - _57 = _1; -- _56 = Shr(move _57, const 0_i32); -+ _56 = Shr(_1, const 0_i32); - StorageDead(_57); - _55 = opaque::(move _56) -> [return: bb24, unwind unreachable]; + StorageLive(_58); + _58 = _1; +- _57 = BitOr(move _58, const 0_u64); ++ _57 = _1; + StorageDead(_58); +- _56 = opaque::(move _57) -> [return: bb24, unwind unreachable]; ++ _56 = opaque::(_1) -> [return: bb24, unwind unreachable]; } bb24: { + StorageDead(_57); StorageDead(_56); - StorageDead(_55); - StorageLive(_58); StorageLive(_59); StorageLive(_60); - _60 = _1; -- _59 = Shl(move _60, const 0_i32); -+ _59 = Shl(_1, const 0_i32); - StorageDead(_60); - _58 = opaque::(move _59) -> [return: bb25, unwind unreachable]; + StorageLive(_61); + _61 = _1; +- _60 = BitOr(move _61, const _); ++ _60 = const u64::MAX; + StorageDead(_61); +- _59 = opaque::(move _60) -> [return: bb25, unwind unreachable]; ++ _59 = opaque::(const u64::MAX) -> [return: bb25, unwind unreachable]; } bb25: { + StorageDead(_60); StorageDead(_59); - StorageDead(_58); + StorageLive(_62); + StorageLive(_63); + StorageLive(_64); + _64 = _1; +- _63 = BitXor(move _64, const 0_u64); ++ _63 = _1; + StorageDead(_64); +- _62 = opaque::(move _63) -> [return: bb26, unwind unreachable]; ++ _62 = opaque::(_1) -> [return: bb26, unwind unreachable]; + } + + bb26: { + StorageDead(_63); + StorageDead(_62); + StorageLive(_65); + StorageLive(_66); + StorageLive(_67); + _67 = _1; + StorageLive(_68); + _68 = _1; +- _66 = BitXor(move _67, move _68); ++ _66 = const 0_u64; + StorageDead(_68); + StorageDead(_67); +- _65 = opaque::(move _66) -> [return: bb27, unwind unreachable]; ++ _65 = opaque::(const 0_u64) -> [return: bb27, unwind unreachable]; + } + + bb27: { + StorageDead(_66); + StorageDead(_65); + StorageLive(_69); + StorageLive(_70); + StorageLive(_71); + _71 = _1; +- _70 = Shr(move _71, const 0_i32); ++ _70 = _1; + StorageDead(_71); +- _69 = opaque::(move _70) -> [return: bb28, unwind unreachable]; ++ _69 = opaque::(_1) -> [return: bb28, unwind unreachable]; + } + + bb28: { + StorageDead(_70); + StorageDead(_69); + StorageLive(_72); + StorageLive(_73); + StorageLive(_74); + _74 = _1; +- _73 = Shl(move _74, const 0_i32); ++ _73 = _1; + StorageDead(_74); +- _72 = opaque::(move _73) -> [return: bb29, unwind unreachable]; ++ _72 = opaque::(_1) -> [return: bb29, unwind unreachable]; + } + + bb29: { + StorageDead(_73); + StorageDead(_72); _0 = const (); return; } diff --git a/tests/mir-opt/gvn.arithmetic.GVN.panic-unwind.diff b/tests/mir-opt/gvn.arithmetic.GVN.panic-unwind.diff index 9d69353934c7..98e92d2a3104 100644 --- a/tests/mir-opt/gvn.arithmetic.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.arithmetic.GVN.panic-unwind.diff @@ -13,13 +13,13 @@ let _8: (); let mut _9: u64; let mut _10: u64; - let _11: (); - let mut _12: u64; + let mut _11: u64; + let _12: (); let mut _13: u64; - let _14: (); - let mut _15: u64; + let mut _14: u64; + let _15: (); let mut _16: u64; - let mut _17: bool; + let mut _17: u64; let _18: (); let mut _19: u64; let mut _20: u64; @@ -51,18 +51,32 @@ let _46: (); let mut _47: u64; let mut _48: u64; - let _49: (); - let mut _50: u64; + let mut _49: bool; + let _50: (); let mut _51: u64; - let _52: (); - let mut _53: u64; + let mut _52: u64; + let _53: (); let mut _54: u64; - let _55: (); - let mut _56: u64; + let mut _55: u64; + let _56: (); let mut _57: u64; - let _58: (); - let mut _59: u64; + let mut _58: u64; + let _59: (); let mut _60: u64; + let mut _61: u64; + let _62: (); + let mut _63: u64; + let mut _64: u64; + let _65: (); + let mut _66: u64; + let mut _67: u64; + let mut _68: u64; + let _69: (); + let mut _70: u64; + let mut _71: u64; + let _72: (); + let mut _73: u64; + let mut _74: u64; bb0: { StorageLive(_2); @@ -70,9 +84,10 @@ StorageLive(_4); _4 = _1; - _3 = Add(move _4, const 0_u64); -+ _3 = Add(_1, const 0_u64); ++ _3 = _1; StorageDead(_4); - _2 = opaque::(move _3) -> [return: bb1, unwind continue]; +- _2 = opaque::(move _3) -> [return: bb1, unwind continue]; ++ _2 = opaque::(_1) -> [return: bb1, unwind continue]; } bb1: { @@ -83,98 +98,101 @@ StorageLive(_7); _7 = _1; - _6 = Sub(move _7, const 0_u64); -+ _6 = Sub(_1, const 0_u64); ++ _6 = _1; StorageDead(_7); - _5 = opaque::(move _6) -> [return: bb2, unwind continue]; +- _5 = opaque::(move _6) -> [return: bb2, unwind continue]; ++ _5 = opaque::(_1) -> [return: bb2, unwind continue]; } bb2: { StorageDead(_6); StorageDead(_5); StorageLive(_8); - StorageLive(_9); +- StorageLive(_9); ++ nop; StorageLive(_10); _10 = _1; -- _9 = Mul(move _10, const 0_u64); -+ _9 = Mul(_1, const 0_u64); + StorageLive(_11); + _11 = _1; +- _9 = Sub(move _10, move _11); ++ _9 = const 0_u64; + StorageDead(_11); StorageDead(_10); - _8 = opaque::(move _9) -> [return: bb3, unwind continue]; +- _8 = opaque::(move _9) -> [return: bb3, unwind continue]; ++ _8 = opaque::(const 0_u64) -> [return: bb3, unwind continue]; } bb3: { - StorageDead(_9); +- StorageDead(_9); ++ nop; StorageDead(_8); - StorageLive(_11); StorageLive(_12); StorageLive(_13); - _13 = _1; -- _12 = Mul(move _13, const 1_u64); -+ _12 = Mul(_1, const 1_u64); - StorageDead(_13); - _11 = opaque::(move _12) -> [return: bb4, unwind continue]; + StorageLive(_14); + _14 = _1; +- _13 = Mul(move _14, const 0_u64); ++ _13 = const 0_u64; + StorageDead(_14); +- _12 = opaque::(move _13) -> [return: bb4, unwind continue]; ++ _12 = opaque::(const 0_u64) -> [return: bb4, unwind continue]; } bb4: { + StorageDead(_13); StorageDead(_12); - StorageDead(_11); - StorageLive(_14); StorageLive(_15); StorageLive(_16); - _16 = _1; -- _17 = Eq(const 0_u64, const 0_u64); -- assert(!move _17, "attempt to divide `{}` by zero", _16) -> [success: bb5, unwind continue]; -+ _17 = const true; -+ assert(!const true, "attempt to divide `{}` by zero", _1) -> [success: bb5, unwind continue]; + StorageLive(_17); + _17 = _1; +- _16 = Mul(move _17, const 1_u64); ++ _16 = _1; + StorageDead(_17); +- _15 = opaque::(move _16) -> [return: bb5, unwind continue]; ++ _15 = opaque::(_1) -> [return: bb5, unwind continue]; } bb5: { -- _15 = Div(move _16, const 0_u64); -+ _15 = Div(_1, const 0_u64); StorageDead(_16); - _14 = opaque::(move _15) -> [return: bb6, unwind continue]; - } - - bb6: { StorageDead(_15); - StorageDead(_14); StorageLive(_18); StorageLive(_19); StorageLive(_20); _20 = _1; -- _21 = Eq(const 1_u64, const 0_u64); -- assert(!move _21, "attempt to divide `{}` by zero", _20) -> [success: bb7, unwind continue]; -+ _21 = const false; -+ assert(!const false, "attempt to divide `{}` by zero", _1) -> [success: bb7, unwind continue]; +- _21 = Eq(const 0_u64, const 0_u64); +- assert(!move _21, "attempt to divide `{}` by zero", _20) -> [success: bb6, unwind continue]; ++ _21 = const true; ++ assert(!const true, "attempt to divide `{}` by zero", _1) -> [success: bb6, unwind continue]; + } + + bb6: { +- _19 = Div(move _20, const 0_u64); ++ _19 = Div(_1, const 0_u64); + StorageDead(_20); + _18 = opaque::(move _19) -> [return: bb7, unwind continue]; } bb7: { -- _19 = Div(move _20, const 1_u64); -+ _19 = Div(_1, const 1_u64); - StorageDead(_20); - _18 = opaque::(move _19) -> [return: bb8, unwind continue]; - } - - bb8: { StorageDead(_19); StorageDead(_18); StorageLive(_22); StorageLive(_23); StorageLive(_24); _24 = _1; -- _25 = Eq(_24, const 0_u64); -- assert(!move _25, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb9, unwind continue]; -+ _25 = Eq(_1, const 0_u64); -+ assert(!_25, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb9, unwind continue]; +- _25 = Eq(const 1_u64, const 0_u64); +- assert(!move _25, "attempt to divide `{}` by zero", _24) -> [success: bb8, unwind continue]; ++ _25 = const false; ++ assert(!const false, "attempt to divide `{}` by zero", _1) -> [success: bb8, unwind continue]; + } + + bb8: { +- _23 = Div(move _24, const 1_u64); ++ _23 = _1; + StorageDead(_24); +- _22 = opaque::(move _23) -> [return: bb9, unwind continue]; ++ _22 = opaque::(_1) -> [return: bb9, unwind continue]; } bb9: { -- _23 = Div(const 0_u64, move _24); -+ _23 = Div(const 0_u64, _1); - StorageDead(_24); - _22 = opaque::(move _23) -> [return: bb10, unwind continue]; - } - - bb10: { StorageDead(_23); StorageDead(_22); StorageLive(_26); @@ -182,79 +200,81 @@ StorageLive(_28); _28 = _1; - _29 = Eq(_28, const 0_u64); -- assert(!move _29, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb11, unwind continue]; -+ _29 = _25; -+ assert(!_25, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb11, unwind continue]; +- assert(!move _29, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb10, unwind continue]; ++ _29 = Eq(_1, const 0_u64); ++ assert(!_29, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb10, unwind continue]; + } + + bb10: { +- _27 = Div(const 0_u64, move _28); ++ _27 = const 0_u64; + StorageDead(_28); +- _26 = opaque::(move _27) -> [return: bb11, unwind continue]; ++ _26 = opaque::(const 0_u64) -> [return: bb11, unwind continue]; } bb11: { -- _27 = Div(const 1_u64, move _28); -+ _27 = Div(const 1_u64, _1); - StorageDead(_28); - _26 = opaque::(move _27) -> [return: bb12, unwind continue]; - } - - bb12: { StorageDead(_27); StorageDead(_26); StorageLive(_30); StorageLive(_31); StorageLive(_32); _32 = _1; -- _33 = Eq(const 0_u64, const 0_u64); -- assert(!move _33, "attempt to calculate the remainder of `{}` with a divisor of zero", _32) -> [success: bb13, unwind continue]; -+ _33 = const true; -+ assert(!const true, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb13, unwind continue]; +- _33 = Eq(_32, const 0_u64); +- assert(!move _33, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb12, unwind continue]; ++ _33 = _29; ++ assert(!_29, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb12, unwind continue]; + } + + bb12: { +- _31 = Div(const 1_u64, move _32); ++ _31 = Div(const 1_u64, _1); + StorageDead(_32); + _30 = opaque::(move _31) -> [return: bb13, unwind continue]; } bb13: { -- _31 = Rem(move _32, const 0_u64); -+ _31 = Rem(_1, const 0_u64); - StorageDead(_32); - _30 = opaque::(move _31) -> [return: bb14, unwind continue]; - } - - bb14: { StorageDead(_31); StorageDead(_30); StorageLive(_34); StorageLive(_35); StorageLive(_36); _36 = _1; -- _37 = Eq(const 1_u64, const 0_u64); -- assert(!move _37, "attempt to calculate the remainder of `{}` with a divisor of zero", _36) -> [success: bb15, unwind continue]; -+ _37 = const false; -+ assert(!const false, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb15, unwind continue]; +- _37 = Eq(const 0_u64, const 0_u64); +- assert(!move _37, "attempt to calculate the remainder of `{}` with a divisor of zero", _36) -> [success: bb14, unwind continue]; ++ _37 = const true; ++ assert(!const true, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb14, unwind continue]; + } + + bb14: { +- _35 = Rem(move _36, const 0_u64); ++ _35 = Rem(_1, const 0_u64); + StorageDead(_36); + _34 = opaque::(move _35) -> [return: bb15, unwind continue]; } bb15: { -- _35 = Rem(move _36, const 1_u64); -+ _35 = Rem(_1, const 1_u64); - StorageDead(_36); - _34 = opaque::(move _35) -> [return: bb16, unwind continue]; - } - - bb16: { StorageDead(_35); StorageDead(_34); StorageLive(_38); StorageLive(_39); StorageLive(_40); _40 = _1; -- _41 = Eq(_40, const 0_u64); -- assert(!move _41, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb17, unwind continue]; -+ _41 = _25; -+ assert(!_25, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb17, unwind continue]; +- _41 = Eq(const 1_u64, const 0_u64); +- assert(!move _41, "attempt to calculate the remainder of `{}` with a divisor of zero", _40) -> [success: bb16, unwind continue]; ++ _41 = const false; ++ assert(!const false, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb16, unwind continue]; + } + + bb16: { +- _39 = Rem(move _40, const 1_u64); ++ _39 = const 0_u64; + StorageDead(_40); +- _38 = opaque::(move _39) -> [return: bb17, unwind continue]; ++ _38 = opaque::(const 0_u64) -> [return: bb17, unwind continue]; } bb17: { -- _39 = Rem(const 0_u64, move _40); -+ _39 = Rem(const 0_u64, _1); - StorageDead(_40); - _38 = opaque::(move _39) -> [return: bb18, unwind continue]; - } - - bb18: { StorageDead(_39); StorageDead(_38); StorageLive(_42); @@ -262,27 +282,35 @@ StorageLive(_44); _44 = _1; - _45 = Eq(_44, const 0_u64); -- assert(!move _45, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb19, unwind continue]; -+ _45 = _25; -+ assert(!_25, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb19, unwind continue]; +- assert(!move _45, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb18, unwind continue]; ++ _45 = _29; ++ assert(!_29, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb18, unwind continue]; + } + + bb18: { +- _43 = Rem(const 0_u64, move _44); ++ _43 = const 0_u64; + StorageDead(_44); +- _42 = opaque::(move _43) -> [return: bb19, unwind continue]; ++ _42 = opaque::(const 0_u64) -> [return: bb19, unwind continue]; } bb19: { -- _43 = Rem(const 1_u64, move _44); -+ _43 = Rem(const 1_u64, _1); - StorageDead(_44); - _42 = opaque::(move _43) -> [return: bb20, unwind continue]; - } - - bb20: { StorageDead(_43); StorageDead(_42); StorageLive(_46); StorageLive(_47); StorageLive(_48); _48 = _1; -- _47 = BitAnd(move _48, const 0_u64); -+ _47 = BitAnd(_1, const 0_u64); +- _49 = Eq(_48, const 0_u64); +- assert(!move _49, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb20, unwind continue]; ++ _49 = _29; ++ assert(!_29, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb20, unwind continue]; + } + + bb20: { +- _47 = Rem(const 1_u64, move _48); ++ _47 = Rem(const 1_u64, _1); StorageDead(_48); _46 = opaque::(move _47) -> [return: bb21, unwind continue]; } @@ -290,58 +318,121 @@ bb21: { StorageDead(_47); StorageDead(_46); - StorageLive(_49); StorageLive(_50); StorageLive(_51); - _51 = _1; -- _50 = BitOr(move _51, const 0_u64); -+ _50 = BitOr(_1, const 0_u64); - StorageDead(_51); - _49 = opaque::(move _50) -> [return: bb22, unwind continue]; + StorageLive(_52); + _52 = _1; +- _51 = BitAnd(move _52, const 0_u64); ++ _51 = const 0_u64; + StorageDead(_52); +- _50 = opaque::(move _51) -> [return: bb22, unwind continue]; ++ _50 = opaque::(const 0_u64) -> [return: bb22, unwind continue]; } bb22: { + StorageDead(_51); StorageDead(_50); - StorageDead(_49); - StorageLive(_52); StorageLive(_53); StorageLive(_54); - _54 = _1; -- _53 = BitXor(move _54, const 0_u64); -+ _53 = BitXor(_1, const 0_u64); - StorageDead(_54); - _52 = opaque::(move _53) -> [return: bb23, unwind continue]; + StorageLive(_55); + _55 = _1; +- _54 = BitAnd(move _55, const _); ++ _54 = _1; + StorageDead(_55); +- _53 = opaque::(move _54) -> [return: bb23, unwind continue]; ++ _53 = opaque::(_1) -> [return: bb23, unwind continue]; } bb23: { + StorageDead(_54); StorageDead(_53); - StorageDead(_52); - StorageLive(_55); StorageLive(_56); StorageLive(_57); - _57 = _1; -- _56 = Shr(move _57, const 0_i32); -+ _56 = Shr(_1, const 0_i32); - StorageDead(_57); - _55 = opaque::(move _56) -> [return: bb24, unwind continue]; + StorageLive(_58); + _58 = _1; +- _57 = BitOr(move _58, const 0_u64); ++ _57 = _1; + StorageDead(_58); +- _56 = opaque::(move _57) -> [return: bb24, unwind continue]; ++ _56 = opaque::(_1) -> [return: bb24, unwind continue]; } bb24: { + StorageDead(_57); StorageDead(_56); - StorageDead(_55); - StorageLive(_58); StorageLive(_59); StorageLive(_60); - _60 = _1; -- _59 = Shl(move _60, const 0_i32); -+ _59 = Shl(_1, const 0_i32); - StorageDead(_60); - _58 = opaque::(move _59) -> [return: bb25, unwind continue]; + StorageLive(_61); + _61 = _1; +- _60 = BitOr(move _61, const _); ++ _60 = const u64::MAX; + StorageDead(_61); +- _59 = opaque::(move _60) -> [return: bb25, unwind continue]; ++ _59 = opaque::(const u64::MAX) -> [return: bb25, unwind continue]; } bb25: { + StorageDead(_60); StorageDead(_59); - StorageDead(_58); + StorageLive(_62); + StorageLive(_63); + StorageLive(_64); + _64 = _1; +- _63 = BitXor(move _64, const 0_u64); ++ _63 = _1; + StorageDead(_64); +- _62 = opaque::(move _63) -> [return: bb26, unwind continue]; ++ _62 = opaque::(_1) -> [return: bb26, unwind continue]; + } + + bb26: { + StorageDead(_63); + StorageDead(_62); + StorageLive(_65); + StorageLive(_66); + StorageLive(_67); + _67 = _1; + StorageLive(_68); + _68 = _1; +- _66 = BitXor(move _67, move _68); ++ _66 = const 0_u64; + StorageDead(_68); + StorageDead(_67); +- _65 = opaque::(move _66) -> [return: bb27, unwind continue]; ++ _65 = opaque::(const 0_u64) -> [return: bb27, unwind continue]; + } + + bb27: { + StorageDead(_66); + StorageDead(_65); + StorageLive(_69); + StorageLive(_70); + StorageLive(_71); + _71 = _1; +- _70 = Shr(move _71, const 0_i32); ++ _70 = _1; + StorageDead(_71); +- _69 = opaque::(move _70) -> [return: bb28, unwind continue]; ++ _69 = opaque::(_1) -> [return: bb28, unwind continue]; + } + + bb28: { + StorageDead(_70); + StorageDead(_69); + StorageLive(_72); + StorageLive(_73); + StorageLive(_74); + _74 = _1; +- _73 = Shl(move _74, const 0_i32); ++ _73 = _1; + StorageDead(_74); +- _72 = opaque::(move _73) -> [return: bb29, unwind continue]; ++ _72 = opaque::(_1) -> [return: bb29, unwind continue]; + } + + bb29: { + StorageDead(_73); + StorageDead(_72); _0 = const (); return; } diff --git a/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-abort.diff b/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-abort.diff index 6633df3ae702..a45d9920a684 100644 --- a/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-abort.diff @@ -15,11 +15,16 @@ let _10: (); let mut _11: u64; let mut _12: u64; - let mut _13: (u64, bool); - let _14: (); - let mut _15: u64; + let mut _13: u64; + let mut _14: (u64, bool); + let _15: (); let mut _16: u64; - let mut _17: (u64, bool); + let mut _17: u64; + let mut _18: (u64, bool); + let _19: (); + let mut _20: u64; + let mut _21: u64; + let mut _22: (u64, bool); bb0: { StorageLive(_2); @@ -29,13 +34,15 @@ - _5 = CheckedAdd(_4, const 0_u64); - assert(!move (_5.1: bool), "attempt to compute `{} + {}`, which would overflow", move _4, const 0_u64) -> [success: bb1, unwind unreachable]; + _5 = CheckedAdd(_1, const 0_u64); -+ assert(!move (_5.1: bool), "attempt to compute `{} + {}`, which would overflow", _1, const 0_u64) -> [success: bb1, unwind unreachable]; ++ assert(!const false, "attempt to compute `{} + {}`, which would overflow", _1, const 0_u64) -> [success: bb1, unwind unreachable]; } bb1: { - _3 = move (_5.0: u64); +- _3 = move (_5.0: u64); ++ _3 = _1; StorageDead(_4); - _2 = opaque::(move _3) -> [return: bb2, unwind unreachable]; +- _2 = opaque::(move _3) -> [return: bb2, unwind unreachable]; ++ _2 = opaque::(_1) -> [return: bb2, unwind unreachable]; } bb2: { @@ -47,59 +54,95 @@ _8 = _1; - _9 = CheckedSub(_8, const 0_u64); - assert(!move (_9.1: bool), "attempt to compute `{} - {}`, which would overflow", move _8, const 0_u64) -> [success: bb3, unwind unreachable]; -+ _9 = CheckedSub(_1, const 0_u64); -+ assert(!move (_9.1: bool), "attempt to compute `{} - {}`, which would overflow", _1, const 0_u64) -> [success: bb3, unwind unreachable]; ++ _9 = _5; ++ assert(!const false, "attempt to compute `{} - {}`, which would overflow", _1, const 0_u64) -> [success: bb3, unwind unreachable]; } bb3: { - _7 = move (_9.0: u64); +- _7 = move (_9.0: u64); ++ _7 = _1; StorageDead(_8); - _6 = opaque::(move _7) -> [return: bb4, unwind unreachable]; +- _6 = opaque::(move _7) -> [return: bb4, unwind unreachable]; ++ _6 = opaque::(_1) -> [return: bb4, unwind unreachable]; } bb4: { StorageDead(_7); StorageDead(_6); StorageLive(_10); - StorageLive(_11); +- StorageLive(_11); ++ nop; StorageLive(_12); _12 = _1; -- _13 = CheckedMul(_12, const 0_u64); -- assert(!move (_13.1: bool), "attempt to compute `{} * {}`, which would overflow", move _12, const 0_u64) -> [success: bb5, unwind unreachable]; -+ _13 = CheckedMul(_1, const 0_u64); -+ assert(!move (_13.1: bool), "attempt to compute `{} * {}`, which would overflow", _1, const 0_u64) -> [success: bb5, unwind unreachable]; + StorageLive(_13); + _13 = _1; +- _14 = CheckedSub(_12, _13); +- assert(!move (_14.1: bool), "attempt to compute `{} - {}`, which would overflow", move _12, move _13) -> [success: bb5, unwind unreachable]; ++ _14 = const (0_u64, false); ++ assert(!const false, "attempt to compute `{} - {}`, which would overflow", _1, _1) -> [success: bb5, unwind unreachable]; } bb5: { - _11 = move (_13.0: u64); +- _11 = move (_14.0: u64); ++ _11 = const 0_u64; + StorageDead(_13); StorageDead(_12); - _10 = opaque::(move _11) -> [return: bb6, unwind unreachable]; +- _10 = opaque::(move _11) -> [return: bb6, unwind unreachable]; ++ _10 = opaque::(const 0_u64) -> [return: bb6, unwind unreachable]; } bb6: { - StorageDead(_11); +- StorageDead(_11); ++ nop; StorageDead(_10); - StorageLive(_14); StorageLive(_15); StorageLive(_16); - _16 = _1; -- _17 = CheckedMul(_16, const 1_u64); -- assert(!move (_17.1: bool), "attempt to compute `{} * {}`, which would overflow", move _16, const 1_u64) -> [success: bb7, unwind unreachable]; -+ _17 = CheckedMul(_1, const 1_u64); -+ assert(!move (_17.1: bool), "attempt to compute `{} * {}`, which would overflow", _1, const 1_u64) -> [success: bb7, unwind unreachable]; + StorageLive(_17); + _17 = _1; +- _18 = CheckedMul(_17, const 0_u64); +- assert(!move (_18.1: bool), "attempt to compute `{} * {}`, which would overflow", move _17, const 0_u64) -> [success: bb7, unwind unreachable]; ++ _18 = const (0_u64, false); ++ assert(!const false, "attempt to compute `{} * {}`, which would overflow", _1, const 0_u64) -> [success: bb7, unwind unreachable]; } bb7: { - _15 = move (_17.0: u64); - StorageDead(_16); - _14 = opaque::(move _15) -> [return: bb8, unwind unreachable]; +- _16 = move (_18.0: u64); ++ _16 = const 0_u64; + StorageDead(_17); +- _15 = opaque::(move _16) -> [return: bb8, unwind unreachable]; ++ _15 = opaque::(const 0_u64) -> [return: bb8, unwind unreachable]; } bb8: { + StorageDead(_16); StorageDead(_15); - StorageDead(_14); + StorageLive(_19); + StorageLive(_20); + StorageLive(_21); + _21 = _1; +- _22 = CheckedMul(_21, const 1_u64); +- assert(!move (_22.1: bool), "attempt to compute `{} * {}`, which would overflow", move _21, const 1_u64) -> [success: bb9, unwind unreachable]; ++ _22 = _5; ++ assert(!const false, "attempt to compute `{} * {}`, which would overflow", _1, const 1_u64) -> [success: bb9, unwind unreachable]; + } + + bb9: { +- _20 = move (_22.0: u64); ++ _20 = _1; + StorageDead(_21); +- _19 = opaque::(move _20) -> [return: bb10, unwind unreachable]; ++ _19 = opaque::(_1) -> [return: bb10, unwind unreachable]; + } + + bb10: { + StorageDead(_20); + StorageDead(_19); _0 = const (); return; } ++ } ++ ++ ALLOC0 (size: 16, align: 8) { ++ 00 00 00 00 00 00 00 00 00 __ __ __ __ __ __ __ │ .........░░░░░░░ } diff --git a/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-unwind.diff b/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-unwind.diff index d100a77fee5f..9033b392bd4c 100644 --- a/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-unwind.diff @@ -15,11 +15,16 @@ let _10: (); let mut _11: u64; let mut _12: u64; - let mut _13: (u64, bool); - let _14: (); - let mut _15: u64; + let mut _13: u64; + let mut _14: (u64, bool); + let _15: (); let mut _16: u64; - let mut _17: (u64, bool); + let mut _17: u64; + let mut _18: (u64, bool); + let _19: (); + let mut _20: u64; + let mut _21: u64; + let mut _22: (u64, bool); bb0: { StorageLive(_2); @@ -29,13 +34,15 @@ - _5 = CheckedAdd(_4, const 0_u64); - assert(!move (_5.1: bool), "attempt to compute `{} + {}`, which would overflow", move _4, const 0_u64) -> [success: bb1, unwind continue]; + _5 = CheckedAdd(_1, const 0_u64); -+ assert(!move (_5.1: bool), "attempt to compute `{} + {}`, which would overflow", _1, const 0_u64) -> [success: bb1, unwind continue]; ++ assert(!const false, "attempt to compute `{} + {}`, which would overflow", _1, const 0_u64) -> [success: bb1, unwind continue]; } bb1: { - _3 = move (_5.0: u64); +- _3 = move (_5.0: u64); ++ _3 = _1; StorageDead(_4); - _2 = opaque::(move _3) -> [return: bb2, unwind continue]; +- _2 = opaque::(move _3) -> [return: bb2, unwind continue]; ++ _2 = opaque::(_1) -> [return: bb2, unwind continue]; } bb2: { @@ -47,59 +54,95 @@ _8 = _1; - _9 = CheckedSub(_8, const 0_u64); - assert(!move (_9.1: bool), "attempt to compute `{} - {}`, which would overflow", move _8, const 0_u64) -> [success: bb3, unwind continue]; -+ _9 = CheckedSub(_1, const 0_u64); -+ assert(!move (_9.1: bool), "attempt to compute `{} - {}`, which would overflow", _1, const 0_u64) -> [success: bb3, unwind continue]; ++ _9 = _5; ++ assert(!const false, "attempt to compute `{} - {}`, which would overflow", _1, const 0_u64) -> [success: bb3, unwind continue]; } bb3: { - _7 = move (_9.0: u64); +- _7 = move (_9.0: u64); ++ _7 = _1; StorageDead(_8); - _6 = opaque::(move _7) -> [return: bb4, unwind continue]; +- _6 = opaque::(move _7) -> [return: bb4, unwind continue]; ++ _6 = opaque::(_1) -> [return: bb4, unwind continue]; } bb4: { StorageDead(_7); StorageDead(_6); StorageLive(_10); - StorageLive(_11); +- StorageLive(_11); ++ nop; StorageLive(_12); _12 = _1; -- _13 = CheckedMul(_12, const 0_u64); -- assert(!move (_13.1: bool), "attempt to compute `{} * {}`, which would overflow", move _12, const 0_u64) -> [success: bb5, unwind continue]; -+ _13 = CheckedMul(_1, const 0_u64); -+ assert(!move (_13.1: bool), "attempt to compute `{} * {}`, which would overflow", _1, const 0_u64) -> [success: bb5, unwind continue]; + StorageLive(_13); + _13 = _1; +- _14 = CheckedSub(_12, _13); +- assert(!move (_14.1: bool), "attempt to compute `{} - {}`, which would overflow", move _12, move _13) -> [success: bb5, unwind continue]; ++ _14 = const (0_u64, false); ++ assert(!const false, "attempt to compute `{} - {}`, which would overflow", _1, _1) -> [success: bb5, unwind continue]; } bb5: { - _11 = move (_13.0: u64); +- _11 = move (_14.0: u64); ++ _11 = const 0_u64; + StorageDead(_13); StorageDead(_12); - _10 = opaque::(move _11) -> [return: bb6, unwind continue]; +- _10 = opaque::(move _11) -> [return: bb6, unwind continue]; ++ _10 = opaque::(const 0_u64) -> [return: bb6, unwind continue]; } bb6: { - StorageDead(_11); +- StorageDead(_11); ++ nop; StorageDead(_10); - StorageLive(_14); StorageLive(_15); StorageLive(_16); - _16 = _1; -- _17 = CheckedMul(_16, const 1_u64); -- assert(!move (_17.1: bool), "attempt to compute `{} * {}`, which would overflow", move _16, const 1_u64) -> [success: bb7, unwind continue]; -+ _17 = CheckedMul(_1, const 1_u64); -+ assert(!move (_17.1: bool), "attempt to compute `{} * {}`, which would overflow", _1, const 1_u64) -> [success: bb7, unwind continue]; + StorageLive(_17); + _17 = _1; +- _18 = CheckedMul(_17, const 0_u64); +- assert(!move (_18.1: bool), "attempt to compute `{} * {}`, which would overflow", move _17, const 0_u64) -> [success: bb7, unwind continue]; ++ _18 = const (0_u64, false); ++ assert(!const false, "attempt to compute `{} * {}`, which would overflow", _1, const 0_u64) -> [success: bb7, unwind continue]; } bb7: { - _15 = move (_17.0: u64); - StorageDead(_16); - _14 = opaque::(move _15) -> [return: bb8, unwind continue]; +- _16 = move (_18.0: u64); ++ _16 = const 0_u64; + StorageDead(_17); +- _15 = opaque::(move _16) -> [return: bb8, unwind continue]; ++ _15 = opaque::(const 0_u64) -> [return: bb8, unwind continue]; } bb8: { + StorageDead(_16); StorageDead(_15); - StorageDead(_14); + StorageLive(_19); + StorageLive(_20); + StorageLive(_21); + _21 = _1; +- _22 = CheckedMul(_21, const 1_u64); +- assert(!move (_22.1: bool), "attempt to compute `{} * {}`, which would overflow", move _21, const 1_u64) -> [success: bb9, unwind continue]; ++ _22 = _5; ++ assert(!const false, "attempt to compute `{} * {}`, which would overflow", _1, const 1_u64) -> [success: bb9, unwind continue]; + } + + bb9: { +- _20 = move (_22.0: u64); ++ _20 = _1; + StorageDead(_21); +- _19 = opaque::(move _20) -> [return: bb10, unwind continue]; ++ _19 = opaque::(_1) -> [return: bb10, unwind continue]; + } + + bb10: { + StorageDead(_20); + StorageDead(_19); _0 = const (); return; } ++ } ++ ++ ALLOC0 (size: 16, align: 8) { ++ 00 00 00 00 00 00 00 00 00 __ __ __ __ __ __ __ │ .........░░░░░░░ } diff --git a/tests/mir-opt/gvn.comparison.GVN.panic-abort.diff b/tests/mir-opt/gvn.comparison.GVN.panic-abort.diff index ee3b9da2122b..fefdf14bddcd 100644 --- a/tests/mir-opt/gvn.comparison.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.comparison.GVN.panic-abort.diff @@ -30,10 +30,11 @@ StorageLive(_6); _6 = _1; - _4 = Eq(move _5, move _6); -+ _4 = Eq(_1, _1); ++ _4 = const true; StorageDead(_6); StorageDead(_5); - _3 = opaque::(move _4) -> [return: bb1, unwind unreachable]; +- _3 = opaque::(move _4) -> [return: bb1, unwind unreachable]; ++ _3 = opaque::(const true) -> [return: bb1, unwind unreachable]; } bb1: { @@ -46,10 +47,11 @@ StorageLive(_10); _10 = _1; - _8 = Ne(move _9, move _10); -+ _8 = Ne(_1, _1); ++ _8 = const false; StorageDead(_10); StorageDead(_9); - _7 = opaque::(move _8) -> [return: bb2, unwind unreachable]; +- _7 = opaque::(move _8) -> [return: bb2, unwind unreachable]; ++ _7 = opaque::(const false) -> [return: bb2, unwind unreachable]; } bb2: { diff --git a/tests/mir-opt/gvn.comparison.GVN.panic-unwind.diff b/tests/mir-opt/gvn.comparison.GVN.panic-unwind.diff index a1408fe3434c..9f19b2b59fa5 100644 --- a/tests/mir-opt/gvn.comparison.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.comparison.GVN.panic-unwind.diff @@ -30,10 +30,11 @@ StorageLive(_6); _6 = _1; - _4 = Eq(move _5, move _6); -+ _4 = Eq(_1, _1); ++ _4 = const true; StorageDead(_6); StorageDead(_5); - _3 = opaque::(move _4) -> [return: bb1, unwind continue]; +- _3 = opaque::(move _4) -> [return: bb1, unwind continue]; ++ _3 = opaque::(const true) -> [return: bb1, unwind continue]; } bb1: { @@ -46,10 +47,11 @@ StorageLive(_10); _10 = _1; - _8 = Ne(move _9, move _10); -+ _8 = Ne(_1, _1); ++ _8 = const false; StorageDead(_10); StorageDead(_9); - _7 = opaque::(move _8) -> [return: bb2, unwind continue]; +- _7 = opaque::(move _8) -> [return: bb2, unwind continue]; ++ _7 = opaque::(const false) -> [return: bb2, unwind continue]; } bb2: { diff --git a/tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff b/tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff index a587b1e6b1de..46bf13985daf 100644 --- a/tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff @@ -72,8 +72,7 @@ bb2: { StorageDead(_7); StorageDead(_6); -- StorageLive(_8); -+ nop; + StorageLive(_8); _8 = &raw const (*_1); StorageLive(_9); StorageLive(_10); @@ -93,8 +92,7 @@ bb4: { StorageDead(_12); StorageDead(_11); -- StorageLive(_13); -+ nop; + StorageLive(_13); _13 = &raw mut (*_1); StorageLive(_14); StorageLive(_15); @@ -114,8 +112,7 @@ bb6: { StorageDead(_17); StorageDead(_16); -- StorageLive(_18); -+ nop; + StorageLive(_18); _18 = &(*_1); StorageLive(_19); - StorageLive(_20); @@ -191,12 +188,9 @@ StorageDead(_32); StorageDead(_31); _0 = const (); -- StorageDead(_18); -- StorageDead(_13); -- StorageDead(_8); -+ nop; -+ nop; -+ nop; + StorageDead(_18); + StorageDead(_13); + StorageDead(_8); return; } } diff --git a/tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff b/tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff index 6fdda5e99887..3e731ead859e 100644 --- a/tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff @@ -72,8 +72,7 @@ bb2: { StorageDead(_7); StorageDead(_6); -- StorageLive(_8); -+ nop; + StorageLive(_8); _8 = &raw const (*_1); StorageLive(_9); StorageLive(_10); @@ -93,8 +92,7 @@ bb4: { StorageDead(_12); StorageDead(_11); -- StorageLive(_13); -+ nop; + StorageLive(_13); _13 = &raw mut (*_1); StorageLive(_14); StorageLive(_15); @@ -114,8 +112,7 @@ bb6: { StorageDead(_17); StorageDead(_16); -- StorageLive(_18); -+ nop; + StorageLive(_18); _18 = &(*_1); StorageLive(_19); - StorageLive(_20); @@ -191,12 +188,9 @@ StorageDead(_32); StorageDead(_31); _0 = const (); -- StorageDead(_18); -- StorageDead(_13); -- StorageDead(_8); -+ nop; -+ nop; -+ nop; + StorageDead(_18); + StorageDead(_13); + StorageDead(_8); return; } } diff --git a/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff b/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff index d8248d22d38b..02bf95840daf 100644 --- a/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff @@ -8,10 +8,10 @@ let mut _3: fn(u8) -> u8; let _5: (); let mut _6: fn(u8) -> u8; - let mut _9: {closure@$DIR/gvn.rs:591:19: 591:21}; + let mut _9: {closure@$DIR/gvn.rs:610:19: 610:21}; let _10: (); let mut _11: fn(); - let mut _13: {closure@$DIR/gvn.rs:591:19: 591:21}; + let mut _13: {closure@$DIR/gvn.rs:610:19: 610:21}; let _14: (); let mut _15: fn(); scope 1 { @@ -19,7 +19,7 @@ let _4: fn(u8) -> u8; scope 2 { debug g => _4; - let _7: {closure@$DIR/gvn.rs:591:19: 591:21}; + let _7: {closure@$DIR/gvn.rs:610:19: 610:21}; scope 3 { debug closure => _7; let _8: fn(); @@ -62,16 +62,16 @@ StorageDead(_6); StorageDead(_5); - StorageLive(_7); -- _7 = {closure@$DIR/gvn.rs:591:19: 591:21}; +- _7 = {closure@$DIR/gvn.rs:610:19: 610:21}; - StorageLive(_8); + nop; -+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:591:19: 591:21}; ++ _7 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21}; + nop; StorageLive(_9); - _9 = _7; - _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Normal))); -+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:591:19: 591:21}; -+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:591:19: 591:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); ++ _9 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21}; ++ _8 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); StorageDead(_9); StorageLive(_10); StorageLive(_11); @@ -88,8 +88,8 @@ StorageLive(_13); - _13 = _7; - _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Normal))); -+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:591:19: 591:21}; -+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:591:19: 591:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); ++ _13 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21}; ++ _12 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); StorageDead(_13); StorageLive(_14); StorageLive(_15); diff --git a/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff b/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff index e38a3d852092..c5dcc8a8ec9d 100644 --- a/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff @@ -8,10 +8,10 @@ let mut _3: fn(u8) -> u8; let _5: (); let mut _6: fn(u8) -> u8; - let mut _9: {closure@$DIR/gvn.rs:591:19: 591:21}; + let mut _9: {closure@$DIR/gvn.rs:610:19: 610:21}; let _10: (); let mut _11: fn(); - let mut _13: {closure@$DIR/gvn.rs:591:19: 591:21}; + let mut _13: {closure@$DIR/gvn.rs:610:19: 610:21}; let _14: (); let mut _15: fn(); scope 1 { @@ -19,7 +19,7 @@ let _4: fn(u8) -> u8; scope 2 { debug g => _4; - let _7: {closure@$DIR/gvn.rs:591:19: 591:21}; + let _7: {closure@$DIR/gvn.rs:610:19: 610:21}; scope 3 { debug closure => _7; let _8: fn(); @@ -62,16 +62,16 @@ StorageDead(_6); StorageDead(_5); - StorageLive(_7); -- _7 = {closure@$DIR/gvn.rs:591:19: 591:21}; +- _7 = {closure@$DIR/gvn.rs:610:19: 610:21}; - StorageLive(_8); + nop; -+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:591:19: 591:21}; ++ _7 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21}; + nop; StorageLive(_9); - _9 = _7; - _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Normal))); -+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:591:19: 591:21}; -+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:591:19: 591:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); ++ _9 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21}; ++ _8 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); StorageDead(_9); StorageLive(_10); StorageLive(_11); @@ -88,8 +88,8 @@ StorageLive(_13); - _13 = _7; - _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Normal))); -+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:591:19: 591:21}; -+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:591:19: 591:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); ++ _13 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21}; ++ _12 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21} as fn() (PointerCoercion(ClosureFnPointer(Normal))); StorageDead(_13); StorageLive(_14); StorageLive(_15); diff --git a/tests/mir-opt/gvn.repeated_index.GVN.panic-abort.diff b/tests/mir-opt/gvn.repeated_index.GVN.panic-abort.diff index d937902e8913..8ce05c9b340f 100644 --- a/tests/mir-opt/gvn.repeated_index.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.repeated_index.GVN.panic-abort.diff @@ -32,11 +32,12 @@ StorageLive(_6); StorageLive(_7); _7 = const 0_usize; - _8 = Len(_3); +- _8 = Len(_3); - _9 = Lt(_7, _8); - assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, _7) -> [success: bb1, unwind unreachable]; -+ _9 = Lt(const 0_usize, _8); -+ assert(move _9, "index out of bounds: the length is {} but the index is {}", _8, const 0_usize) -> [success: bb1, unwind unreachable]; ++ _8 = const N; ++ _9 = Lt(const 0_usize, const N); ++ assert(move _9, "index out of bounds: the length is {} but the index is {}", const N, const 0_usize) -> [success: bb1, unwind unreachable]; } bb1: { @@ -57,9 +58,9 @@ - _13 = Len(_3); - _14 = Lt(_12, _13); - assert(move _14, "index out of bounds: the length is {} but the index is {}", move _13, _12) -> [success: bb3, unwind unreachable]; -+ _13 = _8; -+ _14 = Lt(_2, _8); -+ assert(move _14, "index out of bounds: the length is {} but the index is {}", _8, _2) -> [success: bb3, unwind unreachable]; ++ _13 = const N; ++ _14 = Lt(_2, const N); ++ assert(move _14, "index out of bounds: the length is {} but the index is {}", const N, _2) -> [success: bb3, unwind unreachable]; } bb3: { diff --git a/tests/mir-opt/gvn.repeated_index.GVN.panic-unwind.diff b/tests/mir-opt/gvn.repeated_index.GVN.panic-unwind.diff index dd4d24b12ea6..7ed547eeb4ad 100644 --- a/tests/mir-opt/gvn.repeated_index.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.repeated_index.GVN.panic-unwind.diff @@ -32,11 +32,12 @@ StorageLive(_6); StorageLive(_7); _7 = const 0_usize; - _8 = Len(_3); +- _8 = Len(_3); - _9 = Lt(_7, _8); - assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, _7) -> [success: bb1, unwind continue]; -+ _9 = Lt(const 0_usize, _8); -+ assert(move _9, "index out of bounds: the length is {} but the index is {}", _8, const 0_usize) -> [success: bb1, unwind continue]; ++ _8 = const N; ++ _9 = Lt(const 0_usize, const N); ++ assert(move _9, "index out of bounds: the length is {} but the index is {}", const N, const 0_usize) -> [success: bb1, unwind continue]; } bb1: { @@ -57,9 +58,9 @@ - _13 = Len(_3); - _14 = Lt(_12, _13); - assert(move _14, "index out of bounds: the length is {} but the index is {}", move _13, _12) -> [success: bb3, unwind continue]; -+ _13 = _8; -+ _14 = Lt(_2, _8); -+ assert(move _14, "index out of bounds: the length is {} but the index is {}", _8, _2) -> [success: bb3, unwind continue]; ++ _13 = const N; ++ _14 = Lt(_2, const N); ++ assert(move _14, "index out of bounds: the length is {} but the index is {}", const N, _2) -> [success: bb3, unwind continue]; } bb3: { diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs index 23e33a0fa49e..31ea237cbec8 100644 --- a/tests/mir-opt/gvn.rs +++ b/tests/mir-opt/gvn.rs @@ -166,69 +166,89 @@ fn repeated_index(x: T, idx: usize) { opaque(a[idx]); } +fn unary(x: i64) { + // CHECK-LABEL: fn unary( + // CHECK: opaque::(_1) + opaque(--x); // This is `x`. + + // CHECK: [[b:_.*]] = Lt(_1, const 13_i64); + // CHECK: opaque::([[b]]) + let b = x < 13; + opaque(!!b); // This is `b`. + + // Both lines should test the same thing. + // CHECK: [[c:_.*]] = Ne(_1, const 15_i64); + // CHECK: opaque::([[c]]) + // CHECK: opaque::([[c]]) + opaque(x != 15); + opaque(!(x == 15)); + + // Both lines should test the same thing. + // CHECK: [[d:_.*]] = Eq(_1, const 35_i64); + // CHECK: opaque::([[d]]) + // CHECK: opaque::([[d]]) + opaque(x == 35); + opaque(!(x != 35)); +} + /// Verify symbolic integer arithmetic simplifications. fn arithmetic(x: u64) { // CHECK-LABEL: fn arithmetic( - // CHECK: [[add:_.*]] = Add(_1, const 0_u64); - // CHECK: opaque::(move [[add]]) + // CHECK: opaque::(_1) opaque(x + 0); - // CHECK: [[sub:_.*]] = Sub(_1, const 0_u64); - // CHECK: opaque::(move [[sub]]) + // CHECK: opaque::(_1) opaque(x - 0); - // CHECK: [[mul0:_.*]] = Mul(_1, const 0_u64); - // CHECK: opaque::(move [[mul0]]) + // CHECK: opaque::(const 0_u64) + opaque(x - x); + // CHECK: opaque::(const 0_u64) opaque(x * 0); - // CHECK: [[mul1:_.*]] = Mul(_1, const 1_u64); - // CHECK: opaque::(move [[mul1]]) + // CHECK: opaque::(_1) opaque(x * 1); + // CHECK: assert(!const true, "attempt to divide `{}` by zero", // CHECK: [[div0:_.*]] = Div(_1, const 0_u64); // CHECK: opaque::(move [[div0]]) opaque(x / 0); - // CHECK: [[div1:_.*]] = Div(_1, const 1_u64); - // CHECK: opaque::(move [[div1]]) + // CHECK: opaque::(_1) opaque(x / 1); - // CHECK: [[zdiv:_.*]] = Div(const 0_u64, _1); - // CHECK: opaque::(move [[zdiv]]) + // CHECK: opaque::(const 0_u64) opaque(0 / x); // CHECK: [[odiv:_.*]] = Div(const 1_u64, _1); // CHECK: opaque::(move [[odiv]]) opaque(1 / x); + // CHECK: assert(!const true, "attempt to calculate the remainder of `{}` with a divisor of zero" // CHECK: [[rem0:_.*]] = Rem(_1, const 0_u64); // CHECK: opaque::(move [[rem0]]) opaque(x % 0); - // CHECK: [[rem1:_.*]] = Rem(_1, const 1_u64); - // CHECK: opaque::(move [[rem1]]) + // CHECK: opaque::(const 0_u64) opaque(x % 1); - // CHECK: [[zrem:_.*]] = Rem(const 0_u64, _1); - // CHECK: opaque::(move [[zrem]]) + // CHECK: opaque::(const 0_u64) opaque(0 % x); // CHECK: [[orem:_.*]] = Rem(const 1_u64, _1); // CHECK: opaque::(move [[orem]]) opaque(1 % x); - // CHECK: [[and:_.*]] = BitAnd(_1, const 0_u64); - // CHECK: opaque::(move [[and]]) + // CHECK: opaque::(const 0_u64) opaque(x & 0); - // CHECK: [[or:_.*]] = BitOr(_1, const 0_u64); - // CHECK: opaque::(move [[or]]) + // CHECK: opaque::(_1) + opaque(x & u64::MAX); + // CHECK: opaque::(_1) opaque(x | 0); - // CHECK: [[xor:_.*]] = BitXor(_1, const 0_u64); - // CHECK: opaque::(move [[xor]]) + // CHECK: opaque::(const u64::MAX) + opaque(x | u64::MAX); + // CHECK: opaque::(_1) opaque(x ^ 0); - // CHECK: [[shr:_.*]] = Shr(_1, const 0_i32); - // CHECK: opaque::(move [[shr]]) + // CHECK: opaque::(const 0_u64) + opaque(x ^ x); + // CHECK: opaque::(_1) opaque(x >> 0); - // CHECK: [[shl:_.*]] = Shl(_1, const 0_i32); - // CHECK: opaque::(move [[shl]]) + // CHECK: opaque::(_1) opaque(x << 0); } fn comparison(x: u64, y: u64) { // CHECK-LABEL: fn comparison( - // CHECK: [[eqxx:_.*]] = Eq(_1, _1); - // CHECK: opaque::(move [[eqxx]]) + // CHECK: opaque::(const true) opaque(x == x); - // CHECK: [[nexx:_.*]] = Ne(_1, _1); - // CHECK: opaque::(move [[nexx]]) + // CHECK: opaque::(const false) opaque(x != x); // CHECK: [[eqxy:_.*]] = Eq(_1, _2); // CHECK: opaque::(move [[eqxy]]) @@ -242,21 +262,20 @@ fn comparison(x: u64, y: u64) { #[rustc_inherit_overflow_checks] fn arithmetic_checked(x: u64) { // CHECK-LABEL: fn arithmetic_checked( - // CHECK: [[cadd:_.*]] = CheckedAdd(_1, const 0_u64); - // CHECK: [[add:_.*]] = move ([[cadd]].0: u64); - // CHECK: opaque::(move [[add]]) + // CHECK: assert(!const false, + // CHECK: opaque::(_1) opaque(x + 0); - // CHECK: [[csub:_.*]] = CheckedSub(_1, const 0_u64); - // CHECK: [[sub:_.*]] = move ([[csub]].0: u64); - // CHECK: opaque::(move [[sub]]) + // CHECK: assert(!const false, + // CHECK: opaque::(_1) opaque(x - 0); - // CHECK: [[cmul0:_.*]] = CheckedMul(_1, const 0_u64); - // CHECK: [[mul0:_.*]] = move ([[cmul0]].0: u64); - // CHECK: opaque::(move [[mul0]]) + // CHECK: assert(!const false, + // CHECK: opaque::(const 0_u64) + opaque(x - x); + // CHECK: assert(!const false, + // CHECK: opaque::(const 0_u64) opaque(x * 0); - // CHECK: [[cmul1:_.*]] = CheckedMul(_1, const 1_u64); - // CHECK: [[mul1:_.*]] = move ([[cmul1]].0: u64); - // CHECK: opaque::(move [[mul1]]) + // CHECK: assert(!const false, + // CHECK: opaque::(_1) opaque(x * 1); } @@ -625,10 +644,32 @@ fn constant_index_overflow(x: &[T]) { opaque(b) } +fn wide_ptr_ops() { + let a: *const dyn Send = &1 as &dyn Send; + let b: *const dyn Send = &1 as &dyn Send; + let _val = a == b; + let _val = a != b; + let _val = a < b; + let _val = a <= b; + let _val = a > b; + let _val = a >= b; + + let a: *const [u8] = unsafe { transmute((1usize, 1usize)) }; + let b: *const [u8] = unsafe { transmute((1usize, 2usize)) }; + + opaque(!(a == b)); + opaque(a != b); + opaque(a <= b); + opaque(a < b); + opaque(!(a >= b)); + opaque(!(a > b)); +} + fn main() { subexpression_elimination(2, 4, 5); wrap_unwrap(5); repeated_index::(5, 3); + unary(i64::MIN); arithmetic(5); comparison(5, 6); arithmetic_checked(5); @@ -644,6 +685,7 @@ fn main() { fn_pointers(); indirect_static(); constant_index_overflow(&[5, 3]); + wide_ptr_ops(); } #[inline(never)] @@ -657,6 +699,7 @@ fn identity(x: T) -> T { // EMIT_MIR gvn.subexpression_elimination.GVN.diff // EMIT_MIR gvn.wrap_unwrap.GVN.diff // EMIT_MIR gvn.repeated_index.GVN.diff +// EMIT_MIR gvn.unary.GVN.diff // EMIT_MIR gvn.arithmetic.GVN.diff // EMIT_MIR gvn.comparison.GVN.diff // EMIT_MIR gvn.arithmetic_checked.GVN.diff @@ -671,3 +714,4 @@ fn identity(x: T) -> T { // EMIT_MIR gvn.fn_pointers.GVN.diff // EMIT_MIR gvn.indirect_static.GVN.diff // EMIT_MIR gvn.constant_index_overflow.GVN.diff +// EMIT_MIR gvn.wide_ptr_ops.GVN.diff diff --git a/tests/mir-opt/gvn.slices.GVN.panic-abort.diff b/tests/mir-opt/gvn.slices.GVN.panic-abort.diff index ec4499803124..f3f9073909e3 100644 --- a/tests/mir-opt/gvn.slices.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.slices.GVN.panic-abort.diff @@ -194,15 +194,13 @@ - _23 = move _21; + _23 = const core::panicking::AssertKind::Eq; StorageLive(_24); -- StorageLive(_25); + StorageLive(_25); - _25 = &(*_15); -+ nop; + _25 = &(*_9); _24 = &(*_25); StorageLive(_26); -- StorageLive(_27); + StorageLive(_27); - _27 = &(*_16); -+ nop; + _27 = &(*_12); _26 = &(*_27); StorageLive(_28); @@ -293,15 +291,13 @@ - _49 = move _47; + _49 = const core::panicking::AssertKind::Eq; StorageLive(_50); -- StorageLive(_51); + StorageLive(_51); - _51 = &(*_41); -+ nop; + _51 = &(*_35); _50 = &(*_51); StorageLive(_52); -- StorageLive(_53); + StorageLive(_53); - _53 = &(*_42); -+ nop; + _53 = &(*_38); _52 = &(*_53); StorageLive(_54); diff --git a/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff b/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff index 56a78ca86946..383152cce5e2 100644 --- a/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff @@ -194,15 +194,13 @@ - _23 = move _21; + _23 = const core::panicking::AssertKind::Eq; StorageLive(_24); -- StorageLive(_25); + StorageLive(_25); - _25 = &(*_15); -+ nop; + _25 = &(*_9); _24 = &(*_25); StorageLive(_26); -- StorageLive(_27); + StorageLive(_27); - _27 = &(*_16); -+ nop; + _27 = &(*_12); _26 = &(*_27); StorageLive(_28); @@ -293,15 +291,13 @@ - _49 = move _47; + _49 = const core::panicking::AssertKind::Eq; StorageLive(_50); -- StorageLive(_51); + StorageLive(_51); - _51 = &(*_41); -+ nop; + _51 = &(*_35); _50 = &(*_51); StorageLive(_52); -- StorageLive(_53); + StorageLive(_53); - _53 = &(*_42); -+ nop; + _53 = &(*_38); _52 = &(*_53); StorageLive(_54); diff --git a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff index 0a747d3aef0f..3ecd4650d810 100644 --- a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff @@ -757,8 +757,7 @@ bb34: { StorageDead(_121); StorageDead(_120); -- StorageLive(_126); -+ nop; + StorageLive(_126); _126 = &_3; StorageLive(_127); - StorageLive(_128); @@ -799,8 +798,7 @@ bb36: { StorageDead(_132); StorageDead(_131); -- StorageLive(_135); -+ nop; + StorageLive(_135); _135 = &mut _3; StorageLive(_136); StorageLive(_137); @@ -835,8 +833,7 @@ StorageDead(_141); StorageDead(_140); StorageLive(_144); -- StorageLive(_145); -+ nop; + StorageLive(_145); _145 = &raw const _3; StorageLive(_146); StorageLive(_147); @@ -870,8 +867,7 @@ bb40: { StorageDead(_151); StorageDead(_150); -- StorageLive(_154); -+ nop; + StorageLive(_154); _154 = &raw mut _3; StorageLive(_155); StorageLive(_156); @@ -906,13 +902,10 @@ StorageDead(_160); StorageDead(_159); _144 = const (); -- StorageDead(_154); -- StorageDead(_145); -+ nop; -+ nop; + StorageDead(_154); + StorageDead(_145); StorageDead(_144); -- StorageLive(_163); -+ nop; + StorageLive(_163); _163 = &_3; StorageLive(_164); - StorageLive(_165); @@ -954,12 +947,9 @@ StorageDead(_169); StorageDead(_168); _0 = const (); -- StorageDead(_163); -- StorageDead(_135); -- StorageDead(_126); -+ nop; -+ nop; -+ nop; + StorageDead(_163); + StorageDead(_135); + StorageDead(_126); return; } } diff --git a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff index 119a4d9bbe90..bf448280b1ed 100644 --- a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff @@ -757,8 +757,7 @@ bb34: { StorageDead(_121); StorageDead(_120); -- StorageLive(_126); -+ nop; + StorageLive(_126); _126 = &_3; StorageLive(_127); - StorageLive(_128); @@ -799,8 +798,7 @@ bb36: { StorageDead(_132); StorageDead(_131); -- StorageLive(_135); -+ nop; + StorageLive(_135); _135 = &mut _3; StorageLive(_136); StorageLive(_137); @@ -835,8 +833,7 @@ StorageDead(_141); StorageDead(_140); StorageLive(_144); -- StorageLive(_145); -+ nop; + StorageLive(_145); _145 = &raw const _3; StorageLive(_146); StorageLive(_147); @@ -870,8 +867,7 @@ bb40: { StorageDead(_151); StorageDead(_150); -- StorageLive(_154); -+ nop; + StorageLive(_154); _154 = &raw mut _3; StorageLive(_155); StorageLive(_156); @@ -906,13 +902,10 @@ StorageDead(_160); StorageDead(_159); _144 = const (); -- StorageDead(_154); -- StorageDead(_145); -+ nop; -+ nop; + StorageDead(_154); + StorageDead(_145); StorageDead(_144); -- StorageLive(_163); -+ nop; + StorageLive(_163); _163 = &_3; StorageLive(_164); - StorageLive(_165); @@ -954,12 +947,9 @@ StorageDead(_169); StorageDead(_168); _0 = const (); -- StorageDead(_163); -- StorageDead(_135); -- StorageDead(_126); -+ nop; -+ nop; -+ nop; + StorageDead(_163); + StorageDead(_135); + StorageDead(_126); return; } } diff --git a/tests/mir-opt/gvn.unary.GVN.panic-abort.diff b/tests/mir-opt/gvn.unary.GVN.panic-abort.diff new file mode 100644 index 000000000000..9469032f294e --- /dev/null +++ b/tests/mir-opt/gvn.unary.GVN.panic-abort.diff @@ -0,0 +1,153 @@ +- // MIR for `unary` before GVN ++ // MIR for `unary` after GVN + + fn unary(_1: i64) -> () { + debug x => _1; + let mut _0: (); + let _2: (); + let mut _3: i64; + let mut _4: i64; + let mut _5: i64; + let _6: bool; + let mut _7: i64; + let _8: (); + let mut _9: bool; + let mut _10: bool; + let mut _11: bool; + let _12: (); + let mut _13: bool; + let mut _14: i64; + let _15: (); + let mut _16: bool; + let mut _17: bool; + let mut _18: i64; + let _19: (); + let mut _20: bool; + let mut _21: i64; + let _22: (); + let mut _23: bool; + let mut _24: bool; + let mut _25: i64; + scope 1 { + debug b => _6; + } + + bb0: { + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + StorageLive(_5); + _5 = _1; +- _4 = Neg(move _5); ++ _4 = Neg(_1); + StorageDead(_5); +- _3 = Neg(move _4); ++ _3 = _1; + StorageDead(_4); +- _2 = opaque::(move _3) -> [return: bb1, unwind unreachable]; ++ _2 = opaque::(_1) -> [return: bb1, unwind unreachable]; + } + + bb1: { + StorageDead(_3); + StorageDead(_2); +- StorageLive(_6); ++ nop; + StorageLive(_7); + _7 = _1; +- _6 = Lt(move _7, const 13_i64); ++ _6 = Lt(_1, const 13_i64); + StorageDead(_7); + StorageLive(_8); + StorageLive(_9); + StorageLive(_10); + StorageLive(_11); + _11 = _6; +- _10 = Not(move _11); ++ _10 = Not(_6); + StorageDead(_11); +- _9 = Not(move _10); ++ _9 = _6; + StorageDead(_10); +- _8 = opaque::(move _9) -> [return: bb2, unwind unreachable]; ++ _8 = opaque::(_6) -> [return: bb2, unwind unreachable]; + } + + bb2: { + StorageDead(_9); + StorageDead(_8); + StorageLive(_12); +- StorageLive(_13); ++ nop; + StorageLive(_14); + _14 = _1; +- _13 = Ne(move _14, const 15_i64); ++ _13 = Ne(_1, const 15_i64); + StorageDead(_14); +- _12 = opaque::(move _13) -> [return: bb3, unwind unreachable]; ++ _12 = opaque::(_13) -> [return: bb3, unwind unreachable]; + } + + bb3: { +- StorageDead(_13); ++ nop; + StorageDead(_12); + StorageLive(_15); + StorageLive(_16); + StorageLive(_17); + StorageLive(_18); + _18 = _1; +- _17 = Eq(move _18, const 15_i64); ++ _17 = Eq(_1, const 15_i64); + StorageDead(_18); +- _16 = Not(move _17); ++ _16 = _13; + StorageDead(_17); +- _15 = opaque::(move _16) -> [return: bb4, unwind unreachable]; ++ _15 = opaque::(_13) -> [return: bb4, unwind unreachable]; + } + + bb4: { + StorageDead(_16); + StorageDead(_15); + StorageLive(_19); +- StorageLive(_20); ++ nop; + StorageLive(_21); + _21 = _1; +- _20 = Eq(move _21, const 35_i64); ++ _20 = Eq(_1, const 35_i64); + StorageDead(_21); +- _19 = opaque::(move _20) -> [return: bb5, unwind unreachable]; ++ _19 = opaque::(_20) -> [return: bb5, unwind unreachable]; + } + + bb5: { +- StorageDead(_20); ++ nop; + StorageDead(_19); + StorageLive(_22); + StorageLive(_23); + StorageLive(_24); + StorageLive(_25); + _25 = _1; +- _24 = Ne(move _25, const 35_i64); ++ _24 = Ne(_1, const 35_i64); + StorageDead(_25); +- _23 = Not(move _24); ++ _23 = _20; + StorageDead(_24); +- _22 = opaque::(move _23) -> [return: bb6, unwind unreachable]; ++ _22 = opaque::(_20) -> [return: bb6, unwind unreachable]; + } + + bb6: { + StorageDead(_23); + StorageDead(_22); + _0 = const (); +- StorageDead(_6); ++ nop; + return; + } + } + diff --git a/tests/mir-opt/gvn.unary.GVN.panic-unwind.diff b/tests/mir-opt/gvn.unary.GVN.panic-unwind.diff new file mode 100644 index 000000000000..e672f6fb6ba7 --- /dev/null +++ b/tests/mir-opt/gvn.unary.GVN.panic-unwind.diff @@ -0,0 +1,153 @@ +- // MIR for `unary` before GVN ++ // MIR for `unary` after GVN + + fn unary(_1: i64) -> () { + debug x => _1; + let mut _0: (); + let _2: (); + let mut _3: i64; + let mut _4: i64; + let mut _5: i64; + let _6: bool; + let mut _7: i64; + let _8: (); + let mut _9: bool; + let mut _10: bool; + let mut _11: bool; + let _12: (); + let mut _13: bool; + let mut _14: i64; + let _15: (); + let mut _16: bool; + let mut _17: bool; + let mut _18: i64; + let _19: (); + let mut _20: bool; + let mut _21: i64; + let _22: (); + let mut _23: bool; + let mut _24: bool; + let mut _25: i64; + scope 1 { + debug b => _6; + } + + bb0: { + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + StorageLive(_5); + _5 = _1; +- _4 = Neg(move _5); ++ _4 = Neg(_1); + StorageDead(_5); +- _3 = Neg(move _4); ++ _3 = _1; + StorageDead(_4); +- _2 = opaque::(move _3) -> [return: bb1, unwind continue]; ++ _2 = opaque::(_1) -> [return: bb1, unwind continue]; + } + + bb1: { + StorageDead(_3); + StorageDead(_2); +- StorageLive(_6); ++ nop; + StorageLive(_7); + _7 = _1; +- _6 = Lt(move _7, const 13_i64); ++ _6 = Lt(_1, const 13_i64); + StorageDead(_7); + StorageLive(_8); + StorageLive(_9); + StorageLive(_10); + StorageLive(_11); + _11 = _6; +- _10 = Not(move _11); ++ _10 = Not(_6); + StorageDead(_11); +- _9 = Not(move _10); ++ _9 = _6; + StorageDead(_10); +- _8 = opaque::(move _9) -> [return: bb2, unwind continue]; ++ _8 = opaque::(_6) -> [return: bb2, unwind continue]; + } + + bb2: { + StorageDead(_9); + StorageDead(_8); + StorageLive(_12); +- StorageLive(_13); ++ nop; + StorageLive(_14); + _14 = _1; +- _13 = Ne(move _14, const 15_i64); ++ _13 = Ne(_1, const 15_i64); + StorageDead(_14); +- _12 = opaque::(move _13) -> [return: bb3, unwind continue]; ++ _12 = opaque::(_13) -> [return: bb3, unwind continue]; + } + + bb3: { +- StorageDead(_13); ++ nop; + StorageDead(_12); + StorageLive(_15); + StorageLive(_16); + StorageLive(_17); + StorageLive(_18); + _18 = _1; +- _17 = Eq(move _18, const 15_i64); ++ _17 = Eq(_1, const 15_i64); + StorageDead(_18); +- _16 = Not(move _17); ++ _16 = _13; + StorageDead(_17); +- _15 = opaque::(move _16) -> [return: bb4, unwind continue]; ++ _15 = opaque::(_13) -> [return: bb4, unwind continue]; + } + + bb4: { + StorageDead(_16); + StorageDead(_15); + StorageLive(_19); +- StorageLive(_20); ++ nop; + StorageLive(_21); + _21 = _1; +- _20 = Eq(move _21, const 35_i64); ++ _20 = Eq(_1, const 35_i64); + StorageDead(_21); +- _19 = opaque::(move _20) -> [return: bb5, unwind continue]; ++ _19 = opaque::(_20) -> [return: bb5, unwind continue]; + } + + bb5: { +- StorageDead(_20); ++ nop; + StorageDead(_19); + StorageLive(_22); + StorageLive(_23); + StorageLive(_24); + StorageLive(_25); + _25 = _1; +- _24 = Ne(move _25, const 35_i64); ++ _24 = Ne(_1, const 35_i64); + StorageDead(_25); +- _23 = Not(move _24); ++ _23 = _20; + StorageDead(_24); +- _22 = opaque::(move _23) -> [return: bb6, unwind continue]; ++ _22 = opaque::(_20) -> [return: bb6, unwind continue]; + } + + bb6: { + StorageDead(_23); + StorageDead(_22); + _0 = const (); +- StorageDead(_6); ++ nop; + return; + } + } + diff --git a/tests/mir-opt/gvn.wide_ptr_ops.GVN.panic-abort.diff b/tests/mir-opt/gvn.wide_ptr_ops.GVN.panic-abort.diff new file mode 100644 index 000000000000..e49d759b8fc3 --- /dev/null +++ b/tests/mir-opt/gvn.wide_ptr_ops.GVN.panic-abort.diff @@ -0,0 +1,386 @@ +- // MIR for `wide_ptr_ops` before GVN ++ // MIR for `wide_ptr_ops` after GVN + + fn wide_ptr_ops() -> () { + let mut _0: (); + let _1: *const dyn std::marker::Send; + let mut _2: *const dyn std::marker::Send; + let _3: &dyn std::marker::Send; + let mut _4: &i32; + let _5: &i32; + let _6: i32; + let mut _8: *const dyn std::marker::Send; + let _9: &dyn std::marker::Send; + let mut _10: &i32; + let _11: &i32; + let _12: i32; + let mut _14: *const dyn std::marker::Send; + let mut _15: *const dyn std::marker::Send; + let mut _16: *const dyn std::marker::Send; + let mut _18: *const dyn std::marker::Send; + let mut _19: *const dyn std::marker::Send; + let mut _20: *const dyn std::marker::Send; + let mut _22: *const dyn std::marker::Send; + let mut _23: *const dyn std::marker::Send; + let mut _24: *const dyn std::marker::Send; + let mut _26: *const dyn std::marker::Send; + let mut _27: *const dyn std::marker::Send; + let mut _28: *const dyn std::marker::Send; + let mut _30: *const dyn std::marker::Send; + let mut _31: *const dyn std::marker::Send; + let mut _32: *const dyn std::marker::Send; + let mut _34: *const dyn std::marker::Send; + let mut _35: *const dyn std::marker::Send; + let mut _36: *const dyn std::marker::Send; + let mut _38: (usize, usize); + let mut _40: (usize, usize); + let _41: (); + let mut _42: bool; + let mut _43: bool; + let mut _44: *const [u8]; + let mut _45: *const [u8]; + let _46: (); + let mut _47: bool; + let mut _48: *const [u8]; + let mut _49: *const [u8]; + let _50: (); + let mut _51: bool; + let mut _52: *const [u8]; + let mut _53: *const [u8]; + let _54: (); + let mut _55: bool; + let mut _56: *const [u8]; + let mut _57: *const [u8]; + let _58: (); + let mut _59: bool; + let mut _60: bool; + let mut _61: *const [u8]; + let mut _62: *const [u8]; + let _63: (); + let mut _64: bool; + let mut _65: bool; + let mut _66: *const [u8]; + let mut _67: *const [u8]; + let mut _69: &i32; + scope 1 { + debug a => _1; + let _7: *const dyn std::marker::Send; + let mut _68: &i32; + scope 2 { + debug b => _7; + let _13: bool; + scope 3 { + debug _val => _13; + let _17: bool; + scope 4 { + debug _val => _17; + let _21: bool; + scope 5 { + debug _val => _21; + let _25: bool; + scope 6 { + debug _val => _25; + let _29: bool; + scope 7 { + debug _val => _29; + let _33: bool; + scope 8 { + debug _val => _33; + let _37: *const [u8]; + scope 9 { + debug a => _37; + let _39: *const [u8]; + scope 11 { + debug b => _39; + } + scope 12 { + } + } + scope 10 { + } + } + } + } + } + } + } + } + } + + bb0: { +- StorageLive(_1); ++ nop; + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + StorageLive(_5); + _69 = const _; + _5 = &(*_69); + _4 = &(*_5); + _3 = move _4 as &dyn std::marker::Send (PointerCoercion(Unsize)); + StorageDead(_4); + _2 = &raw const (*_3); + _1 = move _2 as *const dyn std::marker::Send (PointerCoercion(Unsize)); + StorageDead(_2); + StorageDead(_5); + StorageDead(_3); +- StorageLive(_7); ++ nop; + StorageLive(_8); + StorageLive(_9); + StorageLive(_10); + StorageLive(_11); + _68 = const _; + _11 = &(*_68); + _10 = &(*_11); + _9 = move _10 as &dyn std::marker::Send (PointerCoercion(Unsize)); + StorageDead(_10); + _8 = &raw const (*_9); + _7 = move _8 as *const dyn std::marker::Send (PointerCoercion(Unsize)); + StorageDead(_8); + StorageDead(_11); + StorageDead(_9); + StorageLive(_13); + StorageLive(_14); + _14 = _1; +- StorageLive(_15); ++ nop; + StorageLive(_16); + _16 = _7; +- _15 = move _16 as *const dyn std::marker::Send (PointerCoercion(Unsize)); ++ _15 = _7 as *const dyn std::marker::Send (PointerCoercion(Unsize)); + StorageDead(_16); +- _13 = Eq(move _14, move _15); +- StorageDead(_15); ++ _13 = Eq(_1, _15); ++ nop; + StorageDead(_14); + StorageLive(_17); + StorageLive(_18); + _18 = _1; + StorageLive(_19); + StorageLive(_20); + _20 = _7; +- _19 = move _20 as *const dyn std::marker::Send (PointerCoercion(Unsize)); ++ _19 = _15; + StorageDead(_20); +- _17 = Ne(move _18, move _19); ++ _17 = Ne(_1, _15); + StorageDead(_19); + StorageDead(_18); + StorageLive(_21); + StorageLive(_22); + _22 = _1; + StorageLive(_23); + StorageLive(_24); + _24 = _7; +- _23 = move _24 as *const dyn std::marker::Send (PointerCoercion(Unsize)); ++ _23 = _15; + StorageDead(_24); +- _21 = Lt(move _22, move _23); ++ _21 = Lt(_1, _15); + StorageDead(_23); + StorageDead(_22); + StorageLive(_25); + StorageLive(_26); + _26 = _1; + StorageLive(_27); + StorageLive(_28); + _28 = _7; +- _27 = move _28 as *const dyn std::marker::Send (PointerCoercion(Unsize)); ++ _27 = _15; + StorageDead(_28); +- _25 = Le(move _26, move _27); ++ _25 = Le(_1, _15); + StorageDead(_27); + StorageDead(_26); + StorageLive(_29); + StorageLive(_30); + _30 = _1; + StorageLive(_31); + StorageLive(_32); + _32 = _7; +- _31 = move _32 as *const dyn std::marker::Send (PointerCoercion(Unsize)); ++ _31 = _15; + StorageDead(_32); +- _29 = Gt(move _30, move _31); ++ _29 = Gt(_1, _15); + StorageDead(_31); + StorageDead(_30); + StorageLive(_33); + StorageLive(_34); + _34 = _1; + StorageLive(_35); + StorageLive(_36); + _36 = _7; +- _35 = move _36 as *const dyn std::marker::Send (PointerCoercion(Unsize)); ++ _35 = _15; + StorageDead(_36); +- _33 = Ge(move _34, move _35); ++ _33 = Ge(_1, _15); + StorageDead(_35); + StorageDead(_34); +- StorageLive(_37); ++ nop; + StorageLive(_38); +- _38 = (const 1_usize, const 1_usize); +- _37 = move _38 as *const [u8] (Transmute); ++ _38 = const (1_usize, 1_usize); ++ _37 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; + StorageDead(_38); +- StorageLive(_39); ++ nop; + StorageLive(_40); +- _40 = (const 1_usize, const 2_usize); +- _39 = move _40 as *const [u8] (Transmute); ++ _40 = const (1_usize, 2_usize); ++ _39 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; + StorageDead(_40); + StorageLive(_41); +- StorageLive(_42); ++ nop; + StorageLive(_43); + StorageLive(_44); +- _44 = _37; ++ _44 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; + StorageLive(_45); +- _45 = _39; +- _43 = Eq(move _44, move _45); ++ _45 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; ++ _43 = Eq(const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8], const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]); + StorageDead(_45); + StorageDead(_44); + _42 = Not(move _43); + StorageDead(_43); +- _41 = opaque::(move _42) -> [return: bb1, unwind unreachable]; ++ _41 = opaque::(_42) -> [return: bb1, unwind unreachable]; + } + + bb1: { +- StorageDead(_42); ++ nop; + StorageDead(_41); + StorageLive(_46); + StorageLive(_47); + StorageLive(_48); +- _48 = _37; ++ _48 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; + StorageLive(_49); +- _49 = _39; +- _47 = Ne(move _48, move _49); ++ _49 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; ++ _47 = _42; + StorageDead(_49); + StorageDead(_48); +- _46 = opaque::(move _47) -> [return: bb2, unwind unreachable]; ++ _46 = opaque::(_42) -> [return: bb2, unwind unreachable]; + } + + bb2: { + StorageDead(_47); + StorageDead(_46); + StorageLive(_50); + StorageLive(_51); + StorageLive(_52); +- _52 = _37; ++ _52 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; + StorageLive(_53); +- _53 = _39; +- _51 = Le(move _52, move _53); ++ _53 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; ++ _51 = Le(const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8], const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]); + StorageDead(_53); + StorageDead(_52); + _50 = opaque::(move _51) -> [return: bb3, unwind unreachable]; + } + + bb3: { + StorageDead(_51); + StorageDead(_50); + StorageLive(_54); + StorageLive(_55); + StorageLive(_56); +- _56 = _37; ++ _56 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; + StorageLive(_57); +- _57 = _39; +- _55 = Lt(move _56, move _57); ++ _57 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; ++ _55 = Lt(const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8], const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]); + StorageDead(_57); + StorageDead(_56); + _54 = opaque::(move _55) -> [return: bb4, unwind unreachable]; + } + + bb4: { + StorageDead(_55); + StorageDead(_54); + StorageLive(_58); + StorageLive(_59); + StorageLive(_60); + StorageLive(_61); +- _61 = _37; ++ _61 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; + StorageLive(_62); +- _62 = _39; +- _60 = Ge(move _61, move _62); ++ _62 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; ++ _60 = Ge(const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8], const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]); + StorageDead(_62); + StorageDead(_61); + _59 = Not(move _60); + StorageDead(_60); + _58 = opaque::(move _59) -> [return: bb5, unwind unreachable]; + } + + bb5: { + StorageDead(_59); + StorageDead(_58); + StorageLive(_63); + StorageLive(_64); + StorageLive(_65); + StorageLive(_66); +- _66 = _37; ++ _66 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; + StorageLive(_67); +- _67 = _39; +- _65 = Gt(move _66, move _67); ++ _67 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; ++ _65 = Gt(const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8], const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]); + StorageDead(_67); + StorageDead(_66); + _64 = Not(move _65); + StorageDead(_65); + _63 = opaque::(move _64) -> [return: bb6, unwind unreachable]; + } + + bb6: { + StorageDead(_64); + StorageDead(_63); + _0 = const (); +- StorageDead(_39); +- StorageDead(_37); ++ nop; ++ nop; + StorageDead(_33); + StorageDead(_29); + StorageDead(_25); + StorageDead(_21); + StorageDead(_17); + StorageDead(_13); +- StorageDead(_7); +- StorageDead(_1); ++ nop; ++ nop; + return; + } ++ } ++ ++ ALLOC1 (size: 16, align: 8) { ++ 01 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 │ ................ ++ } ++ ++ ALLOC0 (size: 16, align: 8) { ++ 01 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 │ ................ + } + diff --git a/tests/mir-opt/gvn.wide_ptr_ops.GVN.panic-unwind.diff b/tests/mir-opt/gvn.wide_ptr_ops.GVN.panic-unwind.diff new file mode 100644 index 000000000000..4e5608a4425f --- /dev/null +++ b/tests/mir-opt/gvn.wide_ptr_ops.GVN.panic-unwind.diff @@ -0,0 +1,386 @@ +- // MIR for `wide_ptr_ops` before GVN ++ // MIR for `wide_ptr_ops` after GVN + + fn wide_ptr_ops() -> () { + let mut _0: (); + let _1: *const dyn std::marker::Send; + let mut _2: *const dyn std::marker::Send; + let _3: &dyn std::marker::Send; + let mut _4: &i32; + let _5: &i32; + let _6: i32; + let mut _8: *const dyn std::marker::Send; + let _9: &dyn std::marker::Send; + let mut _10: &i32; + let _11: &i32; + let _12: i32; + let mut _14: *const dyn std::marker::Send; + let mut _15: *const dyn std::marker::Send; + let mut _16: *const dyn std::marker::Send; + let mut _18: *const dyn std::marker::Send; + let mut _19: *const dyn std::marker::Send; + let mut _20: *const dyn std::marker::Send; + let mut _22: *const dyn std::marker::Send; + let mut _23: *const dyn std::marker::Send; + let mut _24: *const dyn std::marker::Send; + let mut _26: *const dyn std::marker::Send; + let mut _27: *const dyn std::marker::Send; + let mut _28: *const dyn std::marker::Send; + let mut _30: *const dyn std::marker::Send; + let mut _31: *const dyn std::marker::Send; + let mut _32: *const dyn std::marker::Send; + let mut _34: *const dyn std::marker::Send; + let mut _35: *const dyn std::marker::Send; + let mut _36: *const dyn std::marker::Send; + let mut _38: (usize, usize); + let mut _40: (usize, usize); + let _41: (); + let mut _42: bool; + let mut _43: bool; + let mut _44: *const [u8]; + let mut _45: *const [u8]; + let _46: (); + let mut _47: bool; + let mut _48: *const [u8]; + let mut _49: *const [u8]; + let _50: (); + let mut _51: bool; + let mut _52: *const [u8]; + let mut _53: *const [u8]; + let _54: (); + let mut _55: bool; + let mut _56: *const [u8]; + let mut _57: *const [u8]; + let _58: (); + let mut _59: bool; + let mut _60: bool; + let mut _61: *const [u8]; + let mut _62: *const [u8]; + let _63: (); + let mut _64: bool; + let mut _65: bool; + let mut _66: *const [u8]; + let mut _67: *const [u8]; + let mut _69: &i32; + scope 1 { + debug a => _1; + let _7: *const dyn std::marker::Send; + let mut _68: &i32; + scope 2 { + debug b => _7; + let _13: bool; + scope 3 { + debug _val => _13; + let _17: bool; + scope 4 { + debug _val => _17; + let _21: bool; + scope 5 { + debug _val => _21; + let _25: bool; + scope 6 { + debug _val => _25; + let _29: bool; + scope 7 { + debug _val => _29; + let _33: bool; + scope 8 { + debug _val => _33; + let _37: *const [u8]; + scope 9 { + debug a => _37; + let _39: *const [u8]; + scope 11 { + debug b => _39; + } + scope 12 { + } + } + scope 10 { + } + } + } + } + } + } + } + } + } + + bb0: { +- StorageLive(_1); ++ nop; + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + StorageLive(_5); + _69 = const _; + _5 = &(*_69); + _4 = &(*_5); + _3 = move _4 as &dyn std::marker::Send (PointerCoercion(Unsize)); + StorageDead(_4); + _2 = &raw const (*_3); + _1 = move _2 as *const dyn std::marker::Send (PointerCoercion(Unsize)); + StorageDead(_2); + StorageDead(_5); + StorageDead(_3); +- StorageLive(_7); ++ nop; + StorageLive(_8); + StorageLive(_9); + StorageLive(_10); + StorageLive(_11); + _68 = const _; + _11 = &(*_68); + _10 = &(*_11); + _9 = move _10 as &dyn std::marker::Send (PointerCoercion(Unsize)); + StorageDead(_10); + _8 = &raw const (*_9); + _7 = move _8 as *const dyn std::marker::Send (PointerCoercion(Unsize)); + StorageDead(_8); + StorageDead(_11); + StorageDead(_9); + StorageLive(_13); + StorageLive(_14); + _14 = _1; +- StorageLive(_15); ++ nop; + StorageLive(_16); + _16 = _7; +- _15 = move _16 as *const dyn std::marker::Send (PointerCoercion(Unsize)); ++ _15 = _7 as *const dyn std::marker::Send (PointerCoercion(Unsize)); + StorageDead(_16); +- _13 = Eq(move _14, move _15); +- StorageDead(_15); ++ _13 = Eq(_1, _15); ++ nop; + StorageDead(_14); + StorageLive(_17); + StorageLive(_18); + _18 = _1; + StorageLive(_19); + StorageLive(_20); + _20 = _7; +- _19 = move _20 as *const dyn std::marker::Send (PointerCoercion(Unsize)); ++ _19 = _15; + StorageDead(_20); +- _17 = Ne(move _18, move _19); ++ _17 = Ne(_1, _15); + StorageDead(_19); + StorageDead(_18); + StorageLive(_21); + StorageLive(_22); + _22 = _1; + StorageLive(_23); + StorageLive(_24); + _24 = _7; +- _23 = move _24 as *const dyn std::marker::Send (PointerCoercion(Unsize)); ++ _23 = _15; + StorageDead(_24); +- _21 = Lt(move _22, move _23); ++ _21 = Lt(_1, _15); + StorageDead(_23); + StorageDead(_22); + StorageLive(_25); + StorageLive(_26); + _26 = _1; + StorageLive(_27); + StorageLive(_28); + _28 = _7; +- _27 = move _28 as *const dyn std::marker::Send (PointerCoercion(Unsize)); ++ _27 = _15; + StorageDead(_28); +- _25 = Le(move _26, move _27); ++ _25 = Le(_1, _15); + StorageDead(_27); + StorageDead(_26); + StorageLive(_29); + StorageLive(_30); + _30 = _1; + StorageLive(_31); + StorageLive(_32); + _32 = _7; +- _31 = move _32 as *const dyn std::marker::Send (PointerCoercion(Unsize)); ++ _31 = _15; + StorageDead(_32); +- _29 = Gt(move _30, move _31); ++ _29 = Gt(_1, _15); + StorageDead(_31); + StorageDead(_30); + StorageLive(_33); + StorageLive(_34); + _34 = _1; + StorageLive(_35); + StorageLive(_36); + _36 = _7; +- _35 = move _36 as *const dyn std::marker::Send (PointerCoercion(Unsize)); ++ _35 = _15; + StorageDead(_36); +- _33 = Ge(move _34, move _35); ++ _33 = Ge(_1, _15); + StorageDead(_35); + StorageDead(_34); +- StorageLive(_37); ++ nop; + StorageLive(_38); +- _38 = (const 1_usize, const 1_usize); +- _37 = move _38 as *const [u8] (Transmute); ++ _38 = const (1_usize, 1_usize); ++ _37 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; + StorageDead(_38); +- StorageLive(_39); ++ nop; + StorageLive(_40); +- _40 = (const 1_usize, const 2_usize); +- _39 = move _40 as *const [u8] (Transmute); ++ _40 = const (1_usize, 2_usize); ++ _39 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; + StorageDead(_40); + StorageLive(_41); +- StorageLive(_42); ++ nop; + StorageLive(_43); + StorageLive(_44); +- _44 = _37; ++ _44 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; + StorageLive(_45); +- _45 = _39; +- _43 = Eq(move _44, move _45); ++ _45 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; ++ _43 = Eq(const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8], const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]); + StorageDead(_45); + StorageDead(_44); + _42 = Not(move _43); + StorageDead(_43); +- _41 = opaque::(move _42) -> [return: bb1, unwind continue]; ++ _41 = opaque::(_42) -> [return: bb1, unwind continue]; + } + + bb1: { +- StorageDead(_42); ++ nop; + StorageDead(_41); + StorageLive(_46); + StorageLive(_47); + StorageLive(_48); +- _48 = _37; ++ _48 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; + StorageLive(_49); +- _49 = _39; +- _47 = Ne(move _48, move _49); ++ _49 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; ++ _47 = _42; + StorageDead(_49); + StorageDead(_48); +- _46 = opaque::(move _47) -> [return: bb2, unwind continue]; ++ _46 = opaque::(_42) -> [return: bb2, unwind continue]; + } + + bb2: { + StorageDead(_47); + StorageDead(_46); + StorageLive(_50); + StorageLive(_51); + StorageLive(_52); +- _52 = _37; ++ _52 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; + StorageLive(_53); +- _53 = _39; +- _51 = Le(move _52, move _53); ++ _53 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; ++ _51 = Le(const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8], const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]); + StorageDead(_53); + StorageDead(_52); + _50 = opaque::(move _51) -> [return: bb3, unwind continue]; + } + + bb3: { + StorageDead(_51); + StorageDead(_50); + StorageLive(_54); + StorageLive(_55); + StorageLive(_56); +- _56 = _37; ++ _56 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; + StorageLive(_57); +- _57 = _39; +- _55 = Lt(move _56, move _57); ++ _57 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; ++ _55 = Lt(const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8], const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]); + StorageDead(_57); + StorageDead(_56); + _54 = opaque::(move _55) -> [return: bb4, unwind continue]; + } + + bb4: { + StorageDead(_55); + StorageDead(_54); + StorageLive(_58); + StorageLive(_59); + StorageLive(_60); + StorageLive(_61); +- _61 = _37; ++ _61 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; + StorageLive(_62); +- _62 = _39; +- _60 = Ge(move _61, move _62); ++ _62 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; ++ _60 = Ge(const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8], const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]); + StorageDead(_62); + StorageDead(_61); + _59 = Not(move _60); + StorageDead(_60); + _58 = opaque::(move _59) -> [return: bb5, unwind continue]; + } + + bb5: { + StorageDead(_59); + StorageDead(_58); + StorageLive(_63); + StorageLive(_64); + StorageLive(_65); + StorageLive(_66); +- _66 = _37; ++ _66 = const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8]; + StorageLive(_67); +- _67 = _39; +- _65 = Gt(move _66, move _67); ++ _67 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]; ++ _65 = Gt(const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8], const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]); + StorageDead(_67); + StorageDead(_66); + _64 = Not(move _65); + StorageDead(_65); + _63 = opaque::(move _64) -> [return: bb6, unwind continue]; + } + + bb6: { + StorageDead(_64); + StorageDead(_63); + _0 = const (); +- StorageDead(_39); +- StorageDead(_37); ++ nop; ++ nop; + StorageDead(_33); + StorageDead(_29); + StorageDead(_25); + StorageDead(_21); + StorageDead(_17); + StorageDead(_13); +- StorageDead(_7); +- StorageDead(_1); ++ nop; ++ nop; + return; + } ++ } ++ ++ ALLOC1 (size: 16, align: 8) { ++ 01 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 │ ................ ++ } ++ ++ ALLOC0 (size: 16, align: 8) { ++ 01 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 │ ................ + } + diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff index 68c612314f6d..8e53427e7e06 100644 --- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff @@ -36,7 +36,7 @@ - _4 = g() -> [return: bb1, unwind unreachable]; + _4 = {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8 (#0)}; + _3 = &mut _4; -+ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}> { pointer: move _3 }; ++ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}> { pointer: _3 }; + StorageDead(_3); + StorageLive(_5); + _5 = const false; diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff index 1bf14e8c3b33..b06db41af9d4 100644 --- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff @@ -36,7 +36,7 @@ - _4 = g() -> [return: bb1, unwind continue]; + _4 = {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8 (#0)}; + _3 = &mut _4; -+ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}> { pointer: move _3 }; ++ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}> { pointer: _3 }; + StorageDead(_3); + StorageLive(_5); + _5 = const false; diff --git a/tests/mir-opt/inline/inline_diverging.h.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_diverging.h.Inline.panic-abort.diff index da45ebcb4d85..2bbb830fc779 100644 --- a/tests/mir-opt/inline/inline_diverging.h.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_diverging.h.Inline.panic-abort.diff @@ -40,7 +40,7 @@ + + bb2: { + StorageDead(_5); -+ _1 = (move _4, move _6); ++ _1 = (_4, _6); + drop(_2) -> [return: bb3, unwind unreachable]; + } + diff --git a/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff index d65c65e5fd03..bc4f2d24df0b 100644 --- a/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff @@ -43,7 +43,7 @@ + StorageDead(_5); + StorageLive(_7); + _7 = move _4; -+ _1 = (move _7, move _6); ++ _1 = (move _7, _6); + StorageDead(_7); + StorageDead(_4); + drop(_2) -> [return: bb3, unwind continue]; diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir index aeb93bd334fe..d6a608476df9 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir @@ -31,7 +31,7 @@ fn unwrap_unchecked(_1: Option) -> T { _2 = discriminant(_1); _3 = Eq(_2, const 1_isize); assume(move _3); - _0 = move ((_1 as Some).0: T); + _0 = ((_1 as Some).0: T); StorageDead(_3); StorageDead(_2); StorageDead(_4); diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir index aeb93bd334fe..d6a608476df9 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir @@ -31,7 +31,7 @@ fn unwrap_unchecked(_1: Option) -> T { _2 = discriminant(_1); _3 = Eq(_2, const 1_isize); assume(move _3); - _0 = move ((_1 as Some).0: T); + _0 = ((_1 as Some).0: T); StorageDead(_3); StorageDead(_2); StorageDead(_4); diff --git a/tests/mir-opt/issue_101973.inner.GVN.panic-abort.diff b/tests/mir-opt/issue_101973.inner.GVN.panic-abort.diff index d2db8f61916a..187290785c03 100644 --- a/tests/mir-opt/issue_101973.inner.GVN.panic-abort.diff +++ b/tests/mir-opt/issue_101973.inner.GVN.panic-abort.diff @@ -17,9 +17,8 @@ let mut _12: u32; let mut _13: bool; scope 1 (inlined imm8) { - debug x => _1; + debug x => _5; let mut _14: u32; - let mut _15: u32; scope 2 { debug out => _4; } @@ -33,17 +32,23 @@ StorageLive(_2); StorageLive(_3); StorageLive(_4); + StorageLive(_5); + _5 = _1; _4 = const 0_u32; - StorageLive(_15); - StorageLive(_14); - _14 = Shr(_1, const 0_i32); - _15 = BitAnd(move _14, const 255_u32); - StorageDead(_14); - _4 = BitOr(const 0_u32, move _15); - StorageDead(_15); +- StorageLive(_14); +- _14 = BitAnd(_5, const 255_u32); +- _4 = BitOr(const 0_u32, move _14); +- StorageDead(_14); ++ nop; ++ _14 = BitAnd(_1, const 255_u32); ++ _4 = _14; ++ nop; + StorageDead(_5); StorageLive(_6); StorageLive(_7); StorageLive(_8); + StorageLive(_9); + _9 = _1; - _10 = const 8_i32 as u32 (IntToInt); - _11 = Lt(move _10, const 32_u32); - assert(move _11, "attempt to shift right by `{}`, which would overflow", const 8_i32) -> [success: bb1, unwind unreachable]; @@ -53,7 +58,9 @@ } bb1: { - _8 = Shr(_1, const 8_i32); +- _8 = Shr(move _9, const 8_i32); ++ _8 = Shr(_1, const 8_i32); + StorageDead(_9); _7 = BitAnd(move _8, const 15_u32); StorageDead(_8); - _12 = const 1_i32 as u32 (IntToInt); diff --git a/tests/mir-opt/issue_101973.inner.GVN.panic-unwind.diff b/tests/mir-opt/issue_101973.inner.GVN.panic-unwind.diff index 514183b3bc05..99350bac478d 100644 --- a/tests/mir-opt/issue_101973.inner.GVN.panic-unwind.diff +++ b/tests/mir-opt/issue_101973.inner.GVN.panic-unwind.diff @@ -17,9 +17,8 @@ let mut _12: u32; let mut _13: bool; scope 1 (inlined imm8) { - debug x => _1; + debug x => _5; let mut _14: u32; - let mut _15: u32; scope 2 { debug out => _4; } @@ -33,17 +32,23 @@ StorageLive(_2); StorageLive(_3); StorageLive(_4); + StorageLive(_5); + _5 = _1; _4 = const 0_u32; - StorageLive(_15); - StorageLive(_14); - _14 = Shr(_1, const 0_i32); - _15 = BitAnd(move _14, const 255_u32); - StorageDead(_14); - _4 = BitOr(const 0_u32, move _15); - StorageDead(_15); +- StorageLive(_14); +- _14 = BitAnd(_5, const 255_u32); +- _4 = BitOr(const 0_u32, move _14); +- StorageDead(_14); ++ nop; ++ _14 = BitAnd(_1, const 255_u32); ++ _4 = _14; ++ nop; + StorageDead(_5); StorageLive(_6); StorageLive(_7); StorageLive(_8); + StorageLive(_9); + _9 = _1; - _10 = const 8_i32 as u32 (IntToInt); - _11 = Lt(move _10, const 32_u32); - assert(move _11, "attempt to shift right by `{}`, which would overflow", const 8_i32) -> [success: bb1, unwind continue]; @@ -53,7 +58,9 @@ } bb1: { - _8 = Shr(_1, const 8_i32); +- _8 = Shr(move _9, const 8_i32); ++ _8 = Shr(_1, const 8_i32); + StorageDead(_9); _7 = BitAnd(move _8, const 15_u32); StorageDead(_8); - _12 = const 1_i32 as u32 (IntToInt); diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir index 5d25c6557002..f7be8b75db7b 100644 --- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir @@ -51,7 +51,7 @@ fn num_to_digit(_1: char) -> u32 { } bb4: { - _7 = core::panicking::panic(const "called `Option::unwrap()` on a `None` value") -> unwind unreachable; + _7 = option::unwrap_failed() -> unwind unreachable; } bb5: { diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir index 4677c0108e3b..e76fe992ac7d 100644 --- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir @@ -51,7 +51,7 @@ fn num_to_digit(_1: char) -> u32 { } bb4: { - _7 = core::panicking::panic(const "called `Option::unwrap()` on a `None` value") -> unwind continue; + _7 = option::unwrap_failed() -> unwind continue; } bb5: { diff --git a/tests/mir-opt/jump_threading.aggregate.JumpThreading.panic-abort.diff b/tests/mir-opt/jump_threading.aggregate.JumpThreading.panic-abort.diff new file mode 100644 index 000000000000..66aa892c6f33 --- /dev/null +++ b/tests/mir-opt/jump_threading.aggregate.JumpThreading.panic-abort.diff @@ -0,0 +1,52 @@ +- // MIR for `aggregate` before JumpThreading ++ // MIR for `aggregate` after JumpThreading + + fn aggregate(_1: u8) -> u8 { + debug x => _1; + let mut _0: u8; + let _2: u8; + let _3: u8; + let mut _4: (u8, u8); + let mut _5: bool; + let mut _6: u8; + scope 1 { + debug a => _2; + debug b => _3; + } + + bb0: { + StorageLive(_4); + _4 = const _; + StorageLive(_2); + _2 = (_4.0: u8); + StorageLive(_3); + _3 = (_4.1: u8); + StorageDead(_4); + StorageLive(_5); + StorageLive(_6); + _6 = _2; + _5 = Eq(move _6, const 7_u8); +- switchInt(move _5) -> [0: bb2, otherwise: bb1]; ++ goto -> bb2; + } + + bb1: { + StorageDead(_6); + _0 = _3; + goto -> bb3; + } + + bb2: { + StorageDead(_6); + _0 = _2; + goto -> bb3; + } + + bb3: { + StorageDead(_5); + StorageDead(_3); + StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/jump_threading.aggregate.JumpThreading.panic-unwind.diff b/tests/mir-opt/jump_threading.aggregate.JumpThreading.panic-unwind.diff new file mode 100644 index 000000000000..66aa892c6f33 --- /dev/null +++ b/tests/mir-opt/jump_threading.aggregate.JumpThreading.panic-unwind.diff @@ -0,0 +1,52 @@ +- // MIR for `aggregate` before JumpThreading ++ // MIR for `aggregate` after JumpThreading + + fn aggregate(_1: u8) -> u8 { + debug x => _1; + let mut _0: u8; + let _2: u8; + let _3: u8; + let mut _4: (u8, u8); + let mut _5: bool; + let mut _6: u8; + scope 1 { + debug a => _2; + debug b => _3; + } + + bb0: { + StorageLive(_4); + _4 = const _; + StorageLive(_2); + _2 = (_4.0: u8); + StorageLive(_3); + _3 = (_4.1: u8); + StorageDead(_4); + StorageLive(_5); + StorageLive(_6); + _6 = _2; + _5 = Eq(move _6, const 7_u8); +- switchInt(move _5) -> [0: bb2, otherwise: bb1]; ++ goto -> bb2; + } + + bb1: { + StorageDead(_6); + _0 = _3; + goto -> bb3; + } + + bb2: { + StorageDead(_6); + _0 = _2; + goto -> bb3; + } + + bb3: { + StorageDead(_5); + StorageDead(_3); + StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff index f04ca72dd6d9..9cc4385f60b8 100644 --- a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff +++ b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff @@ -110,7 +110,7 @@ bb6: { _12 = move ((_4 as Err).0: i32); StorageLive(_13); - _13 = Result::::Err(move _12); + _13 = Result::::Err(_12); _3 = ControlFlow::, i32>::Break(move _13); StorageDead(_13); - goto -> bb5; @@ -119,7 +119,7 @@ bb7: { _11 = move ((_4 as Ok).0: i32); - _3 = ControlFlow::, i32>::Continue(move _11); + _3 = ControlFlow::, i32>::Continue(_11); goto -> bb5; + } + diff --git a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff index f04ca72dd6d9..9cc4385f60b8 100644 --- a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff +++ b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff @@ -110,7 +110,7 @@ bb6: { _12 = move ((_4 as Err).0: i32); StorageLive(_13); - _13 = Result::::Err(move _12); + _13 = Result::::Err(_12); _3 = ControlFlow::, i32>::Break(move _13); StorageDead(_13); - goto -> bb5; @@ -119,7 +119,7 @@ bb7: { _11 = move ((_4 as Ok).0: i32); - _3 = ControlFlow::, i32>::Continue(move _11); + _3 = ControlFlow::, i32>::Continue(_11); goto -> bb5; + } + diff --git a/tests/mir-opt/jump_threading.rs b/tests/mir-opt/jump_threading.rs index 0cbdaa085bc9..7c2fa42828be 100644 --- a/tests/mir-opt/jump_threading.rs +++ b/tests/mir-opt/jump_threading.rs @@ -453,7 +453,23 @@ fn disappearing_bb(x: u8) -> u8 { ) } +/// Verify that we can thread jumps when we assign from an aggregate constant. +fn aggregate(x: u8) -> u8 { + // CHECK-LABEL: fn aggregate( + // CHECK-NOT: switchInt( + + const FOO: (u8, u8) = (5, 13); + + let (a, b) = FOO; + if a == 7 { + b + } else { + a + } +} + fn main() { + // CHECK-LABEL: fn main( too_complex(Ok(0)); identity(Ok(0)); custom_discr(false); @@ -464,6 +480,7 @@ fn main() { mutable_ref(); renumbered_bb(true); disappearing_bb(7); + aggregate(7); } // EMIT_MIR jump_threading.too_complex.JumpThreading.diff @@ -476,3 +493,4 @@ fn main() { // EMIT_MIR jump_threading.mutable_ref.JumpThreading.diff // EMIT_MIR jump_threading.renumbered_bb.JumpThreading.diff // EMIT_MIR jump_threading.disappearing_bb.JumpThreading.diff +// EMIT_MIR jump_threading.aggregate.JumpThreading.diff diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff index 47e0d402347d..de9a1a075ad5 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff @@ -19,7 +19,7 @@ } scope 5 (inlined ::allocate) { debug self => _9; - debug layout => _1; + debug layout => _8; } scope 6 (inlined #[track_caller] Result::, std::alloc::AllocError>::unwrap) { debug self => _6; @@ -51,6 +51,8 @@ } bb0: { +- StorageLive(_1); ++ nop; StorageLive(_2); - _2 = Option::::None; + _2 = const Option::::None; @@ -62,7 +64,7 @@ } bb1: { - _11 = core::panicking::panic(const "called `Option::unwrap()` on a `None` value") -> unwind unreachable; + _11 = option::unwrap_failed() -> unwind unreachable; } bb2: { @@ -74,12 +76,20 @@ StorageLive(_4); StorageLive(_5); StorageLive(_6); + StorageLive(_7); _9 = const _; -- _6 = std::alloc::Global::alloc_impl(_9, _1, const false) -> [return: bb3, unwind unreachable]; +- _7 = _9; ++ _7 = const {ALLOC1: &std::alloc::Global}; + StorageLive(_8); +- _8 = _1; +- _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb3, unwind unreachable]; ++ _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum32) }}; + _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum32) }}, const false) -> [return: bb3, unwind unreachable]; } bb3: { + StorageDead(_8); + StorageDead(_7); StorageLive(_12); StorageLive(_15); _12 = discriminant(_6); @@ -109,6 +119,8 @@ _3 = move _4 as *mut u8 (PtrToPtr); StorageDead(_4); StorageDead(_3); +- StorageDead(_1); ++ nop; return; } diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff index dee57ce6c27b..f784db0f4094 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff @@ -19,7 +19,7 @@ } scope 5 (inlined ::allocate) { debug self => _9; - debug layout => _1; + debug layout => _8; } scope 6 (inlined NonNull::<[u8]>::as_ptr) { debug self => _5; @@ -36,6 +36,8 @@ } bb0: { +- StorageLive(_1); ++ nop; StorageLive(_2); - _2 = Option::::None; + _2 = const Option::::None; @@ -56,11 +58,13 @@ _3 = move _4 as *mut u8 (PtrToPtr); StorageDead(_4); StorageDead(_3); +- StorageDead(_1); ++ nop; return; } bb2: { - _11 = core::panicking::panic(const "called `Option::unwrap()` on a `None` value") -> unwind continue; + _11 = option::unwrap_failed() -> unwind continue; } bb3: { @@ -72,12 +76,20 @@ StorageLive(_4); StorageLive(_5); StorageLive(_6); + StorageLive(_7); _9 = const _; -- _6 = std::alloc::Global::alloc_impl(_9, _1, const false) -> [return: bb4, unwind continue]; +- _7 = _9; ++ _7 = const {ALLOC1: &std::alloc::Global}; + StorageLive(_8); +- _8 = _1; +- _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb4, unwind continue]; ++ _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum32) }}; + _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum32) }}, const false) -> [return: bb4, unwind continue]; } bb4: { + StorageDead(_8); + StorageDead(_7); _5 = Result::, std::alloc::AllocError>::unwrap(move _6) -> [return: bb1, unwind continue]; } diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff index a255b15920cb..162b7fa4618d 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff @@ -19,7 +19,7 @@ } scope 5 (inlined ::allocate) { debug self => _9; - debug layout => _1; + debug layout => _8; } scope 6 (inlined #[track_caller] Result::, std::alloc::AllocError>::unwrap) { debug self => _6; @@ -51,6 +51,8 @@ } bb0: { +- StorageLive(_1); ++ nop; StorageLive(_2); - _2 = Option::::None; + _2 = const Option::::None; @@ -62,7 +64,7 @@ } bb1: { - _11 = core::panicking::panic(const "called `Option::unwrap()` on a `None` value") -> unwind unreachable; + _11 = option::unwrap_failed() -> unwind unreachable; } bb2: { @@ -74,12 +76,20 @@ StorageLive(_4); StorageLive(_5); StorageLive(_6); + StorageLive(_7); _9 = const _; -- _6 = std::alloc::Global::alloc_impl(_9, _1, const false) -> [return: bb3, unwind unreachable]; +- _7 = _9; ++ _7 = const {ALLOC1: &std::alloc::Global}; + StorageLive(_8); +- _8 = _1; +- _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb3, unwind unreachable]; ++ _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum64) }}; + _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum64) }}, const false) -> [return: bb3, unwind unreachable]; } bb3: { + StorageDead(_8); + StorageDead(_7); StorageLive(_12); StorageLive(_15); _12 = discriminant(_6); @@ -109,6 +119,8 @@ _3 = move _4 as *mut u8 (PtrToPtr); StorageDead(_4); StorageDead(_3); +- StorageDead(_1); ++ nop; return; } diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff index 192ffea25915..400aac6d64bb 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff @@ -19,7 +19,7 @@ } scope 5 (inlined ::allocate) { debug self => _9; - debug layout => _1; + debug layout => _8; } scope 6 (inlined NonNull::<[u8]>::as_ptr) { debug self => _5; @@ -36,6 +36,8 @@ } bb0: { +- StorageLive(_1); ++ nop; StorageLive(_2); - _2 = Option::::None; + _2 = const Option::::None; @@ -56,11 +58,13 @@ _3 = move _4 as *mut u8 (PtrToPtr); StorageDead(_4); StorageDead(_3); +- StorageDead(_1); ++ nop; return; } bb2: { - _11 = core::panicking::panic(const "called `Option::unwrap()` on a `None` value") -> unwind continue; + _11 = option::unwrap_failed() -> unwind continue; } bb3: { @@ -72,12 +76,20 @@ StorageLive(_4); StorageLive(_5); StorageLive(_6); + StorageLive(_7); _9 = const _; -- _6 = std::alloc::Global::alloc_impl(_9, _1, const false) -> [return: bb4, unwind continue]; +- _7 = _9; ++ _7 = const {ALLOC1: &std::alloc::Global}; + StorageLive(_8); +- _8 = _1; +- _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb4, unwind continue]; ++ _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum64) }}; + _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum64) }}, const false) -> [return: bb4, unwind continue]; } bb4: { + StorageDead(_8); + StorageDead(_7); _5 = Result::, std::alloc::AllocError>::unwrap(move _6) -> [return: bb1, unwind continue]; } diff --git a/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir index 8dbb688999a0..8d182069adc9 100644 --- a/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir @@ -32,7 +32,7 @@ fn filter_mapped(_1: impl Iterator, _2: impl Fn(T) -> Option) -> () bb1: { StorageLive(_4); - _4 = move _3; + _4 = _3; goto -> bb2; } diff --git a/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir index 42c7eb3c6aad..e27e417ed4ae 100644 --- a/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir @@ -46,7 +46,7 @@ fn int_range(_1: usize, _2: usize) -> () { bb0: { _3 = std::ops::Range:: { start: _1, end: _2 }; StorageLive(_4); - _4 = move _3; + _4 = _3; goto -> bb1; } diff --git a/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir index 30bdc1310908..b800a1be22ba 100644 --- a/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir @@ -27,7 +27,7 @@ fn mapped(_1: impl Iterator, _2: impl Fn(T) -> U) -> () { bb1: { StorageLive(_4); - _4 = move _3; + _4 = _3; goto -> bb2; } diff --git a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir index 713d6cc558ac..f0cb4ca31fec 100644 --- a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir @@ -19,22 +19,23 @@ fn mem_replace(_1: &mut u32, _2: u32) -> u32 { } scope 4 (inlined std::ptr::read::) { debug src => _1; + let mut _3: *const u32; scope 5 { scope 6 (inlined std::ptr::read::runtime::) { - debug src => _1; + debug src => _3; scope 7 (inlined intrinsics::is_aligned_and_not_null::) { - debug ptr => _1; + debug ptr => _3; scope 8 (inlined std::ptr::const_ptr::::is_null) { - debug self => _1; - let mut _3: *const u8; + debug self => _3; + let mut _4: *const u8; scope 9 { scope 10 (inlined std::ptr::const_ptr::::is_null::runtime_impl) { - debug ptr => _3; + debug ptr => _4; scope 11 (inlined std::ptr::const_ptr::::addr) { - debug self => _3; + debug self => _4; scope 12 { scope 13 (inlined std::ptr::const_ptr::::cast::<()>) { - debug self => _3; + debug self => _4; } } } @@ -42,7 +43,7 @@ fn mem_replace(_1: &mut u32, _2: u32) -> u32 { } } scope 14 (inlined std::ptr::const_ptr::::is_aligned) { - debug self => _1; + debug self => _3; scope 15 (inlined align_of::) { } } @@ -55,7 +56,9 @@ fn mem_replace(_1: &mut u32, _2: u32) -> u32 { bb0: { StorageLive(_3); + StorageLive(_4); _0 = (*_1); + StorageDead(_4); StorageDead(_3); (*_1) = _2; return; diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-abort.diff index 4e34233a9798..0e7e1f971ec3 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-abort.diff @@ -17,7 +17,7 @@ debug y => _3; let _8: u32; scope 3 { - debug z => _9; + debug z => _8; } } } @@ -50,7 +50,13 @@ + _3 = const 3_i32; StorageDead(_5); StorageDead(_4); + StorageLive(_8); + StorageLive(_9); _9 = const 42_u32; +- _8 = _9; ++ _8 = const 42_u32; + StorageDead(_9); + StorageDead(_8); StorageDead(_3); StorageDead(_1); return; diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-unwind.diff index 275f17e52aec..9071a3339c08 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-unwind.diff @@ -17,7 +17,7 @@ debug y => _3; let _8: u32; scope 3 { - debug z => _9; + debug z => _8; } } } @@ -50,7 +50,13 @@ + _3 = const 3_i32; StorageDead(_5); StorageDead(_4); + StorageLive(_8); + StorageLive(_9); _9 = const 42_u32; +- _8 = _9; ++ _8 = const 42_u32; + StorageDead(_9); + StorageDead(_8); StorageDead(_3); StorageDead(_1); return; diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-abort.diff index 4e34233a9798..0e7e1f971ec3 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-abort.diff @@ -17,7 +17,7 @@ debug y => _3; let _8: u32; scope 3 { - debug z => _9; + debug z => _8; } } } @@ -50,7 +50,13 @@ + _3 = const 3_i32; StorageDead(_5); StorageDead(_4); + StorageLive(_8); + StorageLive(_9); _9 = const 42_u32; +- _8 = _9; ++ _8 = const 42_u32; + StorageDead(_9); + StorageDead(_8); StorageDead(_3); StorageDead(_1); return; diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-unwind.diff index 275f17e52aec..9071a3339c08 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-unwind.diff @@ -17,7 +17,7 @@ debug y => _3; let _8: u32; scope 3 { - debug z => _9; + debug z => _8; } } } @@ -50,7 +50,13 @@ + _3 = const 3_i32; StorageDead(_5); StorageDead(_4); + StorageLive(_8); + StorageLive(_9); _9 = const 42_u32; +- _8 = _9; ++ _8 = const 42_u32; + StorageDead(_9); + StorageDead(_8); StorageDead(_3); StorageDead(_1); return; diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir index e5940bd82019..99805da56694 100644 --- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir @@ -49,7 +49,7 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { bb0: { _4 = std::ops::Range:: { start: _1, end: _2 }; StorageLive(_5); - _5 = move _4; + _5 = _4; goto -> bb1; } diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir index 87e7485cb360..f40f13071756 100644 --- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -49,7 +49,7 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { bb0: { _4 = std::ops::Range:: { start: _1, end: _2 }; StorageLive(_5); - _5 = move _4; + _5 = _4; goto -> bb1; } diff --git a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir index 1b23e421368b..0836600cb6e6 100644 --- a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir @@ -34,7 +34,7 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { bb0: { _4 = RangeInclusive:: { start: _1, end: _2, exhausted: const false }; StorageLive(_5); - _5 = move _4; + _5 = _4; goto -> bb1; } diff --git a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir index a677e8b439fa..8c1794de5244 100644 --- a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir @@ -34,7 +34,7 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { bb0: { _4 = RangeInclusive:: { start: _1, end: _2, exhausted: const false }; StorageLive(_5); - _5 = move _4; + _5 = _4; goto -> bb1; } diff --git a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir index cc009e45e7e7..7370da5629c1 100644 --- a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir @@ -94,6 +94,8 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:8:25: 8:39}, _2 StorageLive(_9); _9 = _6; _10 = &_9; + StorageLive(_11); + StorageLive(_12); _11 = _4; _12 = _9; StorageLive(_13); @@ -103,6 +105,8 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:8:25: 8:39}, _2 _15 = Le(move _13, move _14); StorageDead(_14); StorageDead(_13); + StorageDead(_12); + StorageDead(_11); switchInt(move _15) -> [0: bb1, otherwise: bb2]; } @@ -124,6 +128,8 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:8:25: 8:39}, _2 StorageLive(_17); _17 = _5; _18 = &_17; + StorageLive(_19); + StorageLive(_20); _19 = _7; _20 = _17; StorageLive(_21); @@ -133,6 +139,8 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:8:25: 8:39}, _2 _23 = Le(move _21, move _22); StorageDead(_22); StorageDead(_21); + StorageDead(_20); + StorageDead(_19); switchInt(move _23) -> [0: bb3, otherwise: bb8]; } @@ -151,6 +159,8 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:8:25: 8:39}, _2 StorageLive(_25); _25 = _4; _26 = &_25; + StorageLive(_27); + StorageLive(_28); _27 = _6; _28 = _25; StorageLive(_29); @@ -160,6 +170,8 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:8:25: 8:39}, _2 _31 = Le(move _29, move _30); StorageDead(_30); StorageDead(_29); + StorageDead(_28); + StorageDead(_27); switchInt(move _31) -> [0: bb5, otherwise: bb6]; } @@ -181,6 +193,8 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:8:25: 8:39}, _2 StorageLive(_33); _33 = _7; _34 = &_33; + StorageLive(_35); + StorageLive(_36); _35 = _5; _36 = _33; StorageLive(_37); @@ -190,6 +204,8 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:8:25: 8:39}, _2 _0 = Le(move _37, move _38); StorageDead(_38); StorageDead(_37); + StorageDead(_36); + StorageDead(_35); StorageDead(_33); StorageDead(_34); StorageDead(_32); diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir index a12411a04137..bc7617bb6ddd 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir @@ -20,7 +20,8 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { debug self => _2; debug slice => _5; let mut _6: *mut u32; - let mut _9: &[&str]; + let mut _9: *mut [u32]; + let mut _10: &[&str]; scope 5 { scope 10 (inlined std::ptr::mut_ptr::::as_mut_ptr) { debug self => _5; @@ -33,16 +34,16 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { } } scope 6 (inlined std::ptr::mut_ptr::::len) { - debug self => _5; - let mut _10: *const [u32]; + debug self => _9; + let mut _11: *const [u32]; scope 7 (inlined std::ptr::metadata::<[u32]>) { - debug ptr => _10; + debug ptr => _11; scope 8 { } } } scope 9 (inlined Arguments::<'_>::new_const) { - debug pieces => _9; + debug pieces => _10; } } } @@ -50,6 +51,7 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { } bb0: { + StorageLive(_7); StorageLive(_4); StorageLive(_3); _3 = Len((*_1)); @@ -70,10 +72,12 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { _5 = &raw mut (*_1); StorageLive(_9); StorageLive(_10); + StorageLive(_11); StorageLive(_6); _6 = _5 as *mut u32 (PtrToPtr); _7 = Offset(_6, _2); StorageDead(_6); + StorageDead(_11); StorageDead(_10); StorageDead(_9); StorageDead(_5); @@ -85,6 +89,7 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { bb3: { StorageDead(_4); + StorageDead(_7); return; } } diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir index a12411a04137..bc7617bb6ddd 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir @@ -20,7 +20,8 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { debug self => _2; debug slice => _5; let mut _6: *mut u32; - let mut _9: &[&str]; + let mut _9: *mut [u32]; + let mut _10: &[&str]; scope 5 { scope 10 (inlined std::ptr::mut_ptr::::as_mut_ptr) { debug self => _5; @@ -33,16 +34,16 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { } } scope 6 (inlined std::ptr::mut_ptr::::len) { - debug self => _5; - let mut _10: *const [u32]; + debug self => _9; + let mut _11: *const [u32]; scope 7 (inlined std::ptr::metadata::<[u32]>) { - debug ptr => _10; + debug ptr => _11; scope 8 { } } } scope 9 (inlined Arguments::<'_>::new_const) { - debug pieces => _9; + debug pieces => _10; } } } @@ -50,6 +51,7 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { } bb0: { + StorageLive(_7); StorageLive(_4); StorageLive(_3); _3 = Len((*_1)); @@ -70,10 +72,12 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { _5 = &raw mut (*_1); StorageLive(_9); StorageLive(_10); + StorageLive(_11); StorageLive(_6); _6 = _5 as *mut u32 (PtrToPtr); _7 = Offset(_6, _2); StorageDead(_6); + StorageDead(_11); StorageDead(_10); StorageDead(_9); StorageDead(_5); @@ -85,6 +89,7 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { bb3: { StorageDead(_4); + StorageDead(_7); return; } } diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir index 0d95f81c37c5..36329f8fc684 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir @@ -19,7 +19,8 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> debug slice => _5; let mut _7: *mut u32; let mut _8: *mut u32; - let mut _14: &[&str]; + let mut _14: *mut [u32]; + let mut _15: &[&str]; scope 4 { let _6: usize; scope 5 { @@ -53,16 +54,16 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> } } scope 6 (inlined std::ptr::mut_ptr::::len) { - debug self => _5; - let mut _15: *const [u32]; + debug self => _14; + let mut _16: *const [u32]; scope 7 (inlined std::ptr::metadata::<[u32]>) { - debug ptr => _15; + debug ptr => _16; scope 8 { } } } scope 9 (inlined Arguments::<'_>::new_const) { - debug pieces => _14; + debug pieces => _15; } } } @@ -74,8 +75,9 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> StorageLive(_5); _5 = &raw mut (*_1); StorageLive(_14); - StorageLive(_6); StorageLive(_15); + StorageLive(_6); + StorageLive(_16); _6 = SubUnchecked(_4, _3); StorageLive(_8); StorageLive(_7); @@ -96,8 +98,9 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> StorageDead(_12); StorageDead(_9); StorageDead(_8); - StorageDead(_15); + StorageDead(_16); StorageDead(_6); + StorageDead(_15); StorageDead(_14); StorageDead(_5); _0 = &mut (*_13); diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir index 0d95f81c37c5..36329f8fc684 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir @@ -19,7 +19,8 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> debug slice => _5; let mut _7: *mut u32; let mut _8: *mut u32; - let mut _14: &[&str]; + let mut _14: *mut [u32]; + let mut _15: &[&str]; scope 4 { let _6: usize; scope 5 { @@ -53,16 +54,16 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> } } scope 6 (inlined std::ptr::mut_ptr::::len) { - debug self => _5; - let mut _15: *const [u32]; + debug self => _14; + let mut _16: *const [u32]; scope 7 (inlined std::ptr::metadata::<[u32]>) { - debug ptr => _15; + debug ptr => _16; scope 8 { } } } scope 9 (inlined Arguments::<'_>::new_const) { - debug pieces => _14; + debug pieces => _15; } } } @@ -74,8 +75,9 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> StorageLive(_5); _5 = &raw mut (*_1); StorageLive(_14); - StorageLive(_6); StorageLive(_15); + StorageLive(_6); + StorageLive(_16); _6 = SubUnchecked(_4, _3); StorageLive(_8); StorageLive(_7); @@ -96,8 +98,9 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> StorageDead(_12); StorageDead(_9); StorageDead(_8); - StorageDead(_15); + StorageDead(_16); StorageDead(_6); + StorageDead(_15); StorageDead(_14); StorageDead(_5); _0 = &mut (*_13); diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir index c58b630a0c36..26b2663fa358 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir @@ -42,20 +42,21 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { scope 13 (inlined NonNull::::new_unchecked) { debug ptr => _9; let mut _10: *const T; + let mut _24: *mut T; scope 14 { scope 15 (inlined NonNull::::new_unchecked::runtime::) { - debug ptr => _9; + debug ptr => _24; scope 16 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _24: *mut u8; + debug self => _24; + let mut _25: *mut u8; scope 17 { scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _24; + debug ptr => _25; scope 19 (inlined std::ptr::mut_ptr::::addr) { - debug self => _24; + debug self => _25; scope 20 { scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _24; + debug self => _25; } } } @@ -131,8 +132,10 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { _9 = _4 as *mut T (PtrToPtr); StorageLive(_10); StorageLive(_24); + StorageLive(_25); _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); _11 = NonNull:: { pointer: _10 }; + StorageDead(_25); StorageDead(_24); StorageDead(_10); StorageDead(_9); @@ -143,10 +146,10 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { StorageDead(_11); StorageDead(_7); StorageDead(_4); - _14 = Enumerate::> { iter: move _13, count: const 0_usize }; + _14 = Enumerate::> { iter: _13, count: const 0_usize }; StorageDead(_13); StorageLive(_15); - _15 = move _14; + _15 = _14; goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir index 1a805f0fd8dc..a055612bd5fe 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir @@ -42,20 +42,21 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { scope 13 (inlined NonNull::::new_unchecked) { debug ptr => _9; let mut _10: *const T; + let mut _24: *mut T; scope 14 { scope 15 (inlined NonNull::::new_unchecked::runtime::) { - debug ptr => _9; + debug ptr => _24; scope 16 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _24: *mut u8; + debug self => _24; + let mut _25: *mut u8; scope 17 { scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _24; + debug ptr => _25; scope 19 (inlined std::ptr::mut_ptr::::addr) { - debug self => _24; + debug self => _25; scope 20 { scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _24; + debug self => _25; } } } @@ -131,8 +132,10 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { _9 = _4 as *mut T (PtrToPtr); StorageLive(_10); StorageLive(_24); + StorageLive(_25); _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); _11 = NonNull:: { pointer: _10 }; + StorageDead(_25); StorageDead(_24); StorageDead(_10); StorageDead(_9); @@ -143,10 +146,10 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { StorageDead(_11); StorageDead(_7); StorageDead(_4); - _14 = Enumerate::> { iter: move _13, count: const 0_usize }; + _14 = Enumerate::> { iter: _13, count: const 0_usize }; StorageDead(_13); StorageLive(_15); - _15 = move _14; + _15 = _14; goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir index 09075eed6a9c..471491108e0b 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir @@ -39,20 +39,21 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 13 (inlined NonNull::::new_unchecked) { debug ptr => _9; let mut _10: *const T; + let mut _22: *mut T; scope 14 { scope 15 (inlined NonNull::::new_unchecked::runtime::) { - debug ptr => _9; + debug ptr => _22; scope 16 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _22: *mut u8; + debug self => _22; + let mut _23: *mut u8; scope 17 { scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _22; + debug ptr => _23; scope 19 (inlined std::ptr::mut_ptr::::addr) { - debug self => _22; + debug self => _23; scope 20 { scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _22; + debug self => _23; } } } @@ -121,8 +122,10 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { _9 = _4 as *mut T (PtrToPtr); StorageLive(_10); StorageLive(_22); + StorageLive(_23); _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); _11 = NonNull:: { pointer: _10 }; + StorageDead(_23); StorageDead(_22); StorageDead(_10); StorageDead(_9); @@ -134,7 +137,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { StorageDead(_7); StorageDead(_4); StorageLive(_14); - _14 = move _13; + _14 = _13; goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir index 47b84746468a..bbf38aba91f0 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -39,20 +39,21 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 13 (inlined NonNull::::new_unchecked) { debug ptr => _9; let mut _10: *const T; + let mut _22: *mut T; scope 14 { scope 15 (inlined NonNull::::new_unchecked::runtime::) { - debug ptr => _9; + debug ptr => _22; scope 16 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _22: *mut u8; + debug self => _22; + let mut _23: *mut u8; scope 17 { scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _22; + debug ptr => _23; scope 19 (inlined std::ptr::mut_ptr::::addr) { - debug self => _22; + debug self => _23; scope 20 { scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _22; + debug self => _23; } } } @@ -121,8 +122,10 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { _9 = _4 as *mut T (PtrToPtr); StorageLive(_10); StorageLive(_22); + StorageLive(_23); _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); _11 = NonNull:: { pointer: _10 }; + StorageDead(_23); StorageDead(_22); StorageDead(_10); StorageDead(_9); @@ -134,7 +137,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { StorageDead(_7); StorageDead(_4); StorageLive(_14); - _14 = move _13; + _14 = _13; goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir index 6a99f15774ff..83915d3c4493 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir @@ -58,7 +58,7 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { _4 = std::ops::Range:: { start: const 0_usize, end: move _3 }; StorageDead(_3); StorageLive(_5); - _5 = move _4; + _5 = _4; goto -> bb1; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir index 4f028fa0a646..0a005a460e84 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir @@ -58,7 +58,7 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { _4 = std::ops::Range:: { start: const 0_usize, end: move _3 }; StorageDead(_3); StorageLive(_5); - _5 = move _4; + _5 = _4; goto -> bb1; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir index 5ed7ca5e2b86..f9c8ab4db60b 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir @@ -44,20 +44,21 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 13 (inlined NonNull::::new_unchecked) { debug ptr => _9; let mut _10: *const T; + let mut _24: *mut T; scope 14 { scope 15 (inlined NonNull::::new_unchecked::runtime::) { - debug ptr => _9; + debug ptr => _24; scope 16 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _24: *mut u8; + debug self => _24; + let mut _25: *mut u8; scope 17 { scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _24; + debug ptr => _25; scope 19 (inlined std::ptr::mut_ptr::::addr) { - debug self => _24; + debug self => _25; scope 20 { scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _24; + debug self => _25; } } } @@ -133,8 +134,10 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { _9 = _4 as *mut T (PtrToPtr); StorageLive(_10); StorageLive(_24); + StorageLive(_25); _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); _11 = NonNull:: { pointer: _10 }; + StorageDead(_25); StorageDead(_24); StorageDead(_10); StorageDead(_9); @@ -145,10 +148,10 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { StorageDead(_11); StorageDead(_7); StorageDead(_4); - _14 = Rev::> { iter: move _13 }; + _14 = Rev::> { iter: _13 }; StorageDead(_13); StorageLive(_15); - _15 = move _14; + _15 = _14; goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir index bbb979d23b36..65f423ac326b 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir @@ -44,20 +44,21 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 13 (inlined NonNull::::new_unchecked) { debug ptr => _9; let mut _10: *const T; + let mut _24: *mut T; scope 14 { scope 15 (inlined NonNull::::new_unchecked::runtime::) { - debug ptr => _9; + debug ptr => _24; scope 16 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _24: *mut u8; + debug self => _24; + let mut _25: *mut u8; scope 17 { scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _24; + debug ptr => _25; scope 19 (inlined std::ptr::mut_ptr::::addr) { - debug self => _24; + debug self => _25; scope 20 { scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _24; + debug self => _25; } } } @@ -133,8 +134,10 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { _9 = _4 as *mut T (PtrToPtr); StorageLive(_10); StorageLive(_24); + StorageLive(_25); _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); _11 = NonNull:: { pointer: _10 }; + StorageDead(_25); StorageDead(_24); StorageDead(_10); StorageDead(_9); @@ -145,10 +148,10 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { StorageDead(_11); StorageDead(_7); StorageDead(_4); - _14 = Rev::> { iter: move _13 }; + _14 = Rev::> { iter: _13 }; StorageDead(_13); StorageLive(_15); - _15 = move _14; + _15 = _14; goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/try_identity.new.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/try_identity.new.PreCodegen.after.mir index 0bf4a2670020..c1d4d4871d02 100644 --- a/tests/mir-opt/pre-codegen/try_identity.new.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/try_identity.new.PreCodegen.after.mir @@ -31,13 +31,13 @@ fn new(_1: Result) -> Result { bb1: { _3 = move ((_1 as Ok).0: T); - _4 = ControlFlow::::Continue(move _3); + _4 = ControlFlow::::Continue(_3); goto -> bb3; } bb2: { _5 = move ((_1 as Err).0: E); - _4 = ControlFlow::::Break(move _5); + _4 = ControlFlow::::Break(_5); goto -> bb3; } @@ -48,14 +48,14 @@ fn new(_1: Result) -> Result { bb4: { _7 = move ((_4 as Continue).0: T); - _0 = Result::::Ok(move _7); + _0 = Result::::Ok(_7); StorageDead(_4); goto -> bb6; } bb5: { _8 = move ((_4 as Break).0: E); - _0 = Result::::Err(move _8); + _0 = Result::::Err(_8); StorageDead(_4); goto -> bb6; } diff --git a/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir index 7ccb8b0430de..d6883ac9fda0 100644 --- a/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir @@ -20,13 +20,13 @@ fn old(_1: Result) -> Result { bb1: { _3 = move ((_1 as Ok).0: T); - _0 = Result::::Ok(move _3); + _0 = Result::::Ok(_3); goto -> bb3; } bb2: { _4 = move ((_1 as Err).0: E); - _0 = Result::::Err(move _4); + _0 = Result::::Err(_4); goto -> bb3; } diff --git a/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff b/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff index a12db0a730c5..e7280f148377 100644 --- a/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff +++ b/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff @@ -4,92 +4,96 @@ fn identity(_1: Result) -> Result { debug x => _1; let mut _0: std::result::Result; - let mut _2: i32; - let mut _3: std::ops::ControlFlow, i32>; - let mut _4: std::result::Result; - let mut _5: isize; - let _6: std::result::Result; - let mut _7: std::result::Result; - let _8: i32; + let mut _2: std::ops::ControlFlow, i32>; + let mut _3: std::result::Result; + let mut _4: isize; + let _5: std::result::Result; + let mut _6: std::result::Result; + let _7: i32; scope 1 { - debug residual => _6; + debug residual => _5; scope 2 { scope 8 (inlined #[track_caller] as FromResidual>>::from_residual) { debug residual => _6; - let _13: i32; - let mut _14: i32; + let _12: i32; scope 9 { - debug e => _13; + debug e => _12; scope 10 (inlined >::from) { - debug t => _13; + debug t => _12; } } } } } scope 3 { - debug val => _8; + debug val => _7; scope 4 { } } scope 5 (inlined as Try>::branch) { - debug self => _1; - let mut _9: isize; + debug self => _3; + let mut _8: isize; + let _9: i32; let _10: i32; - let _11: i32; - let mut _12: std::result::Result; + let mut _11: std::result::Result; scope 6 { - debug v => _10; + debug v => _9; } scope 7 { - debug e => _11; + debug e => _10; } } bb0: { + StorageLive(_2); StorageLive(_3); + _3 = _1; + StorageLive(_8); StorageLive(_9); StorageLive(_10); - StorageLive(_11); - _9 = discriminant(_1); - switchInt(move _9) -> [0: bb5, 1: bb4, otherwise: bb6]; + _8 = discriminant(_1); + switchInt(move _8) -> [0: bb5, 1: bb4, otherwise: bb6]; } bb1: { - _8 = ((_3 as Continue).0: i32); - _0 = Result::::Ok(_8); - StorageDead(_3); + _7 = ((_2 as Continue).0: i32); + _0 = Result::::Ok(_7); + StorageDead(_2); return; } bb2: { - _6 = ((_3 as Break).0: std::result::Result); - _13 = ((_6 as Err).0: i32); - _0 = Result::::Err(move _13); - StorageDead(_3); + _5 = ((_2 as Break).0: std::result::Result); + StorageLive(_6); + _6 = _5; + _12 = move ((_5 as Err).0: i32); + _0 = Result::::Err(_12); + StorageDead(_6); + StorageDead(_2); return; } bb3: { - StorageDead(_11); StorageDead(_10); StorageDead(_9); - _5 = discriminant(_3); - switchInt(move _5) -> [0: bb1, 1: bb2, otherwise: bb6]; + StorageDead(_8); + StorageDead(_3); + _4 = discriminant(_2); + switchInt(move _4) -> [0: bb1, 1: bb2, otherwise: bb6]; } bb4: { - _11 = ((_1 as Err).0: i32); - StorageLive(_12); - _12 = Result::::Err(move _11); - _3 = ControlFlow::, i32>::Break(move _12); - StorageDead(_12); + _10 = move ((_1 as Err).0: i32); + StorageLive(_11); + _11 = Result::::Err(_10); + _2 = ControlFlow::, i32>::Break(move _11); + StorageDead(_11); goto -> bb3; } bb5: { - _10 = ((_1 as Ok).0: i32); - _3 = ControlFlow::, i32>::Continue(move _10); + _9 = move ((_1 as Ok).0: i32); + _2 = ControlFlow::, i32>::Continue(_9); goto -> bb3; } diff --git a/tests/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff b/tests/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff index 80f40b86919e..294bfa661cfa 100644 --- a/tests/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff +++ b/tests/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff @@ -7,24 +7,21 @@ let mut _2: std::ops::ControlFlow; let mut _3: isize; let _4: i32; - let mut _5: i32; - let _6: usize; - let mut _7: usize; - let mut _8: isize; - let _9: i32; - let mut _10: i32; - let _11: usize; + let _5: usize; + let mut _6: isize; + let _7: i32; + let _8: usize; scope 1 { debug v => _4; } scope 2 { - debug r => _6; + debug r => _5; } scope 3 { - debug v => _9; + debug v => _7; } scope 4 { - debug r => _11; + debug r => _8; } bb0: { @@ -34,8 +31,8 @@ } bb1: { - _6 = ((_1 as Err).0: usize); - _2 = ControlFlow::::Break(_6); + _5 = ((_1 as Err).0: usize); + _2 = ControlFlow::::Break(_5); goto -> bb3; } @@ -46,21 +43,21 @@ } bb3: { - _8 = discriminant(_2); - switchInt(move _8) -> [0: bb5, 1: bb4, otherwise: bb7]; + _6 = discriminant(_2); + switchInt(move _6) -> [0: bb5, 1: bb4, otherwise: bb7]; } bb4: { - StorageLive(_11); - _11 = ((_2 as Break).0: usize); - _0 = Option::::None; - StorageDead(_11); + StorageLive(_8); + _8 = ((_2 as Break).0: usize); + _0 = const Option::::None; + StorageDead(_8); goto -> bb6; } bb5: { - _9 = ((_2 as Continue).0: i32); - _0 = Option::::Some(_9); + _7 = ((_2 as Continue).0: i32); + _0 = Option::::Some(_7); goto -> bb6; } @@ -74,3 +71,7 @@ } } + ALLOC0 (size: 8, align: 4) { + 00 00 00 00 __ __ __ __ │ ....░░░░ + } + diff --git a/tests/mir-opt/simplify_match.main.GVN.panic-abort.diff b/tests/mir-opt/simplify_match.main.GVN.panic-abort.diff index d7ade041e4cc..33b36f660cb3 100644 --- a/tests/mir-opt/simplify_match.main.GVN.panic-abort.diff +++ b/tests/mir-opt/simplify_match.main.GVN.panic-abort.diff @@ -10,8 +10,15 @@ } bb0: { + StorageLive(_1); +- StorageLive(_2); ++ nop; _2 = const false; -- switchInt(_2) -> [0: bb2, otherwise: bb1]; +- _1 = _2; +- StorageDead(_2); +- switchInt(_1) -> [0: bb2, otherwise: bb1]; ++ _1 = const false; ++ nop; + switchInt(const false) -> [0: bb2, otherwise: bb1]; } @@ -20,6 +27,7 @@ } bb2: { + StorageDead(_1); return; } } diff --git a/tests/mir-opt/simplify_match.main.GVN.panic-unwind.diff b/tests/mir-opt/simplify_match.main.GVN.panic-unwind.diff index 931c5c43c4c6..e5c3adff6236 100644 --- a/tests/mir-opt/simplify_match.main.GVN.panic-unwind.diff +++ b/tests/mir-opt/simplify_match.main.GVN.panic-unwind.diff @@ -10,8 +10,15 @@ } bb0: { + StorageLive(_1); +- StorageLive(_2); ++ nop; _2 = const false; -- switchInt(_2) -> [0: bb2, otherwise: bb1]; +- _1 = _2; +- StorageDead(_2); +- switchInt(_1) -> [0: bb2, otherwise: bb1]; ++ _1 = const false; ++ nop; + switchInt(const false) -> [0: bb2, otherwise: bb1]; } @@ -20,6 +27,7 @@ } bb2: { + StorageDead(_1); return; } } diff --git a/tests/pretty/offset_of.rs b/tests/pretty/offset_of.rs index e1783432857e..1307c335ad32 100644 --- a/tests/pretty/offset_of.rs +++ b/tests/pretty/offset_of.rs @@ -1,4 +1,3 @@ // pp-exact -#![feature(offset_of)] fn main() { std::mem::offset_of!(std :: ops :: Range < usize >, end); } diff --git a/tests/pretty/tests-are-sorted.pp b/tests/pretty/tests-are-sorted.pp index fd9386be8f3c..fbdad0c323f3 100644 --- a/tests/pretty/tests-are-sorted.pp +++ b/tests/pretty/tests-are-sorted.pp @@ -28,7 +28,8 @@ pub const m_test: test::TestDescAndFn = should_panic: test::ShouldPanic::No, test_type: test::TestType::Unknown, }, - testfn: test::StaticTestFn(|| test::assert_test_result(m_test())), + testfn: test::StaticTestFn(#[coverage(off)] || + test::assert_test_result(m_test())), }; fn m_test() {} @@ -51,7 +52,8 @@ pub const z_test: test::TestDescAndFn = should_panic: test::ShouldPanic::No, test_type: test::TestType::Unknown, }, - testfn: test::StaticTestFn(|| test::assert_test_result(z_test())), + testfn: test::StaticTestFn(#[coverage(off)] || + test::assert_test_result(z_test())), }; #[ignore = "not yet implemented"] fn z_test() {} @@ -75,7 +77,8 @@ pub const a_test: test::TestDescAndFn = should_panic: test::ShouldPanic::No, test_type: test::TestType::Unknown, }, - testfn: test::StaticTestFn(|| test::assert_test_result(a_test())), + testfn: test::StaticTestFn(#[coverage(off)] || + test::assert_test_result(a_test())), }; fn a_test() {} #[rustc_main] diff --git a/tests/rustdoc-gui/docblock-details.goml b/tests/rustdoc-gui/docblock-details.goml index 8e6d2ba824f7..4b8f5b54fac5 100644 --- a/tests/rustdoc-gui/docblock-details.goml +++ b/tests/rustdoc-gui/docblock-details.goml @@ -6,7 +6,7 @@ reload: // We first check that the headers in the `.top-doc` doc block still have their // bottom border. -assert-text: (".top-doc .docblock > h3", "Hello") +assert-text: (".top-doc .docblock > h3", "§Hello") assert-css: ( ".top-doc .docblock > h3", {"border-bottom": "1px solid #d2d2d2"}, diff --git a/tests/rustdoc-gui/headers-color.goml b/tests/rustdoc-gui/headers-color.goml index 19185818f407..80d11c9c849c 100644 --- a/tests/rustdoc-gui/headers-color.goml +++ b/tests/rustdoc-gui/headers-color.goml @@ -1,4 +1,4 @@ -// This test check for headers text and background colors for the different themes. +// This test check for headings text and background colors for the different themes. define-function: ( "check-colors", @@ -45,7 +45,7 @@ call-function: ( "color": "#c5c5c5", "code_header_color": "#e6e1cf", "focus_background_color": "rgba(255, 236, 164, 0.06)", - "headings_color": "#39afd7", + "headings_color": "#c5c5c5", }, ) call-function: ( @@ -55,7 +55,7 @@ call-function: ( "color": "#ddd", "code_header_color": "#ddd", "focus_background_color": "#494a3d", - "headings_color": "#d2991d", + "headings_color": "#ddd", }, ) call-function: ( @@ -65,6 +65,6 @@ call-function: ( "color": "black", "code_header_color": "black", "focus_background_color": "#fdffd3", - "headings_color": "#3873ad", + "headings_color": "black", }, ) diff --git a/tests/rustdoc-gui/headings-anchor.goml b/tests/rustdoc-gui/headings-anchor.goml new file mode 100644 index 000000000000..f568caa3b07f --- /dev/null +++ b/tests/rustdoc-gui/headings-anchor.goml @@ -0,0 +1,32 @@ +// Test to ensure that the headings anchor behave as expected. +go-to: "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html" +show-text: true + +define-function: ( + "check-heading-anchor", + (heading_id), + block { + // The anchor should not be displayed by default. + assert-css: ("#" + |heading_id| + " .doc-anchor", { "display": "none" }) + // We ensure that hovering the heading makes the anchor visible. + move-cursor-to: "#" + |heading_id| + assert-css: ("#" + |heading_id| + ":hover .doc-anchor", { "display": "block" }) + // We then ensure that moving from the heading to the anchor doesn't make the anchor + // disappear. + move-cursor-to: "#" + |heading_id| + " .doc-anchor" + assert-css: ("#" + |heading_id| + " .doc-anchor:hover", { + "display": "block", + // We also ensure that there is no underline decoration. + "text-decoration-line": "none", + }) + } +) + +move-cursor-to: "#top-doc-prose-title" +// If the top documentation block first element is a heading, we should never display its anchor +// to prevent it from overlapping with the `[-]` element. +assert-css: ("#top-doc-prose-title:hover .doc-anchor", { "display": "none" }) + +call-function: ("check-heading-anchor", ("top-doc-prose-sub-heading")) +call-function: ("check-heading-anchor", ("top-doc-prose-sub-sub-heading")) +call-function: ("check-heading-anchor", ("you-know-the-drill")) diff --git a/tests/rustdoc-ui/error-in-impl-trait/README.md b/tests/rustdoc-ui/error-in-impl-trait/README.md index d969ab10ef5e..0b42ff1771e2 100644 --- a/tests/rustdoc-ui/error-in-impl-trait/README.md +++ b/tests/rustdoc-ui/error-in-impl-trait/README.md @@ -1,5 +1,5 @@ Each of these needs to be in a separate file, -because the `span_delayed_bug` ICE in rustdoc won't be triggerred +because the `span_delayed_bug` ICE in rustdoc won't be triggered if even a single other error was emitted. However, conceptually they are all testing basically the same thing. diff --git a/tests/rustdoc/issue-52873.rs b/tests/rustdoc-ui/ice-blanket-impl-52873.rs similarity index 97% rename from tests/rustdoc/issue-52873.rs rename to tests/rustdoc-ui/ice-blanket-impl-52873.rs index 8000ce73bd42..2520957bd005 100644 --- a/tests/rustdoc/issue-52873.rs +++ b/tests/rustdoc-ui/ice-blanket-impl-52873.rs @@ -1,3 +1,7 @@ +// check-pass +// https://github.com/rust-lang/rust/issues/52873 +#![crate_name="foo"] + // Regression test for #52873. We used to ICE due to unexpected // overflows when checking for "blanket impl inclusion". diff --git a/tests/rustdoc/issue-55001.rs b/tests/rustdoc-ui/ice-blanket-impl-selection-55001.rs similarity index 88% rename from tests/rustdoc/issue-55001.rs rename to tests/rustdoc-ui/ice-blanket-impl-selection-55001.rs index f6c7f9a3d082..babcb3dda143 100644 --- a/tests/rustdoc/issue-55001.rs +++ b/tests/rustdoc-ui/ice-blanket-impl-selection-55001.rs @@ -1,3 +1,7 @@ +// check-pass +// https://github.com/rust-lang/rust/issues/55001 +#![crate_name="foo"] + // Regression test for issue #55001. Previously, we would incorrectly // cache certain trait selection results when checking for blanket impls, // resulting in an ICE when we tried to confirm the cached ParamCandidate diff --git a/tests/rustdoc/async-fn.rs b/tests/rustdoc/async-fn.rs index 70bcbcb6ff44..b3c35c8c3f30 100644 --- a/tests/rustdoc/async-fn.rs +++ b/tests/rustdoc/async-fn.rs @@ -48,6 +48,8 @@ impl Foo { pub trait Pattern<'a> {} +impl Pattern<'_> for () {} + pub trait Trait {} // @has async_fn/fn.const_generics.html // @has - '//pre[@class="rust item-decl"]' 'pub async fn const_generics(_: impl Trait)' @@ -57,18 +59,18 @@ pub async fn const_generics(_: impl Trait) {} // regression test for #63037 // @has async_fn/fn.elided.html // @has - '//pre[@class="rust item-decl"]' 'pub async fn elided(foo: &str) -> &str' -pub async fn elided(foo: &str) -> &str {} +pub async fn elided(foo: &str) -> &str { "" } // This should really be shown as written, but for implementation reasons it's difficult. // See `impl Clean for TyKind::Ref`. // @has async_fn/fn.user_elided.html // @has - '//pre[@class="rust item-decl"]' 'pub async fn user_elided(foo: &str) -> &str' -pub async fn user_elided(foo: &'_ str) -> &str {} +pub async fn user_elided(foo: &'_ str) -> &str { "" } // @has async_fn/fn.static_trait.html // @has - '//pre[@class="rust item-decl"]' 'pub async fn static_trait(foo: &str) -> Box' -pub async fn static_trait(foo: &str) -> Box {} +pub async fn static_trait(foo: &str) -> Box { Box::new(()) } // @has async_fn/fn.lifetime_for_trait.html // @has - '//pre[@class="rust item-decl"]' "pub async fn lifetime_for_trait(foo: &str) -> Box" -pub async fn lifetime_for_trait(foo: &str) -> Box {} +pub async fn lifetime_for_trait(foo: &str) -> Box { Box::new(()) } // @has async_fn/fn.elided_in_input_trait.html // @has - '//pre[@class="rust item-decl"]' "pub async fn elided_in_input_trait(t: impl Pattern<'_>)" pub async fn elided_in_input_trait(t: impl Pattern<'_>) {} @@ -78,10 +80,12 @@ struct AsyncFdReadyGuard<'a, T> { x: &'a T } impl Foo { // @has async_fn/struct.Foo.html // @has - '//*[@class="method"]' 'pub async fn complicated_lifetimes( &self, context: &impl Bar ) -> impl Iterator' - pub async fn complicated_lifetimes(&self, context: &impl Bar) -> impl Iterator {} + pub async fn complicated_lifetimes(&self, context: &impl Bar) -> impl Iterator { + [0].iter() + } // taken from `tokio` as an example of a method that was particularly bad before // @has - '//*[@class="method"]' "pub async fn readable(&self) -> Result, ()>" - pub async fn readable(&self) -> Result, ()> {} + pub async fn readable(&self) -> Result, ()> { Err(()) } // @has - '//*[@class="method"]' "pub async fn mut_self(&mut self)" pub async fn mut_self(&mut self) {} } @@ -89,7 +93,7 @@ impl Foo { // test named lifetimes, just in case // @has async_fn/fn.named.html // @has - '//pre[@class="rust item-decl"]' "pub async fn named<'a, 'b>(foo: &'a str) -> &'b str" -pub async fn named<'a, 'b>(foo: &'a str) -> &'b str {} +pub async fn named<'a, 'b>(foo: &'a str) -> &'b str { "" } // @has async_fn/fn.named_trait.html // @has - '//pre[@class="rust item-decl"]' "pub async fn named_trait<'a, 'b>(foo: impl Pattern<'a>) -> impl Pattern<'b>" pub async fn named_trait<'a, 'b>(foo: impl Pattern<'a>) -> impl Pattern<'b> {} diff --git a/tests/rustdoc/issue-50159.rs b/tests/rustdoc/auto-trait-bounds-by-associated-type-50159.rs similarity index 84% rename from tests/rustdoc/issue-50159.rs rename to tests/rustdoc/auto-trait-bounds-by-associated-type-50159.rs index 13bedd5dbb02..0663ed5fc81f 100644 --- a/tests/rustdoc/issue-50159.rs +++ b/tests/rustdoc/auto-trait-bounds-by-associated-type-50159.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/50159 +#![crate_name="foo"] + pub trait Signal { type Item; } @@ -10,7 +13,7 @@ impl Signal2 for B where B: Signal { type Item2 = C; } -// @has issue_50159/struct.Switch.html +// @has foo/struct.Switch.html // @has - '//h3[@class="code-header"]' 'impl Send for Switchwhere ::Item: Send' // @has - '//h3[@class="code-header"]' 'impl Sync for Switchwhere ::Item: Sync' // @count - '//*[@id="implementations-list"]//*[@class="impl"]' 0 diff --git a/tests/rustdoc/issue-54705.rs b/tests/rustdoc/auto-trait-bounds-inference-variables-54705.rs similarity index 87% rename from tests/rustdoc/issue-54705.rs rename to tests/rustdoc/auto-trait-bounds-inference-variables-54705.rs index a886eb0de242..00be0042fb03 100644 --- a/tests/rustdoc/issue-54705.rs +++ b/tests/rustdoc/auto-trait-bounds-inference-variables-54705.rs @@ -1,6 +1,9 @@ +// https://github.com/rust-lang/rust/issues/54705 +#![crate_name="foo"] + pub trait ScopeHandle<'scope> {} -// @has issue_54705/struct.ScopeFutureContents.html +// @has foo/struct.ScopeFutureContents.html // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \ // "impl<'scope, S> Send for ScopeFutureContents<'scope, S>where S: Sync" // diff --git a/tests/rustdoc/issue-51236.rs b/tests/rustdoc/auto-trait-bounds-where-51236.rs similarity index 79% rename from tests/rustdoc/issue-51236.rs rename to tests/rustdoc/auto-trait-bounds-where-51236.rs index 04664805a886..30c81e796013 100644 --- a/tests/rustdoc/issue-51236.rs +++ b/tests/rustdoc/auto-trait-bounds-where-51236.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/51236 +#![crate_name="foo"] + use std::marker::PhantomData; pub mod traits { @@ -6,7 +9,7 @@ pub mod traits { } } -// @has issue_51236/struct.Owned.html +// @has foo/struct.Owned.html // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \ // "impl Send for Ownedwhere >::Reader: Send" pub struct Owned where T: for<'a> ::traits::Owned<'a> { diff --git a/tests/rustdoc/issue-55321.rs b/tests/rustdoc/auto-trait-negative-impl-55321.rs similarity index 83% rename from tests/rustdoc/issue-55321.rs rename to tests/rustdoc/auto-trait-negative-impl-55321.rs index d3c2070d915d..e9be1ff854e0 100644 --- a/tests/rustdoc/issue-55321.rs +++ b/tests/rustdoc/auto-trait-negative-impl-55321.rs @@ -1,6 +1,9 @@ +// https://github.com/rust-lang/rust/issues/55321 +#![crate_name="foo"] + #![feature(negative_impls)] -// @has issue_55321/struct.A.html +// @has foo/struct.A.html // @has - '//*[@id="trait-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \ // "impl !Send for A" // @has - '//*[@id="trait-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \ @@ -10,7 +13,7 @@ pub struct A(); impl !Send for A {} impl !Sync for A {} -// @has issue_55321/struct.B.html +// @has foo/struct.B.html // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \ // "impl !Send for B" // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \ diff --git a/tests/rustdoc/blank-line-in-doc-block-47197.rs b/tests/rustdoc/blank-line-in-doc-block-47197.rs new file mode 100644 index 000000000000..79492b4fa769 --- /dev/null +++ b/tests/rustdoc/blank-line-in-doc-block-47197.rs @@ -0,0 +1,11 @@ +// https://github.com/rust-lang/rust/issues/47197 +#![crate_name="foo"] + +// @has foo/fn.whose_woods_these_are_i_think_i_know.html + +/** +* snow + +* ice +*/ +pub fn whose_woods_these_are_i_think_i_know() {} diff --git a/tests/rustdoc/issue-54478-demo-allocator.rs b/tests/rustdoc/demo-allocator-54478.rs similarity index 94% rename from tests/rustdoc/issue-54478-demo-allocator.rs rename to tests/rustdoc/demo-allocator-54478.rs index 4811f363bc97..39acee36d889 100644 --- a/tests/rustdoc/issue-54478-demo-allocator.rs +++ b/tests/rustdoc/demo-allocator-54478.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/54478 +#![crate_name="foo"] + // Issue #54478: regression test showing that we can demonstrate // `#[global_allocator]` in code blocks built by `rustdoc`. // diff --git a/tests/rustdoc/issue-35169-2.rs b/tests/rustdoc/deref-mut-35169-2.rs similarity index 94% rename from tests/rustdoc/issue-35169-2.rs rename to tests/rustdoc/deref-mut-35169-2.rs index f08466baf8b0..c82323ddc6aa 100644 --- a/tests/rustdoc/issue-35169-2.rs +++ b/tests/rustdoc/deref-mut-35169-2.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/35169 +#![crate_name="foo"] + use std::ops::Deref; use std::ops::DerefMut; @@ -23,7 +26,7 @@ impl DerefMut for Bar { fn deref_mut(&mut self) -> &mut Foo { loop {} } } -// @has issue_35169_2/struct.Bar.html +// @has foo/struct.Bar.html // @has - '//*[@id="method.by_ref"]//h4[@class="code-header"]' 'fn by_ref(&self)' // @has - '//*[@id="method.by_ref"]' 'fn by_ref(&self)' // @has - '//*[@id="method.by_explicit_ref"]//h4[@class="code-header"]' 'fn by_explicit_ref(self: &Foo)' diff --git a/tests/rustdoc/issue-35169.rs b/tests/rustdoc/deref-mut-35169.rs similarity index 94% rename from tests/rustdoc/issue-35169.rs rename to tests/rustdoc/deref-mut-35169.rs index 70a2265c8063..44afaf2e903a 100644 --- a/tests/rustdoc/issue-35169.rs +++ b/tests/rustdoc/deref-mut-35169.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/35169 +#![crate_name="foo"] + use std::ops::Deref; pub struct Foo; @@ -18,7 +21,7 @@ impl Deref for Bar { fn deref(&self) -> &Foo { loop {} } } -// @has issue_35169/struct.Bar.html +// @has foo/struct.Bar.html // @has - '//*[@id="method.by_ref"]//h4[@class="code-header"]' 'fn by_ref(&self)' // @has - '//*[@id="method.by_ref"]' 'fn by_ref(&self)' // @has - '//*[@id="method.by_explicit_ref"]//h4[@class="code-header"]' 'fn by_explicit_ref(self: &Foo)' diff --git a/tests/rustdoc/disambiguate-anchors-header-29449.rs b/tests/rustdoc/disambiguate-anchors-header-29449.rs index 38a4954fc139..1388af7df4b2 100644 --- a/tests/rustdoc/disambiguate-anchors-header-29449.rs +++ b/tests/rustdoc/disambiguate-anchors-header-29449.rs @@ -5,18 +5,23 @@ pub struct Foo; impl Foo { - // @has - '//*[@id="examples"]//a' 'Examples' - // @has - '//*[@id="panics"]//a' 'Panics' + // @has - '//*[@id="examples"]' 'Examples' + // @has - '//*[@id="examples"]/a[@href="#examples"]' '§' + // @has - '//*[@id="panics"]' 'Panics' + // @has - '//*[@id="panics"]/a[@href="#panics"]' '§' /// # Examples /// # Panics pub fn bar() {} - // @has - '//*[@id="examples-1"]//a' 'Examples' + // @has - '//*[@id="examples-1"]' 'Examples' + // @has - '//*[@id="examples-1"]/a[@href="#examples-1"]' '§' /// # Examples pub fn bar_1() {} - // @has - '//*[@id="examples-2"]//a' 'Examples' - // @has - '//*[@id="panics-1"]//a' 'Panics' + // @has - '//*[@id="examples-2"]' 'Examples' + // @has - '//*[@id="examples-2"]/a[@href="#examples-2"]' '§' + // @has - '//*[@id="panics-1"]' 'Panics' + // @has - '//*[@id="panics-1"]/a[@href="#panics-1"]' '§' /// # Examples /// # Panics pub fn bar_2() {} diff --git a/tests/rustdoc/issue-42760.rs b/tests/rustdoc/doc-attr-comment-mix-42760.rs similarity index 65% rename from tests/rustdoc/issue-42760.rs rename to tests/rustdoc/doc-attr-comment-mix-42760.rs index a5394c7d92a9..16c1705eb00c 100644 --- a/tests/rustdoc/issue-42760.rs +++ b/tests/rustdoc/doc-attr-comment-mix-42760.rs @@ -1,6 +1,9 @@ +// https://github.com/rust-lang/rust/issues/42760 +#![crate_name="foo"] + #![allow(rustdoc::invalid_rust_codeblocks)] -// @has issue_42760/struct.NonGen.html +// @has foo/struct.NonGen.html // @has - '//h2' 'Example' /// Item docs. diff --git a/tests/rustdoc/issue-41783.codeblock.html b/tests/rustdoc/doctest/doctest-escape-boring-41783.codeblock.html similarity index 100% rename from tests/rustdoc/issue-41783.codeblock.html rename to tests/rustdoc/doctest/doctest-escape-boring-41783.codeblock.html diff --git a/tests/rustdoc/issue-41783.rs b/tests/rustdoc/doctest/doctest-escape-boring-41783.rs similarity index 81% rename from tests/rustdoc/issue-41783.rs rename to tests/rustdoc/doctest/doctest-escape-boring-41783.rs index 7578d49daa50..7782e148fd9f 100644 --- a/tests/rustdoc/issue-41783.rs +++ b/tests/rustdoc/doctest/doctest-escape-boring-41783.rs @@ -1,4 +1,7 @@ -// @has issue_41783/struct.Foo.html +// https://github.com/rust-lang/rust/issues/41783 +#![crate_name="foo"] + +// @has foo/struct.Foo.html // @!hasraw - 'space' // @!hasraw - 'comment' // @hasraw - '#[outer]' diff --git a/tests/rustdoc/enum-variant-reexport-35488.rs b/tests/rustdoc/enum-variant-reexport-35488.rs new file mode 100644 index 000000000000..ed955dcd770a --- /dev/null +++ b/tests/rustdoc/enum-variant-reexport-35488.rs @@ -0,0 +1,16 @@ +// https://github.com/rust-lang/rust/issues/35488 +#![crate_name="foo"] + +mod foo { + pub enum Foo { + Bar, + } + pub use self::Foo::*; +} + +// @has 'foo/index.html' '//code' 'pub use self::Foo::*;' +// @has 'foo/enum.Foo.html' +pub use self::foo::*; + +// @has 'foo/index.html' '//code' 'pub use std::option::Option::None;' +pub use std::option::Option::None; diff --git a/tests/rustdoc/issue-53689.rs b/tests/rustdoc/impl-blanket-53689.rs similarity index 84% rename from tests/rustdoc/issue-53689.rs rename to tests/rustdoc/impl-blanket-53689.rs index 832140e061b5..7c2edd01a609 100644 --- a/tests/rustdoc/issue-53689.rs +++ b/tests/rustdoc/impl-blanket-53689.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/53689 // aux-build:issue-53689.rs #![crate_name = "foo"] diff --git a/tests/rustdoc/impl-on-ty-alias-issue-119015.rs b/tests/rustdoc/impl-on-ty-alias-issue-119015.rs new file mode 100644 index 000000000000..68996deae6fd --- /dev/null +++ b/tests/rustdoc/impl-on-ty-alias-issue-119015.rs @@ -0,0 +1,27 @@ +#![crate_name = "foo"] + +// @has 'foo/index.html' +// There should be only `type A`. +// @count - '//*[@class="item-table"]//*[@class="item-name"]' 1 +// @has - '//*[@class="item-name"]/a[@href="type.A.html"]' 'A' + +mod foo { + pub struct S; +} + +use foo::S; + +pub type A = S; + +// @has 'foo/type.A.html' +// @has - '//*[@id="method.default"]/h4' 'fn default() -> Self' +impl Default for A { + fn default() -> Self { + S + } +} + +// @has - '//*[@id="method.a"]/h4' 'pub fn a(&self)' +impl A { + pub fn a(&self) {} +} diff --git a/tests/rustdoc/issue-43869.rs b/tests/rustdoc/impl-trait-43869.rs similarity index 73% rename from tests/rustdoc/issue-43869.rs rename to tests/rustdoc/impl-trait-43869.rs index 767d09d85588..9c4ed841f797 100644 --- a/tests/rustdoc/issue-43869.rs +++ b/tests/rustdoc/impl-trait-43869.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/43869 +#![crate_name="foo"] + pub fn g() -> impl Iterator { Some(1u8).into_iter() } @@ -58,15 +61,15 @@ pub fn test_44731_4() -> Box> { Box::new(g()) } -// @has issue_43869/fn.g.html -// @has issue_43869/fn.h.html -// @has issue_43869/fn.i.html -// @has issue_43869/fn.j.html -// @has issue_43869/fn.k.html -// @has issue_43869/fn.l.html -// @has issue_43869/fn.m.html -// @has issue_43869/fn.n.html -// @has issue_43869/fn.o.html -// @has issue_43869/fn.test_44731_0.html -// @has issue_43869/fn.test_44731_1.html -// @has issue_43869/fn.test_44731_4.html +// @has foo/fn.g.html +// @has foo/fn.h.html +// @has foo/fn.i.html +// @has foo/fn.j.html +// @has foo/fn.k.html +// @has foo/fn.l.html +// @has foo/fn.m.html +// @has foo/fn.n.html +// @has foo/fn.o.html +// @has foo/fn.test_44731_0.html +// @has foo/fn.test_44731_1.html +// @has foo/fn.test_44731_4.html diff --git a/tests/rustdoc/auxiliary/issue-46727.rs b/tests/rustdoc/inline_cross/auxiliary/issue-46727.rs similarity index 100% rename from tests/rustdoc/auxiliary/issue-46727.rs rename to tests/rustdoc/inline_cross/auxiliary/issue-46727.rs diff --git a/tests/rustdoc/issue-46727.rs b/tests/rustdoc/inline_cross/const-eval-46727.rs similarity index 61% rename from tests/rustdoc/issue-46727.rs rename to tests/rustdoc/inline_cross/const-eval-46727.rs index 8cfc4827a7f4..d0ce9c34f51b 100644 --- a/tests/rustdoc/issue-46727.rs +++ b/tests/rustdoc/inline_cross/const-eval-46727.rs @@ -1,7 +1,10 @@ +// https://github.com/rust-lang/rust/issues/46727 +#![crate_name="foo"] + // aux-build:issue-46727.rs extern crate issue_46727; -// @has issue_46727/trait.Foo.html +// @has foo/trait.Foo.html // @has - '//h3[@class="code-header"]' 'impl Foo for Bar<[T; 3]>' pub use issue_46727::{Foo, Bar}; diff --git a/tests/rustdoc/issue-55364.rs b/tests/rustdoc/intra-doc/module-scope-name-resolution-55364.rs similarity index 90% rename from tests/rustdoc/issue-55364.rs rename to tests/rustdoc/intra-doc/module-scope-name-resolution-55364.rs index 941cb3ce1ca5..c07aba628c90 100644 --- a/tests/rustdoc/issue-55364.rs +++ b/tests/rustdoc/intra-doc/module-scope-name-resolution-55364.rs @@ -1,6 +1,9 @@ +// https://github.com/rust-lang/rust/issues/55364 +#![crate_name="foo"] + // First a module with inner documentation -// @has issue_55364/subone/index.html +// @has foo/subone/index.html // These foo/bar links in the module's documentation should refer inside `subone` // @has - '//section[@id="main-content"]/details[@open=""]/div[@class="docblock"]//a[@href="fn.foo.html"]' 'foo' // @has - '//section[@id="main-content"]/details[@open=""]/div[@class="docblock"]//a[@href="fn.bar.html"]' 'bar' @@ -8,12 +11,12 @@ pub mod subone { //! See either [foo] or [bar]. // This should refer to subone's `bar` - // @has issue_55364/subone/fn.foo.html + // @has foo/subone/fn.foo.html // @has - '//section[@id="main-content"]/details/div[@class="docblock"]//a[@href="fn.bar.html"]' 'bar' /// See [bar] pub fn foo() {} // This should refer to subone's `foo` - // @has issue_55364/subone/fn.bar.html + // @has foo/subone/fn.bar.html // @has - '//section[@id="main-content"]/details/div[@class="docblock"]//a[@href="fn.foo.html"]' 'foo' /// See [foo] pub fn bar() {} @@ -21,7 +24,7 @@ pub mod subone { // A module with outer documentation -// @has issue_55364/subtwo/index.html +// @has foo/subtwo/index.html // These foo/bar links in the module's documentation should not reference inside `subtwo` // @!has - '//section[@id="main-content"]/div[@class="docblock"]//a[@href="fn.foo.html"]' 'foo' // @!has - '//section[@id="main-content"]/div[@class="docblock"]//a[@href="fn.bar.html"]' 'bar' @@ -36,13 +39,13 @@ pub mod subtwo { // Despite the module's docs referring to the top level foo/bar, // this should refer to subtwo's `bar` - // @has issue_55364/subtwo/fn.foo.html + // @has foo/subtwo/fn.foo.html // @has - '//section[@id="main-content"]/details/div[@class="docblock"]//a[@href="fn.bar.html"]' 'bar' /// See [bar] pub fn foo() {} // Despite the module's docs referring to the top level foo/bar, // this should refer to subtwo's `foo` - // @has issue_55364/subtwo/fn.bar.html + // @has foo/subtwo/fn.bar.html // @has - '//section[@id="main-content"]/details/div[@class="docblock"]//a[@href="fn.foo.html"]' 'foo' /// See [foo] pub fn bar() {} @@ -57,7 +60,7 @@ pub fn bar() {} // This module refers to the outer foo/bar by means of `super::` -// @has issue_55364/subthree/index.html +// @has foo/subthree/index.html // This module should also refer to the top level foo/bar // @has - '//section[@id="main-content"]/details/div[@class="docblock"]//a[@href="../fn.foo.html"]' 'foo' // @has - '//section[@id="main-content"]/details/div[@class="docblock"]//a[@href="../fn.bar.html"]' 'bar' @@ -67,7 +70,7 @@ pub mod subthree { // Next we go *deeper* - In order to ensure it's not just "this or parent" // we test `crate::` and a `super::super::...` chain -// @has issue_55364/subfour/subfive/subsix/subseven/subeight/index.html +// @has foo/subfour/subfive/subsix/subseven/subeight/index.html // @has - '//section[@id="main-content"]/ul[@class="item-table"]//div[@class="desc docblock-short"]//a[@href="../../../../../subone/fn.foo.html"]' 'other foo' // @has - '//section[@id="main-content"]/ul[@class="item-table"]//div[@class="desc docblock-short"]//a[@href="../../../../../subtwo/fn.bar.html"]' 'other bar' pub mod subfour { diff --git a/tests/rustdoc/issue-35488.rs b/tests/rustdoc/issue-35488.rs deleted file mode 100644 index c1bf9ceeac1c..000000000000 --- a/tests/rustdoc/issue-35488.rs +++ /dev/null @@ -1,13 +0,0 @@ -mod foo { - pub enum Foo { - Bar, - } - pub use self::Foo::*; -} - -// @has 'issue_35488/index.html' '//code' 'pub use self::Foo::*;' -// @has 'issue_35488/enum.Foo.html' -pub use self::foo::*; - -// @has 'issue_35488/index.html' '//code' 'pub use std::option::Option::None;' -pub use std::option::Option::None; diff --git a/tests/rustdoc/issue-46377.rs b/tests/rustdoc/issue-46377.rs deleted file mode 100644 index 1311b4721e2f..000000000000 --- a/tests/rustdoc/issue-46377.rs +++ /dev/null @@ -1,3 +0,0 @@ -// @has 'issue_46377/index.html' '//*[@class="desc docblock-short"]' 'Check out this struct!' -/// # Check out this struct! -pub struct SomeStruct; diff --git a/tests/rustdoc/issue-47197-blank-line-in-doc-block.rs b/tests/rustdoc/issue-47197-blank-line-in-doc-block.rs deleted file mode 100644 index 19994475de27..000000000000 --- a/tests/rustdoc/issue-47197-blank-line-in-doc-block.rs +++ /dev/null @@ -1,8 +0,0 @@ -// @has issue_47197_blank_line_in_doc_block/fn.whose_woods_these_are_i_think_i_know.html - -/** -* snow - -* ice -*/ -pub fn whose_woods_these_are_i_think_i_know() {} diff --git a/tests/rustdoc/links-in-headings.rs b/tests/rustdoc/links-in-headings.rs new file mode 100644 index 000000000000..c5bee1a79750 --- /dev/null +++ b/tests/rustdoc/links-in-headings.rs @@ -0,0 +1,14 @@ +#![crate_name = "foo"] + +//! # Heading with [a link](https://a.com) inside +//! +//! And even with +//! +//! ## [multiple](https://b.com) [links](https://c.com) +//! +//! ! + +// @has 'foo/index.html' +// @has - '//h2/a[@href="https://a.com"]' 'a link' +// @has - '//h3/a[@href="https://b.com"]' 'multiple' +// @has - '//h3/a[@href="https://c.com"]' 'links' diff --git a/tests/rustdoc/issue-46380-2.rs b/tests/rustdoc/public-impl-mention-private-generic-46380-2.rs similarity index 66% rename from tests/rustdoc/issue-46380-2.rs rename to tests/rustdoc/public-impl-mention-private-generic-46380-2.rs index 7004d18dc66c..96ebd888eb5c 100644 --- a/tests/rustdoc/issue-46380-2.rs +++ b/tests/rustdoc/public-impl-mention-private-generic-46380-2.rs @@ -1,6 +1,9 @@ +// https://github.com/rust-lang/rust/issues/46380 +#![crate_name="foo"] + pub trait PublicTrait {} -// @has issue_46380_2/struct.PublicStruct.html +// @has foo/struct.PublicStruct.html pub struct PublicStruct; // @!has - '//*[@class="impl"]' 'impl PublicTrait for PublicStruct' diff --git a/tests/rustdoc/remove-url-from-headings.rs b/tests/rustdoc/remove-url-from-headings.rs index 599c429a6e1d..8f4770286192 100644 --- a/tests/rustdoc/remove-url-from-headings.rs +++ b/tests/rustdoc/remove-url-from-headings.rs @@ -1,9 +1,12 @@ +// It actually checks that the link is kept in the headings as expected now. + #![crate_name = "foo"] // @has foo/fn.foo.html -// @!has - '//a[@href="http://a.a"]' '' -// @has - '//a[@href="#implementing-stuff-somewhere"]' 'Implementing stuff somewhere' -// @has - '//a[@href="#another-one-urg"]' 'Another one urg' +// @has - '//a[@href="http://a.a"]' 'stuff' +// @has - '//*[@id="implementing-stuff-somewhere"]' 'Implementing stuff somewhere' +// @has - '//a[@href="http://b.b"]' 'one' +// @has - '//*[@id="another-one-urg"]' 'Another one urg' /// fooo /// @@ -13,5 +16,5 @@ /// /// # Another [one][two] urg /// -/// [two]: http://a.a +/// [two]: http://b.b pub fn foo() {} diff --git a/tests/rustdoc/short-docblock.rs b/tests/rustdoc/short-docblock.rs index 791d3547c9fe..151a42a9c9ee 100644 --- a/tests/rustdoc/short-docblock.rs +++ b/tests/rustdoc/short-docblock.rs @@ -2,8 +2,9 @@ // @has foo/index.html '//*[@class="desc docblock-short"]' 'fooo' // @!has foo/index.html '//*[@class="desc docblock-short"]/h1' 'fooo' -// @has foo/fn.foo.html '//h2[@id="fooo"]/a[@href="#fooo"]' 'fooo' +// @has foo/fn.foo.html '//h2[@id="fooo"]' 'fooo' +// @has foo/fn.foo.html '//h2[@id="fooo"]/a[@href="#fooo"]' '§' /// # fooo /// /// foo @@ -11,8 +12,9 @@ pub fn foo() {} // @has foo/index.html '//*[@class="desc docblock-short"]' 'mooood' // @!has foo/index.html '//*[@class="desc docblock-short"]/h2' 'mooood' -// @has foo/foo/index.html '//h3[@id="mooood"]/a[@href="#mooood"]' 'mooood' +// @has foo/foo/index.html '//h3[@id="mooood"]' 'mooood' +// @has foo/foo/index.html '//h3[@id="mooood"]/a[@href="#mooood"]' '§' /// ## mooood /// /// foo mod diff --git a/tests/rustdoc/issue-53812.rs b/tests/rustdoc/sort-53812.rs similarity index 85% rename from tests/rustdoc/issue-53812.rs rename to tests/rustdoc/sort-53812.rs index dc1eb304c3d1..968ae0350433 100644 --- a/tests/rustdoc/issue-53812.rs +++ b/tests/rustdoc/sort-53812.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/53812 +#![crate_name="foo"] + pub trait MyIterator {} pub struct MyStruct(T); @@ -11,7 +14,7 @@ macro_rules! array_impls { } } -// @has issue_53812/trait.MyIterator.html +// @has foo/trait.MyIterator.html // @has - '//*[@id="implementors-list"]/*[@class="impl"][1]' 'MyStruct<[T; 0]>' // @has - '//*[@id="implementors-list"]/*[@class="impl"][2]' 'MyStruct<[T; 1]>' // @has - '//*[@id="implementors-list"]/*[@class="impl"][3]' 'MyStruct<[T; 2]>' diff --git a/tests/rustdoc/summary-header-46377.rs b/tests/rustdoc/summary-header-46377.rs new file mode 100644 index 000000000000..aec74f493d43 --- /dev/null +++ b/tests/rustdoc/summary-header-46377.rs @@ -0,0 +1,6 @@ +// https://github.com/rust-lang/rust/issues/46377 +#![crate_name="foo"] + +// @has 'foo/index.html' '//*[@class="desc docblock-short"]' 'Check out this struct!' +/// # Check out this struct! +pub struct SomeStruct; diff --git a/tests/ui-fulldeps/stable-mir/check_abi.rs b/tests/ui-fulldeps/stable-mir/check_abi.rs index 30b42bc3bfaf..7d7469597afc 100644 --- a/tests/ui-fulldeps/stable-mir/check_abi.rs +++ b/tests/ui-fulldeps/stable-mir/check_abi.rs @@ -12,14 +12,12 @@ #![feature(ascii_char, ascii_char_variants)] extern crate rustc_hir; -extern crate rustc_middle; #[macro_use] extern crate rustc_smir; extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; use stable_mir::abi::{ArgAbi, CallConvention, FieldsShape, PassMode, VariantsShape}; use stable_mir::mir::mono::Instance; @@ -32,7 +30,7 @@ use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; /// This function uses the Stable MIR APIs to get information about the test crate. -fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { +fn test_stable_mir() -> ControlFlow<()> { // Find items in the local crate. let items = stable_mir::all_local_items(); @@ -117,7 +115,7 @@ fn main() { CRATE_NAME.to_string(), path.to_string(), ]; - run!(args, tcx, test_stable_mir(tcx)).unwrap(); + run!(args, test_stable_mir).unwrap(); } fn generate_input(path: &str) -> std::io::Result<()> { diff --git a/tests/ui-fulldeps/stable-mir/check_allocation.rs b/tests/ui-fulldeps/stable-mir/check_allocation.rs index 7ce3597206b6..fb5e13eb13b1 100644 --- a/tests/ui-fulldeps/stable-mir/check_allocation.rs +++ b/tests/ui-fulldeps/stable-mir/check_allocation.rs @@ -14,14 +14,12 @@ #![feature(ascii_char, ascii_char_variants)] extern crate rustc_hir; -extern crate rustc_middle; #[macro_use] extern crate rustc_smir; extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; use stable_mir::crate_def::CrateDef; use stable_mir::mir::alloc::GlobalAlloc; @@ -40,7 +38,7 @@ use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; /// This function uses the Stable MIR APIs to get information about the test crate. -fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { +fn test_stable_mir() -> ControlFlow<()> { // Find items in the local crate. let items = stable_mir::all_local_items(); check_foo(*get_item(&items, (ItemKind::Static, "FOO")).unwrap()); @@ -111,7 +109,7 @@ fn check_other_consts(item: CrateItem) { // Instance body will force constant evaluation. let body = Instance::try_from(item).unwrap().body().unwrap(); let assigns = collect_consts(&body); - assert_eq!(assigns.len(), 9); + assert_eq!(assigns.len(), 8); for (name, alloc) in assigns { match name.as_str() { "_max_u128" => { @@ -230,7 +228,7 @@ fn main() { CRATE_NAME.to_string(), path.to_string(), ]; - run!(args, tcx, test_stable_mir(tcx)).unwrap(); + run!(args, test_stable_mir).unwrap(); } fn generate_input(path: &str) -> std::io::Result<()> { diff --git a/tests/ui-fulldeps/stable-mir/check_defs.rs b/tests/ui-fulldeps/stable-mir/check_defs.rs index e9a2599d8732..4a124adb2b60 100644 --- a/tests/ui-fulldeps/stable-mir/check_defs.rs +++ b/tests/ui-fulldeps/stable-mir/check_defs.rs @@ -11,7 +11,6 @@ #![feature(assert_matches)] #![feature(control_flow_enum)] -extern crate rustc_middle; #[macro_use] extern crate rustc_smir; extern crate rustc_driver; @@ -20,7 +19,6 @@ extern crate stable_mir; use std::assert_matches::assert_matches; use mir::{mono::Instance, TerminatorKind::*}; -use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; use stable_mir::ty::{RigidTy, TyKind, Ty, UintTy}; use stable_mir::*; @@ -30,7 +28,7 @@ use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; /// This function uses the Stable MIR APIs to get information about the test crate. -fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { +fn test_stable_mir() -> ControlFlow<()> { let entry = stable_mir::entry_fn().unwrap(); let main_fn = Instance::try_from(entry).unwrap(); assert_eq!(main_fn.name(), "main"); @@ -113,7 +111,7 @@ fn main() { CRATE_NAME.to_string(), path.to_string(), ]; - run!(args, tcx, test_stable_mir(tcx)).unwrap(); + run!(args, test_stable_mir).unwrap(); } fn generate_input(path: &str) -> std::io::Result<()> { diff --git a/tests/ui-fulldeps/stable-mir/check_instance.rs b/tests/ui-fulldeps/stable-mir/check_instance.rs index 5cb07eabf41d..1e039e5ae514 100644 --- a/tests/ui-fulldeps/stable-mir/check_instance.rs +++ b/tests/ui-fulldeps/stable-mir/check_instance.rs @@ -11,7 +11,6 @@ #![feature(assert_matches)] #![feature(control_flow_enum)] -extern crate rustc_middle; #[macro_use] extern crate rustc_smir; extern crate rustc_driver; @@ -19,7 +18,6 @@ extern crate rustc_interface; extern crate stable_mir; use mir::{mono::Instance, TerminatorKind::*}; -use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; use stable_mir::ty::{RigidTy, TyKind}; use stable_mir::*; @@ -29,7 +27,7 @@ use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; /// This function uses the Stable MIR APIs to get information about the test crate. -fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { +fn test_stable_mir() -> ControlFlow<()> { let items = stable_mir::all_local_items(); // Get all items and split generic vs monomorphic items. @@ -96,7 +94,7 @@ fn main() { CRATE_NAME.to_string(), path.to_string(), ]; - run!(args, tcx, test_stable_mir(tcx)).unwrap(); + run!(args, test_stable_mir).unwrap(); } fn generate_input(path: &str) -> std::io::Result<()> { diff --git a/tests/ui-fulldeps/stable-mir/check_item_kind.rs b/tests/ui-fulldeps/stable-mir/check_item_kind.rs index 72e0e09e6e36..0a7f00029f2a 100644 --- a/tests/ui-fulldeps/stable-mir/check_item_kind.rs +++ b/tests/ui-fulldeps/stable-mir/check_item_kind.rs @@ -11,14 +11,12 @@ #![feature(assert_matches)] #![feature(control_flow_enum)] -extern crate rustc_middle; #[macro_use] extern crate rustc_smir; extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; use stable_mir::*; use std::io::Write; @@ -27,7 +25,7 @@ use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; /// This function uses the Stable MIR APIs to get information about the test crate. -fn test_item_kind(_tcx: TyCtxt<'_>) -> ControlFlow<()> { +fn test_item_kind() -> ControlFlow<()> { let items = stable_mir::all_local_items(); assert_eq!(items.len(), 4); // Constructor item. @@ -59,7 +57,7 @@ fn main() { CRATE_NAME.to_string(), path.to_string(), ]; - run!(args, tcx, test_item_kind(tcx)).unwrap(); + run!(args, test_item_kind).unwrap(); } fn generate_input(path: &str) -> std::io::Result<()> { diff --git a/tests/ui-fulldeps/stable-mir/check_trait_queries.rs b/tests/ui-fulldeps/stable-mir/check_trait_queries.rs index fb1197e4ecc4..c9fbe15ffb03 100644 --- a/tests/ui-fulldeps/stable-mir/check_trait_queries.rs +++ b/tests/ui-fulldeps/stable-mir/check_trait_queries.rs @@ -11,14 +11,12 @@ #![feature(assert_matches)] #![feature(control_flow_enum)] -extern crate rustc_middle; #[macro_use] extern crate rustc_smir; extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; use stable_mir::CrateDef; use std::collections::HashSet; @@ -83,7 +81,7 @@ fn main() { CRATE_NAME.to_string(), path.to_string(), ]; - run!(args, test_traits()).unwrap(); + run!(args, test_traits).unwrap(); } fn generate_input(path: &str) -> std::io::Result<()> { diff --git a/tests/ui-fulldeps/stable-mir/check_ty_fold.rs b/tests/ui-fulldeps/stable-mir/check_ty_fold.rs index b90d47d4540b..14cbf9e9f81f 100644 --- a/tests/ui-fulldeps/stable-mir/check_ty_fold.rs +++ b/tests/ui-fulldeps/stable-mir/check_ty_fold.rs @@ -12,14 +12,12 @@ #![feature(assert_matches)] #![feature(control_flow_enum)] -extern crate rustc_middle; #[macro_use] extern crate rustc_smir; extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; use stable_mir::ty::{RigidTy, TyKind, Ty, }; use stable_mir::mir::{Body, MirVisitor, FieldIdx, Place, ProjectionElem, visit::{Location, @@ -30,7 +28,7 @@ use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; /// This function uses the Stable MIR APIs to get information about the test crate. -fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { +fn test_stable_mir() -> ControlFlow<()> { let main_fn = stable_mir::entry_fn(); let body = main_fn.unwrap().body(); let mut visitor = PlaceVisitor{ body: &body, tested: false}; @@ -87,7 +85,7 @@ fn main() { CRATE_NAME.to_string(), path.to_string(), ]; - run!(args, tcx, test_stable_mir(tcx)).unwrap(); + run!(args, test_stable_mir).unwrap(); } fn generate_input(path: &str) -> std::io::Result<()> { diff --git a/tests/ui-fulldeps/stable-mir/compilation-result.rs b/tests/ui-fulldeps/stable-mir/compilation-result.rs index fc56e24814b0..e6dd9fa132d8 100644 --- a/tests/ui-fulldeps/stable-mir/compilation-result.rs +++ b/tests/ui-fulldeps/stable-mir/compilation-result.rs @@ -10,14 +10,12 @@ #![feature(rustc_private)] #![feature(assert_matches)] -extern crate rustc_middle; #[macro_use] extern crate rustc_smir; extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; use std::io::Write; @@ -32,33 +30,41 @@ fn main() { test_continue(args.clone()); test_break(args.clone()); test_failed(args.clone()); - test_skipped(args); + test_skipped(args.clone()); + test_captured(args) } fn test_continue(args: Vec) { - let result = run!(args, ControlFlow::Continue::<(), bool>(true)); + let result = run!(args, || ControlFlow::Continue::<(), bool>(true)); assert_eq!(result, Ok(true)); } fn test_break(args: Vec) { - let result = run!(args, ControlFlow::Break::(false)); + let result = run!(args, || ControlFlow::Break::(false)); assert_eq!(result, Err(stable_mir::CompilerError::Interrupted(false))); } #[allow(unreachable_code)] fn test_skipped(mut args: Vec) { args.push("--version".to_string()); - let result = run!(args, unreachable!() as ControlFlow<()>); + let result = run!(args, || unreachable!() as ControlFlow<()>); assert_eq!(result, Err(stable_mir::CompilerError::Skipped)); } #[allow(unreachable_code)] fn test_failed(mut args: Vec) { args.push("--cfg=broken".to_string()); - let result = run!(args, unreachable!() as ControlFlow<()>); + let result = run!(args, || unreachable!() as ControlFlow<()>); assert_eq!(result, Err(stable_mir::CompilerError::CompilationFailed)); } +/// Test that we are able to pass a closure and set the return according to the captured value. +fn test_captured(args: Vec) { + let captured = "10".to_string(); + let result = run!(args, || ControlFlow::Continue::<(), usize>(captured.len())); + assert_eq!(result, Ok(captured.len())); +} + fn generate_input(path: &str) -> std::io::Result<()> { let mut file = std::fs::File::create(path)?; write!( diff --git a/tests/ui-fulldeps/stable-mir/crate-info.rs b/tests/ui-fulldeps/stable-mir/crate-info.rs index c2035430a33b..8258883436f2 100644 --- a/tests/ui-fulldeps/stable-mir/crate-info.rs +++ b/tests/ui-fulldeps/stable-mir/crate-info.rs @@ -12,7 +12,6 @@ #![feature(control_flow_enum)] extern crate rustc_hir; -extern crate rustc_middle; #[macro_use] extern crate rustc_smir; extern crate rustc_driver; @@ -20,7 +19,6 @@ extern crate rustc_interface; extern crate stable_mir; use rustc_hir::def::DefKind; -use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; use stable_mir::ItemKind; use stable_mir::crate_def::CrateDef; @@ -33,7 +31,7 @@ use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; /// This function uses the Stable MIR APIs to get information about the test crate. -fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { +fn test_stable_mir() -> ControlFlow<()> { // Get the local crate using stable_mir API. let local = stable_mir::local_crate(); assert_eq!(&local.name, CRATE_NAME); @@ -194,7 +192,7 @@ fn main() { CRATE_NAME.to_string(), path.to_string(), ]; - run!(args, tcx, test_stable_mir(tcx)).unwrap(); + run!(args, test_stable_mir).unwrap(); } fn generate_input(path: &str) -> std::io::Result<()> { diff --git a/tests/ui-fulldeps/stable-mir/projections.rs b/tests/ui-fulldeps/stable-mir/projections.rs index 8c3fda7b6bb1..40f2d901a2b2 100644 --- a/tests/ui-fulldeps/stable-mir/projections.rs +++ b/tests/ui-fulldeps/stable-mir/projections.rs @@ -12,14 +12,12 @@ #![feature(control_flow_enum)] extern crate rustc_hir; -extern crate rustc_middle; #[macro_use] extern crate rustc_smir; extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; use stable_mir::crate_def::CrateDef; use stable_mir::mir::{ProjectionElem, Rvalue, StatementKind}; @@ -32,7 +30,7 @@ use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; /// Tests projections within Place objects -fn test_place_projections(_tcx: TyCtxt<'_>) -> ControlFlow<()> { +fn test_place_projections() -> ControlFlow<()> { let items = stable_mir::all_local_items(); let body = get_item(&items, (ItemKind::Fn, "projections")).unwrap().body(); assert_eq!(body.blocks.len(), 4); @@ -159,7 +157,7 @@ fn main() { CRATE_NAME.to_string(), path.to_string(), ]; - run!(args, tcx, test_place_projections(tcx)).unwrap(); + run!(args, test_place_projections).unwrap(); } fn generate_input(path: &str) -> std::io::Result<()> { diff --git a/tests/ui-fulldeps/stable-mir/smir_internal.rs b/tests/ui-fulldeps/stable-mir/smir_internal.rs index b0596b188238..b4faaeb4fc06 100644 --- a/tests/ui-fulldeps/stable-mir/smir_internal.rs +++ b/tests/ui-fulldeps/stable-mir/smir_internal.rs @@ -26,7 +26,7 @@ use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; -fn test_translation(_tcx: TyCtxt<'_>) -> ControlFlow<()> { +fn test_translation(_tcx: TyCtxt) -> ControlFlow<()> { let main_fn = stable_mir::entry_fn().unwrap(); let body = main_fn.body(); let orig_ty = body.locals()[0].ty; @@ -48,7 +48,7 @@ fn main() { CRATE_NAME.to_string(), path.to_string(), ]; - run!(args, tcx, test_translation(tcx)).unwrap(); + run_with_tcx!(args, test_translation).unwrap(); } fn generate_input(path: &str) -> std::io::Result<()> { diff --git a/tests/ui-fulldeps/stable-mir/smir_visitor.rs b/tests/ui-fulldeps/stable-mir/smir_visitor.rs index 027b0e7d9e85..d7739770b706 100644 --- a/tests/ui-fulldeps/stable-mir/smir_visitor.rs +++ b/tests/ui-fulldeps/stable-mir/smir_visitor.rs @@ -11,7 +11,6 @@ #![feature(assert_matches)] #![feature(control_flow_enum)] -extern crate rustc_middle; #[macro_use] extern crate rustc_smir; extern crate rustc_driver; @@ -19,7 +18,6 @@ extern crate rustc_interface; extern crate stable_mir; use std::collections::HashSet; -use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; use stable_mir::*; use stable_mir::mir::MirVisitor; @@ -28,7 +26,7 @@ use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; -fn test_visitor(_tcx: TyCtxt<'_>) -> ControlFlow<()> { +fn test_visitor() -> ControlFlow<()> { let main_fn = stable_mir::entry_fn(); let main_body = main_fn.unwrap().body(); let main_visitor = TestVisitor::collect(&main_body); @@ -116,7 +114,7 @@ fn main() { CRATE_NAME.to_string(), path.to_string(), ]; - run!(args, tcx, test_visitor(tcx)).unwrap(); + run!(args, test_visitor).unwrap(); } fn generate_input(path: &str) -> std::io::Result<()> { diff --git a/tests/ui/asm/inline-syntax.arm.stderr b/tests/ui/asm/inline-syntax.arm.stderr index 1352fb3771be..6bc38811f1b5 100644 --- a/tests/ui/asm/inline-syntax.arm.stderr +++ b/tests/ui/asm/inline-syntax.arm.stderr @@ -13,7 +13,7 @@ LL | .intel_syntax noprefix | ^ error: unknown directive - --> $DIR/inline-syntax.rs:32:15 + --> $DIR/inline-syntax.rs:38:15 | LL | asm!(".intel_syntax noprefix", "nop"); | ^ @@ -25,7 +25,7 @@ LL | .intel_syntax noprefix | ^ error: unknown directive - --> $DIR/inline-syntax.rs:35:15 + --> $DIR/inline-syntax.rs:42:15 | LL | asm!(".intel_syntax aaa noprefix", "nop"); | ^ @@ -37,7 +37,7 @@ LL | .intel_syntax aaa noprefix | ^ error: unknown directive - --> $DIR/inline-syntax.rs:38:15 + --> $DIR/inline-syntax.rs:46:15 | LL | asm!(".att_syntax noprefix", "nop"); | ^ @@ -49,7 +49,7 @@ LL | .att_syntax noprefix | ^ error: unknown directive - --> $DIR/inline-syntax.rs:41:15 + --> $DIR/inline-syntax.rs:50:15 | LL | asm!(".att_syntax bbb noprefix", "nop"); | ^ @@ -61,7 +61,7 @@ LL | .att_syntax bbb noprefix | ^ error: unknown directive - --> $DIR/inline-syntax.rs:44:15 + --> $DIR/inline-syntax.rs:54:15 | LL | asm!(".intel_syntax noprefix; nop"); | ^ @@ -73,7 +73,7 @@ LL | .intel_syntax noprefix; nop | ^ error: unknown directive - --> $DIR/inline-syntax.rs:50:13 + --> $DIR/inline-syntax.rs:61:13 | LL | .intel_syntax noprefix | ^ diff --git a/tests/ui/asm/inline-syntax.arm_llvm_18.stderr b/tests/ui/asm/inline-syntax.arm_llvm_18.stderr new file mode 100644 index 000000000000..4926293bb88a --- /dev/null +++ b/tests/ui/asm/inline-syntax.arm_llvm_18.stderr @@ -0,0 +1,90 @@ +error: unknown directive + | +note: instantiated into assembly here + --> :1:1 + | +LL | .intel_syntax noprefix + | ^ + +error: unknown directive + | +note: instantiated into assembly here + --> :1:1 + | +LL | .intel_syntax noprefix + | ^ + +error: unknown directive + --> $DIR/inline-syntax.rs:38:15 + | +LL | asm!(".intel_syntax noprefix", "nop"); + | ^ + | +note: instantiated into assembly here + --> :1:2 + | +LL | .intel_syntax noprefix + | ^ + +error: unknown directive + --> $DIR/inline-syntax.rs:42:15 + | +LL | asm!(".intel_syntax aaa noprefix", "nop"); + | ^ + | +note: instantiated into assembly here + --> :1:2 + | +LL | .intel_syntax aaa noprefix + | ^ + +error: unknown directive + --> $DIR/inline-syntax.rs:46:15 + | +LL | asm!(".att_syntax noprefix", "nop"); + | ^ + | +note: instantiated into assembly here + --> :1:2 + | +LL | .att_syntax noprefix + | ^ + +error: unknown directive + --> $DIR/inline-syntax.rs:50:15 + | +LL | asm!(".att_syntax bbb noprefix", "nop"); + | ^ + | +note: instantiated into assembly here + --> :1:2 + | +LL | .att_syntax bbb noprefix + | ^ + +error: unknown directive + --> $DIR/inline-syntax.rs:54:15 + | +LL | asm!(".intel_syntax noprefix; nop"); + | ^ + | +note: instantiated into assembly here + --> :1:2 + | +LL | .intel_syntax noprefix; nop + | ^ + +error: unknown directive + --> $DIR/inline-syntax.rs:61:13 + | +LL | .intel_syntax noprefix + | ^ + | +note: instantiated into assembly here + --> :2:13 + | +LL | .intel_syntax noprefix + | ^ + +error: aborting due to 8 previous errors + diff --git a/tests/ui/asm/inline-syntax.rs b/tests/ui/asm/inline-syntax.rs index d06796e33d51..9398a87df627 100644 --- a/tests/ui/asm/inline-syntax.rs +++ b/tests/ui/asm/inline-syntax.rs @@ -1,4 +1,4 @@ -// revisions: x86_64 arm +// revisions: x86_64 arm arm_llvm_18 //[x86_64] compile-flags: --target x86_64-unknown-linux-gnu //[x86_64] check-pass //[x86_64] needs-llvm-components: x86 @@ -8,6 +8,12 @@ //[arm] compile-flags: --target armv7-unknown-linux-gnueabihf //[arm] build-fail //[arm] needs-llvm-components: arm +//[arm] ignore-llvm-version: 18 - 99 +// Newer LLVM produces extra error notes. +//[arm_llvm_18] compile-flags: --target armv7-unknown-linux-gnueabihf +//[arm_llvm_18] build-fail +//[arm_llvm_18] needs-llvm-components: arm +//[arm_llvm_18] min-llvm-version: 18 // needs-asm-support #![feature(no_core, lang_items, rustc_attrs)] @@ -32,18 +38,23 @@ pub fn main() { asm!(".intel_syntax noprefix", "nop"); //[x86_64]~^ WARN avoid using `.intel_syntax` //[arm]~^^ ERROR unknown directive + //[arm_llvm_18]~^^^ ERROR unknown directive asm!(".intel_syntax aaa noprefix", "nop"); //[x86_64]~^ WARN avoid using `.intel_syntax` //[arm]~^^ ERROR unknown directive + //[arm_llvm_18]~^^^ ERROR unknown directive asm!(".att_syntax noprefix", "nop"); //[x86_64]~^ WARN avoid using `.att_syntax` //[arm]~^^ ERROR unknown directive + //[arm_llvm_18]~^^^ ERROR unknown directive asm!(".att_syntax bbb noprefix", "nop"); //[x86_64]~^ WARN avoid using `.att_syntax` //[arm]~^^ ERROR unknown directive + //[arm_llvm_18]~^^^ ERROR unknown directive asm!(".intel_syntax noprefix; nop"); //[x86_64]~^ WARN avoid using `.intel_syntax` //[arm]~^^ ERROR unknown directive + //[arm_llvm_18]~^^^ ERROR unknown directive asm!( r" @@ -52,6 +63,7 @@ pub fn main() { ); //[x86_64]~^^^ WARN avoid using `.intel_syntax` //[arm]~^^^^ ERROR unknown directive + //[arm_llvm_18]~^^^^^ ERROR unknown directive } } diff --git a/tests/ui/asm/inline-syntax.x86_64.stderr b/tests/ui/asm/inline-syntax.x86_64.stderr index 840b250f87d7..b54b3560447c 100644 --- a/tests/ui/asm/inline-syntax.x86_64.stderr +++ b/tests/ui/asm/inline-syntax.x86_64.stderr @@ -1,5 +1,5 @@ warning: avoid using `.intel_syntax`, Intel syntax is the default - --> $DIR/inline-syntax.rs:58:14 + --> $DIR/inline-syntax.rs:70:14 | LL | global_asm!(".intel_syntax noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -7,37 +7,37 @@ LL | global_asm!(".intel_syntax noprefix", "nop"); = note: `#[warn(bad_asm_style)]` on by default warning: avoid using `.intel_syntax`, Intel syntax is the default - --> $DIR/inline-syntax.rs:32:15 + --> $DIR/inline-syntax.rs:38:15 | LL | asm!(".intel_syntax noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^^^ warning: avoid using `.intel_syntax`, Intel syntax is the default - --> $DIR/inline-syntax.rs:35:15 + --> $DIR/inline-syntax.rs:42:15 | LL | asm!(".intel_syntax aaa noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead - --> $DIR/inline-syntax.rs:38:15 + --> $DIR/inline-syntax.rs:46:15 | LL | asm!(".att_syntax noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^ warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead - --> $DIR/inline-syntax.rs:41:15 + --> $DIR/inline-syntax.rs:50:15 | LL | asm!(".att_syntax bbb noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: avoid using `.intel_syntax`, Intel syntax is the default - --> $DIR/inline-syntax.rs:44:15 + --> $DIR/inline-syntax.rs:54:15 | LL | asm!(".intel_syntax noprefix; nop"); | ^^^^^^^^^^^^^^^^^^^^^^ warning: avoid using `.intel_syntax`, Intel syntax is the default - --> $DIR/inline-syntax.rs:50:13 + --> $DIR/inline-syntax.rs:61:13 | LL | .intel_syntax noprefix | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr index 21062fdaf585..88b17be601ce 100644 --- a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr +++ b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr @@ -9,11 +9,6 @@ note: ...which requires simplifying constant for the type system `IMPL_REF_BAR`. | LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR; | ^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires simplifying constant for the type system `IMPL_REF_BAR`... - --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1 - | -LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires const-evaluating + checking `IMPL_REF_BAR`... --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:27 | diff --git a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr index e4abf6203e8f..fd1b4f2f964b 100644 --- a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr +++ b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr @@ -9,11 +9,6 @@ note: ...which requires simplifying constant for the type system `DEFAULT_REF_BA | LL | const DEFAULT_REF_BAR: u32 = ::BAR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires simplifying constant for the type system `DEFAULT_REF_BAR`... - --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:1 - | -LL | const DEFAULT_REF_BAR: u32 = ::BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires const-evaluating + checking `DEFAULT_REF_BAR`... --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:30 | diff --git a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr index 05ebd76f5001..303400f928e6 100644 --- a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr +++ b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr @@ -9,11 +9,6 @@ note: ...which requires simplifying constant for the type system `TRAIT_REF_BAR` | LL | const TRAIT_REF_BAR: u32 = ::BAR; | ^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires simplifying constant for the type system `TRAIT_REF_BAR`... - --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1 - | -LL | const TRAIT_REF_BAR: u32 = ::BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires const-evaluating + checking `TRAIT_REF_BAR`... --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:28 | diff --git a/tests/ui/async-await/async-borrowck-escaping-closure-error.rs b/tests/ui/async-await/async-borrowck-escaping-closure-error.rs index e667b72aee53..f8ff9186842b 100644 --- a/tests/ui/async-await/async-borrowck-escaping-closure-error.rs +++ b/tests/ui/async-await/async-borrowck-escaping-closure-error.rs @@ -1,9 +1,10 @@ // edition:2018 +// check-pass + #![feature(async_closure)] fn foo() -> Box> { let x = 0u32; Box::new((async || x)()) - //~^ ERROR E0373 } fn main() { diff --git a/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr b/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr deleted file mode 100644 index 1d8d1c67bae1..000000000000 --- a/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function - --> $DIR/async-borrowck-escaping-closure-error.rs:5:15 - | -LL | Box::new((async || x)()) - | ^^^^^^^^ - `x` is borrowed here - | | - | may outlive borrowed value `x` - | -note: closure is returned here - --> $DIR/async-borrowck-escaping-closure-error.rs:5:5 - | -LL | Box::new((async || x)()) - | ^^^^^^^^^^^^^^^^^^^^^^^^ -help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword - | -LL | Box::new((async move || x)()) - | ++++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0373`. diff --git a/tests/ui/async-await/for-await-passthrough.rs b/tests/ui/async-await/for-await-passthrough.rs index 7fa133aaedcd..b1a382958a15 100644 --- a/tests/ui/async-await/for-await-passthrough.rs +++ b/tests/ui/async-await/for-await-passthrough.rs @@ -25,8 +25,7 @@ async fn real_main() { fn main() { let future = real_main(); - let waker = std::task::Waker::noop(); - let mut cx = &mut core::task::Context::from_waker(&waker); + let mut cx = &mut core::task::Context::from_waker(std::task::Waker::noop()); let mut future = core::pin::pin!(future); while let core::task::Poll::Pending = future.as_mut().poll(&mut cx) {} } diff --git a/tests/ui/async-await/for-await.rs b/tests/ui/async-await/for-await.rs index 6345ceb0c279..00dbdfb2389d 100644 --- a/tests/ui/async-await/for-await.rs +++ b/tests/ui/async-await/for-await.rs @@ -17,8 +17,7 @@ async fn real_main() { fn main() { let future = real_main(); - let waker = std::task::Waker::noop(); - let mut cx = &mut core::task::Context::from_waker(&waker); + let mut cx = &mut core::task::Context::from_waker(std::task::Waker::noop()); let mut future = core::pin::pin!(future); while let core::task::Poll::Pending = future.as_mut().poll(&mut cx) {} } diff --git a/tests/ui/async-await/in-trait/async-default-fn-overridden.rs b/tests/ui/async-await/in-trait/async-default-fn-overridden.rs index 491dfcc6ae0f..8c01f1bddefd 100644 --- a/tests/ui/async-await/in-trait/async-default-fn-overridden.rs +++ b/tests/ui/async-await/in-trait/async-default-fn-overridden.rs @@ -40,8 +40,7 @@ fn main() { let mut fut = pin!(async_main()); // Poll loop, just to test the future... - let waker = Waker::noop(); - let ctx = &mut Context::from_waker(&waker); + let ctx = &mut Context::from_waker(Waker::noop()); loop { match fut.as_mut().poll(ctx) { diff --git a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs index f21abf012ba9..e2fd9f9dfea4 100644 --- a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs +++ b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs @@ -43,8 +43,7 @@ fn main() { let mut fut = pin!(async_main()); // Poll loop, just to test the future... - let waker = Waker::noop(); - let ctx = &mut Context::from_waker(&waker); + let ctx = &mut Context::from_waker(Waker::noop()); loop { match fut.as_mut().poll(ctx) { diff --git a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr index 0560cd9c5fe1..b7336485eb84 100644 --- a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr +++ b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr @@ -21,7 +21,7 @@ LL | default async fn foo(_: T) -> &'static str { = note: specialization behaves in inconsistent and surprising ways with async functions in traits, and for now is disallowed error[E0599]: no method named `poll` found for struct `Pin<&mut impl Future>` in the current scope - --> $DIR/dont-project-to-specializable-projection.rs:50:28 + --> $DIR/dont-project-to-specializable-projection.rs:49:28 | LL | match fut.as_mut().poll(ctx) { | ^^^^ method not found in `Pin<&mut impl Future>` diff --git a/tests/ui/async-await/inference_var_self_argument.rs b/tests/ui/async-await/inference_var_self_argument.rs new file mode 100644 index 000000000000..fd8482f86b4f --- /dev/null +++ b/tests/ui/async-await/inference_var_self_argument.rs @@ -0,0 +1,12 @@ +//! This is a regression test for an ICE. +// edition: 2021 + +trait Foo { + async fn foo(self: &dyn Foo) { + //~^ ERROR: `Foo` cannot be made into an object + //~| ERROR invalid `self` parameter type: &dyn Foo + todo!() + } +} + +fn main() {} diff --git a/tests/ui/async-await/inference_var_self_argument.stderr b/tests/ui/async-await/inference_var_self_argument.stderr new file mode 100644 index 000000000000..8a8c1ea03f14 --- /dev/null +++ b/tests/ui/async-await/inference_var_self_argument.stderr @@ -0,0 +1,28 @@ +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/inference_var_self_argument.rs:5:5 + | +LL | async fn foo(self: &dyn Foo) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/inference_var_self_argument.rs:5:14 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | async fn foo(self: &dyn Foo) { + | ^^^ ...because method `foo` is `async` + = help: consider moving `foo` to another trait + +error[E0307]: invalid `self` parameter type: &dyn Foo + --> $DIR/inference_var_self_argument.rs:5:24 + | +LL | async fn foo(self: &dyn Foo) { + | ^^^^^^^^ + | + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0038, E0307. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/async-await/issues/issue-65159.rs b/tests/ui/async-await/issues/issue-65159.rs index aed111e21442..7197a4fb91a0 100644 --- a/tests/ui/async-await/issues/issue-65159.rs +++ b/tests/ui/async-await/issues/issue-65159.rs @@ -5,7 +5,7 @@ async fn copy() -> Result<()> //~^ ERROR enum takes 2 generic arguments { - Ok(()) //~ ERROR: type annotations needed + Ok(()) } -fn main() { } +fn main() {} diff --git a/tests/ui/async-await/issues/issue-65159.stderr b/tests/ui/async-await/issues/issue-65159.stderr index 77a0ea5027c1..19512116a66c 100644 --- a/tests/ui/async-await/issues/issue-65159.stderr +++ b/tests/ui/async-await/issues/issue-65159.stderr @@ -11,18 +11,6 @@ help: add missing generic argument LL | async fn copy() -> Result<(), E> | +++ -error[E0282]: type annotations needed - --> $DIR/issue-65159.rs:8:5 - | -LL | Ok(()) - | ^^ cannot infer type of the type parameter `E` declared on the enum `Result` - | -help: consider specifying the generic arguments - | -LL | Ok::<(), E>(()) - | +++++++++ +error: aborting due to 1 previous error -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0107, E0282. -For more information about an error, try `rustc --explain E0107`. +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/async-await/no-params-non-move-async-closure.rs b/tests/ui/async-await/no-params-non-move-async-closure.rs index 3b15f35c260d..1440d918c50e 100644 --- a/tests/ui/async-await/no-params-non-move-async-closure.rs +++ b/tests/ui/async-await/no-params-non-move-async-closure.rs @@ -1,8 +1,8 @@ // edition:2018 +// check-pass #![feature(async_closure)] fn main() { let _ = async |x: u8| {}; - //~^ ERROR `async` non-`move` closures with parameters are not currently supported } diff --git a/tests/ui/async-await/no-params-non-move-async-closure.stderr b/tests/ui/async-await/no-params-non-move-async-closure.stderr deleted file mode 100644 index d26595536990..000000000000 --- a/tests/ui/async-await/no-params-non-move-async-closure.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0708]: `async` non-`move` closures with parameters are not currently supported - --> $DIR/no-params-non-move-async-closure.rs:6:13 - | -LL | let _ = async |x: u8| {}; - | ^^^^^^^^^^^^^ - | - = help: consider using `let` statements to manually capture variables by reference before entering an `async move` closure - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0708`. diff --git a/tests/ui/binop/binary-op-suggest-deref.rs b/tests/ui/binop/binary-op-suggest-deref.rs index 57f24a4c28ed..ae442a0d0b48 100644 --- a/tests/ui/binop/binary-op-suggest-deref.rs +++ b/tests/ui/binop/binary-op-suggest-deref.rs @@ -72,4 +72,12 @@ fn baz() { //~^ERROR can't compare `str` with `&String` [E0277] } +fn qux() { + // Issue #119352 + const FOO: i32 = 42; + let _ = FOO & (*"Sized".to_string().into_boxed_str()); + //~^ ERROR the size for values of type `str` cannot be known at compilation time + //~| ERROR no implementation for `i32 & str` [E0277] +} + fn main() {} diff --git a/tests/ui/binop/binary-op-suggest-deref.stderr b/tests/ui/binop/binary-op-suggest-deref.stderr index 68b5a24bf974..a98a2ab07066 100644 --- a/tests/ui/binop/binary-op-suggest-deref.stderr +++ b/tests/ui/binop/binary-op-suggest-deref.stderr @@ -295,7 +295,28 @@ help: consider dereferencing here LL | _ = partial[..3] == *string_ref; | + -error: aborting due to 22 previous errors +error[E0277]: no implementation for `i32 & str` + --> $DIR/binary-op-suggest-deref.rs:78:17 + | +LL | let _ = FOO & (*"Sized".to_string().into_boxed_str()); + | ^ no implementation for `i32 & str` + | + = help: the trait `BitAnd` is not implemented for `i32` + = help: the following other types implement trait `BitAnd`: + + > + <&'a i32 as BitAnd> + <&i32 as BitAnd<&i32>> + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/binary-op-suggest-deref.rs:78:17 + | +LL | let _ = FOO & (*"Sized".to_string().into_boxed_str()); + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + +error: aborting due to 24 previous errors Some errors have detailed explanations: E0277, E0308, E0369. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/borrowck/fn-item-check-trait-ref.rs b/tests/ui/borrowck/fn-item-check-trait-ref.rs new file mode 100644 index 000000000000..bdbb52e974f6 --- /dev/null +++ b/tests/ui/borrowck/fn-item-check-trait-ref.rs @@ -0,0 +1,15 @@ +// The method `assert_static` should be callable only for static values, +// because the impl has an implied bound `where T: 'static`. + +// check-fail + +trait AnyStatic: Sized { + fn assert_static(self) {} +} + +impl AnyStatic<&'static T> for T {} + +fn main() { + (&String::new()).assert_static(); + //~^ ERROR temporary value dropped while borrowed +} diff --git a/tests/ui/borrowck/fn-item-check-trait-ref.stderr b/tests/ui/borrowck/fn-item-check-trait-ref.stderr new file mode 100644 index 000000000000..92fd67c316c9 --- /dev/null +++ b/tests/ui/borrowck/fn-item-check-trait-ref.stderr @@ -0,0 +1,12 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/fn-item-check-trait-ref.rs:13:7 + | +LL | (&String::new()).assert_static(); + | --^^^^^^^^^^^^^------------------ temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | argument requires that borrow lasts for `'static` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/borrowck/fn-item-check-type-params.rs b/tests/ui/borrowck/fn-item-check-type-params.rs new file mode 100644 index 000000000000..805c0d00de5d --- /dev/null +++ b/tests/ui/borrowck/fn-item-check-type-params.rs @@ -0,0 +1,57 @@ +// Regression test for #104005. +// +// Previously, different borrowck implementations used to disagree here. +// The status of each is documented on `fn test_*`. + +// check-fail + +use std::fmt::Display; + +trait Displayable { + fn display(self) -> Box; +} + +impl Displayable for (T, Option<&'static T>) { + fn display(self) -> Box { + Box::new(self.0) + } +} + +fn extend_lt(val: T) -> Box +where + (T, Option): Displayable, +{ + Displayable::display((val, None)) +} + +// AST: fail +// HIR: pass +// MIR: pass +pub fn test_call<'a>(val: &'a str) { + extend_lt(val); + //~^ ERROR borrowed data escapes outside of function +} + +// AST: fail +// HIR: fail +// MIR: pass +pub fn test_coercion<'a>() { + let _: fn(&'a str) -> _ = extend_lt; + //~^ ERROR lifetime may not live long enough +} + +// AST: fail +// HIR: fail +// MIR: fail +pub fn test_arg() { + fn want(_: I, _: impl Fn(I) -> O) {} + want(&String::new(), extend_lt); + //~^ ERROR temporary value dropped while borrowed +} + +// An exploit of the unsoundness. +fn main() { + let val = extend_lt(&String::from("blah blah blah")); + //~^ ERROR temporary value dropped while borrowed + println!("{}", val); +} diff --git a/tests/ui/borrowck/fn-item-check-type-params.stderr b/tests/ui/borrowck/fn-item-check-type-params.stderr new file mode 100644 index 000000000000..3a29edc55c54 --- /dev/null +++ b/tests/ui/borrowck/fn-item-check-type-params.stderr @@ -0,0 +1,43 @@ +error[E0521]: borrowed data escapes outside of function + --> $DIR/fn-item-check-type-params.rs:31:5 + | +LL | pub fn test_call<'a>(val: &'a str) { + | -- --- `val` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | extend_lt(val); + | ^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/fn-item-check-type-params.rs:39:12 + | +LL | pub fn test_coercion<'a>() { + | -- lifetime `'a` defined here +LL | let _: fn(&'a str) -> _ = extend_lt; + | ^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/fn-item-check-type-params.rs:48:11 + | +LL | want(&String::new(), extend_lt); + | ------^^^^^^^^^^^^^------------- temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | argument requires that borrow lasts for `'static` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/fn-item-check-type-params.rs:54:26 + | +LL | let val = extend_lt(&String::from("blah blah blah")); + | -----------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-- temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | argument requires that borrow lasts for `'static` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0521, E0716. +For more information about an error, try `rustc --explain E0521`. diff --git a/tests/ui/borrowck/issue-119915-bad-clone-suggestion.rs b/tests/ui/borrowck/issue-119915-bad-clone-suggestion.rs new file mode 100644 index 000000000000..0b0ac9448dbd --- /dev/null +++ b/tests/ui/borrowck/issue-119915-bad-clone-suggestion.rs @@ -0,0 +1,28 @@ +use std::marker::PhantomData; + +struct Example(PhantomData<(fn(E), fn(FakeParam))>); + +struct NoLifetime; +struct Immutable<'a>(PhantomData<&'a ()>); + +impl<'a, E: 'a> Copy for Example> {} +impl<'a, E: 'a> Clone for Example> { + fn clone(&self) -> Self { + *self + } +} + +impl Example { + unsafe fn change(self) -> Example { + Example(PhantomData) + } +} + +impl Example { + fn the_ice(&mut self) -> Example> { + unsafe { self.change() } + //~^ ERROR cannot move out of `*self` which is behind a mutable reference + } +} + +fn main() {} diff --git a/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr b/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr new file mode 100644 index 000000000000..ab42205d510f --- /dev/null +++ b/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr @@ -0,0 +1,17 @@ +error[E0507]: cannot move out of `*self` which is behind a mutable reference + --> $DIR/issue-119915-bad-clone-suggestion.rs:23:18 + | +LL | unsafe { self.change() } + | ^^^^ -------- `*self` moved due to this method call + | | + | move occurs because `*self` has type `Example`, which does not implement the `Copy` trait + | +note: `Example::::change` takes ownership of the receiver `self`, which moves `*self` + --> $DIR/issue-119915-bad-clone-suggestion.rs:16:36 + | +LL | unsafe fn change(self) -> Example { + | ^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs b/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs index c10246eec649..b52939ffc119 100644 --- a/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs +++ b/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs @@ -17,7 +17,6 @@ async fn buy_lock(coroutine: &Mutex) -> LockedMarket<'_> { //~^ ERROR struct takes 0 lifetime arguments but 1 lifetime argument was supplied //~^^ ERROR struct takes 1 generic argument but 0 generic arguments were supplied LockedMarket(coroutine.lock().unwrap().buy()) - //~^ ERROR: cannot return value referencing temporary value } struct LockedMarket(T); diff --git a/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr b/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr index 2b10cf67d15b..516c1d065e67 100644 --- a/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr +++ b/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr @@ -7,7 +7,7 @@ LL | async fn buy_lock(coroutine: &Mutex) -> LockedMarket<'_> | expected 0 lifetime arguments | note: struct defined here, with 0 lifetime parameters - --> $DIR/issue-82126-mismatched-subst-and-hir.rs:23:8 + --> $DIR/issue-82126-mismatched-subst-and-hir.rs:22:8 | LL | struct LockedMarket(T); | ^^^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | async fn buy_lock(coroutine: &Mutex) -> LockedMarket<'_> | ^^^^^^^^^^^^ expected 1 generic argument | note: struct defined here, with 1 generic parameter: `T` - --> $DIR/issue-82126-mismatched-subst-and-hir.rs:23:8 + --> $DIR/issue-82126-mismatched-subst-and-hir.rs:22:8 | LL | struct LockedMarket(T); | ^^^^^^^^^^^^ - @@ -28,16 +28,6 @@ help: add missing generic argument LL | async fn buy_lock(coroutine: &Mutex) -> LockedMarket<'_, T> { | +++ -error[E0515]: cannot return value referencing temporary value - --> $DIR/issue-82126-mismatched-subst-and-hir.rs:19:5 - | -LL | LockedMarket(coroutine.lock().unwrap().buy()) - | ^^^^^^^^^^^^^-------------------------^^^^^^^ - | | | - | | temporary value created here - | returns a value referencing data owned by the current function +error: aborting due to 2 previous errors -error: aborting due to 3 previous errors - -Some errors have detailed explanations: E0107, E0515. -For more information about an error, try `rustc --explain E0107`. +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/borrowck/issue-85765-closure.rs b/tests/ui/borrowck/issue-85765-closure.rs index edc9eeaffb5a..f2d1dd0fbc3f 100644 --- a/tests/ui/borrowck/issue-85765-closure.rs +++ b/tests/ui/borrowck/issue-85765-closure.rs @@ -3,7 +3,6 @@ fn main() { let mut test = Vec::new(); let rofl: &Vec> = &mut test; //~^ HELP consider changing this binding's type - //~| HELP you can `clone` the `Vec>` value and consume it, but this might not be your desired behavior rofl.push(Vec::new()); //~^ ERROR cannot borrow `*rofl` as mutable, as it is behind a `&` reference //~| NOTE `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable diff --git a/tests/ui/borrowck/issue-85765-closure.stderr b/tests/ui/borrowck/issue-85765-closure.stderr index 4a6a0e94becd..936ddd67bcd8 100644 --- a/tests/ui/borrowck/issue-85765-closure.stderr +++ b/tests/ui/borrowck/issue-85765-closure.stderr @@ -1,21 +1,16 @@ error[E0596]: cannot borrow `*rofl` as mutable, as it is behind a `&` reference - --> $DIR/issue-85765-closure.rs:7:9 + --> $DIR/issue-85765-closure.rs:6:9 | LL | rofl.push(Vec::new()); | ^^^^ `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable | -help: you can `clone` the `Vec>` value and consume it, but this might not be your desired behavior - --> $DIR/issue-85765-closure.rs:4:36 - | -LL | let rofl: &Vec> = &mut test; - | ^^^^^^^^^ help: consider changing this binding's type | LL | let rofl: &mut Vec> = &mut test; | ~~~~~~~~~~~~~~~~~~ error[E0594]: cannot assign to `*r`, which is behind a `&` reference - --> $DIR/issue-85765-closure.rs:14:9 + --> $DIR/issue-85765-closure.rs:13:9 | LL | *r = 0; | ^^^^^^ `r` is a `&` reference, so the data it refers to cannot be written @@ -26,7 +21,7 @@ LL | let r = &mut mutvar; | +++ error[E0594]: cannot assign to `*x`, which is behind a `&` reference - --> $DIR/issue-85765-closure.rs:21:9 + --> $DIR/issue-85765-closure.rs:20:9 | LL | *x = 1; | ^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written @@ -37,7 +32,7 @@ LL | let x: &mut usize = &mut{0}; | ~~~~~~~~~~ error[E0594]: cannot assign to `*y`, which is behind a `&` reference - --> $DIR/issue-85765-closure.rs:28:9 + --> $DIR/issue-85765-closure.rs:27:9 | LL | *y = 1; | ^^^^^^ `y` is a `&` reference, so the data it refers to cannot be written diff --git a/tests/ui/borrowck/issue-85765.rs b/tests/ui/borrowck/issue-85765.rs index ce5740bc0e7c..76e0b5173541 100644 --- a/tests/ui/borrowck/issue-85765.rs +++ b/tests/ui/borrowck/issue-85765.rs @@ -2,7 +2,6 @@ fn main() { let mut test = Vec::new(); let rofl: &Vec> = &mut test; //~^ HELP consider changing this binding's type - //~| HELP you can `clone` the `Vec>` value and consume it, but this might not be your desired behavior rofl.push(Vec::new()); //~^ ERROR cannot borrow `*rofl` as mutable, as it is behind a `&` reference //~| NOTE `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable diff --git a/tests/ui/borrowck/issue-85765.stderr b/tests/ui/borrowck/issue-85765.stderr index 4889f774afa8..57900bfb612e 100644 --- a/tests/ui/borrowck/issue-85765.stderr +++ b/tests/ui/borrowck/issue-85765.stderr @@ -1,21 +1,16 @@ error[E0596]: cannot borrow `*rofl` as mutable, as it is behind a `&` reference - --> $DIR/issue-85765.rs:6:5 + --> $DIR/issue-85765.rs:5:5 | LL | rofl.push(Vec::new()); | ^^^^ `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable | -help: you can `clone` the `Vec>` value and consume it, but this might not be your desired behavior - --> $DIR/issue-85765.rs:3:32 - | -LL | let rofl: &Vec> = &mut test; - | ^^^^^^^^^ help: consider changing this binding's type | LL | let rofl: &mut Vec> = &mut test; | ~~~~~~~~~~~~~~~~~~ error[E0594]: cannot assign to `*r`, which is behind a `&` reference - --> $DIR/issue-85765.rs:13:5 + --> $DIR/issue-85765.rs:12:5 | LL | *r = 0; | ^^^^^^ `r` is a `&` reference, so the data it refers to cannot be written @@ -26,7 +21,7 @@ LL | let r = &mut mutvar; | +++ error[E0594]: cannot assign to `*x`, which is behind a `&` reference - --> $DIR/issue-85765.rs:20:5 + --> $DIR/issue-85765.rs:19:5 | LL | *x = 1; | ^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written @@ -37,7 +32,7 @@ LL | let x: &mut usize = &mut{0}; | ~~~~~~~~~~ error[E0594]: cannot assign to `*y`, which is behind a `&` reference - --> $DIR/issue-85765.rs:27:5 + --> $DIR/issue-85765.rs:26:5 | LL | *y = 1; | ^^^^^^ `y` is a `&` reference, so the data it refers to cannot be written diff --git a/tests/ui/borrowck/issue-91206.rs b/tests/ui/borrowck/issue-91206.rs index c60ac62fa347..e062a253767d 100644 --- a/tests/ui/borrowck/issue-91206.rs +++ b/tests/ui/borrowck/issue-91206.rs @@ -10,7 +10,6 @@ fn main() { let client = TestClient; let inner = client.get_inner_ref(); //~^ HELP consider specifying this binding's type - //~| HELP you can `clone` the `Vec` value and consume it, but this might not be your desired behavior inner.clear(); //~^ ERROR cannot borrow `*inner` as mutable, as it is behind a `&` reference [E0596] //~| NOTE `inner` is a `&` reference, so the data it refers to cannot be borrowed as mutable diff --git a/tests/ui/borrowck/issue-91206.stderr b/tests/ui/borrowck/issue-91206.stderr index e3dd65b64197..f96b0c7d9e1a 100644 --- a/tests/ui/borrowck/issue-91206.stderr +++ b/tests/ui/borrowck/issue-91206.stderr @@ -1,14 +1,9 @@ error[E0596]: cannot borrow `*inner` as mutable, as it is behind a `&` reference - --> $DIR/issue-91206.rs:14:5 + --> $DIR/issue-91206.rs:13:5 | LL | inner.clear(); | ^^^^^ `inner` is a `&` reference, so the data it refers to cannot be borrowed as mutable | -help: you can `clone` the `Vec` value and consume it, but this might not be your desired behavior - --> $DIR/issue-91206.rs:11:17 - | -LL | let inner = client.get_inner_ref(); - | ^^^^^^^^^^^^^^^^^^^^^^ help: consider specifying this binding's type | LL | let inner: &mut Vec = client.get_inner_ref(); diff --git a/tests/ui/check-cfg/cargo-feature.none.stderr b/tests/ui/check-cfg/cargo-feature.none.stderr index 9a3084294847..aed4fd2a8c0e 100644 --- a/tests/ui/check-cfg/cargo-feature.none.stderr +++ b/tests/ui/check-cfg/cargo-feature.none.stderr @@ -1,34 +1,36 @@ -warning: unexpected `cfg` condition name: `feature` - --> $DIR/cargo-feature.rs:13:7 +warning: unexpected `cfg` condition value: `serde` + --> $DIR/cargo-feature.rs:14:7 | LL | #[cfg(feature = "serde")] - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ help: remove the condition | - = help: consider defining some features in `Cargo.toml` + = note: no expected values for `feature` + = help: consider adding `serde` as a feature in `Cargo.toml` = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default -warning: unexpected `cfg` condition name: `feature` +warning: unexpected `cfg` condition value: (none) --> $DIR/cargo-feature.rs:18:7 | LL | #[cfg(feature)] - | ^^^^^^^ + | ^^^^^^^ help: remove the condition | + = note: no expected values for `feature` = help: consider defining some features in `Cargo.toml` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `tokio_unstable` - --> $DIR/cargo-feature.rs:23:7 + --> $DIR/cargo-feature.rs:22:7 | LL | #[cfg(tokio_unstable)] | ^^^^^^^^^^^^^^ | - = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` + = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` = help: consider using a Cargo feature instead or adding `println!("cargo:rustc-check-cfg=cfg(tokio_unstable)");` to the top of a `build.rs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `CONFIG_NVME` - --> $DIR/cargo-feature.rs:27:7 + --> $DIR/cargo-feature.rs:26:7 | LL | #[cfg(CONFIG_NVME = "m")] | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/check-cfg/cargo-feature.rs b/tests/ui/check-cfg/cargo-feature.rs index f2fd0fd6420f..8542174d0c09 100644 --- a/tests/ui/check-cfg/cargo-feature.rs +++ b/tests/ui/check-cfg/cargo-feature.rs @@ -5,19 +5,18 @@ // check-pass // revisions: some none // rustc-env:CARGO=/usr/bin/cargo -// compile-flags: --check-cfg=cfg() -Z unstable-options +// compile-flags: -Z unstable-options +// [none]compile-flags: --check-cfg=cfg(feature,values()) // [some]compile-flags: --check-cfg=cfg(feature,values("bitcode")) // [some]compile-flags: --check-cfg=cfg(CONFIG_NVME,values("y")) // [none]error-pattern:Cargo.toml #[cfg(feature = "serde")] -//[none]~^ WARNING unexpected `cfg` condition name -//[some]~^^ WARNING unexpected `cfg` condition value +//~^ WARNING unexpected `cfg` condition value fn ser() {} #[cfg(feature)] -//[none]~^ WARNING unexpected `cfg` condition name -//[some]~^^ WARNING unexpected `cfg` condition value +//~^ WARNING unexpected `cfg` condition value fn feat() {} #[cfg(tokio_unstable)] diff --git a/tests/ui/check-cfg/cargo-feature.some.stderr b/tests/ui/check-cfg/cargo-feature.some.stderr index fc6951b56174..74d65e550bbe 100644 --- a/tests/ui/check-cfg/cargo-feature.some.stderr +++ b/tests/ui/check-cfg/cargo-feature.some.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `serde` - --> $DIR/cargo-feature.rs:13:7 + --> $DIR/cargo-feature.rs:14:7 | LL | #[cfg(feature = "serde")] | ^^^^^^^^^^^^^^^^^ @@ -16,10 +16,11 @@ LL | #[cfg(feature)] | ^^^^^^^- help: specify a config value: `= "bitcode"` | = note: expected values for `feature` are: `bitcode` + = help: consider defining some features in `Cargo.toml` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `tokio_unstable` - --> $DIR/cargo-feature.rs:23:7 + --> $DIR/cargo-feature.rs:22:7 | LL | #[cfg(tokio_unstable)] | ^^^^^^^^^^^^^^ @@ -29,7 +30,7 @@ LL | #[cfg(tokio_unstable)] = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `m` - --> $DIR/cargo-feature.rs:27:7 + --> $DIR/cargo-feature.rs:26:7 | LL | #[cfg(CONFIG_NVME = "m")] | ^^^^^^^^^^^^^^--- diff --git a/tests/ui/check-cfg/concat-values.rs b/tests/ui/check-cfg/concat-values.rs index 0f9178ce6a57..ad922f8c9088 100644 --- a/tests/ui/check-cfg/concat-values.rs +++ b/tests/ui/check-cfg/concat-values.rs @@ -1,6 +1,7 @@ // check-pass // compile-flags: -Z unstable-options // compile-flags: --check-cfg=cfg(my_cfg,values("foo")) --check-cfg=cfg(my_cfg,values("bar")) +// compile-flags: --check-cfg=cfg(my_cfg,values()) #[cfg(my_cfg)] //~^ WARNING unexpected `cfg` condition value @@ -10,4 +11,7 @@ fn my_cfg() {} //~^ WARNING unexpected `cfg` condition value fn my_cfg() {} +#[cfg(any(my_cfg = "foo", my_cfg = "bar"))] +fn foo_and_bar() {} + fn main() {} diff --git a/tests/ui/check-cfg/concat-values.stderr b/tests/ui/check-cfg/concat-values.stderr index dec43f5bda3b..6fe9f2baa09f 100644 --- a/tests/ui/check-cfg/concat-values.stderr +++ b/tests/ui/check-cfg/concat-values.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: (none) - --> $DIR/concat-values.rs:5:7 + --> $DIR/concat-values.rs:6:7 | LL | #[cfg(my_cfg)] | ^^^^^^ @@ -10,7 +10,7 @@ LL | #[cfg(my_cfg)] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: `unk` - --> $DIR/concat-values.rs:9:7 + --> $DIR/concat-values.rs:10:7 | LL | #[cfg(my_cfg = "unk")] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/check-cfg/empty-values.rs b/tests/ui/check-cfg/empty-values.rs new file mode 100644 index 000000000000..7e6ba6ae84a8 --- /dev/null +++ b/tests/ui/check-cfg/empty-values.rs @@ -0,0 +1,14 @@ +// Check that we detect unexpected value when none are allowed +// +// check-pass +// compile-flags: --check-cfg=cfg(foo,values()) -Zunstable-options + +#[cfg(foo = "foo")] +//~^ WARNING unexpected `cfg` condition value +fn do_foo() {} + +#[cfg(foo)] +//~^ WARNING unexpected `cfg` condition value +fn do_foo() {} + +fn main() {} diff --git a/tests/ui/check-cfg/empty-values.stderr b/tests/ui/check-cfg/empty-values.stderr new file mode 100644 index 000000000000..e7b0b05d5616 --- /dev/null +++ b/tests/ui/check-cfg/empty-values.stderr @@ -0,0 +1,23 @@ +warning: unexpected `cfg` condition value: `foo` + --> $DIR/empty-values.rs:6:7 + | +LL | #[cfg(foo = "foo")] + | ^^^^^^^^^^^ help: remove the condition + | + = note: no expected values for `foo` + = help: to expect this configuration use `--check-cfg=cfg(foo, values("foo"))` + = note: see for more information about checking conditional configuration + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `cfg` condition value: (none) + --> $DIR/empty-values.rs:10:7 + | +LL | #[cfg(foo)] + | ^^^ help: remove the condition + | + = note: no expected values for `foo` + = help: to expect this configuration use `--check-cfg=cfg(foo)` + = note: see for more information about checking conditional configuration + +warning: 2 warnings emitted + diff --git a/tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr b/tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr index 1a13255429f0..02d75ff1228d 100644 --- a/tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr +++ b/tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr @@ -9,7 +9,7 @@ LL | let c1 : () = c; | expected due to this | = note: expected unit type `()` - found closure `{mod1::f::{closure#0} closure_args=(unavailable) args=[T, ?16t, extern "rust-call" fn(()), ?15t]}` + found closure `{mod1::f::{closure#0} closure_args=(unavailable) args=[T, ?8t, extern "rust-call" fn(()), ?7t]}` help: use parentheses to call this closure | LL | let c1 : () = c(); diff --git a/tests/ui/closures/print/closure-print-generic-verbose-2.stderr b/tests/ui/closures/print/closure-print-generic-verbose-2.stderr index 8553817247d5..a53676889898 100644 --- a/tests/ui/closures/print/closure-print-generic-verbose-2.stderr +++ b/tests/ui/closures/print/closure-print-generic-verbose-2.stderr @@ -9,7 +9,7 @@ LL | let c1 : () = c; | expected due to this | = note: expected unit type `()` - found closure `{f::{closure#0} closure_args=(unavailable) args=[T, ?16t, extern "rust-call" fn(()), ?15t]}` + found closure `{f::{closure#0} closure_args=(unavailable) args=[T, ?8t, extern "rust-call" fn(()), ?7t]}` help: use parentheses to call this closure | LL | let c1 : () = c(); diff --git a/tests/ui/closures/print/closure-print-verbose.stderr b/tests/ui/closures/print/closure-print-verbose.stderr index 3d0af5eb171c..fca8f25792ac 100644 --- a/tests/ui/closures/print/closure-print-verbose.stderr +++ b/tests/ui/closures/print/closure-print-verbose.stderr @@ -7,7 +7,7 @@ LL | let foo: fn(u8) -> u8 = |v: u8| { a += v; a }; | expected due to this | = note: expected fn pointer `fn(u8) -> u8` - found closure `{main::{closure#0} closure_args=(unavailable) args=[i8, extern "rust-call" fn((u8,)) -> u8, ?6t]}` + found closure `{main::{closure#0} closure_args=(unavailable) args=[i8, extern "rust-call" fn((u8,)) -> u8, ?4t]}` note: closures can only be coerced to `fn` types if they do not capture any variables --> $DIR/closure-print-verbose.rs:10:39 | diff --git a/tests/ui/consts/const-eval/const-eval-query-stack.stderr b/tests/ui/consts/const-eval/const-eval-query-stack.stderr index c748af608d1e..2fcb3d41dd92 100644 --- a/tests/ui/consts/const-eval/const-eval-query-stack.stderr +++ b/tests/ui/consts/const-eval/const-eval-query-stack.stderr @@ -7,7 +7,6 @@ LL | const X: i32 = 1 / 0; query stack during panic: #0 [eval_to_allocation_raw] const-evaluating + checking `X` #1 [eval_to_const_value_raw] simplifying constant for the type system `X` -#2 [eval_to_const_value_raw] simplifying constant for the type system `X` -#3 [lint_mod] linting top-level module -#4 [analysis] running analysis passes on this crate +#2 [lint_mod] linting top-level module +#3 [analysis] running analysis passes on this crate end of query stack diff --git a/tests/ui/consts/const-eval/infinite_loop.rs b/tests/ui/consts/const-eval/infinite_loop.rs index 217814906379..9bdb9929becd 100644 --- a/tests/ui/consts/const-eval/infinite_loop.rs +++ b/tests/ui/consts/const-eval/infinite_loop.rs @@ -1,7 +1,13 @@ +//! This test tests two things at once: +//! 1. we error if a const evaluation hits the deny-by-default lint limit +//! 2. we do not ICE on invalid follow-up code + +// compile-flags: -Z tiny-const-eval-limit + fn main() { // Tests the Collatz conjecture with an incorrect base case (0 instead of 1). // The value of `n` will loop indefinitely (4 - 2 - 1 - 4). - let _ = [(); { + let s = [(); { let mut n = 113383; // #20 in https://oeis.org/A006884 while n != 0 { //~^ ERROR is taking a long time @@ -9,4 +15,6 @@ fn main() { } n }]; + + s.nonexistent_method(); } diff --git a/tests/ui/consts/const-eval/infinite_loop.stderr b/tests/ui/consts/const-eval/infinite_loop.stderr index e7a0a96a1e60..37cd94bf7b7c 100644 --- a/tests/ui/consts/const-eval/infinite_loop.stderr +++ b/tests/ui/consts/const-eval/infinite_loop.stderr @@ -1,5 +1,5 @@ error: constant evaluation is taking a long time - --> $DIR/infinite_loop.rs:6:9 + --> $DIR/infinite_loop.rs:12:9 | LL | / while n != 0 { LL | | @@ -10,9 +10,9 @@ LL | | } = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. If your compilation actually takes a long time, you can safely allow the lint. help: the constant being evaluated - --> $DIR/infinite_loop.rs:4:18 + --> $DIR/infinite_loop.rs:10:18 | -LL | let _ = [(); { +LL | let s = [(); { | __________________^ LL | | let mut n = 113383; // #20 in https://oeis.org/A006884 LL | | while n != 0 { diff --git a/tests/ui/consts/const-size_of-cycle.stderr b/tests/ui/consts/const-size_of-cycle.stderr index a5679400c2f0..cd0ea5564254 100644 --- a/tests/ui/consts/const-size_of-cycle.stderr +++ b/tests/ui/consts/const-size_of-cycle.stderr @@ -7,11 +7,6 @@ LL | bytes: [u8; std::mem::size_of::()] note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`... --> $DIR/const-size_of-cycle.rs:4:17 | -LL | bytes: [u8; std::mem::size_of::()] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`... - --> $DIR/const-size_of-cycle.rs:4:17 - | LL | bytes: [u8; std::mem::size_of::()] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires computing layout of `Foo`... diff --git a/tests/ui/consts/issue-36163.stderr b/tests/ui/consts/issue-36163.stderr index 4f2d92ba3cde..de70a457f16f 100644 --- a/tests/ui/consts/issue-36163.stderr +++ b/tests/ui/consts/issue-36163.stderr @@ -20,11 +20,17 @@ note: ...which requires const-evaluating + checking `A`... LL | const A: isize = Foo::B as isize; | ^^^^^^^^^^^^^^^ = note: ...which again requires simplifying constant for the type system `Foo::B::{constant#0}`, completing the cycle -note: cycle used when simplifying constant for the type system `Foo::B::{constant#0}` - --> $DIR/issue-36163.rs:4:9 +note: cycle used when collecting item types in top-level module + --> $DIR/issue-36163.rs:1:1 | -LL | B = A, - | ^ +LL | / const A: isize = Foo::B as isize; +LL | | +LL | | enum Foo { +LL | | B = A, +LL | | } +LL | | +LL | | fn main() {} + | |____________^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: aborting due to 1 previous error diff --git a/tests/ui/consts/issue-44415.stderr b/tests/ui/consts/issue-44415.stderr index adb5747c4240..641945fce9fd 100644 --- a/tests/ui/consts/issue-44415.stderr +++ b/tests/ui/consts/issue-44415.stderr @@ -7,11 +7,6 @@ LL | bytes: [u8; unsafe { intrinsics::size_of::() }], note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`... --> $DIR/issue-44415.rs:6:17 | -LL | bytes: [u8; unsafe { intrinsics::size_of::() }], - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`... - --> $DIR/issue-44415.rs:6:17 - | LL | bytes: [u8; unsafe { intrinsics::size_of::() }], | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires computing layout of `Foo`... diff --git a/tests/ui/consts/recursive-zst-static.default.stderr b/tests/ui/consts/recursive-zst-static.default.stderr index 3bbb685a6781..5b4a0418b1e9 100644 --- a/tests/ui/consts/recursive-zst-static.default.stderr +++ b/tests/ui/consts/recursive-zst-static.default.stderr @@ -1,15 +1,10 @@ error[E0391]: cycle detected when const-evaluating + checking `FOO` - --> $DIR/recursive-zst-static.rs:10:1 - | -LL | static FOO: () = FOO; - | ^^^^^^^^^^^^^^ - | -note: ...which requires const-evaluating + checking `FOO`... --> $DIR/recursive-zst-static.rs:10:18 | LL | static FOO: () = FOO; | ^^^ - = note: ...which again requires const-evaluating + checking `FOO`, completing the cycle + | + = note: ...which immediately requires const-evaluating + checking `FOO` again note: cycle used when linting top-level module --> $DIR/recursive-zst-static.rs:10:1 | diff --git a/tests/ui/consts/recursive-zst-static.unleash.stderr b/tests/ui/consts/recursive-zst-static.unleash.stderr index 3bbb685a6781..5b4a0418b1e9 100644 --- a/tests/ui/consts/recursive-zst-static.unleash.stderr +++ b/tests/ui/consts/recursive-zst-static.unleash.stderr @@ -1,15 +1,10 @@ error[E0391]: cycle detected when const-evaluating + checking `FOO` - --> $DIR/recursive-zst-static.rs:10:1 - | -LL | static FOO: () = FOO; - | ^^^^^^^^^^^^^^ - | -note: ...which requires const-evaluating + checking `FOO`... --> $DIR/recursive-zst-static.rs:10:18 | LL | static FOO: () = FOO; | ^^^ - = note: ...which again requires const-evaluating + checking `FOO`, completing the cycle + | + = note: ...which immediately requires const-evaluating + checking `FOO` again note: cycle used when linting top-level module --> $DIR/recursive-zst-static.rs:10:1 | diff --git a/tests/ui/consts/transmute-const.rs b/tests/ui/consts/transmute-const.rs index 65e5700d083f..5044d99ec518 100644 --- a/tests/ui/consts/transmute-const.rs +++ b/tests/ui/consts/transmute-const.rs @@ -3,7 +3,7 @@ use std::mem; #[repr(transparent)] -struct Foo(#[allow(dead_code)] u32); +struct Foo(u32); const TRANSMUTED_U32: u32 = unsafe { mem::transmute(Foo(3)) }; diff --git a/tests/ui/consts/write-to-static-mut-in-static.stderr b/tests/ui/consts/write-to-static-mut-in-static.stderr index 5665e56439e0..caee433a6813 100644 --- a/tests/ui/consts/write-to-static-mut-in-static.stderr +++ b/tests/ui/consts/write-to-static-mut-in-static.stderr @@ -5,17 +5,12 @@ LL | pub static mut B: () = unsafe { A = 1; }; | ^^^^^ modifying a static's initial value from another static's initializer error[E0391]: cycle detected when const-evaluating + checking `C` - --> $DIR/write-to-static-mut-in-static.rs:5:1 - | -LL | pub static mut C: u32 = unsafe { C = 1; 0 }; - | ^^^^^^^^^^^^^^^^^^^^^ - | -note: ...which requires const-evaluating + checking `C`... --> $DIR/write-to-static-mut-in-static.rs:5:34 | LL | pub static mut C: u32 = unsafe { C = 1; 0 }; | ^^^^^ - = note: ...which again requires const-evaluating + checking `C`, completing the cycle + | + = note: ...which immediately requires const-evaluating + checking `C` again note: cycle used when linting top-level module --> $DIR/write-to-static-mut-in-static.rs:1:1 | diff --git a/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs b/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs index aac74d3eacba..80c0b69a6f7e 100644 --- a/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs +++ b/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs @@ -11,7 +11,6 @@ async gen fn gen_fn() -> &'static str { pub fn main() { let async_iterator = pin!(gen_fn()); - let waker = Waker::noop(); - let ctx = &mut Context::from_waker(&waker); + let ctx = &mut Context::from_waker(Waker::noop()); async_iterator.poll_next(ctx); } diff --git a/tests/ui/coroutine/async_gen_fn_iter.rs b/tests/ui/coroutine/async_gen_fn_iter.rs index ec6464d00487..604156b4d373 100644 --- a/tests/ui/coroutine/async_gen_fn_iter.rs +++ b/tests/ui/coroutine/async_gen_fn_iter.rs @@ -74,8 +74,7 @@ fn main() { let mut fut = pin!(async_main()); // Poll loop, just to test the future... - let waker = Waker::noop(); - let ctx = &mut Context::from_waker(&waker); + let ctx = &mut Context::from_waker(Waker::noop()); loop { match fut.as_mut().poll(ctx) { diff --git a/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs b/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs index c0cde75d4cae..6653bd15ddd2 100644 --- a/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs +++ b/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs @@ -7,5 +7,5 @@ fn main() { } #[deprecated(note = test)] -//~^ ERROR expected unsuffixed literal or identifier, found `test` +//~^ ERROR expected unsuffixed literal, found `test` fn foo() {} diff --git a/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr b/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr index 48c763c50e3b..078c766deedd 100644 --- a/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr +++ b/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr @@ -1,8 +1,13 @@ -error: expected unsuffixed literal or identifier, found `test` +error: expected unsuffixed literal, found `test` --> $DIR/issue-66340-deprecated-attr-non-meta-grammar.rs:9:21 | LL | #[deprecated(note = test)] | ^^^^ + | +help: surround the identifier with quotation marks to parse it as a string + | +LL | #[deprecated(note = "test")] + | + + error: aborting due to 1 previous error diff --git a/tests/ui/dyn-star/dispatch-on-pin-mut.rs b/tests/ui/dyn-star/dispatch-on-pin-mut.rs index c4ae279e6c11..151aa9092fbe 100644 --- a/tests/ui/dyn-star/dispatch-on-pin-mut.rs +++ b/tests/ui/dyn-star/dispatch-on-pin-mut.rs @@ -19,15 +19,14 @@ async fn async_main() { // ------------------------------------------------------------------------- // // Implementation Details Below... -use std::task::*; use std::pin::pin; +use std::task::*; fn main() { let mut fut = pin!(async_main()); // Poll loop, just to test the future... - let waker = Waker::noop(); - let ctx = &mut Context::from_waker(&waker); + let ctx = &mut Context::from_waker(Waker::noop()); loop { match fut.as_mut().poll(ctx) { diff --git a/tests/ui/feature-gates/feature-gate-never_patterns.rs b/tests/ui/feature-gates/feature-gate-never_patterns.rs index f3910622313d..d23405ada2d4 100644 --- a/tests/ui/feature-gates/feature-gate-never_patterns.rs +++ b/tests/ui/feature-gates/feature-gate-never_patterns.rs @@ -7,7 +7,6 @@ fn main() { let res: Result = Ok(0); let (Ok(_x) | Err(&!)) = res.as_ref(); //~^ ERROR `!` patterns are experimental - //~| ERROR: is not bound in all patterns unsafe { let ptr: *const Void = NonNull::dangling().as_ptr(); diff --git a/tests/ui/feature-gates/feature-gate-never_patterns.stderr b/tests/ui/feature-gates/feature-gate-never_patterns.stderr index 1b5485d22fbf..9f94e9620351 100644 --- a/tests/ui/feature-gates/feature-gate-never_patterns.stderr +++ b/tests/ui/feature-gates/feature-gate-never_patterns.stderr @@ -1,5 +1,5 @@ error: unexpected `,` in pattern - --> $DIR/feature-gate-never_patterns.rs:34:16 + --> $DIR/feature-gate-never_patterns.rs:33:16 | LL | Some(_), | ^ @@ -13,14 +13,6 @@ help: ...or a vertical bar to match on multiple alternatives LL | Some(_) | | -error[E0408]: variable `_x` is not bound in all patterns - --> $DIR/feature-gate-never_patterns.rs:8:19 - | -LL | let (Ok(_x) | Err(&!)) = res.as_ref(); - | -- ^^^^^^^ pattern doesn't bind `_x` - | | - | variable not in all patterns - error[E0658]: `!` patterns are experimental --> $DIR/feature-gate-never_patterns.rs:8:24 | @@ -32,7 +24,7 @@ LL | let (Ok(_x) | Err(&!)) = res.as_ref(); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `!` patterns are experimental - --> $DIR/feature-gate-never_patterns.rs:15:13 + --> $DIR/feature-gate-never_patterns.rs:14:13 | LL | ! | ^ @@ -42,7 +34,7 @@ LL | ! = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `!` patterns are experimental - --> $DIR/feature-gate-never_patterns.rs:21:13 + --> $DIR/feature-gate-never_patterns.rs:20:13 | LL | ! | ^ @@ -52,7 +44,7 @@ LL | ! = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `!` patterns are experimental - --> $DIR/feature-gate-never_patterns.rs:26:13 + --> $DIR/feature-gate-never_patterns.rs:25:13 | LL | ! => {} | ^ @@ -62,25 +54,25 @@ LL | ! => {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: `match` arm with no body - --> $DIR/feature-gate-never_patterns.rs:39:9 + --> $DIR/feature-gate-never_patterns.rs:38:9 | LL | Some(_) | ^^^^^^^- help: add a body after the pattern: `=> todo!(),` error: `match` arm with no body - --> $DIR/feature-gate-never_patterns.rs:44:9 + --> $DIR/feature-gate-never_patterns.rs:43:9 | LL | Some(_) if false, | ^^^^^^^- help: add a body after the pattern: `=> todo!(),` error: `match` arm with no body - --> $DIR/feature-gate-never_patterns.rs:46:9 + --> $DIR/feature-gate-never_patterns.rs:45:9 | LL | Some(_) if false | ^^^^^^^- help: add a body after the pattern: `=> todo!(),` error[E0658]: `!` patterns are experimental - --> $DIR/feature-gate-never_patterns.rs:51:13 + --> $DIR/feature-gate-never_patterns.rs:50:13 | LL | Err(!), | ^ @@ -90,7 +82,7 @@ LL | Err(!), = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `!` patterns are experimental - --> $DIR/feature-gate-never_patterns.rs:55:13 + --> $DIR/feature-gate-never_patterns.rs:54:13 | LL | Err(!) if false, | ^ @@ -100,24 +92,23 @@ LL | Err(!) if false, = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: `match` arm with no body - --> $DIR/feature-gate-never_patterns.rs:65:9 + --> $DIR/feature-gate-never_patterns.rs:64:9 | LL | Some(_) | ^^^^^^^- help: add a body after the pattern: `=> todo!(),` error: `match` arm with no body - --> $DIR/feature-gate-never_patterns.rs:71:9 + --> $DIR/feature-gate-never_patterns.rs:70:9 | LL | Some(_) if false | ^^^^^^^- help: add a body after the pattern: `=> todo!(),` error: a guard on a never pattern will never be run - --> $DIR/feature-gate-never_patterns.rs:55:19 + --> $DIR/feature-gate-never_patterns.rs:54:19 | LL | Err(!) if false, | ^^^^^ help: remove this guard -error: aborting due to 14 previous errors +error: aborting due to 13 previous errors -Some errors have detailed explanations: E0408, E0658. -For more information about an error, try `rustc --explain E0408`. +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-offset-of-enum.rs b/tests/ui/feature-gates/feature-gate-offset-of-enum.rs index e19dcf9f6a54..1f2f7ee1e191 100644 --- a/tests/ui/feature-gates/feature-gate-offset-of-enum.rs +++ b/tests/ui/feature-gates/feature-gate-offset-of-enum.rs @@ -1,4 +1,4 @@ -#![feature(offset_of)] +#![feature(offset_of_nested)] use std::mem::offset_of; diff --git a/tests/ui/feature-gates/feature-gate-offset-of-enum.stderr b/tests/ui/feature-gates/feature-gate-offset-of-enum.stderr index 02ee54e8607a..fc7dd7923f7a 100644 --- a/tests/ui/feature-gates/feature-gate-offset-of-enum.stderr +++ b/tests/ui/feature-gates/feature-gate-offset-of-enum.stderr @@ -13,7 +13,7 @@ error[E0658]: using enums in offset_of is experimental LL | offset_of!(Alpha, One); | ^^^ | - = note: see issue #106655 for more information + = note: see issue #120141 for more information = help: add `#![feature(offset_of_enum)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date @@ -29,7 +29,7 @@ error[E0658]: using enums in offset_of is experimental LL | offset_of!(Alpha, Two.0); | ^^^ | - = note: see issue #106655 for more information + = note: see issue #120141 for more information = help: add `#![feature(offset_of_enum)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date diff --git a/tests/ui/feature-gates/feature-gate-offset-of-nested.rs b/tests/ui/feature-gates/feature-gate-offset-of-nested.rs new file mode 100644 index 000000000000..c4eb4720fde5 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-offset-of-nested.rs @@ -0,0 +1,28 @@ +#![feature(offset_of_enum)] + +use std::mem::offset_of; + +struct S { + a: u8, + b: (u8, u8), + c: T, +} + +struct T { + t: &'static str, +} + +enum Alpha { + One(u8), + Two(u8), +} + +fn main() { + offset_of!(Alpha, Two.0); //~ ERROR only a single ident or integer is stable as the field in offset_of + offset_of!(S, a); + offset_of!((u8, S), 1); + offset_of!((u32, (S, T)), 1.1); //~ ERROR only a single ident or integer is stable as the field in offset_of + offset_of!(S, b.0); //~ ERROR only a single ident or integer is stable as the field in offset_of + offset_of!((S, ()), 0.c); //~ ERROR only a single ident or integer is stable as the field in offset_of + offset_of!(S, c.t); //~ ERROR only a single ident or integer is stable as the field in offset_of +} diff --git a/tests/ui/feature-gates/feature-gate-offset-of-nested.stderr b/tests/ui/feature-gates/feature-gate-offset-of-nested.stderr new file mode 100644 index 000000000000..f367fc9fa0dd --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-offset-of-nested.stderr @@ -0,0 +1,60 @@ +error[E0658]: only a single ident or integer is stable as the field in offset_of + --> $DIR/feature-gate-offset-of-nested.rs:21:27 + | +LL | offset_of!(Alpha, Two.0); + | ^ + | + = note: see issue #120140 for more information + = help: add `#![feature(offset_of_nested)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: only a single ident or integer is stable as the field in offset_of + --> $DIR/feature-gate-offset-of-nested.rs:24:33 + | +LL | offset_of!((u32, (S, T)), 1.1); + | _____----------------------------^- + | | | + | | in this macro invocation +LL | | offset_of!(S, b.0); +LL | | offset_of!((S, ()), 0.c); +LL | | offset_of!(S, c.t); +... | + | + = note: see issue #120140 for more information + = help: add `#![feature(offset_of_nested)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0658]: only a single ident or integer is stable as the field in offset_of + --> $DIR/feature-gate-offset-of-nested.rs:25:21 + | +LL | offset_of!(S, b.0); + | ^ + | + = note: see issue #120140 for more information + = help: add `#![feature(offset_of_nested)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: only a single ident or integer is stable as the field in offset_of + --> $DIR/feature-gate-offset-of-nested.rs:26:27 + | +LL | offset_of!((S, ()), 0.c); + | ^ + | + = note: see issue #120140 for more information + = help: add `#![feature(offset_of_nested)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: only a single ident or integer is stable as the field in offset_of + --> $DIR/feature-gate-offset-of-nested.rs:27:21 + | +LL | offset_of!(S, c.t); + | ^ + | + = note: see issue #120140 for more information + = help: add `#![feature(offset_of_nested)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-proc_macro_c_str_literals.rs b/tests/ui/feature-gates/feature-gate-proc_macro_c_str_literals.rs new file mode 100644 index 000000000000..5554c8139255 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-proc_macro_c_str_literals.rs @@ -0,0 +1,11 @@ +// edition: 2021 +// force-host +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::Literal; + +fn test() { + Literal::c_string(c"a"); //~ ERROR use of unstable library feature 'proc_macro_c_str_literals' +} diff --git a/tests/ui/feature-gates/feature-gate-proc_macro_c_str_literals.stderr b/tests/ui/feature-gates/feature-gate-proc_macro_c_str_literals.stderr new file mode 100644 index 000000000000..9bba1d50ce36 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-proc_macro_c_str_literals.stderr @@ -0,0 +1,13 @@ +error[E0658]: use of unstable library feature 'proc_macro_c_str_literals' + --> $DIR/feature-gate-proc_macro_c_str_literals.rs:10:5 + | +LL | Literal::c_string(c"a"); + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #119750 for more information + = help: add `#![feature(proc_macro_c_str_literals)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs b/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs new file mode 100644 index 000000000000..252dc7d751e6 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs @@ -0,0 +1,33 @@ +use std::ops::Deref; + +trait PointerFamily { + type Pointer: Deref; +} + +struct RcFamily; + +impl PointerFamily for RcFamily { + type Pointer = dyn Deref; + //~^ ERROR the size for values of type `(dyn Deref + 'static)` cannot be known at compilation time +} + +enum Node { + Cons(T, P::Pointer>), + Nil, +} + +type RcNode = Node; + +impl Node +where + P::Pointer>: Sized, +{ + fn new() -> P::Pointer { + todo!() + } +} + +fn main() { + let mut list = RcNode::::new(); + //~^ ERROR the size for values of type `Node` cannot be known at compilation time +} diff --git a/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.stderr b/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.stderr new file mode 100644 index 000000000000..3a973d356dc9 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.stderr @@ -0,0 +1,52 @@ +error[E0277]: the size for values of type `(dyn Deref + 'static)` cannot be known at compilation time + --> $DIR/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs:10:23 + | +LL | type Pointer = dyn Deref; + | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn Deref + 'static)` +note: required by a bound in `PointerFamily::Pointer` + --> $DIR/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs:4:5 + | +LL | type Pointer: Deref; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `PointerFamily::Pointer` +help: consider relaxing the implicit `Sized` restriction + | +LL | type Pointer: Deref + ?Sized; + | ++++++++ + +error[E0599]: the size for values of type `Node` cannot be known at compilation time + --> $DIR/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs:31:35 + | +LL | enum Node { + | ------------------------------ + | | + | variant or associated item `new` not found for this enum + | doesn't satisfy `Node: Sized` +... +LL | let mut list = RcNode::::new(); + | ^^^ doesn't have a size known at compile-time + --> $SRC_DIR/core/src/ops/deref.rs:LL:COL + | + = note: doesn't satisfy `_: Sized` + | +note: trait bound `Node: Sized` was not satisfied + --> $DIR/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs:4:18 + | +LL | type Pointer: Deref; + | ------- ^ unsatisfied trait bound introduced here +note: trait bound `(dyn Deref> + 'static): Sized` was not satisfied + --> $DIR/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs:23:29 + | +LL | impl Node + | ---------- +LL | where +LL | P::Pointer>: Sized, + | ^^^^^ unsatisfied trait bound introduced here +note: the trait `Sized` must be implemented + --> $SRC_DIR/core/src/marker.rs:LL:COL + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0599. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/higher-ranked/trait-bounds/issue-59311.rs b/tests/ui/higher-ranked/trait-bounds/issue-59311.rs index 3ad548450e58..387c78a802a7 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-59311.rs +++ b/tests/ui/higher-ranked/trait-bounds/issue-59311.rs @@ -17,6 +17,7 @@ where v.t(|| {}); //~^ ERROR: higher-ranked lifetime error //~| ERROR: higher-ranked lifetime error + //~| ERROR: higher-ranked lifetime error } fn main() {} diff --git a/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr b/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr index e50aad876d8c..3053a2998026 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr +++ b/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr @@ -6,6 +6,15 @@ LL | v.t(|| {}); | = note: could not prove `{closure@$DIR/issue-59311.rs:17:9: 17:11} well-formed` +error: higher-ranked lifetime error + --> $DIR/issue-59311.rs:17:5 + | +LL | v.t(|| {}); + | ^^^^^^^^^^ + | + = note: could not prove `{closure@$DIR/issue-59311.rs:17:9: 17:11} well-formed` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error: higher-ranked lifetime error --> $DIR/issue-59311.rs:17:9 | @@ -14,5 +23,5 @@ LL | v.t(|| {}); | = note: could not prove `for<'a> &'a V: 'b` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/impl-trait/in-ctfe/array-len-size-of.rs b/tests/ui/impl-trait/in-ctfe/array-len-size-of.rs new file mode 100644 index 000000000000..01ba902ef0c0 --- /dev/null +++ b/tests/ui/impl-trait/in-ctfe/array-len-size-of.rs @@ -0,0 +1,16 @@ +//! Check that const eval can use the size of opaque types. +// check-pass +use std::mem; +fn returns_opaque() -> impl Sized { + 0u8 +} + +struct NamedOpaqueType { + data: [mem::MaybeUninit; size_of_fut(returns_opaque)], +} + +const fn size_of_fut(x: fn() -> FUT) -> usize { + mem::size_of::() +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-ctfe/array-len.rs b/tests/ui/impl-trait/in-ctfe/array-len.rs new file mode 100644 index 000000000000..73ae20495d57 --- /dev/null +++ b/tests/ui/impl-trait/in-ctfe/array-len.rs @@ -0,0 +1,22 @@ +//! Check that array lengths can observe associated types of opaque types +// check-pass +trait MyTrait: Copy { + const ASSOC: usize; +} + +impl MyTrait for u8 { + const ASSOC: usize = 32; +} + +const fn yeet() -> impl MyTrait { + 0u8 +} + +const fn output(_: T) -> usize { + ::ASSOC +} + +fn main() { + let x = [0u8; output(yeet())]; + println!("{:?}", x); +} diff --git a/tests/ui/impl-trait/in-ctfe/enum-discr.rs b/tests/ui/impl-trait/in-ctfe/enum-discr.rs new file mode 100644 index 000000000000..8e4384adaa4c --- /dev/null +++ b/tests/ui/impl-trait/in-ctfe/enum-discr.rs @@ -0,0 +1,26 @@ +//! check that const eval can observe associated types of opaque types. +// check-pass +trait MyTrait: Copy { + const ASSOC: usize; +} + +impl MyTrait for u8 { + const ASSOC: usize = 32; +} + +const fn yeet() -> impl MyTrait { + 0u8 +} + +const fn output(_: T) -> usize { + ::ASSOC +} + +#[repr(usize)] +enum Foo { + Bar = output(yeet()), +} + +fn main() { + println!("{}", Foo::Bar as usize); +} diff --git a/tests/ui/impl-trait/in-ctfe/fully_monomorphic_const_eval.rs b/tests/ui/impl-trait/in-ctfe/fully_monomorphic_const_eval.rs new file mode 100644 index 000000000000..82a9a30a6236 --- /dev/null +++ b/tests/ui/impl-trait/in-ctfe/fully_monomorphic_const_eval.rs @@ -0,0 +1,29 @@ +//! This test ensures that we do look at the hidden types of +//! opaque types during const eval in order to obtain the exact type +//! of associated types. + +// check-pass + +trait MyTrait: Copy { + const ASSOC: usize; +} + +impl MyTrait for u8 { + const ASSOC: usize = 32; +} + +const fn yeet() -> impl MyTrait { + 0u8 +} + +const fn output(_: T) -> usize { + ::ASSOC +} + +struct Foo<'a>(&'a ()); +const NEED_REVEAL_ALL: usize = output(yeet()); + +fn promote_div() -> &'static usize { + &(10 / NEED_REVEAL_ALL) +} +fn main() {} diff --git a/tests/ui/impl-trait/in-ctfe/match-arm-exhaustive.rs b/tests/ui/impl-trait/in-ctfe/match-arm-exhaustive.rs new file mode 100644 index 000000000000..8e3269726fc4 --- /dev/null +++ b/tests/ui/impl-trait/in-ctfe/match-arm-exhaustive.rs @@ -0,0 +1,24 @@ +//! Check that pattern matching can observe the hidden type of opaque types. +// check-pass +trait MyTrait: Copy { + const ASSOC: u8; +} + +impl MyTrait for () { + const ASSOC: u8 = 0; +} + +const fn yeet() -> impl MyTrait {} + +const fn output(_: T) -> u8 { + ::ASSOC +} + +const CT: u8 = output(yeet()); + +fn main() { + match 0 { + CT => (), + 1.. => (), + } +} diff --git a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs index ad73b12feb53..ff265e576b90 100644 --- a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs +++ b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs @@ -7,6 +7,8 @@ struct Bar; impl Foo for Bar { fn foo>(self) -> impl Foo { //~^ ERROR: the trait bound `impl Foo: Foo` is not satisfied [E0277] + //~| ERROR: the trait bound `Bar: Foo` is not satisfied [E0277] + //~| ERROR: impl has stricter requirements than trait self } } diff --git a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr index db587d069f8b..638de01f9139 100644 --- a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr +++ b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr @@ -11,6 +11,28 @@ note: required by a bound in `Foo::{opaque#0}` LL | fn foo(self) -> impl Foo; | ^^^^^^ required by this bound in `Foo::{opaque#0}` -error: aborting due to 1 previous error +error[E0276]: impl has stricter requirements than trait + --> $DIR/return-dont-satisfy-bounds.rs:8:16 + | +LL | fn foo(self) -> impl Foo; + | -------------------------------- definition of `foo` from trait +... +LL | fn foo>(self) -> impl Foo { + | ^^^^^^^ impl has extra requirement `F2: Foo` -For more information about this error, try `rustc --explain E0277`. +error[E0277]: the trait bound `Bar: Foo` is not satisfied + --> $DIR/return-dont-satisfy-bounds.rs:8:34 + | +LL | fn foo>(self) -> impl Foo { + | ^^^^^^^^^^^^ the trait `Foo` is not implemented for `Bar` +... +LL | self + | ---- return type was inferred to be `Bar` here + | + = help: the trait `Foo` is implemented for `Bar` + = help: for that trait implementation, expected `char`, found `u8` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0276, E0277. +For more information about an error, try `rustc --explain E0276`. diff --git a/tests/ui/impl-trait/issue-72911.rs b/tests/ui/impl-trait/issue-72911.rs index 63f4898f4306..7ba8579e24fb 100644 --- a/tests/ui/impl-trait/issue-72911.rs +++ b/tests/ui/impl-trait/issue-72911.rs @@ -15,6 +15,7 @@ fn gather_from_file(dir_entry: &foo::MissingItem) -> impl Iterator fn lint_files() -> impl Iterator { //~^ ERROR: failed to resolve + //~| ERROR: `()` is not an iterator unimplemented!() } diff --git a/tests/ui/impl-trait/issue-72911.stderr b/tests/ui/impl-trait/issue-72911.stderr index 0e86561aa277..44c20a7be53d 100644 --- a/tests/ui/impl-trait/issue-72911.stderr +++ b/tests/ui/impl-trait/issue-72911.stderr @@ -1,3 +1,11 @@ +error[E0277]: `()` is not an iterator + --> $DIR/issue-72911.rs:16:20 + | +LL | fn lint_files() -> impl Iterator { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator + | + = help: the trait `Iterator` is not implemented for `()` + error[E0433]: failed to resolve: use of undeclared crate or module `foo` --> $DIR/issue-72911.rs:11:33 | @@ -10,6 +18,7 @@ error[E0433]: failed to resolve: use of undeclared crate or module `foo` LL | fn lint_files() -> impl Iterator { | ^^^ use of undeclared crate or module `foo` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0433`. +Some errors have detailed explanations: E0277, E0433. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/issues/issue-92305.rs b/tests/ui/impl-trait/issues/issue-92305.rs index e16199caaaa2..4a89238d07e6 100644 --- a/tests/ui/impl-trait/issues/issue-92305.rs +++ b/tests/ui/impl-trait/issues/issue-92305.rs @@ -5,7 +5,6 @@ use std::iter; fn f(data: &[T]) -> impl Iterator { //~^ ERROR: missing generics for struct `Vec` [E0107] iter::empty() - //~^ ERROR: type annotations needed } fn g(data: &[T], target: T) -> impl Iterator> { diff --git a/tests/ui/impl-trait/issues/issue-92305.stderr b/tests/ui/impl-trait/issues/issue-92305.stderr index 55e966bd7bfd..88fb1fb27070 100644 --- a/tests/ui/impl-trait/issues/issue-92305.stderr +++ b/tests/ui/impl-trait/issues/issue-92305.stderr @@ -9,18 +9,6 @@ help: add missing generic argument LL | fn f(data: &[T]) -> impl Iterator> { | +++ -error[E0282]: type annotations needed - --> $DIR/issue-92305.rs:7:5 - | -LL | iter::empty() - | ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `empty` - | -help: consider specifying the generic argument - | -LL | iter::empty::() - | +++++ +error: aborting due to 1 previous error -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0107, E0282. -For more information about an error, try `rustc --explain E0107`. +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/impl-trait/opaque-used-in-extraneous-argument.rs b/tests/ui/impl-trait/opaque-used-in-extraneous-argument.rs new file mode 100644 index 000000000000..529913479ef4 --- /dev/null +++ b/tests/ui/impl-trait/opaque-used-in-extraneous-argument.rs @@ -0,0 +1,21 @@ +//! This is a regression test to avoid an ICE in diagnostics code. +//! A typo in the compiler used to get the DefId of FnOnce, and +//! use it where an associated item was expected. + +fn frob() -> impl Fn + '_ {} +//~^ ERROR missing lifetime specifier +//~| ERROR cannot find type `P` +//~| ERROR cannot find type `T` +//~| ERROR `Fn`-family traits' type parameters is subject to change + +fn open_parent<'path>() { + todo!() +} + +fn main() { + let old_path = frob("hello"); + //~^ ERROR function takes 0 arguments + + open_parent(&old_path) + //~^ ERROR function takes 0 arguments +} diff --git a/tests/ui/impl-trait/opaque-used-in-extraneous-argument.stderr b/tests/ui/impl-trait/opaque-used-in-extraneous-argument.stderr new file mode 100644 index 000000000000..b54b9f908b2a --- /dev/null +++ b/tests/ui/impl-trait/opaque-used-in-extraneous-argument.stderr @@ -0,0 +1,78 @@ +error[E0106]: missing lifetime specifier + --> $DIR/opaque-used-in-extraneous-argument.rs:5:39 + | +LL | fn frob() -> impl Fn + '_ {} + | ^^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values + | +LL | fn frob() -> impl Fn + 'static {} + | ~~~~~~~ + +error[E0412]: cannot find type `P` in this scope + --> $DIR/opaque-used-in-extraneous-argument.rs:5:22 + | +LL | fn frob() -> impl Fn + '_ {} + | ^ not found in this scope + | +help: you might be missing a type parameter + | +LL | fn frob

() -> impl Fn + '_ {} + | +++ + +error[E0412]: cannot find type `T` in this scope + --> $DIR/opaque-used-in-extraneous-argument.rs:5:34 + | +LL | fn frob() -> impl Fn + '_ {} + | ^ not found in this scope + | +help: you might be missing a type parameter + | +LL | fn frob() -> impl Fn + '_ {} + | +++ + +error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change + --> $DIR/opaque-used-in-extraneous-argument.rs:5:19 + | +LL | fn frob() -> impl Fn + '_ {} + | ^^^^^^^^^^^^^^^^^ help: use parenthetical notation instead: `Fn(P) -> T` + | + = note: see issue #29625 for more information + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/opaque-used-in-extraneous-argument.rs:16:20 + | +LL | let old_path = frob("hello"); + | ^^^^ ------- + | | + | unexpected argument of type `&'static str` + | help: remove the extra argument + | +note: function defined here + --> $DIR/opaque-used-in-extraneous-argument.rs:5:4 + | +LL | fn frob() -> impl Fn + '_ {} + | ^^^^ + +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/opaque-used-in-extraneous-argument.rs:19:5 + | +LL | open_parent(&old_path) + | ^^^^^^^^^^^ --------- + | | + | unexpected argument of type `&impl FnOnce<{type error}, Output = {type error}> + Fn<{type error}> + 'static` + | help: remove the extra argument + | +note: function defined here + --> $DIR/opaque-used-in-extraneous-argument.rs:11:4 + | +LL | fn open_parent<'path>() { + | ^^^^^^^^^^^ + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0061, E0106, E0412, E0658. +For more information about an error, try `rustc --explain E0061`. diff --git a/tests/ui/impl-trait/transmute/in-defining-scope.rs b/tests/ui/impl-trait/transmute/in-defining-scope.rs new file mode 100644 index 000000000000..b0b77d60b245 --- /dev/null +++ b/tests/ui/impl-trait/transmute/in-defining-scope.rs @@ -0,0 +1,14 @@ +// This causes a query cycle due to using `Reveal::All`, +// in #119821 const eval was changed to always use `Reveal::All` +// +// See that PR for more details. +use std::mem::transmute; +fn foo() -> impl Sized { + //~^ ERROR cycle detected when computing type of + unsafe { + transmute::<_, u8>(foo()); + } + 0u8 +} + +fn main() {} diff --git a/tests/ui/impl-trait/transmute/in-defining-scope.stderr b/tests/ui/impl-trait/transmute/in-defining-scope.stderr new file mode 100644 index 000000000000..69812f43072b --- /dev/null +++ b/tests/ui/impl-trait/transmute/in-defining-scope.stderr @@ -0,0 +1,29 @@ +error[E0391]: cycle detected when computing type of `foo::{opaque#0}` + --> $DIR/in-defining-scope.rs:6:13 + | +LL | fn foo() -> impl Sized { + | ^^^^^^^^^^ + | +note: ...which requires computing type of opaque `foo::{opaque#0}`... + --> $DIR/in-defining-scope.rs:6:13 + | +LL | fn foo() -> impl Sized { + | ^^^^^^^^^^ +note: ...which requires type-checking `foo`... + --> $DIR/in-defining-scope.rs:6:1 + | +LL | fn foo() -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which requires computing layout of `foo::{opaque#0}`... + = note: ...which requires normalizing `foo::{opaque#0}`... + = note: ...which again requires computing type of `foo::{opaque#0}`, completing the cycle +note: cycle used when checking that `foo::{opaque#0}` is well-formed + --> $DIR/in-defining-scope.rs:6:13 + | +LL | fn foo() -> impl Sized { + | ^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/impl-trait/transmute/outside-of-defining-scope.rs b/tests/ui/impl-trait/transmute/outside-of-defining-scope.rs new file mode 100644 index 000000000000..7bc22ea416f0 --- /dev/null +++ b/tests/ui/impl-trait/transmute/outside-of-defining-scope.rs @@ -0,0 +1,12 @@ +//! Check that typeck can observe the size of an opaque type. +// check-pass +use std::mem::transmute; +fn foo() -> impl Sized { + 0u8 +} + +fn main() { + unsafe { + transmute::<_, u8>(foo()); + } +} diff --git a/tests/ui/implied-bounds/auxiliary/bevy_ecs.rs b/tests/ui/implied-bounds/auxiliary/bevy_ecs.rs deleted file mode 100644 index b373d39f4d94..000000000000 --- a/tests/ui/implied-bounds/auxiliary/bevy_ecs.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Related to Bevy regression #118553 - -pub trait WorldQuery {} -impl WorldQuery for &u8 {} - -pub struct Query(Q); - -pub trait SystemParam { - type State; -} -impl SystemParam for Query { - type State = (); - // `Q: 'static` is required because we need the TypeId of Q ... -} - -pub struct ParamSet(T) -where - T::State: Sized; diff --git a/tests/ui/implied-bounds/bevy_world_query.rs b/tests/ui/implied-bounds/bevy_world_query.rs index f8e64632676d..2e3d4e6a7c66 100644 --- a/tests/ui/implied-bounds/bevy_world_query.rs +++ b/tests/ui/implied-bounds/bevy_world_query.rs @@ -1,11 +1,28 @@ -// aux-crate:bevy_ecs=bevy_ecs.rs // check-pass -// Related to Bevy regression #118553 -extern crate bevy_ecs; +// We currently special case bevy from erroring on incorrect implied bounds +// from normalization (issue #109628). +// Otherwise, we would expect this to hit that error. -use bevy_ecs::*; +pub trait WorldQuery {} +impl WorldQuery for &u8 {} -fn handler<'a>(_: ParamSet>) {} +pub struct Query(Q); + +pub trait SystemParam { + type State; +} +impl SystemParam for Query { + type State = (); + // `Q: 'static` is required because we need the TypeId of Q ... +} + +pub struct ParamSet(T) where T::State: Sized; + +fn handler<'a>(x: ParamSet>) { + let _: ParamSet<_> = x; +} + +fn ref_handler<'a>(_: &ParamSet>) {} fn main() {} diff --git a/tests/ui/implied-bounds/from-trait-impl.rs b/tests/ui/implied-bounds/from-trait-impl.rs index d13fddd9b8d4..6e126575aa9a 100644 --- a/tests/ui/implied-bounds/from-trait-impl.rs +++ b/tests/ui/implied-bounds/from-trait-impl.rs @@ -1,6 +1,3 @@ -// check-pass -// known-bug: #109628 - trait Trait { type Assoc; } @@ -14,11 +11,13 @@ where T::Assoc: Clone; // any predicate using `T::Assoc` works here fn func1(foo: Foo<(&str,)>) { + //~^ ERROR `&str` does not fulfill the required lifetime let _: &'static str = foo.0.0; } trait TestTrait {} impl TestTrait for [Foo<(X,)>; 1] {} +//~^ ERROR `X` may not live long enough fn main() {} diff --git a/tests/ui/implied-bounds/from-trait-impl.stderr b/tests/ui/implied-bounds/from-trait-impl.stderr new file mode 100644 index 000000000000..4151d206ae25 --- /dev/null +++ b/tests/ui/implied-bounds/from-trait-impl.stderr @@ -0,0 +1,26 @@ +error[E0477]: the type `&str` does not fulfill the required lifetime + --> $DIR/from-trait-impl.rs:13:15 + | +LL | fn func1(foo: Foo<(&str,)>) { + | ^^^^^^^^^^^^ + | + = note: type must satisfy the static lifetime + +error[E0310]: the parameter type `X` may not live long enough + --> $DIR/from-trait-impl.rs:20:23 + | +LL | impl TestTrait for [Foo<(X,)>; 1] {} + | ^^^^^^^^^^^^^^ + | | + | the parameter type `X` must be valid for the static lifetime... + | ...so that the type `X` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound + | +LL | impl TestTrait for [Foo<(X,)>; 1] {} + | +++++++++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0310, E0477. +For more information about an error, try `rustc --explain E0310`. diff --git a/tests/ui/implied-bounds/gluon_salsa.rs b/tests/ui/implied-bounds/gluon_salsa.rs index 98951af8ac2d..cd5500cb458f 100644 --- a/tests/ui/implied-bounds/gluon_salsa.rs +++ b/tests/ui/implied-bounds/gluon_salsa.rs @@ -1,5 +1,5 @@ // check-pass -// Related to Bevy regression #118553 +// Found in a crater run on #118553 pub trait QueryBase { type Db; @@ -17,8 +17,7 @@ pub struct QueryTable<'me, Q, DB> { _marker: Option<&'me ()>, } -impl<'me, Q> QueryTable<'me, Q, ::Db> -// projection is important +impl<'me, Q> QueryTable<'me, Q, ::Db> // projection is important // ^^^ removing 'me (and in QueryTable) gives a different error where Q: for<'f> AsyncQueryFunction<'f>, diff --git a/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy.rs b/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-1.rs similarity index 72% rename from tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy.rs rename to tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-1.rs index 9c26cd59d100..b532a110a1c7 100644 --- a/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy.rs +++ b/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-1.rs @@ -1,9 +1,7 @@ -// check-pass -// known-bug: #84591 +// issue: #84591 -// Should fail. Subtrait can incorrectly extend supertrait lifetimes even when -// supertrait has weaker implied bounds than subtrait. Strongly related to -// issue #25860. +// Subtrait was able to incorrectly extend supertrait lifetimes even when +// supertrait had weaker implied bounds than subtrait. trait Subtrait: Supertrait {} trait Supertrait { @@ -34,6 +32,7 @@ fn main() { { let x = "Hello World".to_string(); subs_to_soup((x.as_str(), &mut d)); + //~^ does not live long enough } println!("{}", d); } diff --git a/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-1.stderr b/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-1.stderr new file mode 100644 index 000000000000..f44defccf589 --- /dev/null +++ b/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-1.stderr @@ -0,0 +1,16 @@ +error[E0597]: `x` does not live long enough + --> $DIR/implied-bounds-on-trait-hierarchy-1.rs:34:23 + | +LL | let x = "Hello World".to_string(); + | - binding `x` declared here +LL | subs_to_soup((x.as_str(), &mut d)); + | ^ borrowed value does not live long enough +LL | +LL | } + | - `x` dropped here while still borrowed +LL | println!("{}", d); + | - borrow later used here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-2.rs b/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-2.rs new file mode 100644 index 000000000000..511a9ad9a2a2 --- /dev/null +++ b/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-2.rs @@ -0,0 +1,45 @@ +// check-pass +// known-bug: #84591 + +trait Subtrait<'a, 'b, R>: Supertrait<'a, 'b> {} +trait Supertrait<'a, 'b> { + fn convert(x: &'a T) -> &'b T; +} + +fn need_hrtb_subtrait<'a_, 'b_, S, T: ?Sized>(x: &'a_ T) -> &'b_ T +where + S: for<'a, 'b> Subtrait<'a, 'b, &'b &'a ()>, +{ + need_hrtb_supertrait::(x) + // This call works and drops the implied bound `'a: 'b` + // of the where-bound. This means the where-bound can + // now be used to transmute any two lifetimes. +} + +fn need_hrtb_supertrait<'a_, 'b_, S, T: ?Sized>(x: &'a_ T) -> &'b_ T +where + S: for<'a, 'b> Supertrait<'a, 'b>, +{ + S::convert(x) +} + +struct MyStruct; +impl<'a: 'b, 'b> Supertrait<'a, 'b> for MyStruct { + fn convert(x: &'a T) -> &'b T { + x + } +} +impl<'a, 'b> Subtrait<'a, 'b, &'b &'a ()> for MyStruct {} + +fn extend_lifetime<'a, 'b, T: ?Sized>(x: &'a T) -> &'b T { + need_hrtb_subtrait::(x) +} + +fn main() { + let d; + { + let x = "Hello World".to_string(); + d = extend_lifetime(&x); + } + println!("{}", d); +} diff --git a/tests/ui/implied-bounds/normalization-nested.lifetime.stderr b/tests/ui/implied-bounds/normalization-nested.lifetime.stderr index e020230d86a4..c43cc0999f1d 100644 --- a/tests/ui/implied-bounds/normalization-nested.lifetime.stderr +++ b/tests/ui/implied-bounds/normalization-nested.lifetime.stderr @@ -1,33 +1,10 @@ -error[E0759]: `fn` parameter has lifetime `'x` but it needs to satisfy a `'static` lifetime requirement - --> $DIR/normalization-nested.rs:35:28 - | -LL | pub fn test_wfcheck<'x>(_: Map>) {} - | ^^^^^^^^^^^^^^^^ - | | - | this data with lifetime `'x`... - | ...is used and required to live as long as `'static` here - | -note: `'static` lifetime requirement introduced by this bound - --> $DIR/normalization-nested.rs:33:14 - | -LL | I::Item: 'static; - | ^^^^^^^ - -error[E0759]: `fn` parameter has lifetime `'x` but it needs to satisfy a `'static` lifetime requirement - --> $DIR/normalization-nested.rs:37:29 +error: lifetime may not live long enough + --> $DIR/normalization-nested.rs:40:5 | LL | pub fn test_borrowck<'x>(_: Map>, s: &'x str) -> &'static str { - | ^^^^^^^^^^^^^^^^ - | | - | this data with lifetime `'x`... - | ...is used and required to live as long as `'static` here - | -note: `'static` lifetime requirement introduced by this bound - --> $DIR/normalization-nested.rs:33:14 - | -LL | I::Item: 'static; - | ^^^^^^^ + | -- lifetime `'x` defined here +LL | s + | ^ returning this value requires that `'x` must outlive `'static` -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0759`. diff --git a/tests/ui/implied-bounds/normalization-nested.rs b/tests/ui/implied-bounds/normalization-nested.rs index 87903783a678..6ceb13e94731 100644 --- a/tests/ui/implied-bounds/normalization-nested.rs +++ b/tests/ui/implied-bounds/normalization-nested.rs @@ -1,17 +1,19 @@ // Test for normalization of projections that appear in the item bounds // (versus those that appear directly in the input types). -// Both revisions should pass. `lifetime` revision is a bug. // -// revisions: param_ty lifetime -// [param_ty] check-pass -// [lifetime] check-fail -// [lifetime] known-bug: #109799 +// revisions: param_ty lifetime param_ty_no_compat lifetime_no_compat + +//[param_ty] check-pass +//[param_ty_no_compat] check-pass +//[lifetime_no_compat] check-pass +//[param_ty_no_compat] compile-flags: -Zno-implied-bounds-compat +//[lifetime_no_compat] compile-flags: -Zno-implied-bounds-compat pub trait Iter { type Item; } -#[cfg(param_ty)] +#[cfg(any(param_ty, param_ty_no_compat))] impl Iter for I where I: IntoIterator, @@ -19,7 +21,7 @@ where type Item = X; } -#[cfg(lifetime)] +#[cfg(any(lifetime, lifetime_no_compat))] impl<'x, I> Iter for I where I: IntoIterator, @@ -36,6 +38,7 @@ pub fn test_wfcheck<'x>(_: Map>) {} pub fn test_borrowck<'x>(_: Map>, s: &'x str) -> &'static str { s + //[lifetime]~^ ERROR lifetime may not live long enough } fn main() {} diff --git a/tests/ui/implied-bounds/sod_service_chain.rs b/tests/ui/implied-bounds/sod_service_chain.rs index f45ced71f757..7443a29f30cb 100644 --- a/tests/ui/implied-bounds/sod_service_chain.rs +++ b/tests/ui/implied-bounds/sod_service_chain.rs @@ -1,5 +1,4 @@ -// check-pass -// Related to crater regressions on #118553 +// Found in a crater run on #118553 pub trait Debug {} @@ -30,6 +29,9 @@ impl> ServiceChainBuilder { pub fn next>( self, ) -> ServiceChainBuilder, NS> { + //~^ the associated type + //~| the associated type + //~| the associated type panic!(); } } diff --git a/tests/ui/implied-bounds/sod_service_chain.stderr b/tests/ui/implied-bounds/sod_service_chain.stderr new file mode 100644 index 000000000000..1c0ef573e7d3 --- /dev/null +++ b/tests/ui/implied-bounds/sod_service_chain.stderr @@ -0,0 +1,31 @@ +error[E0310]: the associated type `

::Error` may not live long enough + --> $DIR/sod_service_chain.rs:31:10 + | +LL | ) -> ServiceChainBuilder, NS> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the associated type `

::Error` must be valid for the static lifetime... + | ...so that the type `

::Error` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound + | +LL | ) -> ServiceChainBuilder, NS> where

::Error: 'static { + | ++++++++++++++++++++++++++++++++++++ + +error[E0310]: the associated type `::Error` may not live long enough + --> $DIR/sod_service_chain.rs:31:10 + | +LL | ) -> ServiceChainBuilder, NS> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the associated type `::Error` must be valid for the static lifetime... + | ...so that the type `::Error` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound + | +LL | ) -> ServiceChainBuilder, NS> where ::Error: 'static { + | ++++++++++++++++++++++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/inference/issue-80409.no-compat.stderr b/tests/ui/inference/issue-80409.no-compat.stderr new file mode 100644 index 000000000000..7bb4786db3a9 --- /dev/null +++ b/tests/ui/inference/issue-80409.no-compat.stderr @@ -0,0 +1,6 @@ +error: internal compiler error: error performing ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing }, value: ImpliedOutlivesBounds { ty: &'?2 mut StateContext<'?3, usize> } } + | + = query stack during panic: +end of query stack +error: aborting due to 1 previous error + diff --git a/tests/ui/inference/issue-80409.rs b/tests/ui/inference/issue-80409.rs index 80cad6dfc46e..49c9978fe155 100644 --- a/tests/ui/inference/issue-80409.rs +++ b/tests/ui/inference/issue-80409.rs @@ -1,4 +1,17 @@ -// check-pass +// This should not pass, because `usize: Fsm` does not hold. However, it currently ICEs. + +// ignore-tidy-linelength + +// revisions: compat no-compat +//[compat] check-pass +//[no-compat] compile-flags: -Zno-implied-bounds-compat +//[no-compat] check-fail +//[no-compat] known-bug: #80409 +//[no-compat] failure-status: 101 +//[no-compat] normalize-stderr-test "note: .*\n\n" -> "" +//[no-compat] normalize-stderr-test "thread 'rustc' panicked.*\n" -> "" +//[no-compat] normalize-stderr-test "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: " +//[no-compat] rustc-env:RUST_BACKTRACE=0 #![allow(unreachable_code, unused)] diff --git a/tests/ui/issues/issue-23302-1.stderr b/tests/ui/issues/issue-23302-1.stderr index 5c2758dc6090..53131f9130d9 100644 --- a/tests/ui/issues/issue-23302-1.stderr +++ b/tests/ui/issues/issue-23302-1.stderr @@ -10,11 +10,15 @@ note: ...which requires const-evaluating + checking `X::A::{constant#0}`... LL | A = X::A as isize, | ^^^^^^^^^^^^^ = note: ...which again requires simplifying constant for the type system `X::A::{constant#0}`, completing the cycle -note: cycle used when simplifying constant for the type system `X::A::{constant#0}` - --> $DIR/issue-23302-1.rs:4:9 +note: cycle used when collecting item types in top-level module + --> $DIR/issue-23302-1.rs:3:1 | -LL | A = X::A as isize, - | ^^^^^^^^^^^^^ +LL | / enum X { +LL | | A = X::A as isize, +LL | | } +LL | | +LL | | fn main() { } + | |_____________^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-23302-2.stderr b/tests/ui/issues/issue-23302-2.stderr index 93665af69dd8..d55d88762be4 100644 --- a/tests/ui/issues/issue-23302-2.stderr +++ b/tests/ui/issues/issue-23302-2.stderr @@ -10,11 +10,16 @@ note: ...which requires const-evaluating + checking `Y::A::{constant#0}`... LL | A = Y::B as isize, | ^^^^^^^^^^^^^ = note: ...which again requires simplifying constant for the type system `Y::A::{constant#0}`, completing the cycle -note: cycle used when simplifying constant for the type system `Y::A::{constant#0}` - --> $DIR/issue-23302-2.rs:4:9 +note: cycle used when collecting item types in top-level module + --> $DIR/issue-23302-2.rs:3:1 | -LL | A = Y::B as isize, - | ^^^^^^^^^^^^^ +LL | / enum Y { +LL | | A = Y::B as isize, +LL | | B, +LL | | } +LL | | +LL | | fn main() { } + | |_____________^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-23302-3.stderr b/tests/ui/issues/issue-23302-3.stderr index b3e933a21718..e23957c6de75 100644 --- a/tests/ui/issues/issue-23302-3.stderr +++ b/tests/ui/issues/issue-23302-3.stderr @@ -20,11 +20,15 @@ note: ...which requires const-evaluating + checking `B`... LL | const B: i32 = A; | ^ = note: ...which again requires simplifying constant for the type system `A`, completing the cycle -note: cycle used when simplifying constant for the type system `A` +note: cycle used when linting top-level module --> $DIR/issue-23302-3.rs:1:1 | -LL | const A: i32 = B; - | ^^^^^^^^^^^^ +LL | / const A: i32 = B; +LL | | +LL | | const B: i32 = A; +LL | | +LL | | fn main() { } + | |_____________^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: aborting due to 1 previous error diff --git a/tests/ui/layout/issue-112048-unsizing-niche.rs b/tests/ui/layout/issue-112048-unsizing-niche.rs index 23588ba36ee5..e59e063df99b 100644 --- a/tests/ui/layout/issue-112048-unsizing-niche.rs +++ b/tests/ui/layout/issue-112048-unsizing-niche.rs @@ -2,7 +2,6 @@ // Check that unsizing does not change which field is considered for niche layout. -#![feature(offset_of)] #![allow(dead_code)] #[derive(Clone)] diff --git a/tests/ui/layout/unsafe-cell-hides-niche.rs b/tests/ui/layout/unsafe-cell-hides-niche.rs index 8d6cea109336..e87c402f8f96 100644 --- a/tests/ui/layout/unsafe-cell-hides-niche.rs +++ b/tests/ui/layout/unsafe-cell-hides-niche.rs @@ -17,7 +17,7 @@ use std::sync::{Mutex, RwLock}; struct Wrapper(#[allow(dead_code)] T); #[repr(transparent)] -struct Transparent(#[allow(dead_code)] T); +struct Transparent(T); struct NoNiche(UnsafeCell); diff --git a/tests/ui/lifetimes/lifetime-errors/issue_74400.rs b/tests/ui/lifetimes/lifetime-errors/issue_74400.rs index ddb8bacce8f9..f17e0a678c96 100644 --- a/tests/ui/lifetimes/lifetime-errors/issue_74400.rs +++ b/tests/ui/lifetimes/lifetime-errors/issue_74400.rs @@ -11,6 +11,8 @@ fn f(data: &[T], key: impl Fn(&T) -> S) { fn g(data: &[T]) { f(data, identity) //~^ ERROR the parameter type + //~| ERROR the parameter type + //~| ERROR the parameter type //~| ERROR mismatched types //~| ERROR implementation of `FnOnce` is not general } diff --git a/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr b/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr index 677f918fe932..beb838d2ff83 100644 --- a/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr +++ b/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr @@ -12,6 +12,36 @@ help: consider adding an explicit lifetime bound LL | fn g(data: &[T]) { | +++++++++ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/issue_74400.rs:12:5 + | +LL | f(data, identity) + | ^^^^^^^^^^^^^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider adding an explicit lifetime bound + | +LL | fn g(data: &[T]) { + | +++++++++ + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/issue_74400.rs:12:5 + | +LL | f(data, identity) + | ^^^^^^^^^^^^^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider adding an explicit lifetime bound + | +LL | fn g(data: &[T]) { + | +++++++++ + error[E0308]: mismatched types --> $DIR/issue_74400.rs:12:5 | @@ -35,7 +65,7 @@ LL | f(data, identity) = note: `fn(&'2 T) -> &'2 T {identity::<&'2 T>}` must implement `FnOnce<(&'1 T,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 T,)>`, for some specific lifetime `'2` -error: aborting due to 3 previous errors +error: aborting due to 5 previous errors Some errors have detailed explanations: E0308, E0310. For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/lint/dead-code/offset-of-correct-param-env.rs b/tests/ui/lint/dead-code/offset-of-correct-param-env.rs index 2c6fcef25004..ae81a2524396 100644 --- a/tests/ui/lint/dead-code/offset-of-correct-param-env.rs +++ b/tests/ui/lint/dead-code/offset-of-correct-param-env.rs @@ -1,6 +1,6 @@ // check-pass -#![feature(offset_of)] +#![feature(offset_of_nested)] #![deny(dead_code)] // This struct contains a projection that can only be normalized after getting the field type. diff --git a/tests/ui/lint/dead-code/offset-of.rs b/tests/ui/lint/dead-code/offset-of.rs index da91de3862fc..5269426d2ff3 100644 --- a/tests/ui/lint/dead-code/offset-of.rs +++ b/tests/ui/lint/dead-code/offset-of.rs @@ -1,4 +1,4 @@ -#![feature(offset_of)] +#![feature(offset_of_nested)] #![deny(dead_code)] use std::mem::offset_of; diff --git a/tests/ui/lint/dead-code/type-in-transparent.rs b/tests/ui/lint/dead-code/type-in-transparent.rs new file mode 100644 index 000000000000..5dd6f93fd031 --- /dev/null +++ b/tests/ui/lint/dead-code/type-in-transparent.rs @@ -0,0 +1,14 @@ +// Verify that we do not warn on fields that are part of transparent types. +// check-pass +#![deny(dead_code)] + +#[repr(transparent)] +struct NamedStruct { field: u8 } + +#[repr(transparent)] +struct TupleStruct(u8); + +fn main() { + let _ = NamedStruct { field: 1 }; + let _ = TupleStruct(1); +} diff --git a/tests/ui/lint/large_assignments/box_rc_arc_allowed.stderr b/tests/ui/lint/large_assignments/box_rc_arc_allowed.stderr index b45cbe5da4dc..fefb3a9621b5 100644 --- a/tests/ui/lint/large_assignments/box_rc_arc_allowed.stderr +++ b/tests/ui/lint/large_assignments/box_rc_arc_allowed.stderr @@ -1,8 +1,8 @@ error: moving 9999 bytes - --> $DIR/box_rc_arc_allowed.rs:16:13 + --> $DIR/box_rc_arc_allowed.rs:16:25 | LL | let _ = NotBox::new([0; 9999]); - | ^^^^^^^^^^^^^^^^^^^^^^ value moved from here + | ^^^^^^^^^ value moved from here | = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` note: the lint level is defined here diff --git a/tests/ui/lint/large_assignments/copy_into_fn.rs b/tests/ui/lint/large_assignments/copy_into_fn.rs new file mode 100644 index 000000000000..ee204bf7af17 --- /dev/null +++ b/tests/ui/lint/large_assignments/copy_into_fn.rs @@ -0,0 +1,24 @@ +// build-fail + +#![feature(large_assignments)] +#![move_size_limit = "1000"] +#![deny(large_assignments)] +#![allow(unused)] + +// We want copy semantics, because moving data into functions generally do not +// translate to actual `memcpy`s. +#[derive(Copy, Clone)] +struct Data([u8; 9999]); + +fn main() { + one_arg(Data([0; 9999])); //~ ERROR large_assignments + + // each individual large arg shall have its own span + many_args(Data([0; 9999]), true, Data([0; 9999])); + //~^ ERROR large_assignments + //~| ERROR large_assignments +} + +fn one_arg(a: Data) {} + +fn many_args(a: Data, b: bool, c: Data) {} diff --git a/tests/ui/lint/large_assignments/copy_into_fn.stderr b/tests/ui/lint/large_assignments/copy_into_fn.stderr new file mode 100644 index 000000000000..f05fc33e17e1 --- /dev/null +++ b/tests/ui/lint/large_assignments/copy_into_fn.stderr @@ -0,0 +1,31 @@ +error: moving 9999 bytes + --> $DIR/copy_into_fn.rs:14:13 + | +LL | one_arg(Data([0; 9999])); + | ^^^^^^^^^^^^^^^ value moved from here + | + = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` +note: the lint level is defined here + --> $DIR/copy_into_fn.rs:5:9 + | +LL | #![deny(large_assignments)] + | ^^^^^^^^^^^^^^^^^ + +error: moving 9999 bytes + --> $DIR/copy_into_fn.rs:17:15 + | +LL | many_args(Data([0; 9999]), true, Data([0; 9999])); + | ^^^^^^^^^^^^^^^ value moved from here + | + = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` + +error: moving 9999 bytes + --> $DIR/copy_into_fn.rs:17:38 + | +LL | many_args(Data([0; 9999]), true, Data([0; 9999])); + | ^^^^^^^^^^^^^^^ value moved from here + | + = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/moves/move-fn-self-receiver.stderr b/tests/ui/moves/move-fn-self-receiver.stderr index 462deacbe8d6..17f48f5f7bf7 100644 --- a/tests/ui/moves/move-fn-self-receiver.stderr +++ b/tests/ui/moves/move-fn-self-receiver.stderr @@ -55,10 +55,15 @@ note: `Foo::use_box_self` takes ownership of the receiver `self`, which moves `b | LL | fn use_box_self(self: Box) {} | ^^^^ -help: you could `clone` the value and consume it, if the `Box: Clone` trait bound could be satisfied +help: you could `clone` the value and consume it, if the `Foo: Clone` trait bound could be satisfied | LL | boxed_foo.clone().use_box_self(); | ++++++++ +help: consider annotating `Foo` with `#[derive(Clone)]` + | +LL + #[derive(Clone)] +LL | struct Foo; + | error[E0382]: use of moved value: `pin_box_foo` --> $DIR/move-fn-self-receiver.rs:46:5 @@ -75,10 +80,15 @@ note: `Foo::use_pin_box_self` takes ownership of the receiver `self`, which move | LL | fn use_pin_box_self(self: Pin>) {} | ^^^^ -help: you could `clone` the value and consume it, if the `Box: Clone` trait bound could be satisfied +help: you could `clone` the value and consume it, if the `Foo: Clone` trait bound could be satisfied | LL | pin_box_foo.clone().use_pin_box_self(); | ++++++++ +help: consider annotating `Foo` with `#[derive(Clone)]` + | +LL + #[derive(Clone)] +LL | struct Foo; + | error[E0505]: cannot move out of `mut_foo` because it is borrowed --> $DIR/move-fn-self-receiver.rs:50:5 diff --git a/tests/ui/object-safety/avoid-ice-on-warning-2.rs b/tests/ui/object-safety/avoid-ice-on-warning-2.rs new file mode 100644 index 000000000000..cd34362d3dd5 --- /dev/null +++ b/tests/ui/object-safety/avoid-ice-on-warning-2.rs @@ -0,0 +1,9 @@ +fn id(f: Copy) -> usize { +//~^ WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! +//~| ERROR the trait `Copy` cannot be made into an object + f() +} +fn main() {} diff --git a/tests/ui/object-safety/avoid-ice-on-warning-2.stderr b/tests/ui/object-safety/avoid-ice-on-warning-2.stderr new file mode 100644 index 000000000000..2755eee6f352 --- /dev/null +++ b/tests/ui/object-safety/avoid-ice-on-warning-2.stderr @@ -0,0 +1,50 @@ +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/avoid-ice-on-warning-2.rs:1:13 + | +LL | fn id(f: Copy) -> usize { + | ^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `Copy` it is not object safe, so it can't be `dyn` + = note: `#[warn(bare_trait_objects)]` on by default +help: use a new generic type parameter, constrained by `Copy` + | +LL | fn id(f: T) -> usize { + | +++++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn id(f: impl Copy) -> usize { + | ++++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/avoid-ice-on-warning-2.rs:1:13 + | +LL | fn id(f: Copy) -> usize { + | ^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `Copy` it is not object safe, so it can't be `dyn` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: use a new generic type parameter, constrained by `Copy` + | +LL | fn id(f: T) -> usize { + | +++++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn id(f: impl Copy) -> usize { + | ++++ + +error[E0038]: the trait `Copy` cannot be made into an object + --> $DIR/avoid-ice-on-warning-2.rs:1:13 + | +LL | fn id(f: Copy) -> usize { + | ^^^^ `Copy` cannot be made into an object + | + = note: the trait cannot be made into an object because it requires `Self: Sized` + = note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + +error: aborting due to 1 previous error; 2 warnings emitted + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/avoid-ice-on-warning-3.rs b/tests/ui/object-safety/avoid-ice-on-warning-3.rs new file mode 100644 index 000000000000..caaf4d0fd99a --- /dev/null +++ b/tests/ui/object-safety/avoid-ice-on-warning-3.rs @@ -0,0 +1,17 @@ +trait B { fn f(a: A) -> A; } +//~^ WARN trait objects without an explicit `dyn` are deprecated +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition +//~| WARN this is accepted in the current edition +//~| WARN this is accepted in the current edition +//~| ERROR the trait `A` cannot be made into an object +trait A { fn g(b: B) -> B; } +//~^ WARN trait objects without an explicit `dyn` are deprecated +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition +//~| WARN this is accepted in the current edition +//~| WARN this is accepted in the current edition +//~| ERROR the trait `B` cannot be made into an object +fn main() {} diff --git a/tests/ui/object-safety/avoid-ice-on-warning-3.stderr b/tests/ui/object-safety/avoid-ice-on-warning-3.stderr new file mode 100644 index 000000000000..0fc67770b96d --- /dev/null +++ b/tests/ui/object-safety/avoid-ice-on-warning-3.stderr @@ -0,0 +1,148 @@ +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/avoid-ice-on-warning-3.rs:9:19 + | +LL | trait A { fn g(b: B) -> B; } + | ^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `B` it is not object safe, so it can't be `dyn` + = note: `#[warn(bare_trait_objects)]` on by default +help: use a new generic type parameter, constrained by `B` + | +LL | trait A { fn g(b: T) -> B; } + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | trait A { fn g(b: impl B) -> B; } + | ++++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/avoid-ice-on-warning-3.rs:9:25 + | +LL | trait A { fn g(b: B) -> B; } + | ^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: `B` is not object safe, use `impl B` to return an opaque type, as long as you return a single underlying type + | +LL | trait A { fn g(b: B) -> impl B; } + | ++++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/avoid-ice-on-warning-3.rs:1:19 + | +LL | trait B { fn f(a: A) -> A; } + | ^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `A` it is not object safe, so it can't be `dyn` +help: use a new generic type parameter, constrained by `A` + | +LL | trait B { fn f(a: T) -> A; } + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | trait B { fn f(a: impl A) -> A; } + | ++++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/avoid-ice-on-warning-3.rs:1:25 + | +LL | trait B { fn f(a: A) -> A; } + | ^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: `A` is not object safe, use `impl A` to return an opaque type, as long as you return a single underlying type + | +LL | trait B { fn f(a: A) -> impl A; } + | ++++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/avoid-ice-on-warning-3.rs:1:19 + | +LL | trait B { fn f(a: A) -> A; } + | ^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `A` it is not object safe, so it can't be `dyn` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: use a new generic type parameter, constrained by `A` + | +LL | trait B { fn f(a: T) -> A; } + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | trait B { fn f(a: impl A) -> A; } + | ++++ + +error[E0038]: the trait `A` cannot be made into an object + --> $DIR/avoid-ice-on-warning-3.rs:1:19 + | +LL | trait B { fn f(a: A) -> A; } + | ^ `A` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/avoid-ice-on-warning-3.rs:9:14 + | +LL | trait A { fn g(b: B) -> B; } + | - ^ ...because associated function `g` has no `self` parameter + | | + | this trait cannot be made into an object... +help: consider turning `g` into a method by giving it a `&self` argument + | +LL | trait A { fn g(&self, b: B) -> B; } + | ++++++ +help: alternatively, consider constraining `g` so it does not apply to trait objects + | +LL | trait A { fn g(b: B) -> B where Self: Sized; } + | +++++++++++++++++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/avoid-ice-on-warning-3.rs:9:19 + | +LL | trait A { fn g(b: B) -> B; } + | ^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `B` it is not object safe, so it can't be `dyn` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: use a new generic type parameter, constrained by `B` + | +LL | trait A { fn g(b: T) -> B; } + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | trait A { fn g(b: impl B) -> B; } + | ++++ + +error[E0038]: the trait `B` cannot be made into an object + --> $DIR/avoid-ice-on-warning-3.rs:9:19 + | +LL | trait A { fn g(b: B) -> B; } + | ^ `B` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/avoid-ice-on-warning-3.rs:1:14 + | +LL | trait B { fn f(a: A) -> A; } + | - ^ ...because associated function `f` has no `self` parameter + | | + | this trait cannot be made into an object... +help: consider turning `f` into a method by giving it a `&self` argument + | +LL | trait B { fn f(&self, a: A) -> A; } + | ++++++ +help: alternatively, consider constraining `f` so it does not apply to trait objects + | +LL | trait B { fn f(a: A) -> A where Self: Sized; } + | +++++++++++++++++ + +error: aborting due to 2 previous errors; 6 warnings emitted + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/avoid-ice-on-warning.rs b/tests/ui/object-safety/avoid-ice-on-warning.rs new file mode 100644 index 000000000000..d2a1eeb5286b --- /dev/null +++ b/tests/ui/object-safety/avoid-ice-on-warning.rs @@ -0,0 +1,6 @@ +fn call_this(f: F) : Fn(&str) + call_that {} +//~^ ERROR return types are denoted using `->` +//~| ERROR cannot find trait `call_that` in this scope +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! +fn main() {} diff --git a/tests/ui/object-safety/avoid-ice-on-warning.stderr b/tests/ui/object-safety/avoid-ice-on-warning.stderr new file mode 100644 index 000000000000..1046f177e829 --- /dev/null +++ b/tests/ui/object-safety/avoid-ice-on-warning.stderr @@ -0,0 +1,29 @@ +error: return types are denoted using `->` + --> $DIR/avoid-ice-on-warning.rs:1:23 + | +LL | fn call_this(f: F) : Fn(&str) + call_that {} + | ^ help: use `->` instead + +error[E0405]: cannot find trait `call_that` in this scope + --> $DIR/avoid-ice-on-warning.rs:1:36 + | +LL | fn call_this(f: F) : Fn(&str) + call_that {} + | ^^^^^^^^^ not found in this scope + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/avoid-ice-on-warning.rs:1:25 + | +LL | fn call_this(f: F) : Fn(&str) + call_that {} + | ^^^^^^^^^^^^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `#[warn(bare_trait_objects)]` on by default +help: `Fn(&str) + call_that` is not object safe, use `impl Fn(&str) + call_that` to return an opaque type, as long as you return a single underlying type + | +LL | fn call_this(f: F) : impl Fn(&str) + call_that {} + | ++++ + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0405`. diff --git a/tests/ui/object-safety/erroneous_signature.rs b/tests/ui/object-safety/erroneous_signature.rs new file mode 100644 index 000000000000..cc1841cc4b2a --- /dev/null +++ b/tests/ui/object-safety/erroneous_signature.rs @@ -0,0 +1,17 @@ +trait Foo { + fn err(&self) -> MissingType; + //~^ ERROR cannot find type `MissingType` in this scope +} + +impl Foo for i32 { + fn err(&self) -> MissingType { + //~^ ERROR cannot find type `MissingType` in this scope + 0 + } +} + +fn coerce(x: &i32) -> &dyn Foo { + x +} + +fn main() {} diff --git a/tests/ui/object-safety/erroneous_signature.stderr b/tests/ui/object-safety/erroneous_signature.stderr new file mode 100644 index 000000000000..f3b14ffe34c3 --- /dev/null +++ b/tests/ui/object-safety/erroneous_signature.stderr @@ -0,0 +1,15 @@ +error[E0412]: cannot find type `MissingType` in this scope + --> $DIR/erroneous_signature.rs:2:22 + | +LL | fn err(&self) -> MissingType; + | ^^^^^^^^^^^ not found in this scope + +error[E0412]: cannot find type `MissingType` in this scope + --> $DIR/erroneous_signature.rs:7:22 + | +LL | fn err(&self) -> MissingType { + | ^^^^^^^^^^^ not found in this scope + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/offset-of/offset-of-arg-count.rs b/tests/ui/offset-of/offset-of-arg-count.rs index 7b92698c25e8..c86e61a61a72 100644 --- a/tests/ui/offset-of/offset-of-arg-count.rs +++ b/tests/ui/offset-of/offset-of-arg-count.rs @@ -1,5 +1,3 @@ -#![feature(offset_of)] - use std::mem::offset_of; fn main() { diff --git a/tests/ui/offset-of/offset-of-arg-count.stderr b/tests/ui/offset-of/offset-of-arg-count.stderr index af0d42de30d6..4cb24b3d034b 100644 --- a/tests/ui/offset-of/offset-of-arg-count.stderr +++ b/tests/ui/offset-of/offset-of-arg-count.stderr @@ -1,5 +1,5 @@ error: unexpected end of macro invocation - --> $DIR/offset-of-arg-count.rs:6:34 + --> $DIR/offset-of-arg-count.rs:4:34 | LL | offset_of!(NotEnoughArguments); | ^ missing tokens in macro arguments @@ -8,7 +8,7 @@ note: while trying to match `,` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL error: unexpected end of macro invocation - --> $DIR/offset-of-arg-count.rs:7:45 + --> $DIR/offset-of-arg-count.rs:5:45 | LL | offset_of!(NotEnoughArgumentsWithAComma, ); | ^ missing tokens in macro arguments @@ -17,7 +17,7 @@ note: while trying to match meta-variable `$fields:expr` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL error: no rules expected the token `too` - --> $DIR/offset-of-arg-count.rs:8:34 + --> $DIR/offset-of-arg-count.rs:6:34 | LL | offset_of!(Container, field, too many arguments); | ^^^ no rules expected this token in macro call @@ -25,25 +25,25 @@ LL | offset_of!(Container, field, too many arguments); = note: while trying to match sequence end error: unexpected token: `)` - --> $DIR/offset-of-arg-count.rs:11:21 + --> $DIR/offset-of-arg-count.rs:9:21 | LL | offset_of!(S, f.); | ^ error: unexpected token: `,` - --> $DIR/offset-of-arg-count.rs:12:21 + --> $DIR/offset-of-arg-count.rs:10:21 | LL | offset_of!(S, f.,); | ^ error: offset_of expects dot-separated field and variant names - --> $DIR/offset-of-arg-count.rs:13:19 + --> $DIR/offset-of-arg-count.rs:11:19 | LL | offset_of!(S, f..); | ^^^ error: offset_of expects dot-separated field and variant names - --> $DIR/offset-of-arg-count.rs:14:19 + --> $DIR/offset-of-arg-count.rs:12:19 | LL | offset_of!(S, f..,); | ^^^ diff --git a/tests/ui/offset-of/offset-of-dst-field.rs b/tests/ui/offset-of/offset-of-dst-field.rs index e393b159e64d..016ebfadd142 100644 --- a/tests/ui/offset-of/offset-of-dst-field.rs +++ b/tests/ui/offset-of/offset-of-dst-field.rs @@ -1,4 +1,4 @@ -#![feature(offset_of, extern_types)] +#![feature(extern_types)] use std::mem::offset_of; diff --git a/tests/ui/offset-of/offset-of-enum.rs b/tests/ui/offset-of/offset-of-enum.rs index a2d6aace47da..cb2f04786ac5 100644 --- a/tests/ui/offset-of/offset-of-enum.rs +++ b/tests/ui/offset-of/offset-of-enum.rs @@ -1,4 +1,4 @@ -#![feature(offset_of, offset_of_enum)] +#![feature(offset_of_enum, offset_of_nested)] use std::mem::offset_of; diff --git a/tests/ui/offset-of/offset-of-inference.rs b/tests/ui/offset-of/offset-of-inference.rs index ba87574eae04..1b1ae25e1ee6 100644 --- a/tests/ui/offset-of/offset-of-inference.rs +++ b/tests/ui/offset-of/offset-of-inference.rs @@ -1,7 +1,5 @@ // Test that inference types in `offset_of!` don't ICE. -#![feature(offset_of)] - struct Foo { x: T, } diff --git a/tests/ui/offset-of/offset-of-inference.stderr b/tests/ui/offset-of/offset-of-inference.stderr index 1845822f11db..8bd104ed7e27 100644 --- a/tests/ui/offset-of/offset-of-inference.stderr +++ b/tests/ui/offset-of/offset-of-inference.stderr @@ -1,5 +1,5 @@ error[E0282]: type annotations needed - --> $DIR/offset-of-inference.rs:10:35 + --> $DIR/offset-of-inference.rs:8:35 | LL | let _ = core::mem::offset_of!(Foo<_>, x); | ^^^^^^ cannot infer type diff --git a/tests/ui/offset-of/offset-of-must-use.rs b/tests/ui/offset-of/offset-of-must-use.rs index e30145d7a2fe..e4b092fcedf3 100644 --- a/tests/ui/offset-of/offset-of-must-use.rs +++ b/tests/ui/offset-of/offset-of-must-use.rs @@ -1,6 +1,5 @@ // check-pass -#![feature(offset_of)] #![warn(unused)] fn main() { diff --git a/tests/ui/offset-of/offset-of-must-use.stderr b/tests/ui/offset-of/offset-of-must-use.stderr index 5fe387a72553..b6d88e098d00 100644 --- a/tests/ui/offset-of/offset-of-must-use.stderr +++ b/tests/ui/offset-of/offset-of-must-use.stderr @@ -1,11 +1,11 @@ warning: unused return value of `must_use` that must be used - --> $DIR/offset-of-must-use.rs:7:5 + --> $DIR/offset-of-must-use.rs:6:5 | LL | core::mem::offset_of!((String,), 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/offset-of-must-use.rs:4:9 + --> $DIR/offset-of-must-use.rs:3:9 | LL | #![warn(unused)] | ^^^^^^ diff --git a/tests/ui/offset-of/offset-of-output-type.rs b/tests/ui/offset-of/offset-of-output-type.rs index 50c2e93841f9..76a33154ba3d 100644 --- a/tests/ui/offset-of/offset-of-output-type.rs +++ b/tests/ui/offset-of/offset-of-output-type.rs @@ -1,5 +1,3 @@ -#![feature(offset_of)] - use std::mem::offset_of; struct S { diff --git a/tests/ui/offset-of/offset-of-output-type.stderr b/tests/ui/offset-of/offset-of-output-type.stderr index 233d49876436..34ad931d0caa 100644 --- a/tests/ui/offset-of/offset-of-output-type.stderr +++ b/tests/ui/offset-of/offset-of-output-type.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/offset-of-output-type.rs:12:17 + --> $DIR/offset-of-output-type.rs:10:17 | LL | let _: u8 = offset_of!(S, v); | ^^^^^^^^^^^^^^^^ expected `u8`, found `usize` @@ -7,7 +7,7 @@ LL | let _: u8 = offset_of!(S, v); = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types - --> $DIR/offset-of-output-type.rs:13:18 + --> $DIR/offset-of-output-type.rs:11:18 | LL | let _: u16 = offset_of!(S, v); | ^^^^^^^^^^^^^^^^ expected `u16`, found `usize` @@ -15,7 +15,7 @@ LL | let _: u16 = offset_of!(S, v); = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types - --> $DIR/offset-of-output-type.rs:14:18 + --> $DIR/offset-of-output-type.rs:12:18 | LL | let _: u32 = offset_of!(S, v); | ^^^^^^^^^^^^^^^^ expected `u32`, found `usize` @@ -23,7 +23,7 @@ LL | let _: u32 = offset_of!(S, v); = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types - --> $DIR/offset-of-output-type.rs:15:18 + --> $DIR/offset-of-output-type.rs:13:18 | LL | let _: u64 = offset_of!(S, v); | ^^^^^^^^^^^^^^^^ expected `u64`, found `usize` @@ -31,7 +31,7 @@ LL | let _: u64 = offset_of!(S, v); = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types - --> $DIR/offset-of-output-type.rs:16:20 + --> $DIR/offset-of-output-type.rs:14:20 | LL | let _: isize = offset_of!(S, v); | ^^^^^^^^^^^^^^^^ expected `isize`, found `usize` @@ -39,7 +39,7 @@ LL | let _: isize = offset_of!(S, v); = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types - --> $DIR/offset-of-output-type.rs:19:5 + --> $DIR/offset-of-output-type.rs:17:5 | LL | fn main() { | - expected `()` because of default return type diff --git a/tests/ui/offset-of/offset-of-private.rs b/tests/ui/offset-of/offset-of-private.rs index b7affdb79439..1c326b5c79a5 100644 --- a/tests/ui/offset-of/offset-of-private.rs +++ b/tests/ui/offset-of/offset-of-private.rs @@ -1,4 +1,4 @@ -#![feature(offset_of, offset_of_enum)] +#![feature(offset_of_enum, offset_of_nested)] use std::mem::offset_of; diff --git a/tests/ui/offset-of/offset-of-self.rs b/tests/ui/offset-of/offset-of-self.rs index 04dcaf7c0a6b..1558e13b5309 100644 --- a/tests/ui/offset-of/offset-of-self.rs +++ b/tests/ui/offset-of/offset-of-self.rs @@ -1,4 +1,4 @@ -#![feature(offset_of)] +#![feature(offset_of_nested)] use std::mem::offset_of; diff --git a/tests/ui/offset-of/offset-of-tuple-nested.rs b/tests/ui/offset-of/offset-of-tuple-nested.rs index 59b02e3c5c43..212176b24271 100644 --- a/tests/ui/offset-of/offset-of-tuple-nested.rs +++ b/tests/ui/offset-of/offset-of-tuple-nested.rs @@ -2,7 +2,7 @@ // Test for issue #112204 -- make sure this goes through the entire compilation pipeline, // similar to why `offset-of-unsized.rs` is also build-pass -#![feature(offset_of)] +#![feature(offset_of_nested)] use std::mem::offset_of; diff --git a/tests/ui/offset-of/offset-of-tuple.rs b/tests/ui/offset-of/offset-of-tuple.rs index b6fc1e32229a..75ba8d77f2fb 100644 --- a/tests/ui/offset-of/offset-of-tuple.rs +++ b/tests/ui/offset-of/offset-of-tuple.rs @@ -1,4 +1,4 @@ -#![feature(offset_of)] +#![feature(offset_of_nested)] #![feature(builtin_syntax)] use std::mem::offset_of; diff --git a/tests/ui/offset-of/offset-of-unsized.rs b/tests/ui/offset-of/offset-of-unsized.rs index 49c8328da5c5..b70529ed7b85 100644 --- a/tests/ui/offset-of/offset-of-unsized.rs +++ b/tests/ui/offset-of/offset-of-unsized.rs @@ -2,8 +2,6 @@ // regression test for #112051, not in `offset-of-dst` as the issue is in codegen, // and isn't triggered in the presence of typeck errors -#![feature(offset_of)] - struct S { a: u64, b: T, diff --git a/tests/ui/offset-of/offset-of-unstable-with-feature.rs b/tests/ui/offset-of/offset-of-unstable-with-feature.rs index 7d2eb46c056e..be275564a0a4 100644 --- a/tests/ui/offset-of/offset-of-unstable-with-feature.rs +++ b/tests/ui/offset-of/offset-of-unstable-with-feature.rs @@ -1,7 +1,7 @@ // check-pass // aux-build:offset-of-staged-api.rs -#![feature(offset_of, unstable_test_feature)] +#![feature(offset_of_nested, unstable_test_feature)] use std::mem::offset_of; diff --git a/tests/ui/offset-of/offset-of-unstable.rs b/tests/ui/offset-of/offset-of-unstable.rs index 1e19f2091f29..da0882abd228 100644 --- a/tests/ui/offset-of/offset-of-unstable.rs +++ b/tests/ui/offset-of/offset-of-unstable.rs @@ -1,6 +1,6 @@ // aux-build:offset-of-staged-api.rs -#![feature(offset_of)] +#![feature(offset_of_nested)] use std::mem::offset_of; diff --git a/tests/ui/packed/packed-struct-drop-aligned.rs b/tests/ui/packed/packed-struct-drop-aligned.rs index 6c2907c86e91..ddfc86f74d3c 100644 --- a/tests/ui/packed/packed-struct-drop-aligned.rs +++ b/tests/ui/packed/packed-struct-drop-aligned.rs @@ -24,7 +24,7 @@ impl<'a> Drop for Aligned<'a> { } #[repr(transparent)] -struct NotCopy(#[allow(dead_code)] u8); +struct NotCopy(u8); #[repr(packed)] struct Packed<'a>(NotCopy, Aligned<'a>); diff --git a/tests/ui/parser/attribute/attr-unquoted-ident.fixed b/tests/ui/parser/attribute/attr-unquoted-ident.fixed new file mode 100644 index 000000000000..6cdf22f7ec0e --- /dev/null +++ b/tests/ui/parser/attribute/attr-unquoted-ident.fixed @@ -0,0 +1,15 @@ +// compile-flags: -Zdeduplicate-diagnostics=yes +// run-rustfix + +fn main() { + #[cfg(key="foo")] + //~^ ERROR expected unsuffixed literal, found `foo` + //~| HELP surround the identifier with quotation marks to parse it as a string + println!(); + #[cfg(key="bar")] + println!(); + #[cfg(key="foo bar baz")] + //~^ ERROR expected unsuffixed literal, found `foo` + //~| HELP surround the identifier with quotation marks to parse it as a string + println!(); +} diff --git a/tests/ui/parser/attribute/attr-unquoted-ident.rs b/tests/ui/parser/attribute/attr-unquoted-ident.rs new file mode 100644 index 000000000000..75af015c9fee --- /dev/null +++ b/tests/ui/parser/attribute/attr-unquoted-ident.rs @@ -0,0 +1,15 @@ +// compile-flags: -Zdeduplicate-diagnostics=yes +// run-rustfix + +fn main() { + #[cfg(key=foo)] + //~^ ERROR expected unsuffixed literal, found `foo` + //~| HELP surround the identifier with quotation marks to parse it as a string + println!(); + #[cfg(key="bar")] + println!(); + #[cfg(key=foo bar baz)] + //~^ ERROR expected unsuffixed literal, found `foo` + //~| HELP surround the identifier with quotation marks to parse it as a string + println!(); +} diff --git a/tests/ui/parser/attribute/attr-unquoted-ident.stderr b/tests/ui/parser/attribute/attr-unquoted-ident.stderr new file mode 100644 index 000000000000..bc028f39be61 --- /dev/null +++ b/tests/ui/parser/attribute/attr-unquoted-ident.stderr @@ -0,0 +1,24 @@ +error: expected unsuffixed literal, found `foo` + --> $DIR/attr-unquoted-ident.rs:5:15 + | +LL | #[cfg(key=foo)] + | ^^^ + | +help: surround the identifier with quotation marks to parse it as a string + | +LL | #[cfg(key="foo")] + | + + + +error: expected unsuffixed literal, found `foo` + --> $DIR/attr-unquoted-ident.rs:11:15 + | +LL | #[cfg(key=foo bar baz)] + | ^^^ + | +help: surround the identifier with quotation marks to parse it as a string + | +LL | #[cfg(key="foo bar baz")] + | + + + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/bad-let-else-statement.rs b/tests/ui/parser/bad-let-else-statement.rs index 7b927c89ba07..a42e8c41c2ef 100644 --- a/tests/ui/parser/bad-let-else-statement.rs +++ b/tests/ui/parser/bad-let-else-statement.rs @@ -161,4 +161,29 @@ fn q() { }; } +fn r() { + let ok = format_args!("") else { return; }; + + let bad = format_args! {""} else { return; }; + //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed +} + +fn s() { + macro_rules! a { + () => { {} } + } + + macro_rules! b { + (1) => { + let x = a!() else { return; }; + }; + (2) => { + let x = a! {} else { return; }; + //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed + }; + } + + b!(1); b!(2); +} + fn main() {} diff --git a/tests/ui/parser/bad-let-else-statement.stderr b/tests/ui/parser/bad-let-else-statement.stderr index 7cbda25e417f..887455913d84 100644 --- a/tests/ui/parser/bad-let-else-statement.stderr +++ b/tests/ui/parser/bad-let-else-statement.stderr @@ -228,5 +228,31 @@ LL | x LL ~ }) else { | -error: aborting due to 17 previous errors +error: right curly brace `}` before `else` in a `let...else` statement not allowed + --> $DIR/bad-let-else-statement.rs:167:31 + | +LL | let bad = format_args! {""} else { return; }; + | ^ + | +help: use parentheses instead of braces for this macro + | +LL | let bad = format_args! ("") else { return; }; + | ~ ~ + +error: right curly brace `}` before `else` in a `let...else` statement not allowed + --> $DIR/bad-let-else-statement.rs:181:25 + | +LL | let x = a! {} else { return; }; + | ^ +... +LL | b!(1); b!(2); + | ----- in this macro invocation + | + = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use parentheses instead of braces for this macro + | +LL | let x = a! () else { return; }; + | ~~ + +error: aborting due to 19 previous errors diff --git a/tests/ui/parser/removed-syntax-box.fixed b/tests/ui/parser/removed-syntax/removed-syntax-box.fixed similarity index 100% rename from tests/ui/parser/removed-syntax-box.fixed rename to tests/ui/parser/removed-syntax/removed-syntax-box.fixed diff --git a/tests/ui/parser/removed-syntax-box.rs b/tests/ui/parser/removed-syntax/removed-syntax-box.rs similarity index 100% rename from tests/ui/parser/removed-syntax-box.rs rename to tests/ui/parser/removed-syntax/removed-syntax-box.rs diff --git a/tests/ui/parser/removed-syntax-box.stderr b/tests/ui/parser/removed-syntax/removed-syntax-box.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-box.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-box.stderr diff --git a/tests/ui/parser/removed-syntax-closure-lifetime.rs b/tests/ui/parser/removed-syntax/removed-syntax-closure-lifetime.rs similarity index 100% rename from tests/ui/parser/removed-syntax-closure-lifetime.rs rename to tests/ui/parser/removed-syntax/removed-syntax-closure-lifetime.rs diff --git a/tests/ui/parser/removed-syntax-closure-lifetime.stderr b/tests/ui/parser/removed-syntax/removed-syntax-closure-lifetime.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-closure-lifetime.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-closure-lifetime.stderr diff --git a/tests/ui/parser/removed-syntax-enum-newtype.rs b/tests/ui/parser/removed-syntax/removed-syntax-enum-newtype.rs similarity index 100% rename from tests/ui/parser/removed-syntax-enum-newtype.rs rename to tests/ui/parser/removed-syntax/removed-syntax-enum-newtype.rs diff --git a/tests/ui/parser/removed-syntax-enum-newtype.stderr b/tests/ui/parser/removed-syntax/removed-syntax-enum-newtype.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-enum-newtype.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-enum-newtype.stderr diff --git a/tests/ui/parser/removed-syntax-field-let-2.rs b/tests/ui/parser/removed-syntax/removed-syntax-field-let-2.rs similarity index 100% rename from tests/ui/parser/removed-syntax-field-let-2.rs rename to tests/ui/parser/removed-syntax/removed-syntax-field-let-2.rs diff --git a/tests/ui/parser/removed-syntax-field-let-2.stderr b/tests/ui/parser/removed-syntax/removed-syntax-field-let-2.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-field-let-2.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-field-let-2.stderr diff --git a/tests/ui/parser/removed-syntax-field-let.rs b/tests/ui/parser/removed-syntax/removed-syntax-field-let.rs similarity index 100% rename from tests/ui/parser/removed-syntax-field-let.rs rename to tests/ui/parser/removed-syntax/removed-syntax-field-let.rs diff --git a/tests/ui/parser/removed-syntax-field-let.stderr b/tests/ui/parser/removed-syntax/removed-syntax-field-let.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-field-let.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-field-let.stderr diff --git a/tests/ui/parser/removed-syntax-field-semicolon.rs b/tests/ui/parser/removed-syntax/removed-syntax-field-semicolon.rs similarity index 100% rename from tests/ui/parser/removed-syntax-field-semicolon.rs rename to tests/ui/parser/removed-syntax/removed-syntax-field-semicolon.rs diff --git a/tests/ui/parser/removed-syntax-field-semicolon.stderr b/tests/ui/parser/removed-syntax/removed-syntax-field-semicolon.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-field-semicolon.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-field-semicolon.stderr diff --git a/tests/ui/parser/removed-syntax-fixed-vec.rs b/tests/ui/parser/removed-syntax/removed-syntax-fixed-vec.rs similarity index 100% rename from tests/ui/parser/removed-syntax-fixed-vec.rs rename to tests/ui/parser/removed-syntax/removed-syntax-fixed-vec.rs diff --git a/tests/ui/parser/removed-syntax-fixed-vec.stderr b/tests/ui/parser/removed-syntax/removed-syntax-fixed-vec.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-fixed-vec.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-fixed-vec.stderr diff --git a/tests/ui/parser/removed-syntax-fn-sigil.rs b/tests/ui/parser/removed-syntax/removed-syntax-fn-sigil.rs similarity index 100% rename from tests/ui/parser/removed-syntax-fn-sigil.rs rename to tests/ui/parser/removed-syntax/removed-syntax-fn-sigil.rs diff --git a/tests/ui/parser/removed-syntax-fn-sigil.stderr b/tests/ui/parser/removed-syntax/removed-syntax-fn-sigil.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-fn-sigil.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-fn-sigil.stderr diff --git a/tests/ui/parser/removed-syntax-mode.rs b/tests/ui/parser/removed-syntax/removed-syntax-mode.rs similarity index 100% rename from tests/ui/parser/removed-syntax-mode.rs rename to tests/ui/parser/removed-syntax/removed-syntax-mode.rs diff --git a/tests/ui/parser/removed-syntax-mode.stderr b/tests/ui/parser/removed-syntax/removed-syntax-mode.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-mode.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-mode.stderr diff --git a/tests/ui/parser/removed-syntax-mut-vec-expr.rs b/tests/ui/parser/removed-syntax/removed-syntax-mut-vec-expr.rs similarity index 100% rename from tests/ui/parser/removed-syntax-mut-vec-expr.rs rename to tests/ui/parser/removed-syntax/removed-syntax-mut-vec-expr.rs diff --git a/tests/ui/parser/removed-syntax-mut-vec-expr.stderr b/tests/ui/parser/removed-syntax/removed-syntax-mut-vec-expr.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-mut-vec-expr.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-mut-vec-expr.stderr diff --git a/tests/ui/parser/removed-syntax-mut-vec-ty.rs b/tests/ui/parser/removed-syntax/removed-syntax-mut-vec-ty.rs similarity index 100% rename from tests/ui/parser/removed-syntax-mut-vec-ty.rs rename to tests/ui/parser/removed-syntax/removed-syntax-mut-vec-ty.rs diff --git a/tests/ui/parser/removed-syntax-mut-vec-ty.stderr b/tests/ui/parser/removed-syntax/removed-syntax-mut-vec-ty.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-mut-vec-ty.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-mut-vec-ty.stderr diff --git a/tests/ui/parser/removed-syntax-ptr-lifetime.rs b/tests/ui/parser/removed-syntax/removed-syntax-ptr-lifetime.rs similarity index 100% rename from tests/ui/parser/removed-syntax-ptr-lifetime.rs rename to tests/ui/parser/removed-syntax/removed-syntax-ptr-lifetime.rs diff --git a/tests/ui/parser/removed-syntax-ptr-lifetime.stderr b/tests/ui/parser/removed-syntax/removed-syntax-ptr-lifetime.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-ptr-lifetime.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-ptr-lifetime.stderr diff --git a/tests/ui/parser/removed-syntax-record.rs b/tests/ui/parser/removed-syntax/removed-syntax-record.rs similarity index 100% rename from tests/ui/parser/removed-syntax-record.rs rename to tests/ui/parser/removed-syntax/removed-syntax-record.rs diff --git a/tests/ui/parser/removed-syntax-record.stderr b/tests/ui/parser/removed-syntax/removed-syntax-record.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-record.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-record.stderr diff --git a/tests/ui/parser/removed-syntax-static-fn.rs b/tests/ui/parser/removed-syntax/removed-syntax-static-fn.rs similarity index 100% rename from tests/ui/parser/removed-syntax-static-fn.rs rename to tests/ui/parser/removed-syntax/removed-syntax-static-fn.rs diff --git a/tests/ui/parser/removed-syntax-static-fn.stderr b/tests/ui/parser/removed-syntax/removed-syntax-static-fn.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-static-fn.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-static-fn.stderr diff --git a/tests/ui/parser/removed-syntax-uniq-mut-expr.rs b/tests/ui/parser/removed-syntax/removed-syntax-uniq-mut-expr.rs similarity index 100% rename from tests/ui/parser/removed-syntax-uniq-mut-expr.rs rename to tests/ui/parser/removed-syntax/removed-syntax-uniq-mut-expr.rs diff --git a/tests/ui/parser/removed-syntax-uniq-mut-expr.stderr b/tests/ui/parser/removed-syntax/removed-syntax-uniq-mut-expr.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-uniq-mut-expr.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-uniq-mut-expr.stderr diff --git a/tests/ui/parser/removed-syntax-uniq-mut-ty.rs b/tests/ui/parser/removed-syntax/removed-syntax-uniq-mut-ty.rs similarity index 100% rename from tests/ui/parser/removed-syntax-uniq-mut-ty.rs rename to tests/ui/parser/removed-syntax/removed-syntax-uniq-mut-ty.rs diff --git a/tests/ui/parser/removed-syntax-uniq-mut-ty.stderr b/tests/ui/parser/removed-syntax/removed-syntax-uniq-mut-ty.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-uniq-mut-ty.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-uniq-mut-ty.stderr diff --git a/tests/ui/parser/removed-syntax-with-1.rs b/tests/ui/parser/removed-syntax/removed-syntax-with-1.rs similarity index 100% rename from tests/ui/parser/removed-syntax-with-1.rs rename to tests/ui/parser/removed-syntax/removed-syntax-with-1.rs diff --git a/tests/ui/parser/removed-syntax-with-1.stderr b/tests/ui/parser/removed-syntax/removed-syntax-with-1.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-with-1.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-with-1.stderr diff --git a/tests/ui/parser/removed-syntax-with-2.rs b/tests/ui/parser/removed-syntax/removed-syntax-with-2.rs similarity index 100% rename from tests/ui/parser/removed-syntax-with-2.rs rename to tests/ui/parser/removed-syntax/removed-syntax-with-2.rs diff --git a/tests/ui/parser/removed-syntax-with-2.stderr b/tests/ui/parser/removed-syntax/removed-syntax-with-2.stderr similarity index 100% rename from tests/ui/parser/removed-syntax-with-2.stderr rename to tests/ui/parser/removed-syntax/removed-syntax-with-2.stderr diff --git a/tests/ui/pattern/never_patterns.rs b/tests/ui/pattern/never_patterns.rs deleted file mode 100644 index 915f3e75e7bf..000000000000 --- a/tests/ui/pattern/never_patterns.rs +++ /dev/null @@ -1,99 +0,0 @@ -#![feature(never_patterns)] -#![allow(incomplete_features)] - -enum Void {} - -fn main() {} - -// The classic use for empty types. -fn safe_unwrap_result(res: Result) { - let Ok(_x) = res; - // FIXME(never_patterns): These should be allowed - let (Ok(_x) | Err(!)) = &res; - //~^ ERROR: is not bound in all patterns - let (Ok(_x) | Err(&!)) = res.as_ref(); - //~^ ERROR: is not bound in all patterns -} - -// Check we only accept `!` where we want to. -fn never_pattern_location(void: Void) { - // FIXME(never_patterns): Don't accept on a non-empty type. - match Some(0) { - None => {} - Some(!), - } - // FIXME(never_patterns): Don't accept on an arbitrary type, even if there are no more branches. - match () { - () => {} - !, - } - // FIXME(never_patterns): Don't accept even on an empty branch. - match None:: { - None => {} - !, - } - // FIXME(never_patterns): Let alone if the emptiness is behind a reference. - match None::<&Void> { - None => {} - !, - } - // Participate in match ergonomics. - match &void { - ! - } - match &&void { - ! - } - match &&void { - &! - } - match &None:: { - None => {} - Some(!) - } - match None::<&Void> { - None => {} - Some(!), - } - // Accept on a composite empty type. - match None::<&(u32, Void)> { - None => {} - Some(&!), - } - // Accept on an simple empty type. - match None:: { - None => {} - Some(!), - } - match None::<&Void> { - None => {} - Some(&!), - } - match None::<&(u32, Void)> { - None => {} - Some(&(_, !)), - } -} - -fn never_and_bindings() { - let x: Result = Ok(false); - - // FIXME(never_patterns): Never patterns in or-patterns don't need to share the same bindings. - match x { - Ok(_x) | Err(&!) => {} - //~^ ERROR: is not bound in all patterns - } - let (Ok(_x) | Err(&!)) = x; - //~^ ERROR: is not bound in all patterns - - // FIXME(never_patterns): A never pattern mustn't have bindings. - match x { - Ok(_) => {} - Err(&(_b, !)), - } - match x { - Ok(_a) | Err(&(_b, !)) => {} - //~^ ERROR: is not bound in all patterns - //~| ERROR: is not bound in all patterns - } -} diff --git a/tests/ui/pattern/never_patterns.stderr b/tests/ui/pattern/never_patterns.stderr deleted file mode 100644 index 11e50debfd39..000000000000 --- a/tests/ui/pattern/never_patterns.stderr +++ /dev/null @@ -1,51 +0,0 @@ -error[E0408]: variable `_x` is not bound in all patterns - --> $DIR/never_patterns.rs:12:19 - | -LL | let (Ok(_x) | Err(!)) = &res; - | -- ^^^^^^ pattern doesn't bind `_x` - | | - | variable not in all patterns - -error[E0408]: variable `_x` is not bound in all patterns - --> $DIR/never_patterns.rs:14:19 - | -LL | let (Ok(_x) | Err(&!)) = res.as_ref(); - | -- ^^^^^^^ pattern doesn't bind `_x` - | | - | variable not in all patterns - -error[E0408]: variable `_x` is not bound in all patterns - --> $DIR/never_patterns.rs:83:18 - | -LL | Ok(_x) | Err(&!) => {} - | -- ^^^^^^^ pattern doesn't bind `_x` - | | - | variable not in all patterns - -error[E0408]: variable `_x` is not bound in all patterns - --> $DIR/never_patterns.rs:86:19 - | -LL | let (Ok(_x) | Err(&!)) = x; - | -- ^^^^^^^ pattern doesn't bind `_x` - | | - | variable not in all patterns - -error[E0408]: variable `_b` is not bound in all patterns - --> $DIR/never_patterns.rs:95:9 - | -LL | Ok(_a) | Err(&(_b, !)) => {} - | ^^^^^^ -- variable not in all patterns - | | - | pattern doesn't bind `_b` - -error[E0408]: variable `_a` is not bound in all patterns - --> $DIR/never_patterns.rs:95:18 - | -LL | Ok(_a) | Err(&(_b, !)) => {} - | -- ^^^^^^^^^^^^^ pattern doesn't bind `_a` - | | - | variable not in all patterns - -error: aborting due to 6 previous errors - -For more information about this error, try `rustc --explain E0408`. diff --git a/tests/ui/proc-macro/auxiliary/api/mod.rs b/tests/ui/proc-macro/auxiliary/api/mod.rs index 3bea5d75779a..5a533b9e17e1 100644 --- a/tests/ui/proc-macro/auxiliary/api/mod.rs +++ b/tests/ui/proc-macro/auxiliary/api/mod.rs @@ -1,10 +1,12 @@ // force-host // no-prefer-dynamic +// edition: 2021 #![crate_type = "proc-macro"] #![crate_name = "proc_macro_api_tests"] #![feature(proc_macro_span)] #![feature(proc_macro_byte_character)] +#![feature(proc_macro_c_str_literals)] #![deny(dead_code)] // catch if a test function is never called extern crate proc_macro; diff --git a/tests/ui/proc-macro/auxiliary/api/parse.rs b/tests/ui/proc-macro/auxiliary/api/parse.rs index 07c9f464961a..801c616c8040 100644 --- a/tests/ui/proc-macro/auxiliary/api/parse.rs +++ b/tests/ui/proc-macro/auxiliary/api/parse.rs @@ -19,10 +19,8 @@ fn test_display_literal() { "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0", ); - assert_eq!( - Literal::string("a \t ❤ ' \" \u{1}").to_string(), - "\"a \\t ❤ ' \\\" \\u{1}\"", - ); + assert_eq!(Literal::string("a \t ❤ ' \" \u{1}").to_string(), "\"a \\t ❤ ' \\\" \\u{1}\"",); + assert_eq!(Literal::c_string(c"\'\"\x7f\u{7fff}").to_string(), r#"c"\'\"\x7f\xe7\xbf\xbf""#); assert_eq!(Literal::character('a').to_string(), "'a'"); assert_eq!(Literal::character('\t').to_string(), "'\\t'"); assert_eq!(Literal::character('❤').to_string(), "'❤'"); @@ -41,6 +39,7 @@ fn test_parse_literal() { assert_eq!("b'a'".parse::().unwrap().to_string(), "b'a'"); assert_eq!("\"\n\"".parse::().unwrap().to_string(), "\"\n\""); assert_eq!("b\"\"".parse::().unwrap().to_string(), "b\"\""); + assert_eq!("c\"\"".parse::().unwrap().to_string(), "c\"\""); assert_eq!("r##\"\"##".parse::().unwrap().to_string(), "r##\"\"##"); assert_eq!("10ulong".parse::().unwrap().to_string(), "10ulong"); assert_eq!("-10ulong".parse::().unwrap().to_string(), "-10ulong"); diff --git a/tests/ui/proc-macro/test.rs b/tests/ui/proc-macro/test.rs index c96aa73175f2..2ec620720202 100644 --- a/tests/ui/proc-macro/test.rs +++ b/tests/ui/proc-macro/test.rs @@ -1,5 +1,6 @@ // check-pass // aux-build:api/mod.rs +// edition: 2021 //! This is for everything that *would* be a #[test] inside of libproc_macro, //! except for the fact that proc_macro objects are not capable of existing diff --git a/tests/ui/recursion/recursive-static-definition.stderr b/tests/ui/recursion/recursive-static-definition.stderr index 570d203d07f7..4fc3ee68ebc2 100644 --- a/tests/ui/recursion/recursive-static-definition.stderr +++ b/tests/ui/recursion/recursive-static-definition.stderr @@ -1,15 +1,10 @@ error[E0391]: cycle detected when const-evaluating + checking `FOO` - --> $DIR/recursive-static-definition.rs:1:1 - | -LL | pub static FOO: u32 = FOO; - | ^^^^^^^^^^^^^^^^^^^ - | -note: ...which requires const-evaluating + checking `FOO`... --> $DIR/recursive-static-definition.rs:1:23 | LL | pub static FOO: u32 = FOO; | ^^^ - = note: ...which again requires const-evaluating + checking `FOO`, completing the cycle + | + = note: ...which immediately requires const-evaluating + checking `FOO` again note: cycle used when linting top-level module --> $DIR/recursive-static-definition.rs:1:1 | diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/bindings.rs b/tests/ui/rfcs/rfc-0000-never_patterns/bindings.rs new file mode 100644 index 000000000000..f2e238ecb136 --- /dev/null +++ b/tests/ui/rfcs/rfc-0000-never_patterns/bindings.rs @@ -0,0 +1,46 @@ +#![feature(never_patterns)] +#![allow(incomplete_features)] + +enum Void {} + +fn main() { + let x: Result = Ok(false); + + match x { + Ok(_x) | Err(&!) => {} + } + let (Ok(_x) | Err(&!)) = x; + + match x { + Ok(_) => {} + Err(&(_a, _b, !)), + //~^ ERROR: never patterns cannot contain variable bindings + //~| ERROR: never patterns cannot contain variable bindings + } + match x { + Ok(_ok) | Err(&(_a, _b, !)) => {} + //~^ ERROR: never patterns cannot contain variable bindings + //~| ERROR: never patterns cannot contain variable bindings + } +} + +fn void(void: Void) { + let (_a | !) = void; + let (! | _a) = void; + let ((_a, _) | (_a, _ | !)) = (true, void); + let (_a | (! | !,)) = (void,); + let ((_a,) | (!,)) = (void,); + + let (_a, (! | !)) = (true, void); + //~^ ERROR: never patterns cannot contain variable bindings + let (_a, (_b | !)) = (true, void); + + let _a @ ! = void; + //~^ ERROR: never patterns cannot contain variable bindings + let _a @ (_b | !) = void; + let (_a @ (), !) = ((), void); + //~^ ERROR: never patterns cannot contain variable bindings + let (_a | + (_b @ (_, !))) = (true, void); + //~^ ERROR: never patterns cannot contain variable bindings +} diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/bindings.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/bindings.stderr new file mode 100644 index 000000000000..b69ba80af88e --- /dev/null +++ b/tests/ui/rfcs/rfc-0000-never_patterns/bindings.stderr @@ -0,0 +1,50 @@ +error: never patterns cannot contain variable bindings + --> $DIR/bindings.rs:16:15 + | +LL | Err(&(_a, _b, !)), + | ^^ help: use a wildcard `_` instead + +error: never patterns cannot contain variable bindings + --> $DIR/bindings.rs:16:19 + | +LL | Err(&(_a, _b, !)), + | ^^ help: use a wildcard `_` instead + +error: never patterns cannot contain variable bindings + --> $DIR/bindings.rs:21:25 + | +LL | Ok(_ok) | Err(&(_a, _b, !)) => {} + | ^^ help: use a wildcard `_` instead + +error: never patterns cannot contain variable bindings + --> $DIR/bindings.rs:21:29 + | +LL | Ok(_ok) | Err(&(_a, _b, !)) => {} + | ^^ help: use a wildcard `_` instead + +error: never patterns cannot contain variable bindings + --> $DIR/bindings.rs:34:10 + | +LL | let (_a, (! | !)) = (true, void); + | ^^ help: use a wildcard `_` instead + +error: never patterns cannot contain variable bindings + --> $DIR/bindings.rs:38:9 + | +LL | let _a @ ! = void; + | ^^ help: use a wildcard `_` instead + +error: never patterns cannot contain variable bindings + --> $DIR/bindings.rs:41:10 + | +LL | let (_a @ (), !) = ((), void); + | ^^ help: use a wildcard `_` instead + +error: never patterns cannot contain variable bindings + --> $DIR/bindings.rs:44:14 + | +LL | (_b @ (_, !))) = (true, void); + | ^^ help: use a wildcard `_` instead + +error: aborting due to 8 previous errors + diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/parse.rs b/tests/ui/rfcs/rfc-0000-never_patterns/parse.rs index f254b9c201c1..566bb0716464 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/parse.rs +++ b/tests/ui/rfcs/rfc-0000-never_patterns/parse.rs @@ -71,6 +71,7 @@ fn parse(x: Void) { let ! = x; let y @ ! = x; + //~^ ERROR: never patterns cannot contain variable bindings } fn foo(!: Void) {} diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/parse.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/parse.stderr index e81a13a3967c..17d1b7e0d43b 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/parse.stderr +++ b/tests/ui/rfcs/rfc-0000-never_patterns/parse.stderr @@ -22,6 +22,12 @@ error: top-level or-patterns are not allowed in `let` bindings LL | let Ok(_) | Err(!) = &res; // Disallowed; see #82048. | ^^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(Ok(_) | Err(!))` +error: never patterns cannot contain variable bindings + --> $DIR/parse.rs:73:9 + | +LL | let y @ ! = x; + | ^ help: use a wildcard `_` instead + error: a guard on a never pattern will never be run --> $DIR/parse.rs:31:20 | @@ -40,5 +46,5 @@ error: a guard on a never pattern will never be run LL | never!() if true, | ^^^^ help: remove this guard -error: aborting due to 7 previous errors +error: aborting due to 8 previous errors diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/typeck.fail.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.fail.stderr new file mode 100644 index 000000000000..013a8b53a550 --- /dev/null +++ b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.fail.stderr @@ -0,0 +1,66 @@ +error: mismatched types + --> $DIR/typeck.rs:25:9 + | +LL | !, + | ^ a never pattern must be used on an uninhabited type + | + = note: the matched value is of type `()` + +error: mismatched types + --> $DIR/typeck.rs:29:9 + | +LL | !, + | ^ a never pattern must be used on an uninhabited type + | + = note: the matched value is of type `(i32, bool)` + +error: mismatched types + --> $DIR/typeck.rs:33:13 + | +LL | (_, !), + | ^ a never pattern must be used on an uninhabited type + | + = note: the matched value is of type `bool` + +error: mismatched types + --> $DIR/typeck.rs:38:14 + | +LL | Some(!), + | ^ a never pattern must be used on an uninhabited type + | + = note: the matched value is of type `i32` + +error: mismatched types + --> $DIR/typeck.rs:45:9 + | +LL | !, + | ^ a never pattern must be used on an uninhabited type + | + = note: the matched value is of type `()` + +error: mismatched types + --> $DIR/typeck.rs:52:9 + | +LL | !, + | ^ a never pattern must be used on an uninhabited type + | + = note: the matched value is of type `Option` + +error: mismatched types + --> $DIR/typeck.rs:57:9 + | +LL | !, + | ^ a never pattern must be used on an uninhabited type + | + = note: the matched value is of type `[Void]` + +error: mismatched types + --> $DIR/typeck.rs:63:9 + | +LL | !, + | ^ a never pattern must be used on an uninhabited type + | + = note: the matched value is of type `Option<&Void>` + +error: aborting due to 8 previous errors + diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs new file mode 100644 index 000000000000..31a23fa002c3 --- /dev/null +++ b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs @@ -0,0 +1,125 @@ +// revisions: pass fail +//[pass] check-pass +//[fail] check-fail +#![feature(never_patterns)] +#![feature(exhaustive_patterns)] +#![allow(incomplete_features)] + +#[derive(Copy, Clone)] +enum Void {} + +fn main() {} + +// The classic use for empty types. +fn safe_unwrap_result(res: Result) { + let Ok(_x) = res; + let (Ok(_x) | Err(!)) = &res; + let (Ok(_x) | Err(!)) = res.as_ref(); +} + +// Check we only accept `!` where we want to. +#[cfg(fail)] +fn never_pattern_typeck_fail(void: Void) { + // Don't accept on a non-empty type. + match () { + !, + //[fail]~^ ERROR: mismatched types + } + match (0, false) { + !, + //[fail]~^ ERROR: mismatched types + } + match (0, false) { + (_, !), + //[fail]~^ ERROR: mismatched types + } + match Some(0) { + None => {} + Some(!), + //[fail]~^ ERROR: mismatched types + } + + // Don't accept on an arbitrary type, even if there are no more branches. + match () { + () => {} + !, + //[fail]~^ ERROR: mismatched types + } + + // Don't accept even on an empty branch. + match None:: { + None => {} + !, + //[fail]~^ ERROR: mismatched types + } + match (&[] as &[Void]) { + [] => {} + !, + //[fail]~^ ERROR: mismatched types + } + // Let alone if the emptiness is behind a reference. + match None::<&Void> { + None => {} + !, + //[fail]~^ ERROR: mismatched types + } +} + +#[cfg(pass)] +fn never_pattern_typeck_pass(void: Void) { + // Participate in match ergonomics. + match &void { + !, + } + match &&void { + !, + } + match &&void { + &!, + } + match &None:: { + None => {} + Some(!), + } + match None::<&Void> { + None => {} + Some(!), + } + + // Accept on a directly empty type. + match void { + !, + } + match &void { + &!, + } + match None:: { + None => {} + Some(!), + } + match None::<&Void> { + None => {} + Some(&!), + } + match None::<&(u32, Void)> { + None => {} + Some(&(_, !)), + } + match (&[] as &[Void]) { + [] => {} + [!], + } + // Accept on a composite empty type. + match None::<&(u32, Void)> { + None => {} + Some(&!), + } + match None::<&(u32, Void)> { + None => {} + Some(!), + } + match None::<&Result> { + None => {} + Some(!), + } +} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr index 5210a6942010..e5b9493b3ce1 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr @@ -7,6 +7,16 @@ LL | impl A for T { LL | impl const A for T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation -error: aborting due to 1 previous error +error[E0308]: mismatched types + --> $DIR/specializing-constness-2.rs:27:5 + | +LL | ::a(); + | ^^^^^^^^^^^^^ expected `host`, found `true` + | + = note: expected constant `host` + found constant `true` -For more information about this error, try `rustc --explain E0119`. +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0119, E0308. +For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs index e20ca50b88f9..2f9ca09f3a5d 100644 Binary files a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs and b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs differ diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.stderr b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.stderr index ff9006f6f97f..a05dea3ff07e 100644 Binary files a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.stderr and b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.stderr differ diff --git a/tests/ui/single-use-lifetime/issue-117965.rs b/tests/ui/single-use-lifetime/issue-117965.rs new file mode 100644 index 000000000000..5eb2a03e13da --- /dev/null +++ b/tests/ui/single-use-lifetime/issue-117965.rs @@ -0,0 +1,18 @@ +#![deny(single_use_lifetimes)] + +pub enum Data<'a> { + Borrowed(&'a str), + Owned(String), +} + +impl<'a> Data<'a> { + pub fn get<'b: 'a>(&'b self) -> &'a str { + //~^ ERROR lifetime parameter `'b` only used once + match &self { + Self::Borrowed(val) => val, + Self::Owned(val) => &val, + } + } +} + +fn main() {} diff --git a/tests/ui/single-use-lifetime/issue-117965.stderr b/tests/ui/single-use-lifetime/issue-117965.stderr new file mode 100644 index 000000000000..ed14ab92f4d1 --- /dev/null +++ b/tests/ui/single-use-lifetime/issue-117965.stderr @@ -0,0 +1,16 @@ +error: lifetime parameter `'b` only used once + --> $DIR/issue-117965.rs:9:16 + | +LL | pub fn get<'b: 'a>(&'b self) -> &'a str { + | ^^ -- ...is used only here + | | + | this lifetime... + | +note: the lint level is defined here + --> $DIR/issue-117965.rs:1:9 + | +LL | #![deny(single_use_lifetimes)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/specialization/allow_internal_unstable.rs b/tests/ui/specialization/allow_internal_unstable.rs new file mode 100644 index 000000000000..317782b7b728 --- /dev/null +++ b/tests/ui/specialization/allow_internal_unstable.rs @@ -0,0 +1,18 @@ +// check-pass +// test for #119950 +// compile-flags: --crate-type lib + +#![allow(internal_features)] +#![feature(allow_internal_unstable)] + +#[allow_internal_unstable(min_specialization)] +macro_rules! test { + () => { + struct T(U); + trait Tr {} + impl Tr for T {} + impl Tr for T {} + } +} + +test! {} diff --git a/tests/ui/specialization/ctfe/default-assoc-const.rs b/tests/ui/specialization/ctfe/default-assoc-const.rs new file mode 100644 index 000000000000..bb3b735caa31 --- /dev/null +++ b/tests/ui/specialization/ctfe/default-assoc-const.rs @@ -0,0 +1,18 @@ +//! Regression test for revealing associated types through specialization during const eval. +// check-pass +#![feature(specialization)] +//~^ WARNING the feature `specialization` is incomplete and may not be safe to use + +trait Foo { + const ASSOC: usize; +} + +impl Foo for u32 { + default const ASSOC: usize = 0; +} + +fn foo() -> [u8; 0] { + [0; ::ASSOC] +} + +fn main() {} diff --git a/tests/ui/specialization/ctfe/default-assoc-const.stderr b/tests/ui/specialization/ctfe/default-assoc-const.stderr new file mode 100644 index 000000000000..933b6dcf8f99 --- /dev/null +++ b/tests/ui/specialization/ctfe/default-assoc-const.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/default-assoc-const.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/ctfe/default-assoc-type.rs b/tests/ui/specialization/ctfe/default-assoc-type.rs new file mode 100644 index 000000000000..3624a0f160c5 --- /dev/null +++ b/tests/ui/specialization/ctfe/default-assoc-type.rs @@ -0,0 +1,27 @@ +//! Regression test showing that we can access associated types during const eval, +//! even if they rely on specialization. +// check-pass +#![feature(specialization)] +//~^ WARNING the feature `specialization` is incomplete and may not be safe to use + +trait Foo { + type Assoc: Trait; +} + +impl Foo for Vec { + default type Assoc = u32; +} + +trait Trait { + const ASSOC: usize; +} + +impl Trait for u32 { + const ASSOC: usize = 0; +} + +fn foo() -> [u8; 0] { + [0; < as Foo>::Assoc as Trait>::ASSOC] +} + +fn main() {} diff --git a/tests/ui/specialization/ctfe/default-assoc-type.stderr b/tests/ui/specialization/ctfe/default-assoc-type.stderr new file mode 100644 index 000000000000..23fa213caffb --- /dev/null +++ b/tests/ui/specialization/ctfe/default-assoc-type.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/default-assoc-type.rs:4:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.rs b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.rs new file mode 100644 index 000000000000..f48c3d124dda --- /dev/null +++ b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.rs @@ -0,0 +1,23 @@ +// edition:2021 +#![allow(bare_trait_objects)] +trait A: Sized { + fn f(a: A) -> A; + //~^ ERROR trait objects must include the `dyn` keyword + //~| ERROR trait objects must include the `dyn` keyword + //~| ERROR associated item referring to unboxed trait object for its own trait + //~| ERROR the trait `A` cannot be made into an object +} +trait B { + fn f(a: B) -> B; + //~^ ERROR trait objects must include the `dyn` keyword + //~| ERROR trait objects must include the `dyn` keyword + //~| ERROR associated item referring to unboxed trait object for its own trait + //~| ERROR the trait `B` cannot be made into an object +} +trait C { + fn f(&self, a: C) -> C; + //~^ ERROR trait objects must include the `dyn` keyword + //~| ERROR trait objects must include the `dyn` keyword +} + +fn main() {} diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.stderr b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.stderr new file mode 100644 index 000000000000..73d5a24f8313 --- /dev/null +++ b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.stderr @@ -0,0 +1,168 @@ +error: associated item referring to unboxed trait object for its own trait + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:13 + | +LL | trait A: Sized { + | - in this trait +LL | fn f(a: A) -> A; + | ^ ^ + | +help: you might have meant to use `Self` to refer to the implementing type + | +LL | fn f(a: Self) -> Self; + | ~~~~ ~~~~ + +error[E0038]: the trait `A` cannot be made into an object + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:13 + | +LL | fn f(a: A) -> A; + | ^ `A` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:3:10 + | +LL | trait A: Sized { + | - ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + +error: associated item referring to unboxed trait object for its own trait + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:13 + | +LL | trait B { + | - in this trait +LL | fn f(a: B) -> B; + | ^ ^ + | +help: you might have meant to use `Self` to refer to the implementing type + | +LL | fn f(a: Self) -> Self; + | ~~~~ ~~~~ + +error[E0038]: the trait `B` cannot be made into an object + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:13 + | +LL | fn f(a: B) -> B; + | ^ `B` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:8 + | +LL | trait B { + | - this trait cannot be made into an object... +LL | fn f(a: B) -> B; + | ^ ...because associated function `f` has no `self` parameter +help: consider turning `f` into a method by giving it a `&self` argument + | +LL | fn f(&self, a: B) -> B; + | ++++++ +help: alternatively, consider constraining `f` so it does not apply to trait objects + | +LL | fn f(a: B) -> B where Self: Sized; + | +++++++++++++++++ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:13 + | +LL | fn f(a: A) -> A; + | ^ + | +help: use a new generic type parameter, constrained by `A` + | +LL | fn f(a: T) -> A; + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn f(a: impl A) -> A; + | ++++ +help: alternatively, use a trait object to accept any type that implements `A`, accessing its methods at runtime using dynamic dispatch + | +LL | fn f(a: &dyn A) -> A; + | ++++ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:19 + | +LL | fn f(a: A) -> A; + | ^ + | +help: use `impl A` to return an opaque type, as long as you return a single underlying type + | +LL | fn f(a: A) -> impl A; + | ++++ +help: alternatively, you can return an owned trait object + | +LL | fn f(a: A) -> Box; + | +++++++ + + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:13 + | +LL | fn f(a: B) -> B; + | ^ + | +help: use a new generic type parameter, constrained by `B` + | +LL | fn f(a: T) -> B; + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn f(a: impl B) -> B; + | ++++ +help: alternatively, use a trait object to accept any type that implements `B`, accessing its methods at runtime using dynamic dispatch + | +LL | fn f(a: &dyn B) -> B; + | ++++ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:19 + | +LL | fn f(a: B) -> B; + | ^ + | +help: use `impl B` to return an opaque type, as long as you return a single underlying type + | +LL | fn f(a: B) -> impl B; + | ++++ +help: alternatively, you can return an owned trait object + | +LL | fn f(a: B) -> Box; + | +++++++ + + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:20 + | +LL | fn f(&self, a: C) -> C; + | ^ + | +help: use a new generic type parameter, constrained by `C` + | +LL | fn f(&self, a: T) -> C; + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn f(&self, a: impl C) -> C; + | ++++ +help: alternatively, use a trait object to accept any type that implements `C`, accessing its methods at runtime using dynamic dispatch + | +LL | fn f(&self, a: &dyn C) -> C; + | ++++ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:26 + | +LL | fn f(&self, a: C) -> C; + | ^ + | +help: use `impl C` to return an opaque type, as long as you return a single underlying type + | +LL | fn f(&self, a: C) -> impl C; + | ++++ +help: alternatively, you can return an owned trait object + | +LL | fn f(&self, a: C) -> Box; + | +++++++ + + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0038, E0782. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.rs b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.rs new file mode 100644 index 000000000000..a598e883f3fd --- /dev/null +++ b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.rs @@ -0,0 +1,17 @@ +// edition:2021 +#![allow(bare_trait_objects)] +trait A: Sized { + fn f(a: dyn A) -> dyn A; + //~^ ERROR associated item referring to unboxed trait object for its own trait + //~| ERROR the trait `A` cannot be made into an object +} +trait B { + fn f(a: dyn B) -> dyn B; + //~^ ERROR associated item referring to unboxed trait object for its own trait + //~| ERROR the trait `B` cannot be made into an object +} +trait C { + fn f(&self, a: dyn C) -> dyn C; +} + +fn main() {} diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.stderr b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.stderr new file mode 100644 index 000000000000..d6376be9c046 --- /dev/null +++ b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.stderr @@ -0,0 +1,65 @@ +error: associated item referring to unboxed trait object for its own trait + --> $DIR/object-unsafe-trait-should-use-self-2021.rs:4:13 + | +LL | trait A: Sized { + | - in this trait +LL | fn f(a: dyn A) -> dyn A; + | ^^^^^ ^^^^^ + | +help: you might have meant to use `Self` to refer to the implementing type + | +LL | fn f(a: Self) -> Self; + | ~~~~ ~~~~ + +error[E0038]: the trait `A` cannot be made into an object + --> $DIR/object-unsafe-trait-should-use-self-2021.rs:4:13 + | +LL | fn f(a: dyn A) -> dyn A; + | ^^^^^ `A` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-unsafe-trait-should-use-self-2021.rs:3:10 + | +LL | trait A: Sized { + | - ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + +error: associated item referring to unboxed trait object for its own trait + --> $DIR/object-unsafe-trait-should-use-self-2021.rs:9:13 + | +LL | trait B { + | - in this trait +LL | fn f(a: dyn B) -> dyn B; + | ^^^^^ ^^^^^ + | +help: you might have meant to use `Self` to refer to the implementing type + | +LL | fn f(a: Self) -> Self; + | ~~~~ ~~~~ + +error[E0038]: the trait `B` cannot be made into an object + --> $DIR/object-unsafe-trait-should-use-self-2021.rs:9:13 + | +LL | fn f(a: dyn B) -> dyn B; + | ^^^^^ `B` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-unsafe-trait-should-use-self-2021.rs:9:8 + | +LL | trait B { + | - this trait cannot be made into an object... +LL | fn f(a: dyn B) -> dyn B; + | ^ ...because associated function `f` has no `self` parameter +help: consider turning `f` into a method by giving it a `&self` argument + | +LL | fn f(&self, a: dyn B) -> dyn B; + | ++++++ +help: alternatively, consider constraining `f` so it does not apply to trait objects + | +LL | fn f(a: dyn B) -> dyn B where Self: Sized; + | +++++++++++++++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/suggestions/suggest-slice-swap.fixed b/tests/ui/suggestions/suggest-slice-swap.fixed new file mode 100644 index 000000000000..05b7ec263798 --- /dev/null +++ b/tests/ui/suggestions/suggest-slice-swap.fixed @@ -0,0 +1,9 @@ +// run-rustfix +#![allow(dead_code)] + +fn swap(arr: &mut [u32; 2]) { + arr.swap(1, 0); + //~^ ERROR cannot borrow `arr[_]` as mutable more than once at a time +} + +fn main() {} diff --git a/tests/ui/suggestions/suggest-slice-swap.rs b/tests/ui/suggestions/suggest-slice-swap.rs new file mode 100644 index 000000000000..9f3659aac163 --- /dev/null +++ b/tests/ui/suggestions/suggest-slice-swap.rs @@ -0,0 +1,9 @@ +// run-rustfix +#![allow(dead_code)] + +fn swap(arr: &mut [u32; 2]) { + std::mem::swap(&mut arr[0], &mut arr[1]); + //~^ ERROR cannot borrow `arr[_]` as mutable more than once at a time +} + +fn main() {} diff --git a/tests/ui/suggestions/suggest-slice-swap.stderr b/tests/ui/suggestions/suggest-slice-swap.stderr new file mode 100644 index 000000000000..2840fc0a7611 --- /dev/null +++ b/tests/ui/suggestions/suggest-slice-swap.stderr @@ -0,0 +1,17 @@ +error[E0499]: cannot borrow `arr[_]` as mutable more than once at a time + --> $DIR/suggest-slice-swap.rs:5:33 + | +LL | std::mem::swap(&mut arr[0], &mut arr[1]); + | -------------- ----------- ^^^^^^^^^^^ second mutable borrow occurs here + | | | + | | first mutable borrow occurs here + | first borrow later used by call + | +help: use `.swap()` to swap elements at the specified indices instead + | +LL | arr.swap(1, 0); + | ~~~~~~~~~~~~~~ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.current.stderr b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.current.stderr new file mode 100644 index 000000000000..4082d6d47e79 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.current.stderr @@ -0,0 +1,11 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/unifying-placeholders-in-query-response-2.rs:5:12 + | +LL | #![feature(non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #108185 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.next.stderr b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.next.stderr new file mode 100644 index 000000000000..4082d6d47e79 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.next.stderr @@ -0,0 +1,11 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/unifying-placeholders-in-query-response-2.rs:5:12 + | +LL | #![feature(non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #108185 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.rs b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.rs new file mode 100644 index 000000000000..bbf1a1f72db6 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.rs @@ -0,0 +1,23 @@ +// revisions: current next +//[next] compile-flags: -Znext-solver +// check-pass + +#![feature(non_lifetime_binders)] +//~^ WARN the feature `non_lifetime_binders` is incomplete + +trait Id { + type Output: ?Sized; +} + +impl Id for T { + type Output = T; +} + +trait Everyone {} +impl Everyone for T {} + +fn hello() where for ::Output: Everyone {} + +fn main() { + hello(); +} diff --git a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.current.stderr b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.current.stderr new file mode 100644 index 000000000000..040009efbde2 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.current.stderr @@ -0,0 +1,11 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/unifying-placeholders-in-query-response.rs:5:12 + | +LL | #![feature(non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #108185 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.next.stderr b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.next.stderr new file mode 100644 index 000000000000..040009efbde2 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.next.stderr @@ -0,0 +1,11 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/unifying-placeholders-in-query-response.rs:5:12 + | +LL | #![feature(non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #108185 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.rs b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.rs new file mode 100644 index 000000000000..5e28a2ba8b9b --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.rs @@ -0,0 +1,27 @@ +// revisions: current next +//[next] compile-flags: -Znext-solver +// check-pass + +#![feature(non_lifetime_binders)] +//~^ WARN the feature `non_lifetime_binders` is incomplete + +pub trait Foo { + type Bar: ?Sized; +} + +impl Foo for () { + type Bar = K; +} + +pub fn f(a: T1, b: T2) +where + T1: for Foo = T>, + T2: for Foo = >::Bar>, +{ +} + +fn it_works() { + f((), ()); +} + +fn main() {} diff --git a/tests/ui/treat-err-as-bug/err.stderr b/tests/ui/treat-err-as-bug/err.stderr index 4c5d0e5ae798..f1b61c3607b7 100644 --- a/tests/ui/treat-err-as-bug/err.stderr +++ b/tests/ui/treat-err-as-bug/err.stderr @@ -8,5 +8,5 @@ error: the compiler unexpectedly panicked. this is a bug. query stack during panic: #0 [eval_to_allocation_raw] const-evaluating + checking `C` -#1 [eval_to_allocation_raw] const-evaluating + checking `C` +#1 [lint_mod] linting top-level module end of query stack diff --git a/tests/ui/type-alias-enum-variants/self-in-enum-definition.stderr b/tests/ui/type-alias-enum-variants/self-in-enum-definition.stderr index 94113b336c33..7f80c3cfaba4 100644 --- a/tests/ui/type-alias-enum-variants/self-in-enum-definition.stderr +++ b/tests/ui/type-alias-enum-variants/self-in-enum-definition.stderr @@ -4,11 +4,6 @@ error[E0391]: cycle detected when simplifying constant for the type system `Alph LL | V3 = Self::V1 {} as u8 + 2, | ^^^^^^^^^^^^^^^^^^^^^ | -note: ...which requires simplifying constant for the type system `Alpha::V3::{constant#0}`... - --> $DIR/self-in-enum-definition.rs:5:10 - | -LL | V3 = Self::V1 {} as u8 + 2, - | ^^^^^^^^^^^^^^^^^^^^^ note: ...which requires const-evaluating + checking `Alpha::V3::{constant#0}`... --> $DIR/self-in-enum-definition.rs:5:10 | diff --git a/tests/ui/type-alias-impl-trait/closure_infer.rs b/tests/ui/type-alias-impl-trait/closure_infer.rs new file mode 100644 index 000000000000..04e2323ec4ae --- /dev/null +++ b/tests/ui/type-alias-impl-trait/closure_infer.rs @@ -0,0 +1,35 @@ +// check-pass + +// Regression test for an ICE: https://github.com/rust-lang/rust/issues/119916 + +#![feature(impl_trait_in_assoc_type)] +#![feature(type_alias_impl_trait)] + +// `impl_trait_in_assoc_type` example from the bug report. +pub trait StreamConsumer { + type BarrierStream; + fn execute() -> Self::BarrierStream; +} + +pub struct DispatchExecutor; + +impl StreamConsumer for DispatchExecutor { + type BarrierStream = impl Sized; + fn execute() -> Self::BarrierStream { + || -> _ {} + } +} + +// Functions that constrain TAITs can contain closures with an `_` in the return type. +type Foo = impl Sized; +fn foo() -> Foo { + || -> _ {} +} + +// The `_` in the closure return type can also be the TAIT itself. +type Bar = impl Sized; +fn bar() -> impl FnOnce() -> Bar { + || -> _ {} +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/in-where-clause.rs b/tests/ui/type-alias-impl-trait/in-where-clause.rs new file mode 100644 index 000000000000..0ad6e7a6f601 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/in-where-clause.rs @@ -0,0 +1,16 @@ +//! We evaluate `1 + 2` with `Reveal::All` during typeck, causing +//! us to to get the concrete type of `Bar` while computing it. +//! This again requires type checking `foo`. +#![feature(type_alias_impl_trait)] +type Bar = impl Sized; +//~^ ERROR: cycle +//~| ERROR: cycle + +fn foo() -> Bar +where + Bar: Send, +{ + [0; 1 + 2] +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/in-where-clause.stderr b/tests/ui/type-alias-impl-trait/in-where-clause.stderr new file mode 100644 index 000000000000..9c08b8f127d2 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/in-where-clause.stderr @@ -0,0 +1,50 @@ +error[E0391]: cycle detected when computing type of `Bar::{opaque#0}` + --> $DIR/in-where-clause.rs:5:12 + | +LL | type Bar = impl Sized; + | ^^^^^^^^^^ + | +note: ...which requires computing type of opaque `Bar::{opaque#0}`... + --> $DIR/in-where-clause.rs:5:12 + | +LL | type Bar = impl Sized; + | ^^^^^^^^^^ +note: ...which requires type-checking `foo`... + --> $DIR/in-where-clause.rs:9:1 + | +LL | / fn foo() -> Bar +LL | | where +LL | | Bar: Send, + | |______________^ + = note: ...which requires revealing opaque types in `[Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] }]`... + = note: ...which again requires computing type of `Bar::{opaque#0}`, completing the cycle +note: cycle used when checking that `Bar::{opaque#0}` is well-formed + --> $DIR/in-where-clause.rs:5:12 + | +LL | type Bar = impl Sized; + | ^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error[E0391]: cycle detected when computing type of opaque `Bar::{opaque#0}` + --> $DIR/in-where-clause.rs:5:12 + | +LL | type Bar = impl Sized; + | ^^^^^^^^^^ + | +note: ...which requires type-checking `foo`... + --> $DIR/in-where-clause.rs:13:9 + | +LL | [0; 1 + 2] + | ^^^^^ + = note: ...which requires evaluating trait selection obligation `Bar: core::marker::Send`... + = note: ...which again requires computing type of opaque `Bar::{opaque#0}`, completing the cycle +note: cycle used when computing type of `Bar::{opaque#0}` + --> $DIR/in-where-clause.rs:5:12 + | +LL | type Bar = impl Sized; + | ^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/type-alias-impl-trait/issue-77179.rs b/tests/ui/type-alias-impl-trait/issue-77179.rs index 093aeb4b2791..3d6c826d6ac5 100644 --- a/tests/ui/type-alias-impl-trait/issue-77179.rs +++ b/tests/ui/type-alias-impl-trait/issue-77179.rs @@ -12,3 +12,8 @@ fn test() -> Pointer<_> { fn main() { test(); } + +extern "Rust" { + fn bar() -> Pointer<_>; + //~^ ERROR: the placeholder `_` is not allowed within types +} diff --git a/tests/ui/type-alias-impl-trait/issue-77179.stderr b/tests/ui/type-alias-impl-trait/issue-77179.stderr index 68dd6570d00c..c5cacfd3cd35 100644 --- a/tests/ui/type-alias-impl-trait/issue-77179.stderr +++ b/tests/ui/type-alias-impl-trait/issue-77179.stderr @@ -7,6 +7,15 @@ LL | fn test() -> Pointer<_> { | | not allowed in type signatures | help: replace with the correct return type: `Pointer` -error: aborting due to 1 previous error +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/issue-77179.rs:17:25 + | +LL | fn bar() -> Pointer<_>; + | ^ + | | + | not allowed in type signatures + | help: use type parameters instead: `T` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/type-alias-impl-trait/nested_inference_failure.rs b/tests/ui/type-alias-impl-trait/nested_inference_failure.rs new file mode 100644 index 000000000000..d2091ca96ea0 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/nested_inference_failure.rs @@ -0,0 +1,28 @@ +// check-pass +// revisions: new old +//[new] compile-flags: -Znext-solver + +//! This test checks that we can successfully infer +//! the hidden type of `FooImpl` to be `Foo` +//! and `ImplT` to be `i32`. This test used to fail, because +//! we were unable to make the connection that the closure +//! argument is the same as the first argument of `Foo`. + +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; +use std::marker::PhantomData; + +struct Foo { + f: F, + _phantom: PhantomData, +} + +type ImplT = impl Debug; +type FooImpl = Foo; + +fn bar() -> FooImpl { + Foo:: { f: |_| (), _phantom: PhantomData } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/wf-nested.fail.stderr b/tests/ui/type-alias-impl-trait/wf-nested.fail.stderr index dcc4b8021eac..17c1f8897bf0 100644 --- a/tests/ui/type-alias-impl-trait/wf-nested.fail.stderr +++ b/tests/ui/type-alias-impl-trait/wf-nested.fail.stderr @@ -1,5 +1,5 @@ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/wf-nested.rs:55:27 + --> $DIR/wf-nested.rs:57:27 | LL | type InnerOpaque = impl Sized; | ^^^^^^^^^^ diff --git a/tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr b/tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr index 121664bd9569..f5d3a218542c 100644 --- a/tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr +++ b/tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr @@ -12,6 +12,21 @@ help: consider adding an explicit lifetime bound LL | fn test() { | +++++++++ -error: aborting due to 1 previous error +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/wf-nested.rs:46:17 + | +LL | let _ = outer.get(); + | ^^^^^^^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider adding an explicit lifetime bound + | +LL | fn test() { + | +++++++++ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/type-alias-impl-trait/wf-nested.rs b/tests/ui/type-alias-impl-trait/wf-nested.rs index de3883294891..2f90c4e00e38 100644 --- a/tests/ui/type-alias-impl-trait/wf-nested.rs +++ b/tests/ui/type-alias-impl-trait/wf-nested.rs @@ -43,7 +43,9 @@ mod pass_sound { fn test() { let outer = define::(); - let _ = outer.get(); //[pass_sound]~ ERROR `T` may not live long enough + let _ = outer.get(); + //[pass_sound]~^ ERROR `T` may not live long enough + //[pass_sound]~| ERROR `T` may not live long enough } } diff --git a/tests/ui/wf/wf-associated-const.rs b/tests/ui/wf/wf-associated-const.rs new file mode 100644 index 000000000000..629d807cb7f3 --- /dev/null +++ b/tests/ui/wf/wf-associated-const.rs @@ -0,0 +1,41 @@ +// check that associated consts can assume the impl header is well-formed. + +trait Foo<'a, 'b, T>: Sized { + const EVIL: fn(u: &'b u32) -> &'a u32; +} + +struct Evil<'a, 'b: 'a>(Option<&'a &'b ()>); + +impl<'a, 'b> Foo<'a, 'b, Evil<'a, 'b>> for () { + const EVIL: fn(&'b u32) -> &'a u32 = { |u| u }; +} + +struct IndirectEvil<'a, 'b: 'a>(Option<&'a &'b ()>); + +impl<'a, 'b> Foo<'a, 'b, ()> for IndirectEvil<'a, 'b> { + const EVIL: fn(&'b u32) -> &'a u32 = { |u| u }; +} + +impl<'a, 'b> Evil<'a, 'b> { + const INHERENT_EVIL: fn(&'b u32) -> &'a u32 = { |u| u }; +} + +// while static methods can *assume* this, we should still +// *check* that it holds at the use site. + +fn evil<'a, 'b>(b: &'b u32) -> &'a u32 { + <()>::EVIL(b) + //~^ ERROR lifetime may not live long enough +} + +fn indirect_evil<'a, 'b>(b: &'b u32) -> &'a u32 { + ::EVIL(b) + //~^ ERROR lifetime may not live long enough +} + +fn inherent_evil<'a, 'b>(b: &'b u32) -> &'a u32 { + ::INHERENT_EVIL(b) + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/wf/wf-associated-const.stderr b/tests/ui/wf/wf-associated-const.stderr new file mode 100644 index 000000000000..b0e1a118fab6 --- /dev/null +++ b/tests/ui/wf/wf-associated-const.stderr @@ -0,0 +1,38 @@ +error: lifetime may not live long enough + --> $DIR/wf-associated-const.rs:27:5 + | +LL | fn evil<'a, 'b>(b: &'b u32) -> &'a u32 { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | <()>::EVIL(b) + | ^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/wf-associated-const.rs:32:5 + | +LL | fn indirect_evil<'a, 'b>(b: &'b u32) -> &'a u32 { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | ::EVIL(b) + | ^^^^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/wf-associated-const.rs:37:5 + | +LL | fn inherent_evil<'a, 'b>(b: &'b u32) -> &'a u32 { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | ::INHERENT_EVIL(b) + | ^^^^^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/wf/wf-in-fn-type-implicit.rs b/tests/ui/wf/wf-in-fn-type-implicit.rs deleted file mode 100644 index c5ff92c88754..000000000000 --- a/tests/ui/wf/wf-in-fn-type-implicit.rs +++ /dev/null @@ -1,37 +0,0 @@ -// check-pass -// known-bug: #104005 - -// Should fail. Function type parameters with implicit type annotations are not -// checked for well-formedness, which allows incorrect borrowing. - -// In contrast, user annotations are always checked for well-formedness, and the -// commented code below is correctly rejected by the borrow checker. - -use std::fmt::Display; - -trait Displayable { - fn display(self) -> Box; -} - -impl Displayable for (T, Option<&'static T>) { - fn display(self) -> Box { - Box::new(self.0) - } -} - -fn extend_lt(val: T) -> Box -where - (T, Option): Displayable, -{ - Displayable::display((val, None)) -} - -fn main() { - // *incorrectly* compiles - let val = extend_lt(&String::from("blah blah blah")); - println!("{}", val); - - // *correctly* fails to compile - // let val = extend_lt::<_, &_>(&String::from("blah blah blah")); - // println!("{}", val); -} diff --git a/tests/ui/wf/wf-static-method.rs b/tests/ui/wf/wf-static-method.rs index 7ff195230bfe..66546ac489df 100644 --- a/tests/ui/wf/wf-static-method.rs +++ b/tests/ui/wf/wf-static-method.rs @@ -1,8 +1,4 @@ -// check that static methods don't get to assume their trait-ref -// is well-formed. -// FIXME(#27579): this is just a bug. However, our checking with -// static inherent methods isn't quite working - need to -// fix that before removing the check. +// check that static methods can assume their trait-ref is well-formed. trait Foo<'a, 'b, T>: Sized { fn make_me() -> Self { loop {} } @@ -15,7 +11,6 @@ impl<'a, 'b> Foo<'a, 'b, Evil<'a, 'b>> for () { fn make_me() -> Self { } fn static_evil(u: &'b u32) -> &'a u32 { u - //~^ ERROR lifetime may not live long enough } } @@ -25,7 +20,6 @@ impl<'a, 'b> Foo<'a, 'b, ()> for IndirectEvil<'a, 'b> { fn make_me() -> Self { IndirectEvil(None) } fn static_evil(u: &'b u32) -> &'a u32 { let me = Self::make_me(); - //~^ ERROR lifetime may not live long enough loop {} // (`me` could be used for the lifetime transmute). } } @@ -33,12 +27,11 @@ impl<'a, 'b> Foo<'a, 'b, ()> for IndirectEvil<'a, 'b> { impl<'a, 'b> Evil<'a, 'b> { fn inherent_evil(u: &'b u32) -> &'a u32 { u - //~^ ERROR lifetime may not live long enough } } -// while static methods don't get to *assume* this, we still -// *check* that they hold. +// while static methods can *assume* this, we should still +// *check* that it holds at the use site. fn evil<'a, 'b>(b: &'b u32) -> &'a u32 { <()>::static_evil(b) diff --git a/tests/ui/wf/wf-static-method.stderr b/tests/ui/wf/wf-static-method.stderr index 161609a5f86a..6c49098aad39 100644 --- a/tests/ui/wf/wf-static-method.stderr +++ b/tests/ui/wf/wf-static-method.stderr @@ -1,44 +1,5 @@ error: lifetime may not live long enough - --> $DIR/wf-static-method.rs:17:9 - | -LL | impl<'a, 'b> Foo<'a, 'b, Evil<'a, 'b>> for () { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -... -LL | u - | ^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` - | - = help: consider adding the following bound: `'b: 'a` - -error: lifetime may not live long enough - --> $DIR/wf-static-method.rs:27:18 - | -LL | impl<'a, 'b> Foo<'a, 'b, ()> for IndirectEvil<'a, 'b> { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -... -LL | let me = Self::make_me(); - | ^^^^^^^^^^^^^ requires that `'b` must outlive `'a` - | - = help: consider adding the following bound: `'b: 'a` - -error: lifetime may not live long enough - --> $DIR/wf-static-method.rs:35:9 - | -LL | impl<'a, 'b> Evil<'a, 'b> { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -LL | fn inherent_evil(u: &'b u32) -> &'a u32 { -LL | u - | ^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` - | - = help: consider adding the following bound: `'b: 'a` - -error: lifetime may not live long enough - --> $DIR/wf-static-method.rs:44:5 + --> $DIR/wf-static-method.rs:37:5 | LL | fn evil<'a, 'b>(b: &'b u32) -> &'a u32 { | -- -- lifetime `'b` defined here @@ -50,7 +11,7 @@ LL | <()>::static_evil(b) = help: consider adding the following bound: `'b: 'a` error: lifetime may not live long enough - --> $DIR/wf-static-method.rs:49:5 + --> $DIR/wf-static-method.rs:42:5 | LL | fn indirect_evil<'a, 'b>(b: &'b u32) -> &'a u32 { | -- -- lifetime `'b` defined here @@ -62,7 +23,7 @@ LL | ::static_evil(b) = help: consider adding the following bound: `'b: 'a` error: lifetime may not live long enough - --> $DIR/wf-static-method.rs:54:5 + --> $DIR/wf-static-method.rs:47:5 | LL | fn inherent_evil<'a, 'b>(b: &'b u32) -> &'a u32 { | -- -- lifetime `'b` defined here @@ -73,5 +34,5 @@ LL | ::inherent_evil(b) | = help: consider adding the following bound: `'b: 'a` -error: aborting due to 6 previous errors +error: aborting due to 3 previous errors diff --git a/triagebot.toml b/triagebot.toml index 1e1db2d16632..b684f3ca55c6 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -364,7 +364,8 @@ new_pr = true [autolabel."needs-triage"] new_issue = true exclude_labels = [ - "C-tracking-issue" + "C-tracking-issue", + "A-diagnostics", ] [autolabel."WG-trait-system-refactor"] @@ -389,15 +390,6 @@ message_on_remove = "Issue #{number}'s prioritization request has been removed." message_on_close = "Issue #{number} has been closed while requested for prioritization." message_on_reopen = "Issue #{number} has been reopened." -[notify-zulip."T-rustdoc"] -required_labels = ["I-nominated"] -zulip_stream = 266220 # #rustdoc -topic = "nominated: #{number}" -message_on_add = """\ -@*T-rustdoc* issue #{number} "{title}" has been nominated for `T-rustdoc` discussion. -""" -message_on_remove = "Issue #{number}'s nomination request has been removed." - [notify-zulip."I-types-nominated"] zulip_stream = 326866 # #T-types/nominated topic = "#{number}: {title}" @@ -640,7 +632,7 @@ cc = ["@nnethercote"] [assign] warn_non_default_branch = true contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" -users_on_vacation = ["jyn514", "spastorino"] +users_on_vacation = ["jyn514"] [assign.adhoc_groups] compiler-team = [ @@ -653,7 +645,6 @@ compiler-team = [ ] compiler-team-contributors = [ "@TaKO8Ki", - "@WaffleLapkin", "@b-naber", ] compiler = [