diff options
548 files changed, 3948 insertions, 2554 deletions
diff --git a/.mailmap b/.mailmap index a791daa681d..b548d6cc95f 100644 --- a/.mailmap +++ b/.mailmap @@ -276,7 +276,7 @@ Jacob Greenfield <xales@naveria.com> Jacob Pratt <jacob@jhpratt.dev> <the.z.cuber@gmail.com> Jacob Pratt <jacob@jhpratt.dev> <jacopratt@tesla.com> Jake Goulding <jake.goulding@integer32.com> -Jake Goulding <jake.goulding@integer32.com> <jake.goulding@gmail.com> +Jake Goulding <jake.goulding@integer32.com> <jake.goulding@gmail.com> Jake Goulding <jake.goulding@integer32.com> <shepmaster@mac.com> Jake Vossen <jake@vossen.dev> Jakob Degen <jakob.e.degen@gmail.com> <jakob@degen.com> @@ -412,6 +412,7 @@ Malo Jaffré <jaffre.malo@gmail.com> Manish Goregaokar <manishsmail@gmail.com> Mara Bos <m-ou.se@m-ou.se> Marcell Pardavi <marcell.pardavi@gmail.com> +Marco Ieni <11428655+MarcoIeni@users.noreply.github.com> Marcus Klaas de Vries <mail@marcusklaas.nl> Margaret Meyerhofer <mmeyerho@andrew.cmu.edu> <mmeyerho@andrew> Mark Mansi <markm@cs.wisc.edu> @@ -565,6 +566,9 @@ Robert Habermeier <rphmeier@gmail.com> Robert Millar <robert.millar@cantab.net> Roc Yu <rocyu@protonmail.com> Rohit Joshi <rohitjoshi@users.noreply.github.com> Rohit Joshi <rohit.joshi@capitalone.com> +Ross Smyth <18294397+RossSmyth@users.noreply.github.com> +Ross Smyth <18294397+RossSmyth@users.noreply.github.com> <crs2017@gmail.com> +Ross Smyth <18294397+RossSmyth@users.noreply.github.com> <rsmyth@electrocraft.com> Roxane Fruytier <roxane.fruytier@hotmail.com> Rui <xiongmao86dev@sina.com> Russell Johnston <rpjohnst@gmail.com> diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 33c20602dfd..97e6879c33e 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -981,6 +981,75 @@ impl BinOpKind { pub type BinOp = Spanned<BinOpKind>; +// Sometimes `BinOpKind` and `AssignOpKind` need the same treatment. The +// operations covered by `AssignOpKind` are a subset of those covered by +// `BinOpKind`, so it makes sense to convert `AssignOpKind` to `BinOpKind`. +impl From<AssignOpKind> for BinOpKind { + fn from(op: AssignOpKind) -> BinOpKind { + match op { + AssignOpKind::AddAssign => BinOpKind::Add, + AssignOpKind::SubAssign => BinOpKind::Sub, + AssignOpKind::MulAssign => BinOpKind::Mul, + AssignOpKind::DivAssign => BinOpKind::Div, + AssignOpKind::RemAssign => BinOpKind::Rem, + AssignOpKind::BitXorAssign => BinOpKind::BitXor, + AssignOpKind::BitAndAssign => BinOpKind::BitAnd, + AssignOpKind::BitOrAssign => BinOpKind::BitOr, + AssignOpKind::ShlAssign => BinOpKind::Shl, + AssignOpKind::ShrAssign => BinOpKind::Shr, + } + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)] +pub enum AssignOpKind { + /// The `+=` operator (addition) + AddAssign, + /// The `-=` operator (subtraction) + SubAssign, + /// The `*=` operator (multiplication) + MulAssign, + /// The `/=` operator (division) + DivAssign, + /// The `%=` operator (modulus) + RemAssign, + /// The `^=` operator (bitwise xor) + BitXorAssign, + /// The `&=` operator (bitwise and) + BitAndAssign, + /// The `|=` operator (bitwise or) + BitOrAssign, + /// The `<<=` operator (shift left) + ShlAssign, + /// The `>>=` operator (shift right) + ShrAssign, +} + +impl AssignOpKind { + pub fn as_str(&self) -> &'static str { + use AssignOpKind::*; + match self { + AddAssign => "+=", + SubAssign => "-=", + MulAssign => "*=", + DivAssign => "/=", + RemAssign => "%=", + BitXorAssign => "^=", + BitAndAssign => "&=", + BitOrAssign => "|=", + ShlAssign => "<<=", + ShrAssign => ">>=", + } + } + + /// AssignOps are always by value. + pub fn is_by_value(self) -> bool { + true + } +} + +pub type AssignOp = Spanned<AssignOpKind>; + /// Unary operator. /// /// Note that `&data` is not an operator, it's an `AddrOf` expression. @@ -1593,7 +1662,7 @@ pub enum ExprKind { /// An assignment with an operator. /// /// E.g., `a += 1`. - AssignOp(BinOp, P<Expr>, P<Expr>), + AssignOp(AssignOp, P<Expr>, P<Expr>), /// Access of a named (e.g., `obj.foo`) or unnamed (e.g., `obj.0`) struct field. Field(P<Expr>, Ident), /// An indexing operation (e.g., `foo[2]`). diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 4d613085d79..0b65246693d 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -570,6 +570,14 @@ impl MetaItemInner { } } + /// Returns the bool if `self` is a boolean `MetaItemInner::Literal`. + pub fn boolean_literal(&self) -> Option<bool> { + match self { + MetaItemInner::Lit(MetaItemLit { kind: LitKind::Bool(b), .. }) => Some(*b), + _ => None, + } + } + /// Returns the `MetaItem` if `self` is a `MetaItemInner::MetaItem` or if it's /// `MetaItemInner::Lit(MetaItemLit { kind: LitKind::Bool(_), .. })`. pub fn meta_item_or_bool(&self) -> Option<&MetaItemInner> { diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs index 98b1fc52ed7..1e5f414fae1 100644 --- a/compiler/rustc_ast/src/util/parser.rs +++ b/compiler/rustc_ast/src/util/parser.rs @@ -1,6 +1,6 @@ use rustc_span::kw; -use crate::ast::{self, BinOpKind, RangeLimits}; +use crate::ast::{self, AssignOpKind, BinOpKind, RangeLimits}; use crate::token::{self, Token}; /// Associative operator. @@ -9,7 +9,7 @@ pub enum AssocOp { /// A binary op. Binary(BinOpKind), /// `?=` where ? is one of the assignable BinOps - AssignOp(BinOpKind), + AssignOp(AssignOpKind), /// `=` Assign, /// `as` @@ -44,16 +44,16 @@ impl AssocOp { token::Or => Some(Binary(BinOpKind::BitOr)), token::Shl => Some(Binary(BinOpKind::Shl)), token::Shr => Some(Binary(BinOpKind::Shr)), - token::PlusEq => Some(AssignOp(BinOpKind::Add)), - token::MinusEq => Some(AssignOp(BinOpKind::Sub)), - token::StarEq => Some(AssignOp(BinOpKind::Mul)), - token::SlashEq => Some(AssignOp(BinOpKind::Div)), - token::PercentEq => Some(AssignOp(BinOpKind::Rem)), - token::CaretEq => Some(AssignOp(BinOpKind::BitXor)), - token::AndEq => Some(AssignOp(BinOpKind::BitAnd)), - token::OrEq => Some(AssignOp(BinOpKind::BitOr)), - token::ShlEq => Some(AssignOp(BinOpKind::Shl)), - token::ShrEq => Some(AssignOp(BinOpKind::Shr)), + token::PlusEq => Some(AssignOp(AssignOpKind::AddAssign)), + token::MinusEq => Some(AssignOp(AssignOpKind::SubAssign)), + token::StarEq => Some(AssignOp(AssignOpKind::MulAssign)), + token::SlashEq => Some(AssignOp(AssignOpKind::DivAssign)), + token::PercentEq => Some(AssignOp(AssignOpKind::RemAssign)), + token::CaretEq => Some(AssignOp(AssignOpKind::BitXorAssign)), + token::AndEq => Some(AssignOp(AssignOpKind::BitAndAssign)), + token::OrEq => Some(AssignOp(AssignOpKind::BitOrAssign)), + token::ShlEq => Some(AssignOp(AssignOpKind::ShlAssign)), + token::ShrEq => Some(AssignOp(AssignOpKind::ShrAssign)), token::Lt => Some(Binary(BinOpKind::Lt)), token::Le => Some(Binary(BinOpKind::Le)), token::Ge => Some(Binary(BinOpKind::Ge)), diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 52291fdfb30..80bb1e8fc41 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -274,7 +274,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } ExprKind::Assign(el, er, span) => self.lower_expr_assign(el, er, *span, e.span), ExprKind::AssignOp(op, el, er) => hir::ExprKind::AssignOp( - self.lower_binop(*op), + self.lower_assign_op(*op), self.lower_expr(el), self.lower_expr(er), ), @@ -443,6 +443,10 @@ impl<'hir> LoweringContext<'_, 'hir> { Spanned { node: b.node, span: self.lower_span(b.span) } } + fn lower_assign_op(&mut self, a: AssignOp) -> AssignOp { + Spanned { node: a.node, span: self.lower_span(a.span) } + } + fn lower_legacy_const_generics( &mut self, mut f: Expr, diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index ea60e083c4c..e312f15f05b 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -332,17 +332,19 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ast::ExprKind::TryBlock(_) => { gate!(&self, try_blocks, e.span, "`try` expression is experimental"); } - ast::ExprKind::Lit(token::Lit { kind: token::LitKind::Float, suffix, .. }) => { - match suffix { - Some(sym::f16) => { - gate!(&self, f16, e.span, "the type `f16` is unstable") - } - Some(sym::f128) => { - gate!(&self, f128, e.span, "the type `f128` is unstable") - } - _ => (), + ast::ExprKind::Lit(token::Lit { + kind: token::LitKind::Float | token::LitKind::Integer, + suffix, + .. + }) => match suffix { + Some(sym::f16) => { + gate!(&self, f16, e.span, "the type `f16` is unstable") } - } + Some(sym::f128) => { + gate!(&self, f128, e.span, "the type `f128` is unstable") + } + _ => (), + }, _ => {} } visit::walk_expr(self, e) @@ -511,6 +513,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { gate_all!(contracts, "contracts are incomplete"); gate_all!(contracts_internals, "contract internal machinery is for internal use only"); gate_all!(where_clause_attrs, "attributes in `where` clause are unstable"); + gate_all!(super_let, "`super let` is experimental"); if !visitor.features.never_patterns() { if let Some(spans) = spans.get(&sym::never_patterns) { diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index 7d9dc89bd75..df848a26d39 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -274,22 +274,22 @@ impl<'a> State<'a> { fn print_expr_binary( &mut self, - op: ast::BinOp, + op: ast::BinOpKind, lhs: &ast::Expr, rhs: &ast::Expr, fixup: FixupContext, ) { - let binop_prec = op.node.precedence(); + let binop_prec = op.precedence(); let left_prec = lhs.precedence(); let right_prec = rhs.precedence(); - let (mut left_needs_paren, right_needs_paren) = match op.node.fixity() { + let (mut left_needs_paren, right_needs_paren) = match op.fixity() { Fixity::Left => (left_prec < binop_prec, right_prec <= binop_prec), Fixity::Right => (left_prec <= binop_prec, right_prec < binop_prec), Fixity::None => (left_prec <= binop_prec, right_prec <= binop_prec), }; - match (&lhs.kind, op.node) { + match (&lhs.kind, op) { // These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is // the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead // of `(x as i32) < ...`. We need to convince it _not_ to do that. @@ -312,7 +312,7 @@ impl<'a> State<'a> { self.print_expr_cond_paren(lhs, left_needs_paren, fixup.leftmost_subexpression()); self.space(); - self.word_space(op.node.as_str()); + self.word_space(op.as_str()); self.print_expr_cond_paren(rhs, right_needs_paren, fixup.subsequent_subexpression()); } @@ -410,7 +410,7 @@ impl<'a> State<'a> { self.print_expr_method_call(seg, receiver, args, fixup); } ast::ExprKind::Binary(op, lhs, rhs) => { - self.print_expr_binary(*op, lhs, rhs, fixup); + self.print_expr_binary(op.node, lhs, rhs, fixup); } ast::ExprKind::Unary(op, expr) => { self.print_expr_unary(*op, expr, fixup); @@ -605,8 +605,7 @@ impl<'a> State<'a> { fixup.leftmost_subexpression(), ); self.space(); - self.word(op.node.as_str()); - self.word_space("="); + self.word_space(op.node.as_str()); self.print_expr_cond_paren( rhs, rhs.precedence() < ExprPrecedence::Assign, diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 7cc42260906..1f4eb0c449f 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -181,7 +181,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let closure = self.add_moved_or_invoked_closure_note(location, used_place, &mut err); let mut is_loop_move = false; - let mut in_pattern = false; let mut seen_spans = FxIndexSet::default(); for move_site in &move_site_vec { @@ -204,7 +203,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { self.suggest_ref_or_clone( mpi, &mut err, - &mut in_pattern, move_spans, moved_place.as_ref(), &mut has_suggest_reborrow, @@ -256,15 +254,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let place = &self.move_data.move_paths[mpi].place; let ty = place.ty(self.body, self.infcx.tcx).ty; - // If we're in pattern, we do nothing in favor of the previous suggestion (#80913). - // Same for if we're in a loop, see #101119. - if is_loop_move & !in_pattern && !matches!(use_spans, UseSpans::ClosureUse { .. }) { - if let ty::Ref(_, _, hir::Mutability::Mut) = ty.kind() { - // We have a `&mut` ref, we need to reborrow on each iteration (#62112). - self.suggest_reborrow(&mut err, span, moved_place); - } - } - if self.infcx.param_env.caller_bounds().iter().any(|c| { c.as_trait_clause().is_some_and(|pred| { pred.skip_binder().self_ty() == ty && self.infcx.tcx.is_fn_trait(pred.def_id()) @@ -330,7 +319,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { &self, mpi: MovePathIndex, err: &mut Diag<'infcx>, - in_pattern: &mut bool, move_spans: UseSpans<'tcx>, moved_place: PlaceRef<'tcx>, has_suggest_reborrow: &mut bool, @@ -545,7 +533,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { && !move_span.is_dummy() && !self.infcx.tcx.sess.source_map().is_imported(move_span) { - *in_pattern = true; let mut sugg = vec![(pat.span.shrink_to_lo(), "ref ".to_string())]; if let Some(pat) = finder.parent_pat { sugg.insert(0, (pat.span.shrink_to_lo(), "ref ".to_string())); diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index e8076ce77ab..ddd119e0c61 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -641,7 +641,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( .flat_map(|arg_abi| arg_abi.get_abi_param(fx.tcx).into_iter()), ); - if fx.tcx.sess.target.is_like_osx && fx.tcx.sess.target.arch == "aarch64" { + if fx.tcx.sess.target.is_like_darwin && fx.tcx.sess.target.arch == "aarch64" { // Add any padding arguments needed for Apple AArch64. // There's no need to pad the argument list unless variadic arguments are actually being // passed. diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index bcc70f4567f..c8527c3a57d 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -391,7 +391,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant data.set_align(alloc.align.bytes()); if let Some(section_name) = section_name { - let (segment_name, section_name) = if tcx.sess.target.is_like_osx { + let (segment_name, section_name) = if tcx.sess.target.is_like_darwin { // See https://github.com/llvm/llvm-project/blob/main/llvm/lib/MC/MCSectionMachO.cpp let mut parts = section_name.as_str().split(','); let Some(segment_name) = parts.next() else { diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs index bba6567774d..286e02b986b 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs @@ -58,7 +58,7 @@ impl DebugContext { // FIXME this should be configurable // macOS doesn't seem to support DWARF > 3 // 5 version is required for md5 file hash - version: if tcx.sess.target.is_like_osx { + version: if tcx.sess.target.is_like_darwin { 3 } else { // FIXME change to version 5 once the gdb and lldb shipping with the latest debian diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs index 474475f311f..acb39374628 100644 --- a/compiler/rustc_codegen_gcc/src/consts.rs +++ b/compiler/rustc_codegen_gcc/src/consts.rs @@ -131,7 +131,7 @@ impl<'gcc, 'tcx> StaticCodegenMethods for CodegenCx<'gcc, 'tcx> { // will use load-unaligned instructions instead, and thus avoiding the crash. // // We could remove this hack whenever we decide to drop macOS 10.10 support. - if self.tcx.sess.target.options.is_like_osx { + if self.tcx.sess.target.options.is_like_darwin { // The `inspect` method is okay here because we checked for provenance, and // because we are doing this access to inspect the final interpreter state // (not as part of the interpreter execution). diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index bead4c82a81..bf6138142b6 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -1024,7 +1024,7 @@ fn create_section_with_flags_asm(section_name: &str, section_flags: &str, data: } pub(crate) fn bitcode_section_name(cgcx: &CodegenContext<LlvmCodegenBackend>) -> &'static CStr { - if cgcx.target_is_like_osx { + if cgcx.target_is_like_darwin { c"__LLVM,__bitcode" } else if cgcx.target_is_like_aix { c".ipa" @@ -1077,7 +1077,7 @@ unsafe fn embed_bitcode( // and COFF we emit the sections using module level inline assembly for that // reason (see issue #90326 for historical background). unsafe { - if cgcx.target_is_like_osx + if cgcx.target_is_like_darwin || cgcx.target_is_like_aix || cgcx.target_arch == "wasm32" || cgcx.target_arch == "wasm64" @@ -1096,7 +1096,7 @@ unsafe fn embed_bitcode( let llglobal = llvm::add_global(llmod, common::val_ty(llconst), c"rustc.embedded.cmdline"); llvm::set_initializer(llglobal, llconst); - let section = if cgcx.target_is_like_osx { + let section = if cgcx.target_is_like_darwin { c"__LLVM,__cmdline" } else if cgcx.target_is_like_aix { c".info" diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index a64627eaf59..fdf62a08065 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -120,7 +120,7 @@ impl CodegenCx<'_, '_> { } // Match clang by only supporting COFF and ELF for now. - if self.tcx.sess.target.is_like_osx { + if self.tcx.sess.target.is_like_darwin { return false; } diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs index 8baa69cefe1..c216f0f4a09 100644 --- a/compiler/rustc_codegen_llvm/src/va_arg.rs +++ b/compiler/rustc_codegen_llvm/src/va_arg.rs @@ -399,7 +399,7 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(8).unwrap(), false) } // macOS / iOS AArch64 - "aarch64" if target.is_like_osx => { + "aarch64" if target.is_like_darwin => { emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(8).unwrap(), true) } "aarch64" => emit_aapcs_va_arg(bx, addr, target_ty), diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 7d411087241..1c885a2fd5f 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -959,9 +959,9 @@ fn link_natively( } } - let (level, src) = codegen_results.crate_info.lint_levels.linker_messages; + let level = codegen_results.crate_info.lint_levels.linker_messages; let lint = |msg| { - lint_level(sess, LINKER_MESSAGES, level, src, None, |diag| { + lint_level(sess, LINKER_MESSAGES, level, None, |diag| { LinkerOutput { inner: msg }.decorate_lint(diag) }) }; @@ -1012,7 +1012,7 @@ fn link_natively( // On macOS the external `dsymutil` tool is used to create the packed // debug information. Note that this will read debug information from // the objects on the filesystem which we'll clean up later. - SplitDebuginfo::Packed if sess.target.is_like_osx => { + SplitDebuginfo::Packed if sess.target.is_like_darwin => { let prog = Command::new("dsymutil").arg(out_filename).output(); match prog { Ok(prog) => { @@ -1043,7 +1043,7 @@ fn link_natively( let strip = sess.opts.cg.strip; - if sess.target.is_like_osx { + if sess.target.is_like_darwin { let stripcmd = "rust-objcopy"; match (strip, crate_type) { (Strip::Debuginfo, _) => { @@ -1241,7 +1241,7 @@ fn add_sanitizer_libraries( // Everywhere else the runtimes are currently distributed as static // libraries which should be linked to executables only. if matches!(crate_type, CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro) - && !(sess.target.is_like_osx || sess.target.is_like_msvc) + && !(sess.target.is_like_darwin || sess.target.is_like_msvc) { return; } @@ -1294,7 +1294,7 @@ fn link_sanitizer_runtime( let channel = option_env!("CFG_RELEASE_CHANNEL").map(|channel| format!("-{channel}")).unwrap_or_default(); - if sess.target.is_like_osx { + if sess.target.is_like_darwin { // On Apple platforms, the sanitizer is always built as a dylib, and // LLVM will link to `@rpath/*.dylib`, so we need to specify an // rpath to the library as well (the rpath should be absolute, see @@ -2182,7 +2182,7 @@ fn add_rpath_args( let rpath_config = RPathConfig { libs: &*libs, out_filename: out_filename.to_path_buf(), - is_like_osx: sess.target.is_like_osx, + is_like_darwin: sess.target.is_like_darwin, linker_is_gnu: sess.target.linker_flavor.is_gnu(), }; cmd.link_args(&rpath::get_rpath_linker_args(&rpath_config)); @@ -3044,7 +3044,7 @@ pub(crate) fn are_upstream_rust_objects_already_included(sess: &Session) -> bool /// - The deployment target. /// - The SDK version. fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { - if !sess.target.is_like_osx { + if !sess.target.is_like_darwin { return; } let LinkerFlavor::Darwin(cc, _) = flavor else { diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index bcf18cf57be..a09eec5dd74 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -373,7 +373,7 @@ impl<'a> GccLinker<'a> { // * On OSX they have their own linker, not binutils' // * For WebAssembly the only functional linker is LLD, which doesn't // support hint flags - !self.sess.target.is_like_osx && !self.sess.target.is_like_wasm + !self.sess.target.is_like_darwin && !self.sess.target.is_like_wasm } // Some platforms take hints about whether a library is static or dynamic. @@ -425,7 +425,7 @@ impl<'a> GccLinker<'a> { fn build_dylib(&mut self, crate_type: CrateType, out_filename: &Path) { // On mac we need to tell the linker to let this library be rpathed - if self.sess.target.is_like_osx { + if self.sess.target.is_like_darwin { if self.is_cc() { // `-dynamiclib` makes `cc` pass `-dylib` to the linker. self.cc_arg("-dynamiclib"); @@ -471,7 +471,7 @@ impl<'a> GccLinker<'a> { fn with_as_needed(&mut self, as_needed: bool, f: impl FnOnce(&mut Self)) { if !as_needed { - if self.sess.target.is_like_osx { + if self.sess.target.is_like_darwin { // FIXME(81490): ld64 doesn't support these flags but macOS 11 // has -needed-l{} / -needed_library {} // but we have no way to detect that here. @@ -486,7 +486,7 @@ impl<'a> GccLinker<'a> { f(self); if !as_needed { - if self.sess.target.is_like_osx { + if self.sess.target.is_like_darwin { // See above FIXME comment } else if self.is_gnu && !self.sess.target.is_like_windows { self.link_arg("--as-needed"); @@ -619,7 +619,7 @@ impl<'a> Linker for GccLinker<'a> { let colon = if verbatim && self.is_gnu { ":" } else { "" }; if !whole_archive { self.link_or_cc_arg(format!("-l{colon}{name}")); - } else if self.sess.target.is_like_osx { + } else if self.sess.target.is_like_darwin { // -force_load is the macOS equivalent of --whole-archive, but it // involves passing the full path to the library to link. self.link_arg("-force_load"); @@ -635,7 +635,7 @@ impl<'a> Linker for GccLinker<'a> { self.hint_static(); if !whole_archive { self.link_or_cc_arg(path); - } else if self.sess.target.is_like_osx { + } else if self.sess.target.is_like_darwin { self.link_arg("-force_load").link_arg(path); } else { self.link_arg("--whole-archive").link_arg(path).link_arg("--no-whole-archive"); @@ -670,7 +670,7 @@ impl<'a> Linker for GccLinker<'a> { // -dead_strip can't be part of the pre_link_args because it's also used // for partial linking when using multiple codegen units (-r). So we // insert it here. - if self.sess.target.is_like_osx { + if self.sess.target.is_like_darwin { self.link_arg("-dead_strip"); // If we're building a dylib, we don't use --gc-sections because LLVM @@ -728,7 +728,7 @@ impl<'a> Linker for GccLinker<'a> { fn debuginfo(&mut self, strip: Strip, _: &[PathBuf]) { // MacOS linker doesn't support stripping symbols directly anymore. - if self.sess.target.is_like_osx { + if self.sess.target.is_like_darwin { return; } @@ -795,7 +795,7 @@ impl<'a> Linker for GccLinker<'a> { debug!("EXPORTED SYMBOLS:"); - if self.sess.target.is_like_osx { + if self.sess.target.is_like_darwin { // Write a plain, newline-separated list of symbols let res: io::Result<()> = try { let mut f = File::create_buffered(&path)?; @@ -841,7 +841,7 @@ impl<'a> Linker for GccLinker<'a> { } } - if self.sess.target.is_like_osx { + if self.sess.target.is_like_darwin { self.link_arg("-exported_symbols_list").link_arg(path); } else if self.sess.target.is_like_solaris { self.link_arg("-M").link_arg(path); diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index ac9ac9bbb31..e2c009712d1 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -214,7 +214,7 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static let mut file = write::Object::new(binary_format, architecture, endianness); file.set_sub_architecture(sub_architecture); - if sess.target.is_like_osx { + if sess.target.is_like_darwin { if macho_is_arm64e(&sess.target) { file.set_macho_cpu_subtype(object::macho::CPU_SUBTYPE_ARM64E); } diff --git a/compiler/rustc_codegen_ssa/src/back/mod.rs b/compiler/rustc_codegen_ssa/src/back/mod.rs index 64b5d4569ec..875fa6cfa57 100644 --- a/compiler/rustc_codegen_ssa/src/back/mod.rs +++ b/compiler/rustc_codegen_ssa/src/back/mod.rs @@ -19,7 +19,7 @@ pub mod write; /// /// Certain optimizations also depend on the deployment target. pub fn versioned_llvm_target(sess: &Session) -> Cow<'_, str> { - if sess.target.is_like_osx { + if sess.target.is_like_darwin { apple::add_version_to_llvm_target(&sess.target.llvm_target, apple::deployment_target(sess)) .into() } else { diff --git a/compiler/rustc_codegen_ssa/src/back/rpath.rs b/compiler/rustc_codegen_ssa/src/back/rpath.rs index d633cc98ac8..7bb8979e882 100644 --- a/compiler/rustc_codegen_ssa/src/back/rpath.rs +++ b/compiler/rustc_codegen_ssa/src/back/rpath.rs @@ -9,7 +9,7 @@ use tracing::debug; pub(super) struct RPathConfig<'a> { pub libs: &'a [&'a Path], pub out_filename: PathBuf, - pub is_like_osx: bool, + pub is_like_darwin: bool, pub linker_is_gnu: bool, } @@ -63,7 +63,7 @@ fn get_rpaths_relative_to_output(config: &RPathConfig<'_>) -> Vec<OsString> { fn get_rpath_relative_to_output(config: &RPathConfig<'_>, lib: &Path) -> OsString { // Mac doesn't appear to support $ORIGIN - let prefix = if config.is_like_osx { "@loader_path" } else { "$ORIGIN" }; + let prefix = if config.is_like_darwin { "@loader_path" } else { "$ORIGIN" }; // Strip filenames let lib = lib.parent().unwrap(); diff --git a/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs b/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs index f1a30105c59..ab8fbedb812 100644 --- a/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs +++ b/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs @@ -28,7 +28,7 @@ fn test_rpath_relative() { if cfg!(target_os = "macos") { let config = &mut RPathConfig { libs: &[], - is_like_osx: true, + is_like_darwin: true, linker_is_gnu: false, out_filename: PathBuf::from("bin/rustc"), }; @@ -38,7 +38,7 @@ fn test_rpath_relative() { let config = &mut RPathConfig { libs: &[], out_filename: PathBuf::from("bin/rustc"), - is_like_osx: false, + is_like_darwin: false, linker_is_gnu: true, }; let res = get_rpath_relative_to_output(config, Path::new("lib/libstd.so")); @@ -51,7 +51,7 @@ fn test_rpath_relative_issue_119571() { let config = &mut RPathConfig { libs: &[], out_filename: PathBuf::from("rustc"), - is_like_osx: false, + is_like_darwin: false, linker_is_gnu: true, }; // Should not panic when out_filename only contains filename. diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index ccc0273280f..e816e71379a 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -352,7 +352,7 @@ pub struct CodegenContext<B: WriteBackendMethods> { pub is_pe_coff: bool, pub target_can_use_split_dwarf: bool, pub target_arch: String, - pub target_is_like_osx: bool, + pub target_is_like_darwin: bool, pub target_is_like_aix: bool, pub split_debuginfo: rustc_target::spec::SplitDebuginfo, pub split_dwarf_kind: rustc_session::config::SplitDwarfKind, @@ -1216,7 +1216,7 @@ fn start_executing_work<B: ExtraBackendMethods>( is_pe_coff: tcx.sess.target.is_like_windows, target_can_use_split_dwarf: tcx.sess.target_can_use_split_dwarf(), target_arch: tcx.sess.target.arch.to_string(), - target_is_like_osx: tcx.sess.target.is_like_osx, + target_is_like_darwin: tcx.sess.target.is_like_darwin, target_is_like_aix: tcx.sess.target.is_like_aix, split_debuginfo: tcx.sess.split_debuginfo(), split_dwarf_kind: tcx.sess.opts.unstable_opts.split_dwarf_kind, diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index a85d032f36e..8a184fc0bef 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -213,7 +213,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { // somewhat, and is subject to change in the future (which // is a good thing, because this would ideally be a bit // more firmed up). - let is_like_elf = !(tcx.sess.target.is_like_osx + let is_like_elf = !(tcx.sess.target.is_like_darwin || tcx.sess.target.is_like_windows || tcx.sess.target.is_like_wasm); codegen_fn_attrs.flags |= if is_like_elf { diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index d26d6edf314..f36e42cc6b9 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -34,7 +34,7 @@ use rustc_hir::CRATE_HIR_ID; use rustc_hir::def_id::CrateNum; use rustc_macros::{Decodable, Encodable, HashStable}; use rustc_middle::dep_graph::WorkProduct; -use rustc_middle::lint::LintLevelSource; +use rustc_middle::lint::LevelAndSource; use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; use rustc_middle::middle::dependency_format::Dependencies; use rustc_middle::middle::exported_symbols::SymbolExportKind; @@ -45,7 +45,6 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_session::Session; use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT}; use rustc_session::cstore::{self, CrateSource}; -use rustc_session::lint::Level; use rustc_session::lint::builtin::LINKER_MESSAGES; use rustc_session::utils::NativeLibKind; use rustc_span::Symbol; @@ -341,7 +340,7 @@ impl CodegenResults { /// Instead, encode exactly the information we need. #[derive(Copy, Clone, Debug, Encodable, Decodable)] pub struct CodegenLintLevels { - linker_messages: (Level, LintLevelSource), + linker_messages: LevelAndSource, } impl CodegenLintLevels { diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 496f6c86f71..61a7ec13511 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -546,7 +546,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { rustc_session::lint::builtin::LONG_RUNNING_CONST_EVAL, hir_id, ) - .0 + .level .is_error(); let span = ecx.cur_span(); ecx.tcx.emit_node_span_lint( diff --git a/compiler/rustc_data_structures/src/fx.rs b/compiler/rustc_data_structures/src/fx.rs index 80e72250470..f0db9623b67 100644 --- a/compiler/rustc_data_structures/src/fx.rs +++ b/compiler/rustc_data_structures/src/fx.rs @@ -9,6 +9,8 @@ pub type FxIndexSet<V> = indexmap::IndexSet<V, BuildHasherDefault<FxHasher>>; pub type IndexEntry<'a, K, V> = indexmap::map::Entry<'a, K, V>; pub type IndexOccupiedEntry<'a, K, V> = indexmap::map::OccupiedEntry<'a, K, V>; +pub use indexmap::set::MutableValues; + #[macro_export] macro_rules! define_id_collections { ($map_name:ident, $set_name:ident, $entry_name:ident, $key:ty) => { diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index f1dc4bb795e..21b9542d0e1 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -715,7 +715,7 @@ fn print_crate_info( // lint is unstable and feature gate isn't active, don't print continue; } - let level = lint_levels.lint_level(lint).0; + let level = lint_levels.lint_level(lint).level; println_info!("{}={}", lint.name_lower(), level.as_str()); } } @@ -807,7 +807,7 @@ fn print_crate_info( } } DeploymentTarget => { - if sess.target.is_like_osx { + if sess.target.is_like_darwin { println_info!( "{}={}", apple::deployment_target_env_var(&sess.target.os), diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index f0636b600b7..f3aeb8d224b 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -91,13 +91,13 @@ fn annotation_level_for_level(level: Level) -> annotate_snippets::Level { Level::Bug | Level::Fatal | Level::Error | Level::DelayedBug => { annotate_snippets::Level::Error } - Level::ForceWarning(_) | Level::Warning => annotate_snippets::Level::Warning, + Level::ForceWarning | Level::Warning => annotate_snippets::Level::Warning, Level::Note | Level::OnceNote => annotate_snippets::Level::Note, Level::Help | Level::OnceHelp => annotate_snippets::Level::Help, // FIXME(#59346): Not sure how to map this level Level::FailureNote => annotate_snippets::Level::Error, Level::Allow => panic!("Should not call with Allow"), - Level::Expect(_) => panic!("Should not call with Expect"), + Level::Expect => panic!("Should not call with Expect"), } } diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 9f4d2ea5c1a..794502d7aae 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -9,7 +9,7 @@ use std::thread::panicking; use rustc_data_structures::fx::FxIndexMap; use rustc_error_messages::{FluentValue, fluent_value_from_str_list_sep_by_and}; -use rustc_lint_defs::Applicability; +use rustc_lint_defs::{Applicability, LintExpectationId}; use rustc_macros::{Decodable, Encodable}; use rustc_span::source_map::Spanned; use rustc_span::{DUMMY_SP, Span, Symbol}; @@ -296,6 +296,7 @@ pub struct DiagInner { pub messages: Vec<(DiagMessage, Style)>, pub code: Option<ErrCode>, + pub lint_id: Option<LintExpectationId>, pub span: MultiSpan, pub children: Vec<Subdiag>, pub suggestions: Suggestions, @@ -324,6 +325,7 @@ impl DiagInner { pub fn new_with_messages(level: Level, messages: Vec<(DiagMessage, Style)>) -> Self { DiagInner { level, + lint_id: None, messages, code: None, span: MultiSpan::new(), @@ -346,7 +348,7 @@ impl DiagInner { match self.level { Level::Bug | Level::Fatal | Level::Error | Level::DelayedBug => true, - Level::ForceWarning(_) + Level::ForceWarning | Level::Warning | Level::Note | Level::OnceNote @@ -354,7 +356,7 @@ impl DiagInner { | Level::OnceHelp | Level::FailureNote | Level::Allow - | Level::Expect(_) => false, + | Level::Expect => false, } } @@ -365,7 +367,7 @@ impl DiagInner { pub(crate) fn is_force_warn(&self) -> bool { match self.level { - Level::ForceWarning(_) => { + Level::ForceWarning => { assert!(self.is_lint.is_some()); true } @@ -1259,6 +1261,17 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { self } } + with_fn! { with_lint_id, + /// Add an argument. + #[rustc_lint_diagnostics] + pub fn lint_id( + &mut self, + id: LintExpectationId, + ) -> &mut Self { + self.lint_id = Some(id); + self + } } + with_fn! { with_primary_message, /// Add a primary message. #[rustc_lint_diagnostics] diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index 7d7f364fec2..a6583407b7e 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -144,7 +144,7 @@ impl Emitter for JsonEmitter { // // So to avoid ICEs and confused users we "upgrade" the lint level for // those `FutureBreakageItem` to warn. - if matches!(diag.level, crate::Level::Allow | crate::Level::Expect(..)) { + if matches!(diag.level, crate::Level::Allow | crate::Level::Expect) { diag.level = crate::Level::Warning; } FutureBreakageItem { diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 80e43ede445..f5f7618285e 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -905,8 +905,8 @@ impl<'a> DiagCtxtHandle<'a> { DelayedBug => { return self.inner.borrow_mut().emit_diagnostic(diag, self.tainted_with_errors); } - ForceWarning(_) | Warning | Note | OnceNote | Help | OnceHelp | FailureNote | Allow - | Expect(_) => None, + ForceWarning | Warning | Note | OnceNote | Help | OnceHelp | FailureNote | Allow + | Expect => None, }; // FIXME(Centril, #69537): Consider reintroducing panic on overwriting a stashed diagnostic @@ -1045,7 +1045,7 @@ impl<'a> DiagCtxtHandle<'a> { // Use `ForceWarning` rather than `Warning` to guarantee emission, e.g. with a // configuration like `--cap-lints allow --force-warn bare_trait_objects`. inner.emit_diagnostic( - DiagInner::new(ForceWarning(None), DiagMessage::Str(warnings)), + DiagInner::new(ForceWarning, DiagMessage::Str(warnings)), None, ); } @@ -1450,7 +1450,7 @@ impl<'a> DiagCtxtHandle<'a> { #[rustc_lint_diagnostics] #[track_caller] pub fn struct_expect(self, msg: impl Into<DiagMessage>, id: LintExpectationId) -> Diag<'a, ()> { - Diag::new(self, Expect(id), msg) + Diag::new(self, Expect, msg).with_lint_id(id) } } @@ -1510,7 +1510,7 @@ impl DiagCtxtInner { // Future breakages aren't emitted if they're `Level::Allow` or // `Level::Expect`, but they still need to be constructed and // stashed below, so they'll trigger the must_produce_diag check. - assert_matches!(diagnostic.level, Error | Warning | Allow | Expect(_)); + assert_matches!(diagnostic.level, Error | Warning | Allow | Expect); self.future_breakage_diagnostics.push(diagnostic.clone()); } @@ -1558,7 +1558,7 @@ impl DiagCtxtInner { }; } } - ForceWarning(None) => {} // `ForceWarning(Some(...))` is below, with `Expect` + ForceWarning if diagnostic.lint_id.is_none() => {} // `ForceWarning(Some(...))` is below, with `Expect` Warning => { if !self.flags.can_emit_warnings { // We are not emitting warnings. @@ -1580,9 +1580,9 @@ impl DiagCtxtInner { } return None; } - Expect(expect_id) | ForceWarning(Some(expect_id)) => { - self.fulfilled_expectations.insert(expect_id); - if let Expect(_) = diagnostic.level { + Expect | ForceWarning => { + self.fulfilled_expectations.insert(diagnostic.lint_id.unwrap()); + if let Expect = diagnostic.level { // Nothing emitted here for expected lints. TRACK_DIAGNOSTIC(diagnostic, &mut |_| None); self.suppressed_expected_diag = true; @@ -1631,7 +1631,7 @@ impl DiagCtxtInner { if is_error { self.deduplicated_err_count += 1; - } else if matches!(diagnostic.level, ForceWarning(_) | Warning) { + } else if matches!(diagnostic.level, ForceWarning | Warning) { self.deduplicated_warn_count += 1; } self.has_printed = true; @@ -1899,9 +1899,9 @@ pub enum Level { /// A `force-warn` lint warning about the code being compiled. Does not prevent compilation /// from finishing. /// - /// The [`LintExpectationId`] is used for expected lint diagnostics. In all other cases this + /// Requires a [`LintExpectationId`] for expected lint diagnostics. In all other cases this /// should be `None`. - ForceWarning(Option<LintExpectationId>), + ForceWarning, /// A warning about the code being compiled. Does not prevent compilation from finishing. /// Will be skipped if `can_emit_warnings` is false. @@ -1926,8 +1926,8 @@ pub enum Level { /// Only used for lints. Allow, - /// Only used for lints. - Expect(LintExpectationId), + /// Only used for lints. Requires a [`LintExpectationId`] for silencing the lints. + Expect, } impl fmt::Display for Level { @@ -1943,7 +1943,7 @@ impl Level { Bug | Fatal | Error | DelayedBug => { spec.set_fg(Some(Color::Red)).set_intense(true); } - ForceWarning(_) | Warning => { + ForceWarning | Warning => { spec.set_fg(Some(Color::Yellow)).set_intense(cfg!(windows)); } Note | OnceNote => { @@ -1953,7 +1953,7 @@ impl Level { spec.set_fg(Some(Color::Cyan)).set_intense(true); } FailureNote => {} - Allow | Expect(_) => unreachable!(), + Allow | Expect => unreachable!(), } spec } @@ -1962,11 +1962,11 @@ impl Level { match self { Bug | DelayedBug => "error: internal compiler error", Fatal | Error => "error", - ForceWarning(_) | Warning => "warning", + ForceWarning | Warning => "warning", Note | OnceNote => "note", Help | OnceHelp => "help", FailureNote => "failure-note", - Allow | Expect(_) => unreachable!(), + Allow | Expect => unreachable!(), } } @@ -1977,8 +1977,7 @@ impl Level { // Can this level be used in a subdiagnostic message? fn can_be_subdiag(&self) -> bool { match self { - Bug | DelayedBug | Fatal | Error | ForceWarning(_) | FailureNote | Allow - | Expect(_) => false, + Bug | DelayedBug | Fatal | Error | ForceWarning | FailureNote | Allow | Expect => false, Warning | Note | Help | OnceNote | OnceHelp => true, } diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 87b88bb4223..710e129b609 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -629,6 +629,8 @@ declare_features! ( (unstable, strict_provenance_lints, "1.61.0", Some(130351)), /// Allows string patterns to dereference values to match them. (unstable, string_deref_patterns, "1.67.0", Some(87121)), + /// Allows `super let` statements. + (incomplete, super_let, "CURRENT_RUSTC_VERSION", Some(139076)), /// Allows subtrait items to shadow supertrait items. (unstable, supertrait_item_shadowing, "1.86.0", Some(89151)), /// Allows using `#[thread_local]` on `static` items. diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index f8af1b81ca9..1a6c15b66a4 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -10,9 +10,9 @@ use rustc_ast::{ LitKind, TraitObjectSyntax, UintTy, UnsafeBinderCastKind, }; pub use rustc_ast::{ - AttrId, AttrStyle, BinOp, BinOpKind, BindingMode, BorrowKind, BoundConstness, BoundPolarity, - ByRef, CaptureBy, DelimArgs, ImplPolarity, IsAuto, MetaItemInner, MetaItemLit, Movability, - Mutability, UnOp, + AssignOp, AssignOpKind, AttrId, AttrStyle, BinOp, BinOpKind, BindingMode, BorrowKind, + BoundConstness, BoundPolarity, ByRef, CaptureBy, DelimArgs, ImplPolarity, IsAuto, + MetaItemInner, MetaItemLit, Movability, Mutability, UnOp, }; use rustc_attr_data_structures::AttributeKind; use rustc_data_structures::fingerprint::Fingerprint; @@ -2648,7 +2648,7 @@ pub enum ExprKind<'hir> { /// An assignment with an operator. /// /// E.g., `a += 1`. - AssignOp(BinOp, &'hir Expr<'hir>, &'hir Expr<'hir>), + AssignOp(AssignOp, &'hir Expr<'hir>, &'hir Expr<'hir>), /// Access of a named (e.g., `obj.foo`) or unnamed (e.g., `obj.0`) struct or tuple field. Field(&'hir Expr<'hir>, Ident), /// An indexing operation (`foo[2]`). diff --git a/compiler/rustc_hir/src/hir_id.rs b/compiler/rustc_hir/src/hir_id.rs index 3fa06620ea8..b48a081d371 100644 --- a/compiler/rustc_hir/src/hir_id.rs +++ b/compiler/rustc_hir/src/hir_id.rs @@ -83,6 +83,12 @@ pub struct HirId { pub local_id: ItemLocalId, } +// To ensure correctness of incremental compilation, +// `HirId` must not implement `Ord` or `PartialOrd`. +// See https://github.com/rust-lang/rust/issues/90317. +impl !Ord for HirId {} +impl !PartialOrd for HirId {} + impl Debug for HirId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // Example: HirId(DefId(0:1 ~ aa[7697]::{use#0}).10) @@ -116,10 +122,6 @@ impl HirId { pub fn make_owner(owner: LocalDefId) -> Self { Self { owner: OwnerId { def_id: owner }, local_id: ItemLocalId::ZERO } } - - pub fn index(self) -> (usize, usize) { - (rustc_index::Idx::index(self.owner.def_id), rustc_index::Idx::index(self.local_id)) - } } impl fmt::Display for HirId { @@ -128,18 +130,6 @@ impl fmt::Display for HirId { } } -impl Ord for HirId { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - (self.index()).cmp(&(other.index())) - } -} - -impl PartialOrd for HirId { - fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { - Some(self.cmp(other)) - } -} - rustc_data_structures::define_stable_id_collections!(HirIdMap, HirIdSet, HirIdMapEntry, HirId); rustc_data_structures::define_id_collections!( ItemLocalMap, diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index e625514e9ff..90fab01ba2d 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -433,6 +433,12 @@ language_item_table! { // Experimental lang items for implementing contract pre- and post-condition checking. ContractBuildCheckEnsures, sym::contract_build_check_ensures, contract_build_check_ensures_fn, Target::Fn, GenericRequirement::None; ContractCheckRequires, sym::contract_check_requires, contract_check_requires_fn, Target::Fn, GenericRequirement::None; + + // Experimental lang items for `MCP: Low level components for async drop`(https://github.com/rust-lang/compiler-team/issues/727) + DefaultTrait4, sym::default_trait4, default_trait4_trait, Target::Trait, GenericRequirement::None; + DefaultTrait3, sym::default_trait3, default_trait3_trait, Target::Trait, GenericRequirement::None; + DefaultTrait2, sym::default_trait2, default_trait2_trait, Target::Trait, GenericRequirement::None; + DefaultTrait1, sym::default_trait1, default_trait1_trait, Target::Trait, GenericRequirement::None; } /// The requirement imposed on the generics of a lang item diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 4a839d40571..6bc0f797cca 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -11,6 +11,7 @@ #![feature(debug_closure_helpers)] #![feature(exhaustive_patterns)] #![feature(let_chains)] +#![feature(negative_impls)] #![feature(never_type)] #![feature(rustc_attrs)] #![feature(variant_count)] diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 177243b1b76..7c5d7b33a34 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -341,9 +341,8 @@ fn bounds_from_generic_predicates<'tcx>( ty::ClauseKind::Trait(trait_predicate) => { let entry = types.entry(trait_predicate.self_ty()).or_default(); let def_id = trait_predicate.def_id(); - if Some(def_id) != tcx.lang_items().sized_trait() { - // Type params are `Sized` by default, do not add that restriction to the list - // if it is a positive requirement. + if !tcx.is_default_trait(def_id) { + // Do not add that restriction to the list if it is a positive requirement. entry.push(trait_predicate.def_id()); } } diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 6e07f0ff53c..279b1e82a71 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -38,13 +38,13 @@ fn associated_type_bounds<'tcx>( let icx = ItemCtxt::new(tcx, assoc_item_def_id); let mut bounds = Vec::new(); icx.lowerer().lower_bounds(item_ty, hir_bounds, &mut bounds, ty::List::empty(), filter); - // Associated types are implicitly sized unless a `?Sized` bound is found + // Implicit bounds are added to associated types unless a `?Trait` bound is found match filter { PredicateFilter::All | PredicateFilter::SelfOnly | PredicateFilter::SelfTraitThatDefines(_) | PredicateFilter::SelfAndAssociatedTypeBounds => { - icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span); + icx.lowerer().add_default_traits(&mut bounds, item_ty, hir_bounds, None, span); } // `ConstIfConst` is only interested in `~const` bounds. PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {} @@ -327,14 +327,13 @@ fn opaque_type_bounds<'tcx>( let icx = ItemCtxt::new(tcx, opaque_def_id); let mut bounds = Vec::new(); icx.lowerer().lower_bounds(item_ty, hir_bounds, &mut bounds, ty::List::empty(), filter); - // Opaque types are implicitly sized unless a `?Sized` bound is found + // Implicit bounds are added to opaque types unless a `?Trait` bound is found match filter { PredicateFilter::All | PredicateFilter::SelfOnly | PredicateFilter::SelfTraitThatDefines(_) | PredicateFilter::SelfAndAssociatedTypeBounds => { - // Associated types are implicitly sized unless a `?Sized` bound is found - icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span); + icx.lowerer().add_default_traits(&mut bounds, item_ty, hir_bounds, None, span); } //`ConstIfConst` is only interested in `~const` bounds. PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {} diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 98da8449d5e..776b23bea8e 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -165,12 +165,42 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen ItemKind::Trait(_, _, _, _, self_bounds, ..) | ItemKind::TraitAlias(_, _, self_bounds) => { - is_trait = Some(self_bounds); + is_trait = Some((self_bounds, item.span)); } _ => {} } }; + if let Node::TraitItem(item) = node { + let parent = tcx.local_parent(item.hir_id().owner.def_id); + let Node::Item(parent_trait) = tcx.hir_node_by_def_id(parent) else { + unreachable!(); + }; + + let (trait_generics, trait_bounds) = match parent_trait.kind { + hir::ItemKind::Trait(_, _, _, generics, supertraits, _) => (generics, supertraits), + hir::ItemKind::TraitAlias(_, generics, supertraits) => (generics, supertraits), + _ => unreachable!(), + }; + + // Implicitly add `Self: DefaultAutoTrait` clauses on trait associated items if + // they are not added as super trait bounds to the trait itself. See comment on + // `requires_default_supertraits` for more details. + if !icx.lowerer().requires_default_supertraits(trait_bounds, trait_generics) { + let mut bounds = Vec::new(); + let self_ty_where_predicates = (parent, item.generics.predicates); + icx.lowerer().add_default_traits_with_filter( + &mut bounds, + tcx.types.self_param, + &[], + Some(self_ty_where_predicates), + item.span, + |tr| tr != hir::LangItem::Sized, + ); + predicates.extend(bounds); + } + } + let generics = tcx.generics_of(def_id); // Below we'll consider the bounds on the type parameters (including `Self`) @@ -181,11 +211,18 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen let mut bounds = Vec::new(); icx.lowerer().lower_bounds( tcx.types.self_param, - self_bounds, + self_bounds.0, &mut bounds, ty::List::empty(), PredicateFilter::All, ); + icx.lowerer().add_default_super_traits( + def_id, + &mut bounds, + self_bounds.0, + hir_generics, + self_bounds.1, + ); predicates.extend(bounds); } @@ -210,8 +247,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen GenericParamKind::Type { .. } => { let param_ty = icx.lowerer().lower_ty_param(param.hir_id); let mut bounds = Vec::new(); - // Params are implicitly sized unless a `?Sized` bound is found - icx.lowerer().add_sized_bound( + // Implicit bounds are added to type params unless a `?Trait` bound is found + icx.lowerer().add_default_traits( &mut bounds, param_ty, &[], @@ -625,6 +662,22 @@ pub(super) fn implied_predicates_with_filter<'tcx>( let self_param_ty = tcx.types.self_param; let mut bounds = Vec::new(); icx.lowerer().lower_bounds(self_param_ty, superbounds, &mut bounds, ty::List::empty(), filter); + match filter { + PredicateFilter::All + | PredicateFilter::SelfOnly + | PredicateFilter::SelfTraitThatDefines(_) + | PredicateFilter::SelfAndAssociatedTypeBounds => { + icx.lowerer().add_default_super_traits( + trait_def_id, + &mut bounds, + superbounds, + generics, + item.span, + ); + } + //`ConstIfConst` is only interested in `~const` bounds. + PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {} + } let where_bounds_that_match = icx.probe_ty_param_bounds_in_generics(generics, item.owner_id.def_id, filter); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 302abc27324..c3bb860538e 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -4,9 +4,9 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::struct_span_code_err; use rustc_hir as hir; -use rustc_hir::HirId; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::{AmbigArg, HirId}; use rustc_middle::bug; use rustc_middle::ty::{ self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, @@ -24,25 +24,190 @@ use crate::hir_ty_lowering::{ }; impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { - /// Add a `Sized` bound to the `bounds` if appropriate. - /// - /// Doesn't add the bound if the HIR bounds contain any of `Sized`, `?Sized` or `!Sized`. - pub(crate) fn add_sized_bound( + pub(crate) fn add_default_traits( &self, bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, self_ty: Ty<'tcx>, + hir_bounds: &[hir::GenericBound<'tcx>], + self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>, + span: Span, + ) { + self.add_default_traits_with_filter( + bounds, + self_ty, + hir_bounds, + self_ty_where_predicates, + span, + |_| true, + ); + } + + /// Checks whether `Self: DefaultAutoTrait` bounds should be added on trait super bounds + /// or associative items. + /// + /// To keep backward compatibility with existing code, `experimental_default_bounds` bounds + /// should be added everywhere, including super bounds. However this causes a huge performance + /// costs. For optimization purposes instead of adding default supertraits, bounds + /// are added to the associative items: + /// + /// ```ignore(illustrative) + /// // Default bounds are generated in the following way: + /// trait Trait { + /// fn foo(&self) where Self: Leak {} + /// } + /// + /// // instead of this: + /// trait Trait: Leak { + /// fn foo(&self) {} + /// } + /// ``` + /// It is not always possible to do this because of backward compatibility: + /// + /// ```ignore(illustrative) + /// pub trait Trait<Rhs = Self> {} + /// pub trait Trait1 : Trait {} + /// //~^ ERROR: `Rhs` requires `DefaultAutoTrait`, but `Self` is not `DefaultAutoTrait` + /// ``` + /// + /// or: + /// + /// ```ignore(illustrative) + /// trait Trait { + /// type Type where Self: Sized; + /// } + /// trait Trait2<T> : Trait<Type = T> {} + /// //~^ ERROR: `DefaultAutoTrait` required for `Trait2`, by implicit `Self: DefaultAutoTrait` in `Trait::Type` + /// ``` + /// + /// Therefore, `experimental_default_bounds` are still being added to supertraits if + /// the `SelfTyParam` or `AssocItemConstraint` were found in a trait header. + pub(crate) fn requires_default_supertraits( + &self, hir_bounds: &'tcx [hir::GenericBound<'tcx>], + hir_generics: &'tcx hir::Generics<'tcx>, + ) -> bool { + struct TraitInfoCollector; + + impl<'tcx> hir::intravisit::Visitor<'tcx> for TraitInfoCollector { + type Result = ControlFlow<()>; + + fn visit_assoc_item_constraint( + &mut self, + _constraint: &'tcx hir::AssocItemConstraint<'tcx>, + ) -> Self::Result { + ControlFlow::Break(()) + } + + fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx, AmbigArg>) -> Self::Result { + if matches!( + &t.kind, + hir::TyKind::Path(hir::QPath::Resolved( + _, + hir::Path { res: hir::def::Res::SelfTyParam { .. }, .. }, + )) + ) { + return ControlFlow::Break(()); + } + hir::intravisit::walk_ty(self, t) + } + } + + let mut found = false; + for bound in hir_bounds { + found |= hir::intravisit::walk_param_bound(&mut TraitInfoCollector, bound).is_break(); + } + found |= hir::intravisit::walk_generics(&mut TraitInfoCollector, hir_generics).is_break(); + found + } + + /// Lazily sets `experimental_default_bounds` to true on trait super bounds. + /// See `requires_default_supertraits` for more information. + pub(crate) fn add_default_super_traits( + &self, + trait_def_id: LocalDefId, + bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, + hir_bounds: &'tcx [hir::GenericBound<'tcx>], + hir_generics: &'tcx hir::Generics<'tcx>, + span: Span, + ) { + assert!(matches!(self.tcx().def_kind(trait_def_id), DefKind::Trait | DefKind::TraitAlias)); + if self.requires_default_supertraits(hir_bounds, hir_generics) { + let self_ty_where_predicates = (trait_def_id, hir_generics.predicates); + self.add_default_traits_with_filter( + bounds, + self.tcx().types.self_param, + hir_bounds, + Some(self_ty_where_predicates), + span, + |default_trait| default_trait != hir::LangItem::Sized, + ); + } + } + + pub(crate) fn add_default_traits_with_filter( + &self, + bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, + self_ty: Ty<'tcx>, + hir_bounds: &[hir::GenericBound<'tcx>], + self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>, + span: Span, + f: impl Fn(hir::LangItem) -> bool, + ) { + self.tcx().default_traits().iter().filter(|&&default_trait| f(default_trait)).for_each( + |default_trait| { + self.add_default_trait( + *default_trait, + bounds, + self_ty, + hir_bounds, + self_ty_where_predicates, + span, + ); + }, + ); + } + + /// Add a `Sized` or `experimental_default_bounds` bounds to the `bounds` if appropriate. + /// + /// Doesn't add the bound if the HIR bounds contain any of `Trait`, `?Trait` or `!Trait`. + pub(crate) fn add_default_trait( + &self, + trait_: hir::LangItem, + bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, + self_ty: Ty<'tcx>, + hir_bounds: &[hir::GenericBound<'tcx>], self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>, span: Span, ) { + let trait_id = self.tcx().lang_items().get(trait_); + if let Some(trait_id) = trait_id + && self.do_not_provide_default_trait_bound( + trait_id, + hir_bounds, + self_ty_where_predicates, + ) + { + // There was no `?Trait` or `!Trait` bound; + // add `Trait` if it's available. + let trait_ref = ty::TraitRef::new(self.tcx(), trait_id, [self_ty]); + // Preferable to put this obligation first, since we report better errors for sized ambiguity. + bounds.insert(0, (trait_ref.upcast(self.tcx()), span)); + } + } + + fn do_not_provide_default_trait_bound<'a>( + &self, + trait_def_id: DefId, + hir_bounds: &'a [hir::GenericBound<'tcx>], + self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>, + ) -> bool { let tcx = self.tcx(); - let sized_def_id = tcx.lang_items().sized_trait(); - let mut seen_negative_sized_bound = false; - let mut seen_positive_sized_bound = false; + let mut seen_negative_bound = false; + let mut seen_positive_bound = false; // Try to find an unbound in bounds. let mut unbounds: SmallVec<[_; 1]> = SmallVec::new(); - let mut search_bounds = |hir_bounds: &'tcx [hir::GenericBound<'tcx>]| { + let mut search_bounds = |hir_bounds: &'a [hir::GenericBound<'tcx>]| { for hir_bound in hir_bounds { let hir::GenericBound::Trait(ptr) = hir_bound else { continue; @@ -50,17 +215,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { match ptr.modifiers.polarity { hir::BoundPolarity::Maybe(_) => unbounds.push(ptr), hir::BoundPolarity::Negative(_) => { - if let Some(sized_def_id) = sized_def_id - && ptr.trait_ref.path.res == Res::Def(DefKind::Trait, sized_def_id) - { - seen_negative_sized_bound = true; + if ptr.trait_ref.path.res == Res::Def(DefKind::Trait, trait_def_id) { + seen_negative_bound = true; } } hir::BoundPolarity::Positive => { - if let Some(sized_def_id) = sized_def_id - && ptr.trait_ref.path.res == Res::Def(DefKind::Trait, sized_def_id) - { - seen_positive_sized_bound = true; + if ptr.trait_ref.path.res == Res::Def(DefKind::Trait, trait_def_id) { + seen_positive_bound = true; } } } @@ -95,32 +256,36 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }; } - let mut seen_sized_unbound = false; + let mut seen_unbound = false; for unbound in unbounds { - if let Some(sized_def_id) = sized_def_id - && unbound.trait_ref.path.res == Res::Def(DefKind::Trait, sized_def_id) - { - seen_sized_unbound = true; - continue; + let unbound_def_id = unbound.trait_ref.trait_def_id(); + if unbound_def_id == Some(trait_def_id) { + seen_unbound = true; + } + let emit_relax_err = || { + let unbound_traits = + match self.tcx().sess.opts.unstable_opts.experimental_default_bounds { + true => "`?Sized` and `experimental_default_bounds`", + false => "`?Sized`", + }; + // There was a `?Trait` bound, but it was neither `?Sized` nor `experimental_default_bounds`. + tcx.dcx().span_err( + unbound.span, + format!( + "relaxing a default bound only does something for {}; \ + all other traits are not bound by default", + unbound_traits + ), + ); + }; + match unbound_def_id { + Some(def_id) if !tcx.is_default_trait(def_id) => emit_relax_err(), + None => emit_relax_err(), + _ => {} } - // There was a `?Trait` bound, but it was not `?Sized` - self.dcx().span_err( - unbound.span, - "relaxing a default bound only does something for `?Sized`; \ - all other traits are not bound by default", - ); } - if seen_sized_unbound || seen_negative_sized_bound || seen_positive_sized_bound { - // There was in fact a `?Sized`, `!Sized` or explicit `Sized` bound; - // we don't need to do anything. - } else if let Some(sized_def_id) = sized_def_id { - // There was no `?Sized`, `!Sized` or explicit `Sized` bound; - // add `Sized` if it's available. - let trait_ref = ty::TraitRef::new(tcx, sized_def_id, [self_ty]); - // Preferable to put this obligation first, since we report better errors for sized ambiguity. - bounds.insert(0, (trait_ref.upcast(tcx), span)); - } + !(seen_unbound || seen_negative_bound || seen_positive_bound) } /// Lower HIR bounds into `bounds` given the self type `param_ty` and the overarching late-bound vars if any. diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index 27643e715e6..aeebe45f881 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -57,6 +57,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } + let ast_bounds: Vec<_> = + hir_bounds.iter().map(|&trait_ref| hir::GenericBound::Trait(trait_ref)).collect(); + + self.add_default_traits_with_filter( + &mut user_written_bounds, + dummy_self, + &ast_bounds, + None, + span, + |tr| tr != hir::LangItem::Sized, + ); + let (elaborated_trait_bounds, elaborated_projection_bounds) = traits::expand_trait_aliases(tcx, user_written_bounds.iter().copied()); let (regular_traits, mut auto_traits): (Vec<_>, Vec<_>) = elaborated_trait_bounds diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 1c23761b2e5..8c0c17f7a7d 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1271,18 +1271,18 @@ impl<'a> State<'a> { self.print_call_post(base_args) } - fn print_expr_binary(&mut self, op: hir::BinOp, lhs: &hir::Expr<'_>, rhs: &hir::Expr<'_>) { - let binop_prec = op.node.precedence(); + fn print_expr_binary(&mut self, op: hir::BinOpKind, lhs: &hir::Expr<'_>, rhs: &hir::Expr<'_>) { + let binop_prec = op.precedence(); let left_prec = lhs.precedence(); let right_prec = rhs.precedence(); - let (mut left_needs_paren, right_needs_paren) = match op.node.fixity() { + let (mut left_needs_paren, right_needs_paren) = match op.fixity() { Fixity::Left => (left_prec < binop_prec, right_prec <= binop_prec), Fixity::Right => (left_prec <= binop_prec, right_prec < binop_prec), Fixity::None => (left_prec <= binop_prec, right_prec <= binop_prec), }; - match (&lhs.kind, op.node) { + match (&lhs.kind, op) { // These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is // the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead // of `(x as i32) < ...`. We need to convince it _not_ to do that. @@ -1297,7 +1297,7 @@ impl<'a> State<'a> { self.print_expr_cond_paren(lhs, left_needs_paren); self.space(); - self.word_space(op.node.as_str()); + self.word_space(op.as_str()); self.print_expr_cond_paren(rhs, right_needs_paren); } @@ -1451,7 +1451,7 @@ impl<'a> State<'a> { self.word(".use"); } hir::ExprKind::Binary(op, lhs, rhs) => { - self.print_expr_binary(op, lhs, rhs); + self.print_expr_binary(op.node, lhs, rhs); } hir::ExprKind::Unary(op, expr) => { self.print_expr_unary(op, expr); @@ -1572,8 +1572,7 @@ impl<'a> State<'a> { hir::ExprKind::AssignOp(op, lhs, rhs) => { self.print_expr_cond_paren(lhs, lhs.precedence() <= ExprPrecedence::Assign); self.space(); - self.word(op.node.as_str()); - self.word_space("="); + self.word_space(op.node.as_str()); self.print_expr_cond_paren(rhs, rhs.precedence() < ExprPrecedence::Assign); } hir::ExprKind::Field(expr, ident) => { diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index a882ea27af6..45ab8e03db5 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -512,7 +512,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.check_expr_assign(expr, expected, lhs, rhs, span) } ExprKind::AssignOp(op, lhs, rhs) => { - self.check_expr_binop_assign(expr, op, lhs, rhs, expected) + self.check_expr_assign_op(expr, op, lhs, rhs, expected) } ExprKind::Unary(unop, oprnd) => self.check_expr_unop(unop, oprnd, expected, expr), ExprKind::AddrOf(kind, mutbl, oprnd) => { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 0097b6ea123..912098c4e2d 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -3477,30 +3477,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { lhs_ty: Ty<'tcx>, rhs_expr: &'tcx hir::Expr<'tcx>, lhs_expr: &'tcx hir::Expr<'tcx>, - op: hir::BinOp, ) { - match op.node { - hir::BinOpKind::Eq => { - if let Some(partial_eq_def_id) = self.infcx.tcx.lang_items().eq_trait() - && self - .infcx - .type_implements_trait(partial_eq_def_id, [rhs_ty, lhs_ty], self.param_env) - .must_apply_modulo_regions() - { - let sm = self.tcx.sess.source_map(); - if let Ok(rhs_snippet) = sm.span_to_snippet(rhs_expr.span) - && let Ok(lhs_snippet) = sm.span_to_snippet(lhs_expr.span) - { - err.note(format!("`{rhs_ty}` implements `PartialEq<{lhs_ty}>`")); - err.multipart_suggestion( - "consider swapping the equality", - vec![(lhs_expr.span, rhs_snippet), (rhs_expr.span, lhs_snippet)], - Applicability::MaybeIncorrect, - ); - } - } + if let Some(partial_eq_def_id) = self.infcx.tcx.lang_items().eq_trait() + && self + .infcx + .type_implements_trait(partial_eq_def_id, [rhs_ty, lhs_ty], self.param_env) + .must_apply_modulo_regions() + { + let sm = self.tcx.sess.source_map(); + if let Ok(rhs_snippet) = sm.span_to_snippet(rhs_expr.span) + && let Ok(lhs_snippet) = sm.span_to_snippet(lhs_expr.span) + { + err.note(format!("`{rhs_ty}` implements `PartialEq<{lhs_ty}>`")); + err.multipart_suggestion( + "consider swapping the equality", + vec![(lhs_expr.span, rhs_snippet), (rhs_expr.span, lhs_snippet)], + Applicability::MaybeIncorrect, + ); } - _ => {} } } } diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index a473e14b244..93f77b8409f 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -4,15 +4,15 @@ use rustc_data_structures::packed::Pu128; use rustc_errors::codes::*; use rustc_errors::{Applicability, Diag, struct_span_code_err}; use rustc_infer::traits::ObligationCauseCode; +use rustc_middle::bug; use rustc_middle::ty::adjustment::{ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, }; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; -use rustc_middle::{bug, span_bug}; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::source_map::Spanned; -use rustc_span::{Ident, Span, sym}; +use rustc_span::{Ident, Span, Symbol, sym}; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::{FulfillmentError, Obligation, ObligationCtxt}; use tracing::debug; @@ -24,24 +24,27 @@ use crate::Expectation; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Checks a `a <op>= b` - pub(crate) fn check_expr_binop_assign( + pub(crate) fn check_expr_assign_op( &self, expr: &'tcx hir::Expr<'tcx>, - op: hir::BinOp, + op: hir::AssignOp, lhs: &'tcx hir::Expr<'tcx>, rhs: &'tcx hir::Expr<'tcx>, expected: Expectation<'tcx>, ) -> Ty<'tcx> { let (lhs_ty, rhs_ty, return_ty) = - self.check_overloaded_binop(expr, lhs, rhs, op, IsAssign::Yes, expected); - - let ty = - if !lhs_ty.is_ty_var() && !rhs_ty.is_ty_var() && is_builtin_binop(lhs_ty, rhs_ty, op) { - self.enforce_builtin_binop_types(lhs.span, lhs_ty, rhs.span, rhs_ty, op); - self.tcx.types.unit - } else { - return_ty - }; + self.check_overloaded_binop(expr, lhs, rhs, Op::AssignOp(op), expected); + + let category = BinOpCategory::from(op.node); + let ty = if !lhs_ty.is_ty_var() + && !rhs_ty.is_ty_var() + && is_builtin_binop(lhs_ty, rhs_ty, category) + { + self.enforce_builtin_binop_types(lhs.span, lhs_ty, rhs.span, rhs_ty, category); + self.tcx.types.unit + } else { + return_ty + }; self.check_lhs_assignable(lhs, E0067, op.span, |err| { if let Some(lhs_deref_ty) = self.deref_once_mutably_for_diagnostic(lhs_ty) { @@ -49,7 +52,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .lookup_op_method( (lhs, lhs_deref_ty), Some((rhs, rhs_ty)), - Op::Binary(op, IsAssign::Yes), + lang_item_for_binop(self.tcx, Op::AssignOp(op)), + op.span, expected, ) .is_ok() @@ -60,7 +64,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .lookup_op_method( (lhs, lhs_ty), Some((rhs, rhs_ty)), - Op::Binary(op, IsAssign::Yes), + lang_item_for_binop(self.tcx, Op::AssignOp(op)), + op.span, expected, ) .is_err() @@ -98,7 +103,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr.hir_id, expr, op, lhs_expr, rhs_expr ); - match BinOpCategory::from(op) { + match BinOpCategory::from(op.node) { BinOpCategory::Shortcircuit => { // && and || are a simple case. self.check_expr_coercible_to_type(lhs_expr, tcx.types.bool, None); @@ -114,14 +119,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Otherwise, we always treat operators as if they are // overloaded. This is the way to be most flexible w/r/t // types that get inferred. - let (lhs_ty, rhs_ty, return_ty) = self.check_overloaded_binop( - expr, - lhs_expr, - rhs_expr, - op, - IsAssign::No, - expected, - ); + let (lhs_ty, rhs_ty, return_ty) = + self.check_overloaded_binop(expr, lhs_expr, rhs_expr, Op::BinOp(op), expected); // Supply type inference hints if relevant. Probably these // hints should be enforced during select as part of the @@ -135,16 +134,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // deduce that the result type should be `u32`, even // though we don't know yet what type 2 has and hence // can't pin this down to a specific impl. + let category = BinOpCategory::from(op.node); if !lhs_ty.is_ty_var() && !rhs_ty.is_ty_var() - && is_builtin_binop(lhs_ty, rhs_ty, op) + && is_builtin_binop(lhs_ty, rhs_ty, category) { let builtin_return_ty = self.enforce_builtin_binop_types( lhs_expr.span, lhs_ty, rhs_expr.span, rhs_ty, - op, + category, ); self.demand_eqtype(expr.span, builtin_return_ty, return_ty); builtin_return_ty @@ -161,16 +161,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { lhs_ty: Ty<'tcx>, rhs_span: Span, rhs_ty: Ty<'tcx>, - op: hir::BinOp, + category: BinOpCategory, ) -> Ty<'tcx> { - debug_assert!(is_builtin_binop(lhs_ty, rhs_ty, op)); + debug_assert!(is_builtin_binop(lhs_ty, rhs_ty, category)); // Special-case a single layer of referencing, so that things like `5.0 + &6.0f32` work. // (See https://github.com/rust-lang/rust/issues/57447.) let (lhs_ty, rhs_ty) = (deref_ty_if_possible(lhs_ty), deref_ty_if_possible(rhs_ty)); let tcx = self.tcx; - match BinOpCategory::from(op) { + match category { BinOpCategory::Shortcircuit => { self.demand_suptype(lhs_span, tcx.types.bool, lhs_ty); self.demand_suptype(rhs_span, tcx.types.bool, rhs_ty); @@ -201,17 +201,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &'tcx hir::Expr<'tcx>, lhs_expr: &'tcx hir::Expr<'tcx>, rhs_expr: &'tcx hir::Expr<'tcx>, - op: hir::BinOp, - is_assign: IsAssign, + op: Op, expected: Expectation<'tcx>, ) -> (Ty<'tcx>, Ty<'tcx>, Ty<'tcx>) { - debug!( - "check_overloaded_binop(expr.hir_id={}, op={:?}, is_assign={:?})", - expr.hir_id, op, is_assign - ); + debug!("check_overloaded_binop(expr.hir_id={}, op={:?})", expr.hir_id, op); - let lhs_ty = match is_assign { - IsAssign::No => { + let lhs_ty = match op { + Op::BinOp(_) => { // Find a suitable supertype of the LHS expression's type, by coercing to // a type variable, to pass as the `Self` to the trait, avoiding invariant // trait matching creating lifetime constraints that are too strict. @@ -221,7 +217,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let fresh_var = self.next_ty_var(lhs_expr.span); self.demand_coerce(lhs_expr, lhs_ty, fresh_var, Some(rhs_expr), AllowTwoPhase::No) } - IsAssign::Yes => { + Op::AssignOp(_) => { // rust-lang/rust#52126: We have to use strict // equivalence on the LHS of an assign-op like `+=`; // overwritten or mutably-borrowed places cannot be @@ -242,7 +238,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let result = self.lookup_op_method( (lhs_expr, lhs_ty), Some((rhs_expr, rhs_ty_var)), - Op::Binary(op, is_assign), + lang_item_for_binop(self.tcx, op), + op.span(), expected, ); @@ -252,15 +249,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rhs_ty_var, Some(lhs_expr), |err, ty| { - self.suggest_swapping_lhs_and_rhs(err, ty, lhs_ty, rhs_expr, lhs_expr, op); + if let Op::BinOp(binop) = op + && binop.node == hir::BinOpKind::Eq + { + self.suggest_swapping_lhs_and_rhs(err, ty, lhs_ty, rhs_expr, lhs_expr); + } }, ); let rhs_ty = self.resolve_vars_with_obligations(rhs_ty); let return_ty = match result { Ok(method) => { - let by_ref_binop = !op.node.is_by_value(); - if is_assign == IsAssign::Yes || by_ref_binop { + let by_ref_binop = !op.is_by_value(); + if matches!(op, Op::AssignOp(_)) || by_ref_binop { if let ty::Ref(_, _, mutbl) = method.sig.inputs()[0].kind() { let mutbl = AutoBorrowMutability::new(*mutbl, AllowTwoPhase::Yes); let autoref = Adjustment { @@ -301,32 +302,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ty::new_misc_error(self.tcx) } Err(errors) => { - let (_, trait_def_id) = - lang_item_for_op(self.tcx, Op::Binary(op, is_assign), op.span); + let (_, trait_def_id) = lang_item_for_binop(self.tcx, op); let missing_trait = trait_def_id .map(|def_id| with_no_trimmed_paths!(self.tcx.def_path_str(def_id))); let mut path = None; let lhs_ty_str = self.tcx.short_string(lhs_ty, &mut path); let rhs_ty_str = self.tcx.short_string(rhs_ty, &mut path); - let (mut err, output_def_id) = match is_assign { - IsAssign::Yes => { + let (mut err, output_def_id) = match op { + Op::AssignOp(assign_op) => { + let s = assign_op.node.as_str(); let mut err = struct_span_code_err!( self.dcx(), expr.span, E0368, - "binary assignment operation `{}=` cannot be applied to type `{}`", - op.node.as_str(), + "binary assignment operation `{}` cannot be applied to type `{}`", + s, lhs_ty_str, ); err.span_label( lhs_expr.span, - format!("cannot use `{}=` on type `{}`", op.node.as_str(), lhs_ty_str), + format!("cannot use `{}` on type `{}`", s, lhs_ty_str), ); self.note_unmet_impls_on_type(&mut err, errors, false); (err, None) } - IsAssign::No => { - let message = match op.node { + Op::BinOp(bin_op) => { + let message = match bin_op.node { hir::BinOpKind::Add => { format!("cannot add `{rhs_ty_str}` to `{lhs_ty_str}`") } @@ -362,8 +363,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } _ => format!( "binary operation `{}` cannot be applied to type `{}`", - op.node.as_str(), - lhs_ty_str, + bin_op.node.as_str(), + lhs_ty_str ), }; let output_def_id = trait_def_id.and_then(|def_id| { @@ -376,7 +377,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .cloned() }); let mut err = - struct_span_code_err!(self.dcx(), op.span, E0369, "{message}"); + struct_span_code_err!(self.dcx(), bin_op.span, E0369, "{message}"); if !lhs_expr.span.eq(&rhs_expr.span) { err.span_label(lhs_expr.span, lhs_ty_str.clone()); err.span_label(rhs_expr.span, rhs_ty_str); @@ -409,18 +410,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .lookup_op_method( (lhs_expr, lhs_deref_ty), Some((rhs_expr, rhs_ty)), - Op::Binary(op, is_assign), + lang_item_for_binop(self.tcx, op), + op.span(), expected, ) .is_ok() { let msg = format!( - "`{}{}` can be used on `{}` if you dereference the left-hand side", - op.node.as_str(), - match is_assign { - IsAssign::Yes => "=", - IsAssign::No => "", - }, + "`{}` can be used on `{}` if you dereference the left-hand side", + op.as_str(), self.tcx.short_string(lhs_deref_ty, err.long_ty_path()), ); err.span_suggestion_verbose( @@ -442,14 +440,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .lookup_op_method( (lhs_expr, lhs_adjusted_ty), Some((rhs_expr, rhs_adjusted_ty)), - Op::Binary(op, is_assign), + lang_item_for_binop(self.tcx, op), + op.span(), expected, ) .is_ok() { let lhs = self.tcx.short_string(lhs_adjusted_ty, err.long_ty_path()); let rhs = self.tcx.short_string(rhs_adjusted_ty, err.long_ty_path()); - let op = op.node.as_str(); + let op = op.as_str(); err.note(format!("an implementation for `{lhs} {op} {rhs}` exists")); if let Some(lhs_new_mutbl) = lhs_new_mutbl @@ -499,7 +498,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.lookup_op_method( (lhs_expr, lhs_ty), Some((rhs_expr, rhs_ty)), - Op::Binary(op, is_assign), + lang_item_for_binop(self.tcx, op), + op.span(), expected, ) .is_ok() @@ -511,13 +511,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We should suggest `a + b` => `*a + b` if `a` is copy, and suggest // `a += b` => `*a += b` if a is a mut ref. - if !op.span.can_be_used_for_suggestions() { + if !op.span().can_be_used_for_suggestions() { // Suppress suggestions when lhs and rhs are not in the same span as the error - } else if is_assign == IsAssign::Yes + } else if let Op::AssignOp(_) = op && let Some(lhs_deref_ty) = self.deref_once_mutably_for_diagnostic(lhs_ty) { suggest_deref_binop(&mut err, lhs_deref_ty); - } else if is_assign == IsAssign::No + } else if let Op::BinOp(_) = op && let ty::Ref(region, lhs_deref_ty, mutbl) = lhs_ty.kind() { if self.type_is_copy_modulo_regions(self.param_env, *lhs_deref_ty) { @@ -572,10 +572,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if let Some(missing_trait) = missing_trait { - if op.node == hir::BinOpKind::Add - && self.check_str_addition( - lhs_expr, rhs_expr, lhs_ty, rhs_ty, &mut err, is_assign, op, - ) + if matches!( + op, + Op::BinOp(Spanned { node: hir::BinOpKind::Add, .. }) + | Op::AssignOp(Spanned { node: hir::AssignOpKind::AddAssign, .. }) + ) && self + .check_str_addition(lhs_expr, rhs_expr, lhs_ty, rhs_ty, &mut err, op) { // This has nothing here because it means we did string // concatenation (e.g., "Hello " + "World!"). This means @@ -592,7 +594,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .lookup_op_method( (lhs_expr, lhs_ty), Some((rhs_expr, rhs_ty)), - Op::Binary(op, is_assign), + lang_item_for_binop(self.tcx, op), + op.span(), expected, ) .unwrap_err(); @@ -642,9 +645,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Suggest using `add`, `offset` or `offset_from` for pointer - {integer}, // pointer + {integer} or pointer - pointer. - if op.span.can_be_used_for_suggestions() { - match op.node { - hir::BinOpKind::Add if lhs_ty.is_raw_ptr() && rhs_ty.is_integral() => { + if op.span().can_be_used_for_suggestions() { + match op { + Op::BinOp(Spanned { node: hir::BinOpKind::Add, .. }) + if lhs_ty.is_raw_ptr() && rhs_ty.is_integral() => + { err.multipart_suggestion( "consider using `wrapping_add` or `add` for pointer + {integer}", vec![ @@ -657,7 +662,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MaybeIncorrect, ); } - hir::BinOpKind::Sub => { + Op::BinOp(Spanned { node: hir::BinOpKind::Sub, .. }) => { if lhs_ty.is_raw_ptr() && rhs_ty.is_integral() { err.multipart_suggestion( "consider using `wrapping_sub` or `sub` for \ @@ -713,8 +718,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { lhs_ty: Ty<'tcx>, rhs_ty: Ty<'tcx>, err: &mut Diag<'_>, - is_assign: IsAssign, - op: hir::BinOp, + op: Op, ) -> bool { let str_concat_note = "string concatenation requires an owned `String` on the left"; let rm_borrow_msg = "remove the borrow to obtain an owned `String`"; @@ -733,8 +737,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { r_ty.kind(), ty::Ref(_, inner_ty, _) if *inner_ty.kind() == ty::Str )) => { - if let IsAssign::No = is_assign { // Do not supply this message if `&str += &str` - err.span_label(op.span, "`+` cannot be used to concatenate two `&str` strings"); + if let Op::BinOp(_) = op { // Do not supply this message if `&str += &str` + err.span_label( + op.span(), + "`+` cannot be used to concatenate two `&str` strings" + ); err.note(str_concat_note); if let hir::ExprKind::AddrOf(_, _, lhs_inner_expr) = lhs_expr.kind { err.span_suggestion_verbose( @@ -758,11 +765,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if (*l_ty.kind() == ty::Str || is_std_string(l_ty)) && is_std_string(rhs_ty) => { err.span_label( - op.span, + op.span(), "`+` cannot be used to concatenate a `&str` with a `String`", ); - match is_assign { - IsAssign::No => { + match op { + Op::BinOp(_) => { let sugg_msg; let lhs_sugg = if let hir::ExprKind::AddrOf(_, _, lhs_inner_expr) = lhs_expr.kind { sugg_msg = "remove the borrow on the left and add one on the right"; @@ -781,7 +788,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MachineApplicable, ); } - IsAssign::Yes => { + Op::AssignOp(_) => { err.note(str_concat_note); } } @@ -799,7 +806,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Expectation<'tcx>, ) -> Ty<'tcx> { assert!(op.is_by_value()); - match self.lookup_op_method((ex, operand_ty), None, Op::Unary(op, ex.span), expected) { + match self.lookup_op_method( + (ex, operand_ty), + None, + lang_item_for_unop(self.tcx, op), + ex.span, + expected, + ) { Ok(method) => { self.write_method_call_and_enforce_effects(ex.hir_id, ex.span, method); method.sig.output() @@ -898,21 +911,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, (lhs_expr, lhs_ty): (&'tcx hir::Expr<'tcx>, Ty<'tcx>), opt_rhs: Option<(&'tcx hir::Expr<'tcx>, Ty<'tcx>)>, - op: Op, + (opname, trait_did): (Symbol, Option<hir::def_id::DefId>), + span: Span, expected: Expectation<'tcx>, ) -> Result<MethodCallee<'tcx>, Vec<FulfillmentError<'tcx>>> { - let span = match op { - Op::Binary(op, _) => op.span, - Op::Unary(_, span) => span, - }; - let (opname, Some(trait_did)) = lang_item_for_op(self.tcx, op, span) else { + let Some(trait_did) = trait_did else { // Bail if the operator trait is not defined. return Err(vec![]); }; debug!( - "lookup_op_method(lhs_ty={:?}, op={:?}, opname={:?}, trait_did={:?})", - lhs_ty, op, opname, trait_did + "lookup_op_method(lhs_ty={:?}, opname={:?}, trait_did={:?})", + lhs_ty, opname, trait_did ); let opname = Ident::with_dummy_span(opname); @@ -980,37 +990,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } -fn lang_item_for_op( - tcx: TyCtxt<'_>, - op: Op, - span: Span, -) -> (rustc_span::Symbol, Option<hir::def_id::DefId>) { +fn lang_item_for_binop(tcx: TyCtxt<'_>, op: Op) -> (Symbol, Option<hir::def_id::DefId>) { let lang = tcx.lang_items(); - if let Op::Binary(op, IsAssign::Yes) = op { - match op.node { - hir::BinOpKind::Add => (sym::add_assign, lang.add_assign_trait()), - hir::BinOpKind::Sub => (sym::sub_assign, lang.sub_assign_trait()), - hir::BinOpKind::Mul => (sym::mul_assign, lang.mul_assign_trait()), - hir::BinOpKind::Div => (sym::div_assign, lang.div_assign_trait()), - hir::BinOpKind::Rem => (sym::rem_assign, lang.rem_assign_trait()), - hir::BinOpKind::BitXor => (sym::bitxor_assign, lang.bitxor_assign_trait()), - hir::BinOpKind::BitAnd => (sym::bitand_assign, lang.bitand_assign_trait()), - hir::BinOpKind::BitOr => (sym::bitor_assign, lang.bitor_assign_trait()), - hir::BinOpKind::Shl => (sym::shl_assign, lang.shl_assign_trait()), - hir::BinOpKind::Shr => (sym::shr_assign, lang.shr_assign_trait()), - hir::BinOpKind::Lt - | hir::BinOpKind::Le - | hir::BinOpKind::Ge - | hir::BinOpKind::Gt - | hir::BinOpKind::Eq - | hir::BinOpKind::Ne - | hir::BinOpKind::And - | hir::BinOpKind::Or => { - span_bug!(span, "impossible assignment operation: {}=", op.node.as_str()) - } - } - } else if let Op::Binary(op, IsAssign::No) = op { - match op.node { + match op { + Op::AssignOp(op) => match op.node { + hir::AssignOpKind::AddAssign => (sym::add_assign, lang.add_assign_trait()), + hir::AssignOpKind::SubAssign => (sym::sub_assign, lang.sub_assign_trait()), + hir::AssignOpKind::MulAssign => (sym::mul_assign, lang.mul_assign_trait()), + hir::AssignOpKind::DivAssign => (sym::div_assign, lang.div_assign_trait()), + hir::AssignOpKind::RemAssign => (sym::rem_assign, lang.rem_assign_trait()), + hir::AssignOpKind::BitXorAssign => (sym::bitxor_assign, lang.bitxor_assign_trait()), + hir::AssignOpKind::BitAndAssign => (sym::bitand_assign, lang.bitand_assign_trait()), + hir::AssignOpKind::BitOrAssign => (sym::bitor_assign, lang.bitor_assign_trait()), + hir::AssignOpKind::ShlAssign => (sym::shl_assign, lang.shl_assign_trait()), + hir::AssignOpKind::ShrAssign => (sym::shr_assign, lang.shr_assign_trait()), + }, + Op::BinOp(op) => match op.node { hir::BinOpKind::Add => (sym::add, lang.add_trait()), hir::BinOpKind::Sub => (sym::sub, lang.sub_trait()), hir::BinOpKind::Mul => (sym::mul, lang.mul_trait()), @@ -1028,20 +1023,24 @@ fn lang_item_for_op( hir::BinOpKind::Eq => (sym::eq, lang.eq_trait()), hir::BinOpKind::Ne => (sym::ne, lang.eq_trait()), hir::BinOpKind::And | hir::BinOpKind::Or => { - span_bug!(span, "&& and || are not overloadable") + bug!("&& and || are not overloadable") } - } - } else if let Op::Unary(hir::UnOp::Not, _) = op { - (sym::not, lang.not_trait()) - } else if let Op::Unary(hir::UnOp::Neg, _) = op { - (sym::neg, lang.neg_trait()) - } else { - bug!("lookup_op_method: op not supported: {:?}", op) + }, + } +} + +fn lang_item_for_unop(tcx: TyCtxt<'_>, op: hir::UnOp) -> (Symbol, Option<hir::def_id::DefId>) { + let lang = tcx.lang_items(); + match op { + hir::UnOp::Not => (sym::not, lang.not_trait()), + hir::UnOp::Neg => (sym::neg, lang.neg_trait()), + hir::UnOp::Deref => bug!("Deref is not overloadable"), } } // Binary operator categories. These categories summarize the behavior // with respect to the builtin operations supported. +#[derive(Clone, Copy)] enum BinOpCategory { /// &&, || -- cannot be overridden Shortcircuit, @@ -1063,44 +1062,58 @@ enum BinOpCategory { Comparison, } -impl BinOpCategory { - fn from(op: hir::BinOp) -> BinOpCategory { - match op.node { - hir::BinOpKind::Shl | hir::BinOpKind::Shr => BinOpCategory::Shift, - - hir::BinOpKind::Add - | hir::BinOpKind::Sub - | hir::BinOpKind::Mul - | hir::BinOpKind::Div - | hir::BinOpKind::Rem => BinOpCategory::Math, - - hir::BinOpKind::BitXor | hir::BinOpKind::BitAnd | hir::BinOpKind::BitOr => { - BinOpCategory::Bitwise - } - - hir::BinOpKind::Eq - | hir::BinOpKind::Ne - | hir::BinOpKind::Lt - | hir::BinOpKind::Le - | hir::BinOpKind::Ge - | hir::BinOpKind::Gt => BinOpCategory::Comparison, +impl From<hir::BinOpKind> for BinOpCategory { + fn from(op: hir::BinOpKind) -> BinOpCategory { + use hir::BinOpKind::*; + match op { + Shl | Shr => BinOpCategory::Shift, + Add | Sub | Mul | Div | Rem => BinOpCategory::Math, + BitXor | BitAnd | BitOr => BinOpCategory::Bitwise, + Eq | Ne | Lt | Le | Ge | Gt => BinOpCategory::Comparison, + And | Or => BinOpCategory::Shortcircuit, + } + } +} - hir::BinOpKind::And | hir::BinOpKind::Or => BinOpCategory::Shortcircuit, +impl From<hir::AssignOpKind> for BinOpCategory { + fn from(op: hir::AssignOpKind) -> BinOpCategory { + use hir::AssignOpKind::*; + match op { + ShlAssign | ShrAssign => BinOpCategory::Shift, + AddAssign | SubAssign | MulAssign | DivAssign | RemAssign => BinOpCategory::Math, + BitXorAssign | BitAndAssign | BitOrAssign => BinOpCategory::Bitwise, } } } -/// Whether the binary operation is an assignment (`a += b`), or not (`a + b`) +/// An assignment op (e.g. `a += b`), or a binary op (e.g. `a + b`). #[derive(Clone, Copy, Debug, PartialEq)] -enum IsAssign { - No, - Yes, +enum Op { + BinOp(hir::BinOp), + AssignOp(hir::AssignOp), } -#[derive(Clone, Copy, Debug)] -enum Op { - Binary(hir::BinOp, IsAssign), - Unary(hir::UnOp, Span), +impl Op { + fn span(&self) -> Span { + match self { + Op::BinOp(op) => op.span, + Op::AssignOp(op) => op.span, + } + } + + fn as_str(&self) -> &'static str { + match self { + Op::BinOp(op) => op.node.as_str(), + Op::AssignOp(op) => op.node.as_str(), + } + } + + fn is_by_value(&self) -> bool { + match self { + Op::BinOp(op) => op.node.is_by_value(), + Op::AssignOp(op) => op.node.is_by_value(), + } + } } /// Dereferences a single level of immutable referencing. @@ -1127,27 +1140,24 @@ fn deref_ty_if_possible(ty: Ty<'_>) -> Ty<'_> { /// Reason #2 is the killer. I tried for a while to always use /// overloaded logic and just check the types in constants/codegen after /// the fact, and it worked fine, except for SIMD types. -nmatsakis -fn is_builtin_binop<'tcx>(lhs: Ty<'tcx>, rhs: Ty<'tcx>, op: hir::BinOp) -> bool { +fn is_builtin_binop<'tcx>(lhs: Ty<'tcx>, rhs: Ty<'tcx>, category: BinOpCategory) -> bool { // Special-case a single layer of referencing, so that things like `5.0 + &6.0f32` work. // (See https://github.com/rust-lang/rust/issues/57447.) let (lhs, rhs) = (deref_ty_if_possible(lhs), deref_ty_if_possible(rhs)); - match BinOpCategory::from(op) { + match category.into() { BinOpCategory::Shortcircuit => true, - BinOpCategory::Shift => { lhs.references_error() || rhs.references_error() || lhs.is_integral() && rhs.is_integral() } - BinOpCategory::Math => { lhs.references_error() || rhs.references_error() || lhs.is_integral() && rhs.is_integral() || lhs.is_floating_point() && rhs.is_floating_point() } - BinOpCategory::Bitwise => { lhs.references_error() || rhs.references_error() @@ -1155,7 +1165,6 @@ fn is_builtin_binop<'tcx>(lhs: Ty<'tcx>, rhs: Ty<'tcx>, op: hir::BinOp) -> bool || lhs.is_floating_point() && rhs.is_floating_point() || lhs.is_bool() && rhs.is_bool() } - BinOpCategory::Comparison => { lhs.references_error() || rhs.references_error() || lhs.is_scalar() && rhs.is_scalar() } diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index b4ac143f513..8ab71e5220b 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -85,7 +85,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Intermediate format to store the hir_id pointing to the use that resulted in the /// corresponding place being captured and a String which contains the captured value's /// name (i.e: a.b.c) -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Clone, Debug, PartialEq, Eq, Hash)] enum UpvarMigrationInfo { /// We previously captured all of `x`, but now we capture some sub-path. CapturingPrecise { source_expr: Option<HirId>, var_name: String }, @@ -1396,14 +1396,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { FxIndexSet::default() }; - // Combine all the captures responsible for needing migrations into one HashSet + // Combine all the captures responsible for needing migrations into one IndexSet let mut capture_diagnostic = drop_reorder_diagnostic.clone(); for key in auto_trait_diagnostic.keys() { capture_diagnostic.insert(key.clone()); } let mut capture_diagnostic = capture_diagnostic.into_iter().collect::<Vec<_>>(); - capture_diagnostic.sort(); + capture_diagnostic.sort_by_cached_key(|info| match info { + UpvarMigrationInfo::CapturingPrecise { source_expr: _, var_name } => { + (0, Some(var_name.clone())) + } + UpvarMigrationInfo::CapturingNothing { use_span: _ } => (1, None), + }); for captures_info in capture_diagnostic { // Get the auto trait reasons of why migration is needed because of that capture, if there are any let capture_trait_reasons = @@ -2323,8 +2328,9 @@ fn should_do_rust_2021_incompatible_closure_captures_analysis( return false; } - let (level, _) = - tcx.lint_level_at_node(lint::builtin::RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES, closure_id); + let level = tcx + .lint_level_at_node(lint::builtin::RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES, closure_id) + .level; !matches!(level, lint::Level::Allow) } diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 588383534f6..992d881374f 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -157,7 +157,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { self.typeck_results.node_args_mut().remove(e.hir_id); } } - hir::ExprKind::Binary(ref op, lhs, rhs) | hir::ExprKind::AssignOp(ref op, lhs, rhs) => { + hir::ExprKind::Binary(ref op, lhs, rhs) => { let lhs_ty = self.typeck_results.node_type(lhs.hir_id); let rhs_ty = self.typeck_results.node_type(rhs.hir_id); @@ -165,25 +165,27 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { self.typeck_results.type_dependent_defs_mut().remove(e.hir_id); self.typeck_results.node_args_mut().remove(e.hir_id); - match e.kind { - hir::ExprKind::Binary(..) => { - if !op.node.is_by_value() { - let mut adjustments = self.typeck_results.adjustments_mut(); - if let Some(a) = adjustments.get_mut(lhs.hir_id) { - a.pop(); - } - if let Some(a) = adjustments.get_mut(rhs.hir_id) { - a.pop(); - } - } + if !op.node.is_by_value() { + let mut adjustments = self.typeck_results.adjustments_mut(); + if let Some(a) = adjustments.get_mut(lhs.hir_id) { + a.pop(); } - hir::ExprKind::AssignOp(..) - if let Some(a) = - self.typeck_results.adjustments_mut().get_mut(lhs.hir_id) => - { + if let Some(a) = adjustments.get_mut(rhs.hir_id) { a.pop(); } - _ => {} + } + } + } + hir::ExprKind::AssignOp(_, lhs, rhs) => { + let lhs_ty = self.typeck_results.node_type(lhs.hir_id); + let rhs_ty = self.typeck_results.node_type(rhs.hir_id); + + if lhs_ty.is_scalar() && rhs_ty.is_scalar() { + self.typeck_results.type_dependent_defs_mut().remove(e.hir_id); + self.typeck_results.node_args_mut().remove(e.hir_id); + + if let Some(a) = self.typeck_results.adjustments_mut().get_mut(lhs.hir_id) { + a.pop(); } } } diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 3f87b1a547b..33b4a48b28d 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -204,6 +204,14 @@ pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec<String>) -> Ch error!("`cfg()` names cannot be after values"); } names.push(ident); + } else if let Some(boolean) = arg.boolean_literal() { + if values_specified { + error!("`cfg()` names cannot be after values"); + } + names.push(rustc_span::Ident::new( + if boolean { rustc_span::kw::True } else { rustc_span::kw::False }, + arg.span(), + )); } else if arg.has_name(sym::any) && let Some(args) = arg.meta_item_list() { diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index c56dbc2e1c4..dae0efcbbc4 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -29,6 +29,7 @@ use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; use rustc_hir::intravisit::FnKind as HirFnKind; use rustc_hir::{Body, FnDecl, GenericParamKind, PatKind, PredicateOrigin}; use rustc_middle::bug; +use rustc_middle::lint::LevelAndSource; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, Upcast, VariantDef}; @@ -694,7 +695,8 @@ impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations { } // Avoid listing trait impls if the trait is allowed. - let (level, _) = cx.tcx.lint_level_at_node(MISSING_DEBUG_IMPLEMENTATIONS, item.hir_id()); + let LevelAndSource { level, .. } = + cx.tcx.lint_level_at_node(MISSING_DEBUG_IMPLEMENTATIONS, item.hir_id()); if level == Level::Allow { return; } diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 017ae943e91..885a7308bdc 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -17,13 +17,12 @@ use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; use rustc_hir::{Pat, PatKind}; use rustc_middle::bug; +use rustc_middle::lint::LevelAndSource; use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout}; use rustc_middle::ty::print::{PrintError, PrintTraitRefExt as _, Printer, with_no_trimmed_paths}; use rustc_middle::ty::{self, GenericArg, RegisteredTools, Ty, TyCtxt, TypingEnv, TypingMode}; -use rustc_session::lint::{ - FutureIncompatibleInfo, Level, Lint, LintBuffer, LintExpectationId, LintId, -}; +use rustc_session::lint::{FutureIncompatibleInfo, Lint, LintBuffer, LintExpectationId, LintId}; use rustc_session::{LintStoreMarker, Session}; use rustc_span::edit_distance::find_best_match_for_names; use rustc_span::{Ident, Span, Symbol, sym}; @@ -573,7 +572,7 @@ pub trait LintContext { } /// This returns the lint level for the given lint at the current location. - fn get_lint_level(&self, lint: &'static Lint) -> Level; + fn get_lint_level(&self, lint: &'static Lint) -> LevelAndSource; /// This function can be used to manually fulfill an expectation. This can /// be used for lints which contain several spans, and should be suppressed, @@ -642,8 +641,8 @@ impl<'tcx> LintContext for LateContext<'tcx> { } } - fn get_lint_level(&self, lint: &'static Lint) -> Level { - self.tcx.lint_level_at_node(lint, self.last_node_with_lint_attrs).0 + fn get_lint_level(&self, lint: &'static Lint) -> LevelAndSource { + self.tcx.lint_level_at_node(lint, self.last_node_with_lint_attrs) } } @@ -663,8 +662,8 @@ impl LintContext for EarlyContext<'_> { self.builder.opt_span_lint(lint, span.map(|s| s.into()), decorate) } - fn get_lint_level(&self, lint: &'static Lint) -> Level { - self.builder.lint_level(lint).0 + fn get_lint_level(&self, lint: &'static Lint) -> LevelAndSource { + self.builder.lint_level(lint) } } diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 313d8f6ba8f..f1fe07cfcfa 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -84,10 +84,10 @@ impl LintLevelSets { ) -> LevelAndSource { let lint = LintId::of(lint); let (level, mut src) = self.raw_lint_id_level(lint, idx, aux); - let level = reveal_actual_level(level, &mut src, sess, lint, |id| { + let (level, lint_id) = reveal_actual_level(level, &mut src, sess, lint, |id| { self.raw_lint_id_level(id, idx, aux) }); - (level, src) + LevelAndSource { level, lint_id, src } } fn raw_lint_id_level( @@ -95,17 +95,17 @@ impl LintLevelSets { id: LintId, mut idx: LintStackIndex, aux: Option<&FxIndexMap<LintId, LevelAndSource>>, - ) -> (Option<Level>, LintLevelSource) { + ) -> (Option<(Level, Option<LintExpectationId>)>, LintLevelSource) { if let Some(specs) = aux - && let Some(&(level, src)) = specs.get(&id) + && let Some(&LevelAndSource { level, lint_id, src }) = specs.get(&id) { - return (Some(level), src); + return (Some((level, lint_id)), src); } loop { let LintSet { ref specs, parent } = self.list[idx]; - if let Some(&(level, src)) = specs.get(&id) { - return (Some(level), src); + if let Some(&LevelAndSource { level, lint_id, src }) = specs.get(&id) { + return (Some((level, lint_id)), src); } if idx == COMMAND_LINE { return (None, LintLevelSource::Default); @@ -131,8 +131,8 @@ fn lints_that_dont_need_to_run(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet<LintId> { }) .filter_map(|lint| { let lint_level = map.lint_level_id_at_node(tcx, LintId::of(lint), CRATE_HIR_ID); - if matches!(lint_level, (Level::Allow, ..)) - || (matches!(lint_level, (.., LintLevelSource::Default))) + if matches!(lint_level.level, Level::Allow) + || (matches!(lint_level.src, LintLevelSource::Default)) && lint.default_level(tcx.sess.edition()) == Level::Allow { Some(LintId::of(lint)) @@ -379,13 +379,7 @@ impl<'tcx> Visitor<'tcx> for LintLevelMaximum<'tcx> { fn visit_attribute(&mut self, attribute: &'tcx hir::Attribute) { if matches!( Level::from_attr(attribute), - Some( - Level::Warn - | Level::Deny - | Level::Forbid - | Level::Expect(..) - | Level::ForceWarn(..), - ) + Some((Level::Warn | Level::Deny | Level::Forbid | Level::Expect | Level::ForceWarn, _)) ) { let store = unerased_lint_store(self.tcx.sess); // Lint attributes are always a metalist inside a @@ -541,9 +535,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { for &(ref lint_name, level) in &self.sess.opts.lint_opts { // Checks the validity of lint names derived from the command line. let (tool_name, lint_name_only) = parse_lint_and_tool_name(lint_name); - if lint_name_only == crate::WARNINGS.name_lower() - && matches!(level, Level::ForceWarn(_)) - { + if lint_name_only == crate::WARNINGS.name_lower() && matches!(level, Level::ForceWarn) { self.sess .dcx() .emit_err(UnsupportedGroup { lint_group: crate::WARNINGS.name_lower() }); @@ -586,7 +578,6 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { _ => {} }; - let orig_level = level; let lint_flag_val = Symbol::intern(lint_name); let Ok(ids) = self.store.find_lints(lint_name) else { @@ -595,15 +586,15 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { }; for id in ids { // ForceWarn and Forbid cannot be overridden - if let Some((Level::ForceWarn(_) | Level::Forbid, _)) = + if let Some(LevelAndSource { level: Level::ForceWarn | Level::Forbid, .. }) = self.current_specs().get(&id) { continue; } if self.check_gated_lint(id, DUMMY_SP, true) { - let src = LintLevelSource::CommandLine(lint_flag_val, orig_level); - self.insert(id, (level, src)); + let src = LintLevelSource::CommandLine(lint_flag_val, level); + self.insert(id, LevelAndSource { level, lint_id: None, src }); } } } @@ -612,8 +603,9 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { /// Attempts to insert the `id` to `level_src` map entry. If unsuccessful /// (e.g. if a forbid was already inserted on the same scope), then emits a /// diagnostic with no change to `specs`. - fn insert_spec(&mut self, id: LintId, (level, src): LevelAndSource) { - let (old_level, old_src) = self.provider.get_lint_level(id.lint, self.sess); + fn insert_spec(&mut self, id: LintId, LevelAndSource { level, lint_id, src }: LevelAndSource) { + let LevelAndSource { level: old_level, src: old_src, .. } = + self.provider.get_lint_level(id.lint, self.sess); // Setting to a non-forbid level is an error if the lint previously had // a forbid level. Note that this is not necessarily true even with a @@ -685,7 +677,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { // The lint `unfulfilled_lint_expectations` can't be expected, as it would suppress itself. // Handling expectations of this lint would add additional complexity with little to no // benefit. The expect level for this lint will therefore be ignored. - if let Level::Expect(_) = level + if let Level::Expect = level && id == LintId::of(UNFULFILLED_LINT_EXPECTATIONS) { return; @@ -693,13 +685,16 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { match (old_level, level) { // If the new level is an expectation store it in `ForceWarn` - (Level::ForceWarn(_), Level::Expect(expectation_id)) => { - self.insert(id, (Level::ForceWarn(Some(expectation_id)), old_src)) + (Level::ForceWarn, Level::Expect) => { + self.insert(id, LevelAndSource { level: Level::ForceWarn, lint_id, src: old_src }) } // Keep `ForceWarn` level but drop the expectation - (Level::ForceWarn(_), _) => self.insert(id, (Level::ForceWarn(None), old_src)), + (Level::ForceWarn, _) => self.insert( + id, + LevelAndSource { level: Level::ForceWarn, lint_id: None, src: old_src }, + ), // Set the lint level as normal - _ => self.insert(id, (level, src)), + _ => self.insert(id, LevelAndSource { level, lint_id, src }), }; } @@ -714,7 +709,11 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { if attr.has_name(sym::automatically_derived) { self.insert( LintId::of(SINGLE_USE_LIFETIMES), - (Level::Allow, LintLevelSource::Default), + LevelAndSource { + level: Level::Allow, + lint_id: None, + src: LintLevelSource::Default, + }, ); continue; } @@ -725,15 +724,22 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { .meta_item_list() .is_some_and(|l| ast::attr::list_contains_name(&l, sym::hidden)) { - self.insert(LintId::of(MISSING_DOCS), (Level::Allow, LintLevelSource::Default)); + self.insert( + LintId::of(MISSING_DOCS), + LevelAndSource { + level: Level::Allow, + lint_id: None, + src: LintLevelSource::Default, + }, + ); continue; } - let level = match Level::from_attr(attr) { + let (level, lint_id) = match Level::from_attr(attr) { None => continue, // This is the only lint level with a `LintExpectationId` that can be created from // an attribute. - Some(Level::Expect(unstable_id)) if let Some(hir_id) = source_hir_id => { + Some((Level::Expect, Some(unstable_id))) if let Some(hir_id) = source_hir_id => { let LintExpectationId::Unstable { lint_index: None, attr_id: _ } = unstable_id else { bug!("stable id Level::from_attr") @@ -745,9 +751,9 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { lint_index: None, }; - Level::Expect(stable_id) + (Level::Expect, Some(stable_id)) } - Some(lvl) => lvl, + Some((lvl, id)) => (lvl, id), }; let Some(mut metas) = attr.meta_item_list() else { continue }; @@ -795,13 +801,10 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { } for (lint_index, li) in metas.iter_mut().enumerate() { - let level = match level { - Level::Expect(mut id) => { - id.set_lint_index(Some(lint_index as u16)); - Level::Expect(id) - } - level => level, - }; + let mut lint_id = lint_id; + if let Some(id) = &mut lint_id { + id.set_lint_index(Some(lint_index as u16)); + } let sp = li.span(); let meta_item = match li { @@ -933,7 +936,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { let src = LintLevelSource::Node { name, span: sp, reason }; for &id in ids { if self.check_gated_lint(id, sp, false) { - self.insert_spec(id, (level, src)); + self.insert_spec(id, LevelAndSource { level, lint_id, src }); } } @@ -942,7 +945,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { // overriding the lint level but instead add an expectation that can't be // fulfilled. The lint message will include an explanation, that the // `unfulfilled_lint_expectations` lint can't be expected. - if let Level::Expect(expect_id) = level { + if let (Level::Expect, Some(expect_id)) = (level, lint_id) { // The `unfulfilled_lint_expectations` lint is not part of any lint // groups. Therefore. we only need to check the slice if it contains a // single lint. @@ -964,7 +967,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { } if self.lint_added_lints && !is_crate_node { - for (id, &(level, ref src)) in self.current_specs().iter() { + for (id, &LevelAndSource { level, ref src, .. }) in self.current_specs().iter() { if !id.lint.crate_level_only { continue; } @@ -1002,10 +1005,10 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { if self.lint_added_lints { let lint = builtin::UNKNOWN_LINTS; - let (level, src) = self.lint_level(builtin::UNKNOWN_LINTS); + let level = self.lint_level(builtin::UNKNOWN_LINTS); // FIXME: make this translatable #[allow(rustc::diagnostic_outside_of_impl)] - lint_level(self.sess, lint, level, src, Some(span.into()), |lint| { + lint_level(self.sess, lint, level, Some(span.into()), |lint| { lint.primary_message(fluent::lint_unknown_gated_lint); lint.arg("name", lint_id.lint.name_lower()); lint.note(fluent::lint_note); @@ -1040,8 +1043,8 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { span: Option<MultiSpan>, decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>), ) { - let (level, src) = self.lint_level(lint); - lint_level(self.sess, lint, level, src, span, decorate) + let level = self.lint_level(lint); + lint_level(self.sess, lint, level, span, decorate) } #[track_caller] @@ -1051,16 +1054,16 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { span: MultiSpan, decorate: impl for<'a> LintDiagnostic<'a, ()>, ) { - let (level, src) = self.lint_level(lint); - lint_level(self.sess, lint, level, src, Some(span), |lint| { + let level = self.lint_level(lint); + lint_level(self.sess, lint, level, Some(span), |lint| { decorate.decorate_lint(lint); }); } #[track_caller] pub fn emit_lint(&self, lint: &'static Lint, decorate: impl for<'a> LintDiagnostic<'a, ()>) { - let (level, src) = self.lint_level(lint); - lint_level(self.sess, lint, level, src, None, |lint| { + let level = self.lint_level(lint); + lint_level(self.sess, lint, level, None, |lint| { decorate.decorate_lint(lint); }); } diff --git a/compiler/rustc_lint/src/non_ascii_idents.rs b/compiler/rustc_lint/src/non_ascii_idents.rs index 66e207a451e..9c11fb41aa6 100644 --- a/compiler/rustc_lint/src/non_ascii_idents.rs +++ b/compiler/rustc_lint/src/non_ascii_idents.rs @@ -159,12 +159,13 @@ impl EarlyLintPass for NonAsciiIdents { use rustc_span::Span; use unicode_security::GeneralSecurityProfile; - let check_non_ascii_idents = cx.builder.lint_level(NON_ASCII_IDENTS).0 != Level::Allow; + let check_non_ascii_idents = cx.builder.lint_level(NON_ASCII_IDENTS).level != Level::Allow; let check_uncommon_codepoints = - cx.builder.lint_level(UNCOMMON_CODEPOINTS).0 != Level::Allow; - let check_confusable_idents = cx.builder.lint_level(CONFUSABLE_IDENTS).0 != Level::Allow; + cx.builder.lint_level(UNCOMMON_CODEPOINTS).level != Level::Allow; + let check_confusable_idents = + cx.builder.lint_level(CONFUSABLE_IDENTS).level != Level::Allow; let check_mixed_script_confusables = - cx.builder.lint_level(MIXED_SCRIPT_CONFUSABLES).0 != Level::Allow; + cx.builder.lint_level(MIXED_SCRIPT_CONFUSABLES).level != Level::Allow; if !check_non_ascii_idents && !check_uncommon_codepoints diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index fec5db64bf2..a6c82f574a1 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -14,7 +14,7 @@ use rustc_middle::ty::{ }; use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass}; use rustc_span::def_id::LocalDefId; -use rustc_span::{Span, Symbol, source_map, sym}; +use rustc_span::{Span, Symbol, sym}; use tracing::debug; use {rustc_ast as ast, rustc_hir as hir}; @@ -223,7 +223,7 @@ impl TypeLimits { fn lint_nan<'tcx>( cx: &LateContext<'tcx>, e: &'tcx hir::Expr<'tcx>, - binop: hir::BinOp, + binop: hir::BinOpKind, l: &'tcx hir::Expr<'tcx>, r: &'tcx hir::Expr<'tcx>, ) { @@ -262,19 +262,19 @@ fn lint_nan<'tcx>( InvalidNanComparisons::EqNe { suggestion } } - let lint = match binop.node { + let lint = match binop { hir::BinOpKind::Eq | hir::BinOpKind::Ne if is_nan(cx, l) => { eq_ne(e, l, r, |l_span, r_span| InvalidNanComparisonsSuggestion::Spanful { nan_plus_binop: l_span.until(r_span), float: r_span.shrink_to_hi(), - neg: (binop.node == hir::BinOpKind::Ne).then(|| r_span.shrink_to_lo()), + neg: (binop == hir::BinOpKind::Ne).then(|| r_span.shrink_to_lo()), }) } hir::BinOpKind::Eq | hir::BinOpKind::Ne if is_nan(cx, r) => { eq_ne(e, l, r, |l_span, r_span| InvalidNanComparisonsSuggestion::Spanful { nan_plus_binop: l_span.shrink_to_hi().to(r_span), float: l_span.shrink_to_hi(), - neg: (binop.node == hir::BinOpKind::Ne).then(|| l_span.shrink_to_lo()), + neg: (binop == hir::BinOpKind::Ne).then(|| l_span.shrink_to_lo()), }) } hir::BinOpKind::Lt | hir::BinOpKind::Le | hir::BinOpKind::Gt | hir::BinOpKind::Ge @@ -560,11 +560,11 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits { } } hir::ExprKind::Binary(binop, ref l, ref r) => { - if is_comparison(binop) { - if !check_limits(cx, binop, l, r) { + if is_comparison(binop.node) { + if !check_limits(cx, binop.node, l, r) { cx.emit_span_lint(UNUSED_COMPARISONS, e.span, UnusedComparisons); } else { - lint_nan(cx, e, binop, l, r); + lint_nan(cx, e, binop.node, l, r); let cmpop = ComparisonOp::BinOp(binop.node); lint_wide_pointer(cx, e, cmpop, l, r); lint_fn_pointer(cx, e, cmpop, l, r); @@ -591,8 +591,8 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits { _ => {} }; - fn is_valid<T: PartialOrd>(binop: hir::BinOp, v: T, min: T, max: T) -> bool { - match binop.node { + fn is_valid<T: PartialOrd>(binop: hir::BinOpKind, v: T, min: T, max: T) -> bool { + match binop { hir::BinOpKind::Lt => v > min && v <= max, hir::BinOpKind::Le => v >= min && v < max, hir::BinOpKind::Gt => v >= min && v < max, @@ -602,22 +602,19 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits { } } - fn rev_binop(binop: hir::BinOp) -> hir::BinOp { - source_map::respan( - binop.span, - match binop.node { - hir::BinOpKind::Lt => hir::BinOpKind::Gt, - hir::BinOpKind::Le => hir::BinOpKind::Ge, - hir::BinOpKind::Gt => hir::BinOpKind::Lt, - hir::BinOpKind::Ge => hir::BinOpKind::Le, - _ => return binop, - }, - ) + fn rev_binop(binop: hir::BinOpKind) -> hir::BinOpKind { + match binop { + hir::BinOpKind::Lt => hir::BinOpKind::Gt, + hir::BinOpKind::Le => hir::BinOpKind::Ge, + hir::BinOpKind::Gt => hir::BinOpKind::Lt, + hir::BinOpKind::Ge => hir::BinOpKind::Le, + _ => binop, + } } fn check_limits( cx: &LateContext<'_>, - binop: hir::BinOp, + binop: hir::BinOpKind, l: &hir::Expr<'_>, r: &hir::Expr<'_>, ) -> bool { @@ -659,9 +656,9 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits { } } - fn is_comparison(binop: hir::BinOp) -> bool { + fn is_comparison(binop: hir::BinOpKind) -> bool { matches!( - binop.node, + binop, hir::BinOpKind::Eq | hir::BinOpKind::Lt | hir::BinOpKind::Le diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 46b4b1d4383..7fdbae3a59d 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -8,7 +8,8 @@ use rustc_data_structures::stable_hasher::{ }; use rustc_error_messages::{DiagMessage, MultiSpan}; use rustc_hir::def::Namespace; -use rustc_hir::{HashStableContext, HirId, MissingLifetimeKind}; +use rustc_hir::def_id::DefPathHash; +use rustc_hir::{HashStableContext, HirId, ItemLocalId, MissingLifetimeKind}; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; pub use rustc_span::edition::Edition; use rustc_span::{Ident, MacroRulesNormalizedIdent, Span, Symbol, sym}; @@ -102,7 +103,7 @@ pub enum Applicability { /// The index values have a type of `u16` to reduce the size of the `LintExpectationId`. /// It's reasonable to assume that no user will define 2^16 attributes on one node or /// have that amount of lints listed. `u16` values should therefore suffice. -#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash, Encodable, Decodable)] +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Encodable, Decodable)] pub enum LintExpectationId { /// Used for lints emitted during the `EarlyLintPass`. This id is not /// hash stable and should not be cached. @@ -156,13 +157,14 @@ impl<HCX: rustc_hir::HashStableContext> HashStable<HCX> for LintExpectationId { } impl<HCX: rustc_hir::HashStableContext> ToStableHashKey<HCX> for LintExpectationId { - type KeyType = (HirId, u16, u16); + type KeyType = (DefPathHash, ItemLocalId, u16, u16); #[inline] - fn to_stable_hash_key(&self, _: &HCX) -> Self::KeyType { + fn to_stable_hash_key(&self, hcx: &HCX) -> Self::KeyType { match self { LintExpectationId::Stable { hir_id, attr_index, lint_index: Some(lint_index) } => { - (*hir_id, *attr_index, *lint_index) + let (def_path_hash, lint_idx) = hir_id.to_stable_hash_key(hcx); + (def_path_hash, lint_idx, *attr_index, *lint_index) } _ => { unreachable!("HashStable should only be called for a filled `LintExpectationId`") @@ -199,9 +201,9 @@ pub enum Level { /// /// See RFC 2383. /// - /// The [`LintExpectationId`] is used to later link a lint emission to the actual + /// Requires a [`LintExpectationId`] to later link a lint emission to the actual /// expectation. It can be ignored in most cases. - Expect(LintExpectationId), + Expect, /// The `warn` level will produce a warning if the lint was violated, however the /// compiler will continue with its execution. Warn, @@ -209,9 +211,9 @@ pub enum Level { /// to ensure that a lint can't be suppressed. This lint level can currently only be set /// via the console and is therefore session specific. /// - /// The [`LintExpectationId`] is intended to fulfill expectations marked via the + /// Requires a [`LintExpectationId`] to fulfill expectations marked via the /// `#[expect]` attribute, that will still be suppressed due to the level. - ForceWarn(Option<LintExpectationId>), + ForceWarn, /// The `deny` level will produce an error and stop further execution after the lint /// pass is complete. Deny, @@ -225,9 +227,9 @@ impl Level { pub fn as_str(self) -> &'static str { match self { Level::Allow => "allow", - Level::Expect(_) => "expect", + Level::Expect => "expect", Level::Warn => "warn", - Level::ForceWarn(_) => "force-warn", + Level::ForceWarn => "force-warn", Level::Deny => "deny", Level::Forbid => "forbid", } @@ -246,24 +248,30 @@ impl Level { } /// Converts an `Attribute` to a level. - pub fn from_attr(attr: &impl AttributeExt) -> Option<Self> { + pub fn from_attr(attr: &impl AttributeExt) -> Option<(Self, Option<LintExpectationId>)> { Self::from_symbol(attr.name_or_empty(), || Some(attr.id())) } /// Converts a `Symbol` to a level. - pub fn from_symbol(s: Symbol, id: impl FnOnce() -> Option<AttrId>) -> Option<Self> { + pub fn from_symbol( + s: Symbol, + id: impl FnOnce() -> Option<AttrId>, + ) -> Option<(Self, Option<LintExpectationId>)> { match s { - sym::allow => Some(Level::Allow), + sym::allow => Some((Level::Allow, None)), sym::expect => { if let Some(attr_id) = id() { - Some(Level::Expect(LintExpectationId::Unstable { attr_id, lint_index: None })) + Some(( + Level::Expect, + Some(LintExpectationId::Unstable { attr_id, lint_index: None }), + )) } else { None } } - sym::warn => Some(Level::Warn), - sym::deny => Some(Level::Deny), - sym::forbid => Some(Level::Forbid), + sym::warn => Some((Level::Warn, None)), + sym::deny => Some((Level::Deny, None)), + sym::forbid => Some((Level::Forbid, None)), _ => None, } } @@ -274,8 +282,8 @@ impl Level { Level::Deny => "-D", Level::Forbid => "-F", Level::Allow => "-A", - Level::ForceWarn(_) => "--force-warn", - Level::Expect(_) => { + Level::ForceWarn => "--force-warn", + Level::Expect => { unreachable!("the expect level does not have a commandline flag") } } @@ -283,17 +291,10 @@ impl Level { pub fn is_error(self) -> bool { match self { - Level::Allow | Level::Expect(_) | Level::Warn | Level::ForceWarn(_) => false, + Level::Allow | Level::Expect | Level::Warn | Level::ForceWarn => false, Level::Deny | Level::Forbid => true, } } - - pub fn get_expectation_id(&self) -> Option<LintExpectationId> { - match self { - Level::Expect(id) | Level::ForceWarn(Some(id)) => Some(*id), - _ => None, - } - } } /// Specification of a single lint. diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 16f87ab79be..1c3222bbfeb 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -340,7 +340,7 @@ impl CStore { } let level = tcx .lint_level_at_node(lint::builtin::UNUSED_CRATE_DEPENDENCIES, rustc_hir::CRATE_HIR_ID) - .0; + .level; if level != lint::Level::Allow { let unused_externs = self.unused_externs.iter().map(|ident| ident.to_ident_string()).collect::<Vec<_>>(); diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index f63ae8079dc..130a425e9c7 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -73,7 +73,7 @@ pub fn walk_native_lib_search_dirs<R>( || sess.target.os == "linux" || sess.target.os == "fuchsia" || sess.target.is_like_aix - || sess.target.is_like_osx && !sess.opts.unstable_opts.sanitizer.is_empty() + || sess.target.is_like_darwin && !sess.opts.unstable_opts.sanitizer.is_empty() { f(&sess.target_tlib_path.dir, false)?; } @@ -257,7 +257,7 @@ impl<'tcx> Collector<'tcx> { "static" => NativeLibKind::Static { bundle: None, whole_archive: None }, "dylib" => NativeLibKind::Dylib { as_needed: None }, "framework" => { - if !sess.target.is_like_osx { + if !sess.target.is_like_darwin { sess.dcx().emit_err(errors::LinkFrameworkApple { span }); } NativeLibKind::Framework { as_needed: None } @@ -531,7 +531,7 @@ impl<'tcx> Collector<'tcx> { let mut renames = FxHashSet::default(); for lib in &self.tcx.sess.opts.libs { if let NativeLibKind::Framework { .. } = lib.kind - && !self.tcx.sess.target.is_like_osx + && !self.tcx.sess.target.is_like_darwin { // Cannot check this when parsing options because the target is not yet available. self.tcx.dcx().emit_err(errors::LibFrameworkApple); diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 88bf17070b9..d5a408fdfa6 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -51,8 +51,13 @@ impl LintLevelSource { } } -/// A tuple of a lint level and its source. -pub type LevelAndSource = (Level, LintLevelSource); +/// Convenience helper for moving things around together that frequently are paired +#[derive(Copy, Clone, Debug, HashStable, Encodable, Decodable)] +pub struct LevelAndSource { + pub level: Level, + pub lint_id: Option<LintExpectationId>, + pub src: LintLevelSource, +} /// Return type for the `shallow_lint_levels_on` query. /// @@ -69,14 +74,18 @@ pub struct ShallowLintLevelMap { /// /// The return of this function is suitable for diagnostics. pub fn reveal_actual_level( - level: Option<Level>, + level: Option<(Level, Option<LintExpectationId>)>, src: &mut LintLevelSource, sess: &Session, lint: LintId, - probe_for_lint_level: impl FnOnce(LintId) -> (Option<Level>, LintLevelSource), -) -> Level { + probe_for_lint_level: impl FnOnce( + LintId, + ) + -> (Option<(Level, Option<LintExpectationId>)>, LintLevelSource), +) -> (Level, Option<LintExpectationId>) { // If `level` is none then we actually assume the default level for this lint. - let mut level = level.unwrap_or_else(|| lint.lint.default_level(sess.edition())); + let (mut level, mut lint_id) = + level.unwrap_or_else(|| (lint.lint.default_level(sess.edition()), None)); // If we're about to issue a warning, check at the last minute for any // directives against the warnings "lint". If, for example, there's an @@ -88,16 +97,17 @@ pub fn reveal_actual_level( // future compatibility warning. if level == Level::Warn && lint != LintId::of(FORBIDDEN_LINT_GROUPS) { let (warnings_level, warnings_src) = probe_for_lint_level(LintId::of(builtin::WARNINGS)); - if let Some(configured_warning_level) = warnings_level { + if let Some((configured_warning_level, configured_lint_id)) = warnings_level { if configured_warning_level != Level::Warn { level = configured_warning_level; + lint_id = configured_lint_id; *src = warnings_src; } } } // Ensure that we never exceed the `--cap-lints` argument unless the source is a --force-warn - level = if let LintLevelSource::CommandLine(_, Level::ForceWarn(_)) = src { + level = if let LintLevelSource::CommandLine(_, Level::ForceWarn) = src { level } else { cmp::min(level, sess.opts.lint_cap.unwrap_or(Level::Forbid)) @@ -108,7 +118,7 @@ pub fn reveal_actual_level( level = cmp::min(*driver_level, level); } - level + (level, lint_id) } impl ShallowLintLevelMap { @@ -121,11 +131,11 @@ impl ShallowLintLevelMap { tcx: TyCtxt<'_>, id: LintId, start: HirId, - ) -> (Option<Level>, LintLevelSource) { + ) -> (Option<(Level, Option<LintExpectationId>)>, LintLevelSource) { if let Some(map) = self.specs.get(&start.local_id) - && let Some(&(level, src)) = map.get(&id) + && let Some(&LevelAndSource { level, lint_id, src }) = map.get(&id) { - return (Some(level), src); + return (Some((level, lint_id)), src); } let mut owner = start.owner; @@ -137,9 +147,9 @@ impl ShallowLintLevelMap { specs = &tcx.shallow_lint_levels_on(owner).specs; } if let Some(map) = specs.get(&parent.local_id) - && let Some(&(level, src)) = map.get(&id) + && let Some(&LevelAndSource { level, lint_id, src }) = map.get(&id) { - return (Some(level), src); + return (Some((level, lint_id)), src); } } @@ -153,18 +163,18 @@ impl ShallowLintLevelMap { tcx: TyCtxt<'_>, lint: LintId, cur: HirId, - ) -> (Level, LintLevelSource) { + ) -> LevelAndSource { let (level, mut src) = self.probe_for_lint_level(tcx, lint, cur); - let level = reveal_actual_level(level, &mut src, tcx.sess, lint, |lint| { + let (level, lint_id) = reveal_actual_level(level, &mut src, tcx.sess, lint, |lint| { self.probe_for_lint_level(tcx, lint, cur) }); - (level, src) + LevelAndSource { level, lint_id, src } } } impl TyCtxt<'_> { /// Fetch and return the user-visible lint level for the given lint at the given HirId. - pub fn lint_level_at_node(self, lint: &'static Lint, id: HirId) -> (Level, LintLevelSource) { + pub fn lint_level_at_node(self, lint: &'static Lint, id: HirId) -> LevelAndSource { self.shallow_lint_levels_on(id.owner).lint_level_id_at_node(self, LintId::of(lint), id) } } @@ -267,8 +277,7 @@ fn explain_lint_level_source( pub fn lint_level( sess: &Session, lint: &'static Lint, - level: Level, - src: LintLevelSource, + level: LevelAndSource, span: Option<MultiSpan>, decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>), ) { @@ -278,11 +287,12 @@ pub fn lint_level( fn lint_level_impl( sess: &Session, lint: &'static Lint, - level: Level, - src: LintLevelSource, + level: LevelAndSource, span: Option<MultiSpan>, decorate: Box<dyn '_ + for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>)>, ) { + let LevelAndSource { level, lint_id, src } = level; + // Check for future incompatibility lints and issue a stronger warning. let future_incompatible = lint.future_incompatible; @@ -301,7 +311,7 @@ pub fn lint_level( return; } } - Level::Expect(expect_id) => { + Level::Expect => { // This case is special as we actually allow the lint itself in this context, but // we can't return early like in the case for `Level::Allow` because we still // need the lint diagnostic to be emitted to `rustc_error::DiagCtxtInner`. @@ -309,10 +319,9 @@ pub fn lint_level( // We can also not mark the lint expectation as fulfilled here right away, as it // can still be cancelled in the decorate function. All of this means that we simply // create a `Diag` and continue as we would for warnings. - rustc_errors::Level::Expect(expect_id) + rustc_errors::Level::Expect } - Level::ForceWarn(Some(expect_id)) => rustc_errors::Level::ForceWarning(Some(expect_id)), - Level::ForceWarn(None) => rustc_errors::Level::ForceWarning(None), + Level::ForceWarn => rustc_errors::Level::ForceWarning, Level::Warn => rustc_errors::Level::Warning, Level::Deny | Level::Forbid => rustc_errors::Level::Error, }; @@ -320,6 +329,9 @@ pub fn lint_level( if let Some(span) = span { err.span(span); } + if let Some(lint_id) = lint_id { + err.lint_id(lint_id); + } // 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 @@ -350,7 +362,7 @@ pub fn lint_level( // the compiler. It is therefore not necessary to add any information for the user. // This will therefore directly call the decorate function which will in turn emit // the diagnostic. - if let Level::Expect(_) = level { + if let Level::Expect = level { decorate(&mut err); err.emit(); return; @@ -419,5 +431,5 @@ pub fn lint_level( explain_lint_level_source(lint, level, src, &mut err); err.emit() } - lint_level_impl(sess, lint, level, src, span, Box::new(decorate)) + lint_level_impl(sess, lint, level, span, Box::new(decorate)) } diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index ec128c8c478..9912e659b05 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -255,7 +255,7 @@ fn late_report_deprecation( // Calculating message for lint involves calling `self.def_path_str`, // which will by default invoke the expensive `visible_parent_map` query. // Skip all that work if the lint is allowed anyway. - if tcx.lint_level_at_node(lint, hir_id).0 == Level::Allow { + if tcx.lint_level_at_node(lint, hir_id).level == Level::Allow { return; } diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 6d6e6a1f185..707c8d04d55 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1668,6 +1668,42 @@ pub enum BinOp { Offset, } +// Assignment operators, e.g. `+=`. See comments on the corresponding variants +// in `BinOp` for details. +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] +pub enum AssignOp { + AddAssign, + SubAssign, + MulAssign, + DivAssign, + RemAssign, + BitXorAssign, + BitAndAssign, + BitOrAssign, + ShlAssign, + ShrAssign, +} + +// Sometimes `BinOp` and `AssignOp` need the same treatment. The operations +// covered by `AssignOp` are a subset of those covered by `BinOp`, so it makes +// sense to convert `AssignOp` to `BinOp`. +impl From<AssignOp> for BinOp { + fn from(op: AssignOp) -> BinOp { + match op { + AssignOp::AddAssign => BinOp::Add, + AssignOp::SubAssign => BinOp::Sub, + AssignOp::MulAssign => BinOp::Mul, + AssignOp::DivAssign => BinOp::Div, + AssignOp::RemAssign => BinOp::Rem, + AssignOp::BitXorAssign => BinOp::BitXor, + AssignOp::BitAndAssign => BinOp::BitAnd, + AssignOp::BitOrAssign => BinOp::BitOr, + AssignOp::ShlAssign => BinOp::Shl, + AssignOp::ShrAssign => BinOp::Shr, + } + } +} + // Some nodes are used a lot. Make sure they don't unintentionally get bigger. #[cfg(target_pointer_width = "64")] mod size_asserts { diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 6783bbf8bf4..8d373cb3b30 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -27,7 +27,7 @@ use tracing::instrument; use crate::middle::region; use crate::mir::interpret::AllocId; -use crate::mir::{self, BinOp, BorrowKind, FakeReadCause, UnOp}; +use crate::mir::{self, AssignOp, BinOp, BorrowKind, FakeReadCause, UnOp}; use crate::thir::visit::for_each_immediate_subpat; use crate::ty::adjustment::PointerCoercion; use crate::ty::layout::IntegerExt; @@ -403,7 +403,7 @@ pub enum ExprKind<'tcx> { }, /// A *non-overloaded* operation assignment, e.g. `lhs += rhs`. AssignOp { - op: BinOp, + op: AssignOp, lhs: ExprId, rhs: ExprId, }, diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 618a65a0186..13217ae58e9 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -446,6 +446,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.is_lang_item(def_id, trait_lang_item_to_lang_item(lang_item)) } + fn is_default_trait(self, def_id: DefId) -> bool { + self.is_default_trait(def_id) + } + fn as_lang_item(self, def_id: DefId) -> Option<TraitSolverLangItem> { lang_item_to_trait_lang_item(self.lang_items().from_def_id(def_id)?) } @@ -1539,6 +1543,25 @@ impl<'tcx> TyCtxt<'tcx> { self.reserve_and_set_memory_dedup(alloc, salt) } + pub fn default_traits(self) -> &'static [rustc_hir::LangItem] { + match self.sess.opts.unstable_opts.experimental_default_bounds { + true => &[ + LangItem::Sized, + LangItem::DefaultTrait1, + LangItem::DefaultTrait2, + LangItem::DefaultTrait3, + LangItem::DefaultTrait4, + ], + false => &[LangItem::Sized], + } + } + + pub fn is_default_trait(self, def_id: DefId) -> bool { + self.default_traits() + .iter() + .any(|&default_trait| self.lang_items().get(default_trait) == Some(def_id)) + } + /// Returns a range of the start/end indices specified with the /// `rustc_layout_scalar_valid_range` attribute. // FIXME(eddyb) this is an awkward spot for this method, maybe move it? @@ -3022,8 +3045,8 @@ impl<'tcx> TyCtxt<'tcx> { span: impl Into<MultiSpan>, decorator: impl for<'a> LintDiagnostic<'a, ()>, ) { - let (level, src) = self.lint_level_at_node(lint, hir_id); - lint_level(self.sess, lint, level, src, Some(span.into()), |lint| { + let level = self.lint_level_at_node(lint, hir_id); + lint_level(self.sess, lint, level, Some(span.into()), |lint| { decorator.decorate_lint(lint); }) } @@ -3040,8 +3063,8 @@ impl<'tcx> TyCtxt<'tcx> { span: impl Into<MultiSpan>, decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>), ) { - let (level, src) = self.lint_level_at_node(lint, hir_id); - lint_level(self.sess, lint, level, src, Some(span.into()), decorate); + let level = self.lint_level_at_node(lint, hir_id); + lint_level(self.sess, lint, level, Some(span.into()), decorate); } /// Find the crate root and the appropriate span where `use` and outer attributes can be @@ -3108,8 +3131,8 @@ impl<'tcx> TyCtxt<'tcx> { id: HirId, decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>), ) { - let (level, src) = self.lint_level_at_node(lint, id); - lint_level(self.sess, lint, level, src, None, decorate); + let level = self.lint_level_at_node(lint, id); + lint_level(self.sess, lint, level, None, decorate); } pub fn in_scope_traits(self, id: HirId) -> Option<&'tcx [TraitCandidate]> { diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 74a94d82784..27ee363f1c1 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -8,7 +8,7 @@ use std::iter; use std::ops::{ControlFlow, Range}; use hir::def::{CtorKind, DefKind}; -use rustc_abi::{ExternAbi, FIRST_VARIANT, FieldIdx, VariantIdx}; +use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx}; use rustc_errors::{ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::LangItem; @@ -1441,23 +1441,7 @@ impl<'tcx> Ty<'tcx> { #[tracing::instrument(level = "trace", skip(tcx))] pub fn fn_sig(self, tcx: TyCtxt<'tcx>) -> PolyFnSig<'tcx> { - match self.kind() { - FnDef(def_id, args) => tcx.fn_sig(*def_id).instantiate(tcx, args), - FnPtr(sig_tys, hdr) => sig_tys.with(*hdr), - Error(_) => { - // ignore errors (#54954) - Binder::dummy(ty::FnSig { - inputs_and_output: ty::List::empty(), - c_variadic: false, - safety: hir::Safety::Safe, - abi: ExternAbi::Rust, - }) - } - Closure(..) => bug!( - "to get the signature of a closure, use `args.as_closure().sig()` not `fn_sig()`", - ), - _ => bug!("Ty::fn_sig() called on non-fn type: {:?}", self), - } + self.kind().fn_sig(tcx) } #[inline] @@ -2043,32 +2027,7 @@ impl<'tcx> Ty<'tcx> { /// nested types may be further simplified, the outermost [`TyKind`] or /// type constructor remains the same. pub fn is_known_rigid(self) -> bool { - match self.kind() { - Bool - | Char - | Int(_) - | Uint(_) - | Float(_) - | Adt(_, _) - | Foreign(_) - | Str - | Array(_, _) - | Pat(_, _) - | Slice(_) - | RawPtr(_, _) - | Ref(_, _, _) - | FnDef(_, _) - | FnPtr(..) - | Dynamic(_, _, _) - | Closure(_, _) - | CoroutineClosure(_, _) - | Coroutine(_, _) - | CoroutineWitness(..) - | Never - | Tuple(_) - | UnsafeBinder(_) => true, - Error(_) | Infer(_) | Alias(_, _) | Param(_) | Bound(_, _) | Placeholder(_) => false, - } + self.kind().is_known_rigid() } } diff --git a/compiler/rustc_mir_build/src/builder/expr/as_place.rs b/compiler/rustc_mir_build/src/builder/expr/as_place.rs index 90e27c85f74..fbe53081156 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_place.rs @@ -159,7 +159,7 @@ fn find_capture_matching_projections<'a, 'tcx>( ) -> Option<(usize, &'a Capture<'tcx>)> { let hir_projections = convert_to_hir_projections_and_truncate_for_capture(projections); - upvars.get_by_key_enumerated(var_hir_id.0).find(|(_, capture)| { + upvars.get_by_key_enumerated(var_hir_id.0.local_id).find(|(_, capture)| { let possible_ancestor_proj_kinds: Vec<_> = capture.captured_place.place.projections.iter().map(|proj| proj.kind).collect(); is_ancestor_or_same_capture(&possible_ancestor_proj_kinds, &hir_projections) diff --git a/compiler/rustc_mir_build/src/builder/expr/stmt.rs b/compiler/rustc_mir_build/src/builder/expr/stmt.rs index 7f8a0a34c31..2dff26f02f3 100644 --- a/compiler/rustc_mir_build/src/builder/expr/stmt.rs +++ b/compiler/rustc_mir_build/src/builder/expr/stmt.rs @@ -78,8 +78,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // because AssignOp is only legal for Copy types // (overloaded ops should be desugared into a call). let result = unpack!( - block = - this.build_binary_op(block, op, expr_span, lhs_ty, Operand::Copy(lhs), rhs) + block = this.build_binary_op( + block, + op.into(), + expr_span, + lhs_ty, + Operand::Copy(lhs), + rhs + ) ); this.cfg.push_assign(block, source_info, lhs, result); diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs index bcc2a4674ea..8ca9ab58e45 100644 --- a/compiler/rustc_mir_build/src/builder/mod.rs +++ b/compiler/rustc_mir_build/src/builder/mod.rs @@ -13,7 +13,7 @@ use rustc_data_structures::sorted_map::SortedIndexMultiMap; use rustc_errors::ErrorGuaranteed; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::{self as hir, BindingMode, ByRef, HirId, Node}; +use rustc_hir::{self as hir, BindingMode, ByRef, HirId, ItemLocalId, Node}; use rustc_index::bit_set::GrowableBitSet; use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; @@ -221,7 +221,7 @@ struct Builder<'a, 'tcx> { coverage_info: Option<coverageinfo::CoverageInfoBuilder>, } -type CaptureMap<'tcx> = SortedIndexMultiMap<usize, HirId, Capture<'tcx>>; +type CaptureMap<'tcx> = SortedIndexMultiMap<usize, ItemLocalId, Capture<'tcx>>; #[derive(Debug)] struct Capture<'tcx> { @@ -853,6 +853,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let capture_tys = upvar_args.upvar_tys(); let tcx = self.tcx; + let mut upvar_owner = None; self.upvars = tcx .closure_captures(self.def_id) .iter() @@ -866,6 +867,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { HirPlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id, _ => bug!("Expected an upvar"), }; + let upvar_base = upvar_owner.get_or_insert(var_id.owner); + assert_eq!(*upvar_base, var_id.owner); + let var_id = var_id.local_id; let mutability = captured_place.mutability; diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 2a9bfb25b84..6fb9974fc8e 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -195,7 +195,7 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { /// Whether the `unsafe_op_in_unsafe_fn` lint is `allow`ed at the current HIR node. fn unsafe_op_in_unsafe_fn_allowed(&self) -> bool { - self.tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, self.hir_context).0 == Level::Allow + self.tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, self.hir_context).level == Level::Allow } /// Handle closures/coroutines/inline-consts, which is unsafecked with their parent body. @@ -292,8 +292,10 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { }); } BlockSafety::ExplicitUnsafe(hir_id) => { - let used = - matches!(self.tcx.lint_level_at_node(UNUSED_UNSAFE, hir_id), (Level::Allow, _)); + let used = matches!( + self.tcx.lint_level_at_node(UNUSED_UNSAFE, hir_id).level, + Level::Allow + ); self.in_safety_context( SafetyContext::UnsafeBlock { span: block.span, diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index b8af77245f2..31e22e69111 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -9,7 +9,7 @@ use rustc_middle::hir::place::{ Place as HirPlace, PlaceBase as HirPlaceBase, ProjectionKind as HirProjectionKind, }; use rustc_middle::middle::region; -use rustc_middle::mir::{self, BinOp, BorrowKind, UnOp}; +use rustc_middle::mir::{self, AssignOp, BinOp, BorrowKind, UnOp}; use rustc_middle::thir::*; use rustc_middle::ty::adjustment::{ Adjust, Adjustment, AutoBorrow, AutoBorrowMutability, PointerCoercion, @@ -489,7 +489,7 @@ impl<'tcx> ThirBuildCx<'tcx> { self.overloaded_operator(expr, Box::new([lhs, rhs])) } else { ExprKind::AssignOp { - op: bin_op(op.node), + op: assign_op(op.node), lhs: self.mirror_expr(lhs), rhs: self.mirror_expr(rhs), } @@ -1347,3 +1347,18 @@ fn bin_op(op: hir::BinOpKind) -> BinOp { _ => bug!("no equivalent for ast binop {:?}", op), } } + +fn assign_op(op: hir::AssignOpKind) -> AssignOp { + match op { + hir::AssignOpKind::AddAssign => AssignOp::AddAssign, + hir::AssignOpKind::SubAssign => AssignOp::SubAssign, + hir::AssignOpKind::MulAssign => AssignOp::MulAssign, + hir::AssignOpKind::DivAssign => AssignOp::DivAssign, + hir::AssignOpKind::RemAssign => AssignOp::RemAssign, + hir::AssignOpKind::BitXorAssign => AssignOp::BitXorAssign, + hir::AssignOpKind::BitAndAssign => AssignOp::BitAndAssign, + hir::AssignOpKind::BitOrAssign => AssignOp::BitOrAssign, + hir::AssignOpKind::ShlAssign => AssignOp::ShlAssign, + hir::AssignOpKind::ShrAssign => AssignOp::ShrAssign, + } +} 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 ea8c7303c0a..9f5e2c06b22 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -1025,7 +1025,7 @@ fn find_fallback_pattern_typo<'tcx>( pat: &Pat<'tcx>, lint: &mut UnreachablePattern<'_>, ) { - if let (Level::Allow, _) = cx.tcx.lint_level_at_node(UNREACHABLE_PATTERNS, hir_id) { + if let Level::Allow = cx.tcx.lint_level_at_node(UNREACHABLE_PATTERNS, hir_id).level { // This is because we use `with_no_trimmed_paths` later, so if we never emit the lint we'd // ICE. At the same time, we don't really need to do all of this if we won't emit anything. return; diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 0a54c780f31..68bc0ffce6b 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -3,14 +3,16 @@ //! MIR may contain repeated and/or redundant computations. The objective of this pass is to detect //! such redundancies and re-use the already-computed result when possible. //! -//! In a first pass, we compute a symbolic representation of values that are assigned to SSA -//! locals. This symbolic representation is defined by the `Value` enum. Each produced instance of -//! `Value` is interned as a `VnIndex`, which allows us to cheaply compute identical values. -//! //! From those assignments, we construct a mapping `VnIndex -> Vec<(Local, Location)>` of available //! values, the locals in which they are stored, and the assignment location. //! -//! In a second pass, we traverse all (non SSA) assignments `x = rvalue` and operands. For each +//! We traverse all assignments `x = rvalue` and operands. +//! +//! For each SSA one, we compute a symbolic representation of values that are assigned to SSA +//! locals. This symbolic representation is defined by the `Value` enum. Each produced instance of +//! `Value` is interned as a `VnIndex`, which allows us to cheaply compute identical values. +//! +//! For each non-SSA //! one, we compute the `VnIndex` of the rvalue. If this `VnIndex` is associated to a constant, we //! replace the rvalue/operand by that constant. Otherwise, if there is an SSA local `y` //! associated to this `VnIndex`, and if its definition location strictly dominates the assignment @@ -91,7 +93,7 @@ use rustc_const_eval::interpret::{ ImmTy, Immediate, InterpCx, MemPlaceMeta, MemoryKind, OpTy, Projectable, Scalar, intern_const_alloc_for_constprop, }; -use rustc_data_structures::fx::FxIndexSet; +use rustc_data_structures::fx::{FxIndexSet, MutableValues}; use rustc_data_structures::graph::dominators::Dominators; use rustc_hir::def::DefKind; use rustc_index::bit_set::DenseBitSet; @@ -107,7 +109,7 @@ use rustc_span::def_id::DefId; use smallvec::SmallVec; use tracing::{debug, instrument, trace}; -use crate::ssa::{AssignedValue, SsaLocals}; +use crate::ssa::SsaLocals; pub(super) struct GVN; @@ -126,31 +128,11 @@ impl<'tcx> crate::MirPass<'tcx> for GVN { let dominators = body.basic_blocks.dominators().clone(); let mut state = VnState::new(tcx, body, typing_env, &ssa, dominators, &body.local_decls); - ssa.for_each_assignment_mut( - body.basic_blocks.as_mut_preserves_cfg(), - |local, value, location| { - let value = match value { - // We do not know anything of this assigned value. - AssignedValue::Arg | AssignedValue::Terminator => None, - // Try to get some insight. - AssignedValue::Rvalue(rvalue) => { - let value = state.simplify_rvalue(rvalue, location); - // FIXME(#112651) `rvalue` may have a subtype to `local`. We can only mark - // `local` as reusable if we have an exact type match. - if state.local_decls[local].ty != rvalue.ty(state.local_decls, tcx) { - return; - } - value - } - }; - // `next_opaque` is `Some`, so `new_opaque` must return `Some`. - let value = value.or_else(|| state.new_opaque()).unwrap(); - state.assign(local, value); - }, - ); - // Stop creating opaques during replacement as it is useless. - state.next_opaque = None; + for local in body.args_iter().filter(|&local| ssa.is_ssa(local)) { + let opaque = state.new_opaque(); + state.assign(local, opaque); + } let reverse_postorder = body.basic_blocks.reverse_postorder().to_vec(); for bb in reverse_postorder { @@ -250,14 +232,14 @@ struct VnState<'body, 'tcx> { locals: IndexVec<Local, Option<VnIndex>>, /// 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<VnIndex, SmallVec<[Local; 1]>>, values: FxIndexSet<Value<'tcx>>, /// Values evaluated as constants if possible. evaluated: IndexVec<VnIndex, Option<OpTy<'tcx>>>, /// Counter to generate different values. - /// This is an option to stop creating opaques during replacement. - next_opaque: Option<usize>, + next_opaque: usize, + /// Cache the deref values. + derefs: Vec<VnIndex>, /// Cache the value of the `unsized_locals` features, to avoid fetching it repeatedly in a loop. feature_unsized_locals: bool, ssa: &'body SsaLocals, @@ -289,7 +271,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { rev_locals: IndexVec::with_capacity(num_values), values: FxIndexSet::with_capacity_and_hasher(num_values, Default::default()), evaluated: IndexVec::with_capacity(num_values), - next_opaque: Some(1), + next_opaque: 1, + derefs: Vec::new(), feature_unsized_locals: tcx.features().unsized_locals(), ssa, dominators, @@ -310,32 +293,31 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { let evaluated = self.eval_to_const(index); let _index = self.evaluated.push(evaluated); debug_assert_eq!(index, _index); - // No need to push to `rev_locals` if we finished listing assignments. - if self.next_opaque.is_some() { - let _index = self.rev_locals.push(SmallVec::new()); - debug_assert_eq!(index, _index); - } + let _index = self.rev_locals.push(SmallVec::new()); + debug_assert_eq!(index, _index); } index } + fn next_opaque(&mut self) -> usize { + let next_opaque = self.next_opaque; + self.next_opaque += 1; + next_opaque + } + /// Create a new `Value` for which we have no information at all, except that it is distinct /// from all the others. #[instrument(level = "trace", skip(self), ret)] - fn new_opaque(&mut self) -> Option<VnIndex> { - let next_opaque = self.next_opaque.as_mut()?; - let value = Value::Opaque(*next_opaque); - *next_opaque += 1; - Some(self.insert(value)) + fn new_opaque(&mut self) -> VnIndex { + let value = Value::Opaque(self.next_opaque()); + self.insert(value) } /// Create a new `Value::Address` distinct from all the others. #[instrument(level = "trace", skip(self), ret)] - fn new_pointer(&mut self, place: Place<'tcx>, kind: AddressKind) -> Option<VnIndex> { - let next_opaque = self.next_opaque.as_mut()?; - let value = Value::Address { place, kind, provenance: *next_opaque }; - *next_opaque += 1; - Some(self.insert(value)) + fn new_pointer(&mut self, place: Place<'tcx>, kind: AddressKind) -> VnIndex { + let value = Value::Address { place, kind, provenance: self.next_opaque() }; + self.insert(value) } fn get(&self, index: VnIndex) -> &Value<'tcx> { @@ -345,6 +327,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { /// Record that `local` is assigned `value`. `local` must be SSA. #[instrument(level = "trace", skip(self))] fn assign(&mut self, local: Local, value: VnIndex) { + debug_assert!(self.ssa.is_ssa(local)); self.locals[local] = Some(value); // Only register the value if its type is `Sized`, as we will emit copies of it. @@ -355,21 +338,19 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } } - fn insert_constant(&mut self, value: Const<'tcx>) -> Option<VnIndex> { + fn insert_constant(&mut self, value: Const<'tcx>) -> VnIndex { let disambiguator = if value.is_deterministic() { // The constant is deterministic, no need to disambiguate. 0 } else { // Multiple mentions of this constant will yield different values, // so assign a different `disambiguator` to ensure they do not get the same `VnIndex`. - let next_opaque = self.next_opaque.as_mut()?; - let disambiguator = *next_opaque; - *next_opaque += 1; + let disambiguator = self.next_opaque(); // `disambiguator: 0` means deterministic. debug_assert_ne!(disambiguator, 0); disambiguator }; - Some(self.insert(Value::Constant { value, disambiguator })) + self.insert(Value::Constant { value, disambiguator }) } fn insert_bool(&mut self, flag: bool) -> VnIndex { @@ -390,6 +371,19 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { self.insert(Value::Aggregate(AggregateTy::Tuple, VariantIdx::ZERO, values)) } + fn insert_deref(&mut self, value: VnIndex) -> VnIndex { + let value = self.insert(Value::Projection(value, ProjectionElem::Deref)); + self.derefs.push(value); + value + } + + fn invalidate_derefs(&mut self) { + for deref in std::mem::take(&mut self.derefs) { + let opaque = self.next_opaque(); + *self.values.get_index_mut2(deref.index()).unwrap() = Value::Opaque(opaque); + } + } + #[instrument(level = "trace", skip(self), ret)] fn eval_to_const(&mut self, value: VnIndex) -> Option<OpTy<'tcx>> { use Value::*; @@ -648,15 +642,13 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { let proj = match proj { ProjectionElem::Deref => { let ty = place.ty(self.local_decls, self.tcx).ty; - // unsound: https://github.com/rust-lang/rust/issues/130853 - if self.tcx.sess.opts.unstable_opts.unsound_mir_opts - && let Some(Mutability::Not) = ty.ref_mutability() + if let Some(Mutability::Not) = ty.ref_mutability() && let Some(pointee_ty) = ty.builtin_deref(true) && pointee_ty.is_freeze(self.tcx, self.typing_env()) { // An immutable borrow `_x` always points to the same value for the // lifetime of the borrow, so we can merge all instances of `*_x`. - ProjectionElem::Deref + return Some(self.insert_deref(value)); } else { return None; } @@ -830,7 +822,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { location: Location, ) -> Option<VnIndex> { match *operand { - Operand::Constant(ref constant) => self.insert_constant(constant.const_), + Operand::Constant(ref constant) => Some(self.insert_constant(constant.const_)), Operand::Copy(ref mut place) | Operand::Move(ref mut place) => { let value = self.simplify_place_value(place, location)?; if let Some(const_) = self.try_as_constant(value) { @@ -866,11 +858,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { Rvalue::Aggregate(..) => return self.simplify_aggregate(rvalue, location), Rvalue::Ref(_, borrow_kind, ref mut place) => { self.simplify_place_projection(place, location); - return self.new_pointer(*place, AddressKind::Ref(borrow_kind)); + return Some(self.new_pointer(*place, AddressKind::Ref(borrow_kind))); } Rvalue::RawPtr(mutbl, ref mut place) => { self.simplify_place_projection(place, location); - return self.new_pointer(*place, AddressKind::Address(mutbl)); + return Some(self.new_pointer(*place, AddressKind::Address(mutbl))); } Rvalue::WrapUnsafeBinder(ref mut op, ty) => { let value = self.simplify_operand(op, location)?; @@ -1034,7 +1026,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { if is_zst { let ty = rvalue.ty(self.local_decls, tcx); - return self.insert_constant(Const::zero_sized(ty)); + return Some(self.insert_constant(Const::zero_sized(ty))); } } @@ -1063,11 +1055,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } }; - let fields: Option<Vec<_>> = field_ops + let mut fields: Vec<_> = field_ops .iter_mut() - .map(|op| self.simplify_operand(op, location).or_else(|| self.new_opaque())) + .map(|op| self.simplify_operand(op, location).unwrap_or_else(|| self.new_opaque())) .collect(); - let mut fields = fields?; if let AggregateTy::RawPtr { data_pointer_ty, output_pointer_ty } = &mut ty { let mut was_updated = false; @@ -1107,9 +1098,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } } - // unsound: https://github.com/rust-lang/rust/issues/132353 - if tcx.sess.opts.unstable_opts.unsound_mir_opts - && let AggregateTy::Def(_, _) = ty + if let AggregateTy::Def(_, _) = ty && let Some(value) = self.simplify_aggregate_to_copy(rvalue, location, &fields, variant_index) { @@ -1195,7 +1184,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { ) if let ty::Slice(..) = to.builtin_deref(true).unwrap().kind() && let ty::Array(_, len) = from.builtin_deref(true).unwrap().kind() => { - return self.insert_constant(Const::Ty(self.tcx.types.usize, *len)); + return Some(self.insert_constant(Const::Ty(self.tcx.types.usize, *len))); } _ => Value::UnaryOp(op, arg_index), }; @@ -1391,7 +1380,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { if let CastKind::PointerCoercion(ReifyFnPointer | ClosureFnPointer(_), _) = kind { // Each reification of a generic fn may get a different pointer. // Do not try to merge them. - return self.new_opaque(); + return Some(self.new_opaque()); } let mut was_ever_updated = false; @@ -1507,7 +1496,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { // 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::Ty(self.tcx.types.usize, *len)); + return Some(self.insert_constant(Const::Ty(self.tcx.types.usize, *len))); } let mut inner = self.simplify_place_value(place, location)?; @@ -1529,7 +1518,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { && let Some(to) = to.builtin_deref(true) && let ty::Slice(..) = to.kind() { - return self.insert_constant(Const::Ty(self.tcx.types.usize, *len)); + return Some(self.insert_constant(Const::Ty(self.tcx.types.usize, *len))); } // Fallback: a symbolic `Len`. @@ -1739,41 +1728,70 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> { self.tcx } - fn visit_place(&mut self, place: &mut Place<'tcx>, _: PlaceContext, location: Location) { + fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) { self.simplify_place_projection(place, location); + if context.is_mutating_use() && !place.projection.is_empty() { + // Non-local mutation maybe invalidate deref. + self.invalidate_derefs(); + } + self.super_place(place, context, location); } fn visit_operand(&mut self, operand: &mut Operand<'tcx>, location: Location) { self.simplify_operand(operand, location); + self.super_operand(operand, location); } fn visit_statement(&mut self, stmt: &mut Statement<'tcx>, location: Location) { 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. - if matches!(rvalue, Rvalue::Use(Operand::Constant(_))) { - return; + let value = self.simplify_rvalue(rvalue, location); + let value = if let Some(local) = lhs.as_local() + && self.ssa.is_ssa(local) + // FIXME(#112651) `rvalue` may have a subtype to `local`. We can only mark + // `local` as reusable if we have an exact type match. + && self.local_decls[local].ty == rvalue.ty(self.local_decls, self.tcx) + { + let value = value.unwrap_or_else(|| self.new_opaque()); + self.assign(local, value); + Some(value) + } else { + value + }; + if let Some(value) = value { + 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); + } } + } + 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())) + fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, location: Location) { + if let Terminator { kind: TerminatorKind::Call { destination, .. }, .. } = terminator { + if let Some(local) = destination.as_local() + && self.ssa.is_ssa(local) { - *rvalue = Rvalue::Use(Operand::Copy(local.into())); - self.reused_locals.insert(local); + let opaque = self.new_opaque(); + self.assign(local, opaque); } - - return; } - self.super_statement(stmt, location); + // Function calls and ASM may invalidate (nested) derefs. We must handle them carefully. + // Currently, only preserving derefs for trivial terminators like SwitchInt and Goto. + let safe_to_preserve_derefs = matches!( + terminator.kind, + TerminatorKind::SwitchInt { .. } | TerminatorKind::Goto { .. } + ); + if !safe_to_preserve_derefs { + self.invalidate_derefs(); + } + self.super_terminator(terminator, location); } } diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs index 3d512fb064e..edd0cabca49 100644 --- a/compiler/rustc_mir_transform/src/ssa.rs +++ b/compiler/rustc_mir_transform/src/ssa.rs @@ -32,12 +32,6 @@ pub(super) struct SsaLocals { borrowed_locals: DenseBitSet<Local>, } -pub(super) enum AssignedValue<'a, 'tcx> { - Arg, - Rvalue(&'a mut Rvalue<'tcx>), - Terminator, -} - impl SsaLocals { pub(super) fn new<'tcx>( tcx: TyCtxt<'tcx>, @@ -152,38 +146,6 @@ impl SsaLocals { }) } - pub(super) fn for_each_assignment_mut<'tcx>( - &self, - basic_blocks: &mut IndexSlice<BasicBlock, BasicBlockData<'tcx>>, - mut f: impl FnMut(Local, AssignedValue<'_, 'tcx>, Location), - ) { - for &local in &self.assignment_order { - match self.assignments[local] { - Set1::One(DefLocation::Argument) => f( - local, - AssignedValue::Arg, - Location { block: START_BLOCK, statement_index: 0 }, - ), - Set1::One(DefLocation::Assignment(loc)) => { - let bb = &mut basic_blocks[loc.block]; - // `loc` must point to a direct assignment to `local`. - let stmt = &mut bb.statements[loc.statement_index]; - let StatementKind::Assign(box (target, ref mut rvalue)) = stmt.kind else { - bug!() - }; - assert_eq!(target.as_local(), Some(local)); - f(local, AssignedValue::Rvalue(rvalue), loc) - } - Set1::One(DefLocation::CallReturn { call, .. }) => { - let bb = &mut basic_blocks[call]; - let loc = Location { block: call, statement_index: bb.statements.len() }; - f(local, AssignedValue::Terminator, loc) - } - _ => {} - } - } - } - /// Compute the equivalence classes for locals, based on copy statements. /// /// The returned vector maps each local to the one it copies. In the following case: diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index a5142de2d39..c2fb592c3f3 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -37,12 +37,16 @@ where | ty::Never | ty::Char => Ok(ty::Binder::dummy(vec![])), + // This branch is only for `experimental_default_bounds`. + // Other foreign types were rejected earlier in + // `disqualify_auto_trait_candidate_due_to_possible_impl`. + ty::Foreign(..) => Ok(ty::Binder::dummy(vec![])), + // Treat `str` like it's defined as `struct str([u8]);` ty::Str => Ok(ty::Binder::dummy(vec![Ty::new_slice(cx, Ty::new_u8(cx))])), ty::Dynamic(..) | ty::Param(..) - | ty::Foreign(..) | ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..) | ty::Placeholder(..) | ty::Bound(..) diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index b72f776e5cb..b7ae96ec9d2 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -1086,6 +1086,25 @@ where goal: Goal<I, TraitPredicate<I>>, ) -> Option<Result<Candidate<I>, NoSolution>> { let self_ty = goal.predicate.self_ty(); + let check_impls = || { + let mut disqualifying_impl = None; + self.cx().for_each_relevant_impl( + goal.predicate.def_id(), + goal.predicate.self_ty(), + |impl_def_id| { + disqualifying_impl = Some(impl_def_id); + }, + ); + if let Some(def_id) = disqualifying_impl { + trace!(?def_id, ?goal, "disqualified auto-trait implementation"); + // No need to actually consider the candidate here, + // since we do that in `consider_impl_candidate`. + return Some(Err(NoSolution)); + } else { + None + } + }; + match self_ty.kind() { // Stall int and float vars until they are resolved to a concrete // numerical type. That's because the check for impls below treats @@ -1096,6 +1115,10 @@ where Some(self.forced_ambiguity(MaybeCause::Ambiguity)) } + // Backward compatibility for default auto traits. + // Test: ui/traits/default_auto_traits/extern-types.rs + ty::Foreign(..) if self.cx().is_default_trait(goal.predicate.def_id()) => check_impls(), + // These types cannot be structurally decomposed into constituent // types, and therefore have no built-in auto impl. ty::Dynamic(..) @@ -1156,24 +1179,7 @@ where | ty::Never | ty::Tuple(_) | ty::Adt(_, _) - | ty::UnsafeBinder(_) => { - let mut disqualifying_impl = None; - self.cx().for_each_relevant_impl( - goal.predicate.def_id(), - goal.predicate.self_ty(), - |impl_def_id| { - disqualifying_impl = Some(impl_def_id); - }, - ); - if let Some(def_id) = disqualifying_impl { - trace!(?def_id, ?goal, "disqualified auto-trait implementation"); - // No need to actually consider the candidate here, - // since we do that in `consider_impl_candidate`. - return Some(Err(NoSolution)); - } else { - None - } - } + | ty::UnsafeBinder(_) => check_impls(), ty::Error(_) => None, } } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index e1e6b93abf3..841d967d934 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -14,10 +14,10 @@ use rustc_ast::util::classify; use rustc_ast::util::parser::{AssocOp, ExprPrecedence, Fixity, prec_let_scrutinee_needs_par}; use rustc_ast::visit::{Visitor, walk_expr}; use rustc_ast::{ - self as ast, AnonConst, Arm, AttrStyle, AttrVec, BinOp, BinOpKind, BlockCheckMode, CaptureBy, - ClosureBinder, DUMMY_NODE_ID, Expr, ExprField, ExprKind, FnDecl, FnRetTy, Label, MacCall, - MetaItemLit, Movability, Param, RangeLimits, StmtKind, Ty, TyKind, UnOp, UnsafeBinderCastKind, - YieldKind, + self as ast, AnonConst, Arm, AssignOp, AssignOpKind, AttrStyle, AttrVec, BinOp, BinOpKind, + BlockCheckMode, CaptureBy, ClosureBinder, DUMMY_NODE_ID, Expr, ExprField, ExprKind, FnDecl, + FnRetTy, Label, MacCall, MetaItemLit, Movability, Param, RangeLimits, StmtKind, Ty, TyKind, + UnOp, UnsafeBinderCastKind, YieldKind, }; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{Applicability, Diag, PResult, StashKey, Subdiagnostic}; @@ -359,7 +359,7 @@ impl<'a> Parser<'a> { ( Some( AssocOp::Binary(BinOpKind::Shr | BinOpKind::Gt | BinOpKind::Ge) - | AssocOp::AssignOp(BinOpKind::Shr), + | AssocOp::AssignOp(AssignOpKind::ShrAssign), ), _, ) if self.restrictions.contains(Restrictions::CONST_EXPR) => { @@ -3914,8 +3914,8 @@ impl<'a> Parser<'a> { self.dcx().emit_err(errors::LeftArrowOperator { span }); } - fn mk_assign_op(&self, binop: BinOp, lhs: P<Expr>, rhs: P<Expr>) -> ExprKind { - ExprKind::AssignOp(binop, lhs, rhs) + fn mk_assign_op(&self, assign_op: AssignOp, lhs: P<Expr>, rhs: P<Expr>) -> ExprKind { + ExprKind::AssignOp(assign_op, lhs, rhs) } fn mk_range( diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 97cd4d2117f..2cd09aa8959 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -73,7 +73,20 @@ impl<'a> Parser<'a> { }); } - let stmt = if self.token.is_keyword(kw::Let) { + let stmt = if self.token.is_keyword(kw::Super) && self.is_keyword_ahead(1, &[kw::Let]) { + self.collect_tokens(None, attrs, force_collect, |this, attrs| { + this.expect_keyword(exp!(Super))?; + this.psess.gated_spans.gate(sym::super_let, this.prev_token.span); + this.expect_keyword(exp!(Let))?; + let local = this.parse_local(attrs)?; // FIXME(mara): implement super let + let trailing = Trailing::from(capture_semi && this.token == token::Semi); + Ok(( + this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)), + trailing, + UsePreAttrPos::No, + )) + })? + } else if self.token.is_keyword(kw::Let) { self.collect_tokens(None, attrs, force_collect, |this, attrs| { this.expect_keyword(exp!(Let))?; let local = this.parse_local(attrs)?; diff --git a/compiler/rustc_parse/src/parser/token_type.rs b/compiler/rustc_parse/src/parser/token_type.rs index 886438fd583..add3c970201 100644 --- a/compiler/rustc_parse/src/parser/token_type.rs +++ b/compiler/rustc_parse/src/parser/token_type.rs @@ -114,6 +114,7 @@ pub enum TokenType { KwSelfUpper, KwStatic, KwStruct, + KwSuper, KwTrait, KwTry, KwType, @@ -250,6 +251,7 @@ impl TokenType { KwSelfUpper, KwStatic, KwStruct, + KwSuper, KwTrait, KwTry, KwType, @@ -324,6 +326,7 @@ impl TokenType { TokenType::KwSelfUpper => Some(kw::SelfUpper), TokenType::KwStatic => Some(kw::Static), TokenType::KwStruct => Some(kw::Struct), + TokenType::KwSuper => Some(kw::Super), TokenType::KwTrait => Some(kw::Trait), TokenType::KwTry => Some(kw::Try), TokenType::KwType => Some(kw::Type), @@ -549,6 +552,7 @@ macro_rules! exp { (SelfUpper) => { exp!(@kw, SelfUpper, KwSelfUpper) }; (Static) => { exp!(@kw, Static, KwStatic) }; (Struct) => { exp!(@kw, Struct, KwStruct) }; + (Super) => { exp!(@kw, Super, KwSuper) }; (Trait) => { exp!(@kw, Trait, KwTrait) }; (Try) => { exp!(@kw, Try, KwTry) }; (Type) => { exp!(@kw, Type, KwType) }; diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index b62d94d65f1..0060e726a8e 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -19,8 +19,8 @@ use rustc_middle::middle::privacy::Level; use rustc_middle::query::Providers; use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::{bug, span_bug}; -use rustc_session::lint; use rustc_session::lint::builtin::DEAD_CODE; +use rustc_session::lint::{self, LintExpectationId}; use rustc_span::{Symbol, sym}; use crate::errors::{ @@ -696,8 +696,8 @@ fn has_allow_dead_code_or_lang_attr( fn has_allow_expect_dead_code(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { let hir_id = tcx.local_def_id_to_hir_id(def_id); - let lint_level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).0; - matches!(lint_level, lint::Allow | lint::Expect(_)) + let lint_level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).level; + matches!(lint_level, lint::Allow | lint::Expect) } fn has_used_like_attr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { @@ -915,7 +915,7 @@ fn live_symbols_and_ignored_derived_traits( struct DeadItem { def_id: LocalDefId, name: Symbol, - level: lint::Level, + level: (lint::Level, Option<LintExpectationId>), } struct DeadVisitor<'tcx> { @@ -959,9 +959,10 @@ impl<'tcx> DeadVisitor<'tcx> { ShouldWarnAboutField::Yes } - fn def_lint_level(&self, id: LocalDefId) -> lint::Level { + fn def_lint_level(&self, id: LocalDefId) -> (lint::Level, Option<LintExpectationId>) { let hir_id = self.tcx.local_def_id_to_hir_id(id); - self.tcx.lint_level_at_node(DEAD_CODE, hir_id).0 + let level = self.tcx.lint_level_at_node(DEAD_CODE, hir_id); + (level.level, level.lint_id) } // # Panics @@ -1129,7 +1130,8 @@ impl<'tcx> DeadVisitor<'tcx> { if dead_codes.is_empty() { return; } - dead_codes.sort_by_key(|v| v.level); + // FIXME: `dead_codes` should probably be morally equivalent to `IndexMap<(Level, LintExpectationId), (DefId, Symbol)>` + dead_codes.sort_by_key(|v| v.level.0); for group in dead_codes.chunk_by(|a, b| a.level == b.level) { self.lint_at_single_level(&group, participle, Some(def_id), report_on); } diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 6dec96f9f50..d7baad69c78 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -980,7 +980,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { // Calculating message for lint involves calling `self.def_path_str`, // which will by default invoke the expensive `visible_parent_map` query. // Skip all that work if the lint is allowed anyway. - if self.tcx.lint_level_at_node(DEPRECATED, id).0 + if self.tcx.lint_level_at_node(DEPRECATED, id).level == lint::Level::Allow { return; diff --git a/compiler/rustc_pattern_analysis/src/lints.rs b/compiler/rustc_pattern_analysis/src/lints.rs index 585cda1d24b..3da744dc8c0 100644 --- a/compiler/rustc_pattern_analysis/src/lints.rs +++ b/compiler/rustc_pattern_analysis/src/lints.rs @@ -1,3 +1,4 @@ +use rustc_middle::lint::LevelAndSource; use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; use rustc_span::ErrorGuaranteed; use tracing::instrument; @@ -64,7 +65,7 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'p, 'tcx>( scrut_ty: RevealedTy<'tcx>, ) -> Result<(), ErrorGuaranteed> { if !matches!( - rcx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, rcx.match_lint_level).0, + rcx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, rcx.match_lint_level).level, rustc_session::lint::Level::Allow ) { let witnesses = collect_nonexhaustive_missing_variants(rcx, pat_column)?; @@ -88,13 +89,13 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'p, 'tcx>( // arm. This no longer makes sense so we warn users, to avoid silently breaking their // usage of the lint. for arm in arms { - let (lint_level, lint_level_source) = + let LevelAndSource { level, src, .. } = rcx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, arm.arm_data); - if !matches!(lint_level, rustc_session::lint::Level::Allow) { + if !matches!(level, rustc_session::lint::Level::Allow) { let decorator = NonExhaustiveOmittedPatternLintOnArm { - lint_span: lint_level_source.span(), + lint_span: src.span(), suggest_lint_on_match: rcx.whole_match_span.map(|span| span.shrink_to_lo()), - lint_level: lint_level.as_str(), + lint_level: level.as_str(), lint_name: "non_exhaustive_omitted_patterns", }; diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 1b01efda2a9..1f18950feac 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1700,7 +1700,7 @@ pub fn get_cmd_lint_options( let mut lint_opts_with_position = vec![]; let mut describe_lints = false; - for level in [lint::Allow, lint::Warn, lint::ForceWarn(None), lint::Deny, lint::Forbid] { + for level in [lint::Allow, lint::Warn, lint::ForceWarn, lint::Deny, lint::Forbid] { for (arg_pos, lint_name) in matches.opt_strs_pos(level.as_str()) { if lint_name == "help" { describe_lints = true; diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index cd5e2c4173e..eb513e00936 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2187,6 +2187,8 @@ options! { "Use WebAssembly error handling for wasm32-unknown-emscripten"), enforce_type_length_limit: bool = (false, parse_bool, [TRACKED], "enforce the type length limit when monomorphizing instances in codegen"), + experimental_default_bounds: bool = (false, parse_bool, [TRACKED], + "enable default bounds for experimental group of auto traits"), export_executable_symbols: bool = (false, parse_bool, [TRACKED], "export symbols from executables, as if they were dynamic libraries"), external_clangrt: bool = (false, parse_bool, [UNTRACKED], diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index bc853fe9079..31847ae3b46 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -800,6 +800,15 @@ symbols! { default_fn, default_lib_allocator, default_method_body_is_const, + // -------------------------- + // Lang items which are used only for experiments with auto traits with default bounds. + // These lang items are not actually defined in core/std. Experiment is a part of + // `MCP: Low level components for async drop`(https://github.com/rust-lang/compiler-team/issues/727) + default_trait1, + default_trait2, + default_trait3, + default_trait4, + // -------------------------- default_type_parameter_fallback, default_type_params, define_opaque, @@ -2040,6 +2049,7 @@ symbols! { sub_assign, sub_with_overflow, suggestion, + super_let, supertrait_item_shadowing, surface_async_drop_in_place, sym, diff --git a/compiler/rustc_target/src/asm/aarch64.rs b/compiler/rustc_target/src/asm/aarch64.rs index cdccb3e5d72..43a8d9ca119 100644 --- a/compiler/rustc_target/src/asm/aarch64.rs +++ b/compiler/rustc_target/src/asm/aarch64.rs @@ -78,7 +78,7 @@ pub(crate) fn target_reserves_x18(target: &Target, target_features: &FxIndexSet< target.os == "android" || target.os == "fuchsia" || target.env == "ohos" - || target.is_like_osx + || target.is_like_darwin || target.is_like_windows || target_features.contains(&sym::reserve_x18) } diff --git a/compiler/rustc_target/src/asm/arm.rs b/compiler/rustc_target/src/asm/arm.rs index ff0cbddecf7..7fea10ff067 100644 --- a/compiler/rustc_target/src/asm/arm.rs +++ b/compiler/rustc_target/src/asm/arm.rs @@ -68,7 +68,7 @@ impl ArmInlineAsmRegClass { // This uses the same logic as useR7AsFramePointer in LLVM fn frame_pointer_is_r7(target_features: &FxIndexSet<Symbol>, target: &Target) -> bool { - target.is_like_osx || (!target.is_like_windows && target_features.contains(&sym::thumb_mode)) + target.is_like_darwin || (!target.is_like_windows && target_features.contains(&sym::thumb_mode)) } fn frame_pointer_r11( diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index a52b2b76bc1..55e39d093e2 100644 --- a/compiler/rustc_target/src/callconv/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -670,7 +670,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { } }, "aarch64" | "arm64ec" => { - let kind = if cx.target_spec().is_like_osx { + let kind = if cx.target_spec().is_like_darwin { aarch64::AbiKind::DarwinPCS } else if cx.target_spec().is_like_windows { aarch64::AbiKind::Win64 diff --git a/compiler/rustc_target/src/callconv/x86.rs b/compiler/rustc_target/src/callconv/x86.rs index 6f112b49400..ba3c1406211 100644 --- a/compiler/rustc_target/src/callconv/x86.rs +++ b/compiler/rustc_target/src/callconv/x86.rs @@ -104,7 +104,7 @@ where let byval_align = if arg.layout.align.abi < align_4 { // (1.) align_4 - } else if t.is_like_osx && contains_vector(cx, arg.layout) { + } else if t.is_like_darwin && contains_vector(cx, arg.layout) { // (3.) align_16 } else { diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs index 66c85146c29..fd0e47b55aa 100644 --- a/compiler/rustc_target/src/spec/base/apple/mod.rs +++ b/compiler/rustc_target/src/spec/base/apple/mod.rs @@ -115,7 +115,7 @@ pub(crate) fn base( function_sections: false, dynamic_linking: true, families: cvs!["unix"], - is_like_osx: true, + is_like_darwin: true, binary_format: BinaryFormat::MachO, // LLVM notes that macOS 10.11+ and iOS 9+ default // to v4, so we do the same. diff --git a/compiler/rustc_target/src/spec/json.rs b/compiler/rustc_target/src/spec/json.rs index 4b6de5e18f5..be71da76b4a 100644 --- a/compiler/rustc_target/src/spec/json.rs +++ b/compiler/rustc_target/src/spec/json.rs @@ -598,7 +598,7 @@ impl Target { key!(families, target_families); key!(abi_return_struct_as_int, bool); key!(is_like_aix, bool); - key!(is_like_osx, bool); + key!(is_like_darwin, bool); key!(is_like_solaris, bool); key!(is_like_windows, bool); key!(is_like_msvc, bool); @@ -777,7 +777,7 @@ impl ToJson for Target { target_option_val!(families, "target-family"); target_option_val!(abi_return_struct_as_int); target_option_val!(is_like_aix); - target_option_val!(is_like_osx); + target_option_val!(is_like_darwin); target_option_val!(is_like_solaris); target_option_val!(is_like_windows); target_option_val!(is_like_msvc); diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 7234d1dc63e..981dded2601 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -81,7 +81,7 @@ pub enum Lld { /// of classes that we call "linker flavors". /// /// Technically, it's not even necessary, we can nearly always infer the flavor from linker name -/// and target properties like `is_like_windows`/`is_like_osx`/etc. However, the PRs originally +/// and target properties like `is_like_windows`/`is_like_darwin`/etc. However, the PRs originally /// introducing `-Clinker-flavor` (#40018 and friends) were aiming to reduce this kind of inference /// and provide something certain and explicitly specified instead, and that design goal is still /// relevant now. @@ -2406,7 +2406,7 @@ pub struct TargetOptions { /// in particular running dsymutil and some other stuff like `-dead_strip`. Defaults to false. /// Also indicates whether to use Apple-specific ABI changes, such as extending function /// parameters to 32-bits. - pub is_like_osx: bool, + pub is_like_darwin: bool, /// Whether the target toolchain is like Solaris's. /// Only useful for compiling against Illumos/Solaris, /// as they have a different set of linker flags. Defaults to false. @@ -2700,7 +2700,7 @@ fn add_link_args(link_args: &mut LinkArgs, flavor: LinkerFlavor, args: &[&'stati impl TargetOptions { pub fn supports_comdat(&self) -> bool { // XCOFF and MachO don't support COMDAT. - !self.is_like_aix && !self.is_like_osx + !self.is_like_aix && !self.is_like_darwin } } @@ -2804,7 +2804,7 @@ impl Default for TargetOptions { families: cvs![], abi_return_struct_as_int: false, is_like_aix: false, - is_like_osx: false, + is_like_darwin: false, is_like_solaris: false, is_like_windows: false, is_like_msvc: false, @@ -3070,9 +3070,9 @@ impl Target { } check_eq!( - self.is_like_osx, + self.is_like_darwin, self.vendor == "apple", - "`is_like_osx` must be set if and only if `vendor` is `apple`" + "`is_like_darwin` must be set if and only if `vendor` is `apple`" ); check_eq!( self.is_like_solaris, @@ -3098,9 +3098,9 @@ impl Target { // Check that default linker flavor is compatible with some other key properties. check_eq!( - self.is_like_osx, + self.is_like_darwin, matches!(self.linker_flavor, LinkerFlavor::Darwin(..)), - "`linker_flavor` must be `darwin` if and only if `is_like_osx` is set" + "`linker_flavor` must be `darwin` if and only if `is_like_darwin` is set" ); check_eq!( self.is_like_msvc, diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index d15c9afef3a..cf6d2bc151f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -692,6 +692,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let def_id = obligation.predicate.def_id(); + let mut check_impls = || { + // Only consider auto impls if there are no manual impls for the root of `self_ty`. + // + // For example, we only consider auto candidates for `&i32: Auto` if no explicit impl + // for `&SomeType: Auto` exists. Due to E0321 the only crate where impls + // for `&SomeType: Auto` can be defined is the crate where `Auto` has been defined. + // + // Generally, we have to guarantee that for all `SimplifiedType`s the only crate + // which may define impls for that type is either the crate defining the type + // or the trait. This should be guaranteed by the orphan check. + let mut has_impl = false; + self.tcx().for_each_relevant_impl(def_id, self_ty, |_| has_impl = true); + if !has_impl { + candidates.vec.push(AutoImplCandidate) + } + }; + if self.tcx().trait_is_auto(def_id) { match *self_ty.kind() { ty::Dynamic(..) => { @@ -705,6 +722,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // we don't add any `..` impl. Default traits could // still be provided by a manual implementation for // this trait and type. + + // Backward compatibility for default auto traits. + // Test: ui/traits/default_auto_traits/extern-types.rs + if self.tcx().is_default_trait(def_id) { + check_impls() + } } ty::Param(..) | ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..) @@ -805,20 +828,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return; } - // Only consider auto impls if there are no manual impls for the root of `self_ty`. - // - // For example, we only consider auto candidates for `&i32: Auto` if no explicit impl - // for `&SomeType: Auto` exists. Due to E0321 the only crate where impls - // for `&SomeType: Auto` can be defined is the crate where `Auto` has been defined. - // - // Generally, we have to guarantee that for all `SimplifiedType`s the only crate - // which may define impls for that type is either the crate defining the type - // or the trait. This should be guaranteed by the orphan check. - let mut has_impl = false; - self.tcx().for_each_relevant_impl(def_id, self_ty, |_| has_impl = true); - if !has_impl { - candidates.vec.push(AutoImplCandidate) - } + check_impls(); } ty::Error(_) => { candidates.vec.push(AutoImplCandidate); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 0679dbf1296..42c598e538d 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2299,6 +2299,11 @@ impl<'tcx> SelectionContext<'_, 'tcx> { | ty::Never | ty::Char => ty::Binder::dummy(Vec::new()), + // This branch is only for `experimental_default_bounds`. + // Other foreign types were rejected earlier in + // `assemble_candidates_from_auto_impls`. + ty::Foreign(..) => ty::Binder::dummy(Vec::new()), + // FIXME(unsafe_binders): Squash the double binder for now, I guess. ty::UnsafeBinder(_) => return Err(SelectionError::Unimplemented), @@ -2308,7 +2313,6 @@ impl<'tcx> SelectionContext<'_, 'tcx> { ty::Placeholder(..) | ty::Dynamic(..) | ty::Param(..) - | ty::Foreign(..) | ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..) | ty::Bound(..) | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index d4134bdf3a7..59c2d3c2fc8 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -146,67 +146,14 @@ pub trait Ty<I: Interner<Ty = Self>>: fn has_unsafe_fields(self) -> bool; fn fn_sig(self, interner: I) -> ty::Binder<I, ty::FnSig<I>> { - match self.kind() { - ty::FnPtr(sig_tys, hdr) => sig_tys.with(hdr), - ty::FnDef(def_id, args) => interner.fn_sig(def_id).instantiate(interner, args), - ty::Error(_) => { - // ignore errors (#54954) - ty::Binder::dummy(ty::FnSig { - inputs_and_output: Default::default(), - c_variadic: false, - safety: I::Safety::safe(), - abi: I::Abi::rust(), - }) - } - ty::Closure(..) => panic!( - "to get the signature of a closure, use `args.as_closure().sig()` not `fn_sig()`", - ), - _ => panic!("Ty::fn_sig() called on non-fn type: {:?}", self), - } + self.kind().fn_sig(interner) } fn discriminant_ty(self, interner: I) -> I::Ty; fn async_destructor_ty(self, interner: I) -> I::Ty; - - /// Returns `true` when the outermost type cannot be further normalized, - /// resolved, or instantiated. This includes all primitive types, but also - /// things like ADTs and trait objects, since even if their arguments or - /// nested types may be further simplified, the outermost [`ty::TyKind`] or - /// type constructor remains the same. fn is_known_rigid(self) -> bool { - match self.kind() { - ty::Bool - | ty::Char - | ty::Int(_) - | ty::Uint(_) - | ty::Float(_) - | ty::Adt(_, _) - | ty::Foreign(_) - | ty::Str - | ty::Array(_, _) - | ty::Pat(_, _) - | ty::Slice(_) - | ty::RawPtr(_, _) - | ty::Ref(_, _, _) - | ty::FnDef(_, _) - | ty::FnPtr(..) - | ty::UnsafeBinder(_) - | ty::Dynamic(_, _, _) - | ty::Closure(_, _) - | ty::CoroutineClosure(_, _) - | ty::Coroutine(_, _) - | ty::CoroutineWitness(..) - | ty::Never - | ty::Tuple(_) => true, - - ty::Error(_) - | ty::Infer(_) - | ty::Alias(_, _) - | ty::Param(_) - | ty::Bound(_, _) - | ty::Placeholder(_) => false, - } + self.kind().is_known_rigid() } } diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 8f86270d7dc..ff0d8cdd585 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -259,6 +259,8 @@ pub trait Interner: fn is_lang_item(self, def_id: Self::DefId, lang_item: TraitSolverLangItem) -> bool; + fn is_default_trait(self, def_id: Self::DefId) -> bool; + fn as_lang_item(self, def_id: Self::DefId) -> Option<TraitSolverLangItem>; fn associated_type_def_ids(self, def_id: Self::DefId) -> impl IntoIterator<Item = Self::DefId>; diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 9bea4482b55..d35b22d517c 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -273,6 +273,68 @@ pub enum TyKind<I: Interner> { Error(I::ErrorGuaranteed), } +impl<I: Interner> TyKind<I> { + pub fn fn_sig(self, interner: I) -> ty::Binder<I, ty::FnSig<I>> { + match self { + ty::FnPtr(sig_tys, hdr) => sig_tys.with(hdr), + ty::FnDef(def_id, args) => interner.fn_sig(def_id).instantiate(interner, args), + ty::Error(_) => { + // ignore errors (#54954) + ty::Binder::dummy(ty::FnSig { + inputs_and_output: Default::default(), + c_variadic: false, + safety: I::Safety::safe(), + abi: I::Abi::rust(), + }) + } + ty::Closure(..) => panic!( + "to get the signature of a closure, use `args.as_closure().sig()` not `fn_sig()`", + ), + _ => panic!("Ty::fn_sig() called on non-fn type: {:?}", self), + } + } + + /// Returns `true` when the outermost type cannot be further normalized, + /// resolved, or instantiated. This includes all primitive types, but also + /// things like ADTs and trait objects, since even if their arguments or + /// nested types may be further simplified, the outermost [`ty::TyKind`] or + /// type constructor remains the same. + pub fn is_known_rigid(self) -> bool { + match self { + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Adt(_, _) + | ty::Foreign(_) + | ty::Str + | ty::Array(_, _) + | ty::Pat(_, _) + | ty::Slice(_) + | ty::RawPtr(_, _) + | ty::Ref(_, _, _) + | ty::FnDef(_, _) + | ty::FnPtr(..) + | ty::UnsafeBinder(_) + | ty::Dynamic(_, _, _) + | ty::Closure(_, _) + | ty::CoroutineClosure(_, _) + | ty::Coroutine(_, _) + | ty::CoroutineWitness(..) + | ty::Never + | ty::Tuple(_) => true, + + ty::Error(_) + | ty::Infer(_) + | ty::Alias(_, _) + | ty::Param(_) + | ty::Bound(_, _) + | ty::Placeholder(_) => false, + } + } +} + // This is manually implemented because a derive would require `I: Debug` impl<I: Interner> fmt::Debug for TyKind<I> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index e789601a409..09117e4968d 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -544,7 +544,7 @@ impl<T: Copy> Cell<T> { unsafe { *self.value.get() } } - /// Updates the contained value using a function and returns the new value. + /// Updates the contained value using a function. /// /// # Examples /// @@ -554,21 +554,14 @@ impl<T: Copy> Cell<T> { /// use std::cell::Cell; /// /// let c = Cell::new(5); - /// let new = c.update(|x| x + 1); - /// - /// assert_eq!(new, 6); + /// c.update(|x| x + 1); /// assert_eq!(c.get(), 6); /// ``` #[inline] #[unstable(feature = "cell_update", issue = "50186")] - pub fn update<F>(&self, f: F) -> T - where - F: FnOnce(T) -> T, - { + pub fn update(&self, f: impl FnOnce(T) -> T) { let old = self.get(); - let new = f(old); - self.set(new); - new + self.set(f(old)); } } diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index ef8fb694a32..e54840c8fcc 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -382,16 +382,11 @@ impl<T> [T] { #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] #[rustc_const_stable(feature = "slice_first_last_chunk", since = "1.77.0")] pub const fn split_first_chunk<const N: usize>(&self) -> Option<(&[T; N], &[T])> { - if self.len() < N { - None - } else { - // SAFETY: We manually verified the bounds of the split. - let (first, tail) = unsafe { self.split_at_unchecked(N) }; + let Some((first, tail)) = self.split_at_checked(N) else { return None }; - // SAFETY: We explicitly check for the correct number of elements, - // and do not let the references outlive the slice. - Some((unsafe { &*(first.as_ptr().cast::<[T; N]>()) }, tail)) - } + // SAFETY: We explicitly check for the correct number of elements, + // and do not let the references outlive the slice. + Some((unsafe { &*(first.as_ptr().cast::<[T; N]>()) }, tail)) } /// Returns a mutable array reference to the first `N` items in the slice and the remaining @@ -419,17 +414,12 @@ impl<T> [T] { pub const fn split_first_chunk_mut<const N: usize>( &mut self, ) -> Option<(&mut [T; N], &mut [T])> { - if self.len() < N { - None - } else { - // SAFETY: We manually verified the bounds of the split. - let (first, tail) = unsafe { self.split_at_mut_unchecked(N) }; + let Some((first, tail)) = self.split_at_mut_checked(N) else { return None }; - // 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().cast::<[T; N]>()) }, tail)) - } + // 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().cast::<[T; N]>()) }, tail)) } /// Returns an array reference to the last `N` items in the slice and the remaining slice. @@ -452,16 +442,12 @@ impl<T> [T] { #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] #[rustc_const_stable(feature = "slice_first_last_chunk", since = "1.77.0")] pub const fn split_last_chunk<const N: usize>(&self) -> Option<(&[T], &[T; N])> { - if self.len() < N { - None - } else { - // SAFETY: We manually verified the bounds of the split. - let (init, last) = unsafe { self.split_at_unchecked(self.len() - N) }; + let Some(index) = self.len().checked_sub(N) else { return None }; + let (init, last) = self.split_at(index); - // SAFETY: We explicitly check for the correct number of elements, - // and do not let the references outlive the slice. - Some((init, unsafe { &*(last.as_ptr().cast::<[T; N]>()) })) - } + // SAFETY: We explicitly check for the correct number of elements, + // and do not let the references outlive the slice. + Some((init, unsafe { &*(last.as_ptr().cast::<[T; N]>()) })) } /// Returns a mutable array reference to the last `N` items in the slice and the remaining @@ -489,17 +475,13 @@ impl<T> [T] { pub const fn split_last_chunk_mut<const N: usize>( &mut self, ) -> Option<(&mut [T], &mut [T; N])> { - if self.len() < N { - None - } else { - // SAFETY: We manually verified the bounds of the split. - let (init, last) = unsafe { self.split_at_mut_unchecked(self.len() - N) }; + let Some(index) = self.len().checked_sub(N) else { return None }; + let (init, last) = self.split_at_mut(index); - // 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((init, unsafe { &mut *(last.as_mut_ptr().cast::<[T; N]>()) })) - } + // 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((init, unsafe { &mut *(last.as_mut_ptr().cast::<[T; N]>()) })) } /// Returns an array reference to the last `N` items in the slice. @@ -522,17 +504,13 @@ impl<T> [T] { #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] #[rustc_const_stable(feature = "const_slice_last_chunk", since = "1.80.0")] pub const fn last_chunk<const N: usize>(&self) -> Option<&[T; N]> { - if self.len() < N { - None - } else { - // SAFETY: We manually verified the bounds of the slice. - // FIXME(const-hack): Without const traits, we need this instead of `get_unchecked`. - let last = unsafe { self.split_at_unchecked(self.len() - N).1 }; + // FIXME(const-hack): Without const traits, we need this instead of `get`. + let Some(index) = self.len().checked_sub(N) else { return None }; + let (_, last) = self.split_at(index); - // SAFETY: We explicitly check for the correct number of elements, - // and do not let the references outlive the slice. - Some(unsafe { &*(last.as_ptr().cast::<[T; N]>()) }) - } + // SAFETY: We explicitly check for the correct number of elements, + // and do not let the references outlive the slice. + Some(unsafe { &*(last.as_ptr().cast::<[T; N]>()) }) } /// Returns a mutable array reference to the last `N` items in the slice. @@ -556,18 +534,14 @@ impl<T> [T] { #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "1.83.0")] pub const fn last_chunk_mut<const N: usize>(&mut self) -> Option<&mut [T; N]> { - if self.len() < N { - None - } else { - // SAFETY: We manually verified the bounds of the slice. - // FIXME(const-hack): Without const traits, we need this instead of `get_unchecked`. - let last = unsafe { self.split_at_mut_unchecked(self.len() - N).1 }; - - // 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().cast::<[T; N]>()) }) - } + // FIXME(const-hack): Without const traits, we need this instead of `get`. + let Some(index) = self.len().checked_sub(N) else { return None }; + let (_, last) = self.split_at_mut(index); + + // 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().cast::<[T; N]>()) }) } /// Returns a reference to an element or subslice depending on the type of diff --git a/library/coretests/tests/cell.rs b/library/coretests/tests/cell.rs index d6a401c2b4d..781a46c3744 100644 --- a/library/coretests/tests/cell.rs +++ b/library/coretests/tests/cell.rs @@ -50,10 +50,10 @@ fn smoketest_cell() { fn cell_update() { let x = Cell::new(10); - assert_eq!(x.update(|x| x + 5), 15); + x.update(|x| x + 5); assert_eq!(x.get(), 15); - assert_eq!(x.update(|x| x / 3), 5); + x.update(|x| x / 3); assert_eq!(x.get(), 5); } diff --git a/library/std/src/io/buffered/bufreader/buffer.rs b/library/std/src/io/buffered/bufreader/buffer.rs index 9fd2472ebdf..574288e579e 100644 --- a/library/std/src/io/buffered/bufreader/buffer.rs +++ b/library/std/src/io/buffered/bufreader/buffer.rs @@ -123,7 +123,6 @@ impl Buffer { /// Remove bytes that have already been read from the buffer. pub fn backshift(&mut self) { self.buf.copy_within(self.pos.., 0); - self.initialized -= self.pos; self.filled -= self.pos; self.pos = 0; } diff --git a/library/std/src/io/copy.rs b/library/std/src/io/copy.rs index 8d733325b3b..15e962924ac 100644 --- a/library/std/src/io/copy.rs +++ b/library/std/src/io/copy.rs @@ -248,8 +248,11 @@ impl<I: Write + ?Sized> BufferedWriterSpec for BufWriter<I> { Err(e) => return Err(e), } } else { + // All the bytes that were already in the buffer are initialized, + // treat them as such when the buffer is flushed. + init += buf.len(); + self.flush_buf()?; - init = 0; } } } diff --git a/library/std/src/sys/pal/windows/pipe.rs b/library/std/src/sys/pal/windows/pipe.rs index c7852464922..7fd62339619 100644 --- a/library/std/src/sys/pal/windows/pipe.rs +++ b/library/std/src/sys/pal/windows/pipe.rs @@ -143,7 +143,6 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res }; opts.security_attributes(&mut sa); let theirs = File::open(Path::new(&name), &opts)?; - let theirs = AnonPipe { inner: theirs.into_inner() }; Ok(Pipes { ours: AnonPipe { inner: ours }, diff --git a/src/doc/rustc-dev-guide/.github/workflows/ci.yml b/src/doc/rustc-dev-guide/.github/workflows/ci.yml index 22a4fb1901a..415d0dc397d 100644 --- a/src/doc/rustc-dev-guide/.github/workflows/ci.yml +++ b/src/doc/rustc-dev-guide/.github/workflows/ci.yml @@ -18,6 +18,7 @@ jobs: MDBOOK_LINKCHECK2_VERSION: 0.9.1 MDBOOK_MERMAID_VERSION: 0.12.6 MDBOOK_TOC_VERSION: 0.11.2 + MDBOOK_OUTPUT__LINKCHECK__FOLLOW_WEB_LINKS: ${{ github.event_name != 'pull_request' }} DEPLOY_DIR: book/html BASE_SHA: ${{ github.event.pull_request.base.sha }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/src/doc/rustc-dev-guide/book.toml b/src/doc/rustc-dev-guide/book.toml index 67069d9930f..eb2f6806b96 100644 --- a/src/doc/rustc-dev-guide/book.toml +++ b/src/doc/rustc-dev-guide/book.toml @@ -62,5 +62,7 @@ warning-policy = "error" "/diagnostics/sessiondiagnostic.html" = "diagnostic-structs.html" "/diagnostics/diagnostic-codes.html" = "error-codes.html" "/miri.html" = "const-eval/interpret.html" -"/tests/integration.html" = "ecosystem.html" +"/tests/fuchsia.html" = "ecosystem-test-jobs/fuchsia.html" "/tests/headers.html" = "directives.html" +"/tests/integration.html" = "ecosystem.html" +"/tests/rust-for-linux.html" = "ecosystem-test-jobs/rust-for-linux.html" diff --git a/src/doc/rustc-dev-guide/ci/date-check/src/main.rs b/src/doc/rustc-dev-guide/ci/date-check/src/main.rs index 5ab3e6c8b65..9af69dbbf3f 100644 --- a/src/doc/rustc-dev-guide/ci/date-check/src/main.rs +++ b/src/doc/rustc-dev-guide/ci/date-check/src/main.rs @@ -1,11 +1,8 @@ -use std::{ - collections::BTreeMap, - convert::TryInto as _, - env, fmt, fs, - path::{Path, PathBuf}, - process, - str::FromStr, -}; +use std::collections::BTreeMap; +use std::convert::TryInto as _; +use std::path::{Path, PathBuf}; +use std::str::FromStr; +use std::{env, fmt, fs, process}; use chrono::{Datelike as _, Month, TimeZone as _, Utc}; use glob::glob; @@ -19,19 +16,13 @@ struct Date { impl Date { fn months_since(self, other: Date) -> Option<u32> { - let self_chrono = Utc - .with_ymd_and_hms(self.year.try_into().unwrap(), self.month, 1, 0, 0, 0) - .unwrap(); - let other_chrono = Utc - .with_ymd_and_hms(other.year.try_into().unwrap(), other.month, 1, 0, 0, 0) - .unwrap(); + let self_chrono = + Utc.with_ymd_and_hms(self.year.try_into().unwrap(), self.month, 1, 0, 0, 0).unwrap(); + let other_chrono = + Utc.with_ymd_and_hms(other.year.try_into().unwrap(), other.month, 1, 0, 0, 0).unwrap(); let duration_since = self_chrono.signed_duration_since(other_chrono); let months_since = duration_since.num_days() / 30; - if months_since < 0 { - None - } else { - Some(months_since.try_into().unwrap()) - } + if months_since < 0 { None } else { Some(months_since.try_into().unwrap()) } } } @@ -66,26 +57,18 @@ fn collect_dates_from_file(date_regex: &Regex, text: &str) -> Vec<(usize, Date)> date_regex .captures_iter(text) .filter_map(|cap| { - if let (Some(month), Some(year), None, None) | (None, None, Some(month), Some(year)) = ( - cap.name("m1"), - cap.name("y1"), - cap.name("m2"), - cap.name("y2"), - ) { + if let (Some(month), Some(year), None, None) | (None, None, Some(month), Some(year)) = + (cap.name("m1"), cap.name("y1"), cap.name("m2"), cap.name("y2")) + { let year = year.as_str().parse().expect("year"); - let month = Month::from_str(month.as_str()) - .expect("month") - .number_from_month(); + let month = Month::from_str(month.as_str()).expect("month").number_from_month(); Some((cap.get(0).expect("all").range(), Date { year, month })) } else { None } }) .map(|(byte_range, date)| { - line += text[end_of_last_cap..byte_range.end] - .chars() - .filter(|c| *c == '\n') - .count(); + line += text[end_of_last_cap..byte_range.end].chars().filter(|c| *c == '\n').count(); end_of_last_cap = byte_range.end; (line, date) }) @@ -138,10 +121,7 @@ fn main() { let root_dir_path = Path::new(&root_dir); let glob_pat = format!("{}/**/*.md", root_dir); let today_chrono = Utc::now().date_naive(); - let current_month = Date { - year: today_chrono.year_ce().1, - month: today_chrono.month(), - }; + let current_month = Date { year: today_chrono.year_ce().1, month: today_chrono.month() }; let dates_by_file = collect_dates(glob(&glob_pat).unwrap().map(Result::unwrap)); let dates_by_file: BTreeMap<_, _> = @@ -173,10 +153,7 @@ fn main() { println!(); for (path, dates) in dates_by_file { - println!( - "- {}", - path.strip_prefix(&root_dir_path).unwrap_or(&path).display(), - ); + println!("- {}", path.strip_prefix(&root_dir_path).unwrap_or(&path).display(),); for (line, date) in dates { println!(" - [ ] line {}: {}", line, date); } @@ -191,14 +168,8 @@ mod tests { #[test] fn test_months_since() { - let date1 = Date { - year: 2020, - month: 3, - }; - let date2 = Date { - year: 2021, - month: 1, - }; + let date1 = Date { year: 2020, month: 3 }; + let date2 = Date { year: 2021, month: 1 }; assert_eq!(date2.months_since(date1), Some(10)); } @@ -273,83 +244,17 @@ Test8 assert_eq!( collect_dates_from_file(&make_date_regex(), text), vec![ - ( - 3, - Date { - year: 2021, - month: 1, - } - ), - ( - 6, - Date { - year: 2021, - month: 2, - } - ), - ( - 9, - Date { - year: 2021, - month: 3, - } - ), - ( - 11, - Date { - year: 2021, - month: 4, - } - ), - ( - 17, - Date { - year: 2021, - month: 5, - } - ), - ( - 20, - Date { - year: 2021, - month: 1, - } - ), - ( - 23, - Date { - year: 2021, - month: 2, - } - ), - ( - 26, - Date { - year: 2021, - month: 3, - } - ), - ( - 28, - Date { - year: 2021, - month: 4, - } - ), - ( - 34, - Date { - year: 2021, - month: 5, - } - ), - ( - 38, - Date { - year: 2021, - month: 6, - } - ), + (3, Date { year: 2021, month: 1 }), + (6, Date { year: 2021, month: 2 }), + (9, Date { year: 2021, month: 3 }), + (11, Date { year: 2021, month: 4 }), + (17, Date { year: 2021, month: 5 }), + (20, Date { year: 2021, month: 1 }), + (23, Date { year: 2021, month: 2 }), + (26, Date { year: 2021, month: 3 }), + (28, Date { year: 2021, month: 4 }), + (34, Date { year: 2021, month: 5 }), + (38, Date { year: 2021, month: 6 }), ], ); } diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs index 984bd3e37ae..db6ac185785 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs @@ -1,4 +1,4 @@ -// Tested with nightly-2025-02-13 +// Tested with nightly-2025-03-28 #![feature(rustc_private)] @@ -34,9 +34,9 @@ impl rustc_span::source_map::FileLoader for MyFileLoader { fn read_file(&self, path: &Path) -> io::Result<String> { if path == Path::new("main.rs") { Ok(r#" +static MESSAGE: &str = "Hello, World!"; fn main() { - let message = "Hello, World!"; - println!("{message}"); + println!("{MESSAGE}"); } "# .to_string()) @@ -71,14 +71,12 @@ impl rustc_driver::Callbacks for MyCallbacks { fn after_analysis(&mut self, _compiler: &Compiler, tcx: TyCtxt<'_>) -> Compilation { // Analyze the program and inspect the types of definitions. - for id in tcx.hir().items() { - let hir = tcx.hir(); - let item = hir.item(id); + for id in tcx.hir_free_items() { + let item = &tcx.hir_item(id); match item.kind { - rustc_hir::ItemKind::Static(_, _, _) | rustc_hir::ItemKind::Fn { .. } => { - let name = item.ident; + rustc_hir::ItemKind::Static(ident, ..) | rustc_hir::ItemKind::Fn { ident, .. } => { let ty = tcx.type_of(item.hir_id().owner.def_id); - println!("{name:?}:\t{ty:?}") + println!("{ident:?}:\t{ty:?}") } _ => (), } diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs index 3270c722e07..c0d7f977d35 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs @@ -1,4 +1,4 @@ -// Tested with nightly-2025-02-13 +// Tested with nightly-2025-03-28 #![feature(rustc_private)] @@ -20,7 +20,7 @@ use std::path::Path; use std::sync::Arc; use rustc_ast_pretty::pprust::item_to_string; -use rustc_driver::{run_compiler, Compilation}; +use rustc_driver::{Compilation, run_compiler}; use rustc_interface::interface::{Compiler, Config}; use rustc_middle::ty::TyCtxt; @@ -70,11 +70,9 @@ impl rustc_driver::Callbacks for MyCallbacks { } fn after_analysis(&mut self, _compiler: &Compiler, tcx: TyCtxt<'_>) -> Compilation { - // Every compilation contains a single crate. - let hir_krate = tcx.hir(); // Iterate over the top-level items in the crate, looking for the main function. - for id in hir_krate.items() { - let item = hir_krate.item(id); + for id in tcx.hir_free_items() { + let item = &tcx.hir_item(id); // Use pattern-matching to find a specific node inside the main function. if let rustc_hir::ItemKind::Fn { body, .. } = item.kind { let expr = &tcx.hir_body(body).value; diff --git a/src/doc/rustc-dev-guide/examples/rustc-interface-example.rs b/src/doc/rustc-dev-guide/examples/rustc-interface-example.rs index 70f27c2a82a..360f70c8e86 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-interface-example.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-interface-example.rs @@ -1,4 +1,4 @@ -// Tested with nightly-2025-02-13 +// Tested with nightly-2025-03-28 #![feature(rustc_private)] @@ -64,14 +64,13 @@ fn main() { println!("{krate:?}"); // Analyze the program and inspect the types of definitions. rustc_interface::create_and_enter_global_ctxt(&compiler, krate, |tcx| { - for id in tcx.hir().items() { - let hir = tcx.hir(); - let item = hir.item(id); + for id in tcx.hir_free_items() { + let item = tcx.hir_item(id); match item.kind { - rustc_hir::ItemKind::Static(_, _, _) | rustc_hir::ItemKind::Fn { .. } => { - let name = item.ident; + rustc_hir::ItemKind::Static(ident, ..) + | rustc_hir::ItemKind::Fn { ident, .. } => { let ty = tcx.type_of(item.hir_id().owner.def_id); - println!("{name:?}:\t{ty:?}") + println!("{ident:?}:\t{ty:?}") } _ => (), } diff --git a/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs b/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs index 39b236e1783..2512ba3c3f9 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs @@ -1,4 +1,4 @@ -// Tested with nightly-2025-02-13 +// Tested with nightly-2025-03-28 #![feature(rustc_private)] @@ -86,8 +86,10 @@ fn main() { rustc_interface::run_compiler(config, |compiler| { let krate = rustc_interface::passes::parse(&compiler.sess); rustc_interface::create_and_enter_global_ctxt(&compiler, krate, |tcx| { - // Run the analysis phase on the local crate to trigger the type error. - let _ = tcx.analysis(()); + // Iterate all the items defined and perform type checking. + tcx.par_hir_body_owners(|item_def_id| { + tcx.ensure_ok().typeck(item_def_id); + }); }); // If the compiler has encountered errors when this closure returns, it will abort (!) the program. // We avoid this by resetting the error count before returning diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version index 6baf43397e8..d7c20d8ce62 100644 --- a/src/doc/rustc-dev-guide/rust-version +++ b/src/doc/rustc-dev-guide/rust-version @@ -1 +1 @@ -493c38ba371929579fe136df26eccd9516347c7a +ae9173d7dd4a31806c950c90dcc331f1508b4d17 diff --git a/src/doc/rustc-dev-guide/rustfmt.toml b/src/doc/rustc-dev-guide/rustfmt.toml new file mode 100644 index 00000000000..b285329c78e --- /dev/null +++ b/src/doc/rustc-dev-guide/rustfmt.toml @@ -0,0 +1,7 @@ +# matches that of rust-lang/rust +style_edition = "2024" +use_small_heuristics = "Max" +merge_derives = false +group_imports = "StdExternalCrate" +imports_granularity = "Module" +use_field_init_shorthand = true diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index ce74c741b39..95a3cd7c790 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -28,8 +28,11 @@ - [Minicore](./tests/minicore.md) - [Ecosystem testing](./tests/ecosystem.md) - [Crater](./tests/crater.md) - - [Fuchsia](./tests/fuchsia.md) - - [Rust for Linux](./tests/rust-for-linux.md) + - [Fuchsia](./tests/ecosystem-test-jobs/fuchsia.md) + - [Rust for Linux](./tests/ecosystem-test-jobs/rust-for-linux.md) + - [Codegen backend testing](./tests/codegen-backend-tests/intro.md) + - [Cranelift codegen backend](./tests/codegen-backend-tests/cg_clif.md) + - [GCC codegen backend](./tests/codegen-backend-tests/cg_gcc.md) - [Performance testing](./tests/perf.md) - [Suggest tests tool](./tests/suggest-tests.md) - [Misc info](./tests/misc.md) @@ -61,12 +64,13 @@ - [ARM](notification-groups/arm.md) - [Cleanup Crew](notification-groups/cleanup-crew.md) - [Emscripten](notification-groups/emscripten.md) + - [Fuchsia](notification-groups/fuchsia.md) - [LLVM](notification-groups/llvm.md) - [RISC-V](notification-groups/risc-v.md) + - [Rust for Linux](notification-groups/rust-for-linux.md) - [WASI](notification-groups/wasi.md) - [WebAssembly](notification-groups/wasm.md) - [Windows](notification-groups/windows.md) - - [Rust for Linux](notification-groups/rust-for-linux.md) - [Licenses](./licenses.md) - [Editions](guides/editions.md) @@ -94,7 +98,7 @@ - [Parallel Compilation](./parallel-rustc.md) - [Rustdoc internals](./rustdoc-internals.md) - [Search](./rustdoc-internals/search.md) - + - [The `rustdoc` test suite](./rustdoc-internals/rustdoc-test-suite.md) # Source Code Representation - [Prologue](./part-3-intro.md) @@ -124,6 +128,7 @@ - [rustc_driver and rustc_interface](./rustc-driver/intro.md) - [Example: Type checking](./rustc-driver/interacting-with-the-ast.md) - [Example: Getting diagnostics](./rustc-driver/getting-diagnostics.md) + - [Remarks on perma-unstable features](./rustc-driver/remarks-on-perma-unstable-features.md) - [Errors and Lints](diagnostics.md) - [Diagnostic and subdiagnostic structs](./diagnostics/diagnostic-structs.md) - [Translation](./diagnostics/translation.md) @@ -144,10 +149,7 @@ - [ADTs and Generic Arguments](./ty_module/generic_arguments.md) - [Parameter types/consts/regions](./ty_module/param_ty_const_regions.md) - [`TypeFolder` and `TypeFoldable`](./ty-fold.md) -- [Parameter Environments](./param_env/param_env_summary.md) - - [What is it?](./param_env/param_env_what_is_it.md) - - [How are `ParamEnv`'s constructed internally](./param_env/param_env_construction_internals.md) - - [Which `ParamEnv` do I use?](./param_env/param_env_acquisition.md) +- [Typing/Param Envs](./typing_parameter_envs.md) - [Type inference](./type-inference.md) - [Trait solving](./traits/resolution.md) - [Higher-ranked trait bounds](./traits/hrtb.md) diff --git a/src/doc/rustc-dev-guide/src/appendix/code-index.md b/src/doc/rustc-dev-guide/src/appendix/code-index.md index b96ede68eab..65fbf752d79 100644 --- a/src/doc/rustc-dev-guide/src/appendix/code-index.md +++ b/src/doc/rustc-dev-guide/src/appendix/code-index.md @@ -40,5 +40,5 @@ Item | Kind | Short description | Chapter | [Emitting Diagnostics]: ../diagnostics.html [Macro expansion]: ../macro-expansion.html [Name resolution]: ../name-resolution.html -[Parameter Environment]: ../param_env/param_env_summary.html +[Parameter Environment]: ../typing_parameter_envs.html [Trait Solving: Goals and Clauses]: ../traits/goals-and-clauses.html#domain-goals diff --git a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md index 067e2871118..c3c1c41e3f6 100644 --- a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md +++ b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md @@ -63,7 +63,7 @@ cd rust > **NOTE**: A shallow clone limits which `git` commands can be run. > If you intend to work on and contribute to the compiler, it is > generally recommended to fully clone the repository [as shown above](#get-the-source-code), -> or to perform a [partial clone](#shallow-clone-the-repository) instead. +> or to perform a [partial clone](#partial-clone-the-repository) instead. > > For example, `git bisect` and `git blame` require access to the commit history, > so they don't work if the repository was cloned with `--depth 1`. diff --git a/src/doc/rustc-dev-guide/src/building/prerequisites.md b/src/doc/rustc-dev-guide/src/building/prerequisites.md index f49f6bb0527..6761cabac1f 100644 --- a/src/doc/rustc-dev-guide/src/building/prerequisites.md +++ b/src/doc/rustc-dev-guide/src/building/prerequisites.md @@ -38,4 +38,4 @@ incremental compilation ([see here][config]). This will make compilation take longer (especially after a rebase), but will save a ton of space from the incremental caches. -[config]: ./how-to-build-and-run.md#create-a-configtoml +[config]: ./how-to-build-and-run.md#create-a-bootstraptoml diff --git a/src/doc/rustc-dev-guide/src/const-eval.md b/src/doc/rustc-dev-guide/src/const-eval.md index 69329a3e085..ca6a35a5e97 100644 --- a/src/doc/rustc-dev-guide/src/const-eval.md +++ b/src/doc/rustc-dev-guide/src/const-eval.md @@ -35,7 +35,7 @@ They're the wrappers of the `const_eval` query. Statics are special; all other functions do not represent statics correctly and have thus assertions preventing their use on statics. -The `const_eval_*` functions use a [`ParamEnv`](./param_env/param_env_summary.html) of environment +The `const_eval_*` functions use a [`ParamEnv`](./typing_parameter_envs.html) of environment in which the constant is evaluated (e.g. the function within which the constant is used) and a [`GlobalId`]. The `GlobalId` is made up of an `Instance` referring to a constant or static or of an `Instance` of a function and an index into the function's `Promoted` table. diff --git a/src/doc/rustc-dev-guide/src/diagnostics.md b/src/doc/rustc-dev-guide/src/diagnostics.md index 972309b5cd3..6f72ea902f5 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics.md +++ b/src/doc/rustc-dev-guide/src/diagnostics.md @@ -954,9 +954,6 @@ application of these fields based on a variety of attributes when using `Self="std::iter::Iterator<char>"`. This is needed because `Self` is a keyword which cannot appear in attributes. - `direct`: user-specified rather than derived obligation. - - `from_method`: usable both as boolean (whether the flag is present, like - `crate_local`) or matching against a particular method. Currently used - for `try`. - `from_desugaring`: usable both as boolean (whether the flag is present) or matching against a particular desugaring. The desugaring is identified with its variant name in the `DesugaringKind` enum. diff --git a/src/doc/rustc-dev-guide/src/name-resolution.md b/src/doc/rustc-dev-guide/src/name-resolution.md index 2727b8142f2..719ebce8553 100644 --- a/src/doc/rustc-dev-guide/src/name-resolution.md +++ b/src/doc/rustc-dev-guide/src/name-resolution.md @@ -120,9 +120,9 @@ even though they should be visible by ordinary scoping rules. An example: fn do_something<T: Default>(val: T) { // <- New rib in both types and values (1) // `val` is accessible, as is the helper function // `T` is accessible - let helper = || { // New rib on `helper` (2) and another on the block (3) + let helper = || { // New rib on the block (2) // `val` is accessible here - }; // End of (3) + }; // End of (2), new rib on `helper` (3) // `val` is accessible, `helper` variable shadows `helper` function fn helper() { // <- New rib in both types and values (4) // `val` is not accessible here, (4) is not transparent for locals @@ -130,7 +130,7 @@ fn do_something<T: Default>(val: T) { // <- New rib in both types and values (1) } // End of (4) let val = T::default(); // New rib (5) // `val` is the variable, not the parameter here -} // End of (5), (2) and (1) +} // End of (5), (3) and (1) ``` Because the rules for different namespaces are a bit different, each namespace diff --git a/src/doc/rustc-dev-guide/src/notification-groups/fuchsia.md b/src/doc/rustc-dev-guide/src/notification-groups/fuchsia.md new file mode 100644 index 00000000000..e3c1a7148d3 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/notification-groups/fuchsia.md @@ -0,0 +1,12 @@ +# Fuchsia notification group + +**Github Label:** [O-fuchsia] <br> +**Ping command:** `@rustbot ping fuchsia` + +[O-fuchsia]: https://github.com/rust-lang/rust/labels/O-fuchsia + +This list will be used to notify [Fuchsia][fuchsia] maintainers +when the compiler or the standard library changes in a way that would +break the Fuchsia integration. + +[fuchsia]: ../tests/ecosystem-test-jobs/fuchsia.md diff --git a/src/doc/rustc-dev-guide/src/param_env/param_env_acquisition.md b/src/doc/rustc-dev-guide/src/param_env/param_env_acquisition.md deleted file mode 100644 index f6cff2d6c63..00000000000 --- a/src/doc/rustc-dev-guide/src/param_env/param_env_acquisition.md +++ /dev/null @@ -1,43 +0,0 @@ - -# Which `ParamEnv` do I use? - -When needing a [`ParamEnv`][pe] in the compiler there are a few options for obtaining one: -- The correct env is already in scope simply use it (or pass it down the call stack to where you are). -- The [`tcx.param_env(def_id)` query][param_env_query] -- Use [`ParamEnv::new`][param_env_new] to construct an env with an arbitrary set of where clauses. Then call [`traits::normalize_param_env_or_error`][normalize_env_or_error] which will handle normalizing and elaborating all the where clauses in the env for you. -- Creating an empty environment via [`ParamEnv::reveal_all`][env_reveal_all] or [`ParamEnv::empty`][env_empty] - -In the large majority of cases a `ParamEnv` when required already exists somewhere in scope or above in the call stack and should be passed down. A non exhaustive list of places where you might find an existing `ParamEnv`: -- During typeck `FnCtxt` has a [`param_env` field][fnctxt_param_env] -- When writing late lints the `LateContext` has a [`param_env` field][latectxt_param_env] -- During well formedness checking the `WfCheckingCtxt` has a [`param_env` field][wfckctxt_param_env] -- The `TypeChecker` used by Mir Typeck has a [`param_env` field][mirtypeck_param_env] -- In the next-gen trait solver all `Goal`s have a [`param_env` field][goal_param_env] specifying what environment to prove the goal in -- When editing an existing [`TypeRelation`][typerelation] if it implements `PredicateEmittingRelation` then a [`param_env` method][typerelation_param_env] will be available. - -Using the `param_env` query to obtain an env is generally done at the start of some kind of analysis and then passed everywhere that a `ParamEnv` is required. For example the type checker will create a `ParamEnv` for the item it is type checking and then pass it around everywhere. - -Creating an env from an arbitrary set of where clauses is usually unnecessary and should only be done if the environment you need does not correspond to an actual item in the source code (i.e. [`compare_method_predicate_entailment`][method_pred_entailment] as mentioned earlier). - -Creating an empty environment via `ParamEnv::empty` is almost always wrong. There are very few places where we actually know that the environment should be empty. One of the only places where we do actually know this is after monomorphization, however the `ParamEnv` there should be constructed via `ParamEnv::reveal_all` instead as at this point we should be able to determine the hidden type of opaque types. Codegen/Post-mono is one of the only places that should be using `ParamEnv::reveal_all`. - -An additional piece of complexity here is specifying the `Reveal` (see linked docs for explanation of what reveal does) used for the `ParamEnv`. When constructing a param env using the `param_env` query it will have `Reveal::UserFacing`, if `Reveal::All` is desired then the [`tcx.param_env_reveal_all_normalized`][env_reveal_all_normalized] query can be used instead. - -The `ParamEnv` type has a method [`ParamEnv::with_reveal_all_normalized`][with_reveal_all] which converts an existing `ParamEnv` into one with `Reveal::All` specified. Where possible the previously mentioned query should be preferred as it is more efficient. - -[param_env_new]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html#method.new -[normalize_env_or_error]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/fn.normalize_param_env_or_error.html -[fnctxt_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/fn_ctxt/struct.FnCtxt.html#structfield.param_env -[latectxt_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/context/struct.LateContext.html#structfield.param_env -[wfckctxt_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/wfcheck/struct.WfCheckingCtxt.html#structfield.param_env -[goal_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/infer/canonical/ir/solve/struct.Goal.html#structfield.param_env -[typerelation_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/infer/trait.PredicateEmittingRelation.html#tymethod.param_env -[typerelation]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/relate/trait.TypeRelation.html -[mirtypeck_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/type_check/struct.TypeChecker.html#structfield.param_env -[env_reveal_all_normalized]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.param_env_reveal_all_normalized -[with_reveal_all]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html#method.with_reveal_all_normalized -[env_reveal_all]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html#method.reveal_all -[env_empty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html#method.empty -[pe]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html -[param_env_query]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/fn_ctxt/struct.FnCtxt.html#structfield.param_env -[method_pred_entailment]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/compare_impl_item/fn.compare_method_predicate_entailment.html diff --git a/src/doc/rustc-dev-guide/src/param_env/param_env_construction_internals.md b/src/doc/rustc-dev-guide/src/param_env/param_env_construction_internals.md deleted file mode 100644 index 69a262a176e..00000000000 --- a/src/doc/rustc-dev-guide/src/param_env/param_env_construction_internals.md +++ /dev/null @@ -1,83 +0,0 @@ - -# How are `ParamEnv`'s constructed internally? - -Creating a [`ParamEnv`][pe] is more complicated than simply using the list of where clauses defined on an item as written by the user. We need to both elaborate supertraits into the env and fully normalize all aliases. This logic is handled by [`traits::normalize_param_env_or_error`][normalize_env_or_error] (even though it does not mention anything about elaboration). - -## Elaborating supertraits - -When we have a function such as `fn foo<T: Copy>()` we would like to be able to prove `T: Clone` inside of the function as the `Copy` trait has a `Clone` supertrait. Constructing a `ParamEnv` looks at all of the trait bounds in the env and explicitly adds new where clauses to the `ParamEnv` for any supertraits found on the traits. - -A concrete example would be the following function: -```rust -trait Trait: SuperTrait {} -trait SuperTrait: SuperSuperTrait {} - -// `bar`'s unelaborated `ParamEnv` would be: -// `[T: Sized, T: Copy, T: Trait]` -fn bar<T: Copy + Trait>(a: T) { - requires_impl(a); -} - -fn requires_impl<T: Clone + SuperSuperTrait>(a: T) {} -``` - -If we did not elaborate the env then the `requires_impl` call would fail to typecheck as we would not be able to prove `T: Clone` or `T: SuperSuperTrait`. In practice we elaborate the env which means that `bar`'s `ParamEnv` is actually: -`[T: Sized, T: Copy, T: Clone, T: Trait, T: SuperTrait, T: SuperSuperTrait]` -This allows us to prove `T: Clone` and `T: SuperSuperTrait` when type checking `bar`. - -The `Clone` trait has a `Sized` supertrait however we do not end up with two `T: Sized` bounds in the env (one for the supertrait and one for the implicitly added `T: Sized` bound). This is because the elaboration process (implemented via [`util::elaborate`][elaborate]) deduplicates the where clauses to avoid this. - -As a side effect this also means that even if no actual elaboration of supertraits takes place, the existing where clauses in the env are _also_ deduplicated. See the following example: -```rust -trait Trait {} -// The unelaborated `ParamEnv` would be: -// `[T: Sized, T: Trait, T: Trait]` -// but after elaboration it would be: -// `[T: Sized, T: Trait]` -fn foo<T: Trait + Trait>() {} -``` - -The [next-gen trait solver][next-gen-solver] also requires this elaboration to take place. - -[elaborate]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/traits/util/fn.elaborate.html -[next-gen-solver]: ../solve/trait-solving.md - -## Normalizing all bounds - -In the old trait solver the where clauses stored in `ParamEnv` are required to be fully normalized or else the trait solver will not function correctly. A concrete example of needing to normalize the `ParamEnv` is the following: -```rust -trait Trait<T> { - type Assoc; -} - -trait Other { - type Bar; -} - -impl<T> Other for T { - type Bar = u32; -} - -// `foo`'s unnormalized `ParamEnv` would be: -// `[T: Sized, U: Sized, U: Trait<T::Bar>]` -fn foo<T, U>(a: U) -where - U: Trait<<T as Other>::Bar>, -{ - requires_impl(a); -} - -fn requires_impl<U: Trait<u32>>(_: U) {} -``` - -As humans we can tell that `<T as Other>::Bar` is equal to `u32` so the trait bound on `U` is equivalent to `U: Trait<u32>`. In practice trying to prove `U: Trait<u32>` in the old solver in this environment would fail as it is unable to determine that `<T as Other>::Bar` is equal to `u32`. - -To work around this we normalize `ParamEnv`'s after constructing them so that `foo`'s `ParamEnv` is actually: `[T: Sized, U: Sized, U: Trait<u32>]` which means the trait solver is now able to use the `U: Trait<u32>` in the `ParamEnv` to determine that the trait bound `U: Trait<u32>` holds. - -This workaround does not work in all cases as normalizing associated types requires a `ParamEnv` which introduces a bootstrapping problem. We need a normalized `ParamEnv` in order for normalization to give correct results, but we need to normalize to get that `ParamEnv`. Currently we normalize the `ParamEnv` once using the unnormalized param env and it tends to give okay results in practice even though there are some examples where this breaks ([example]). - -In the next-gen trait solver the requirement for all where clauses in the `ParamEnv` to be fully normalized is not present and so we do not normalize when constructing `ParamEnv`s. - -[example]: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=e6933265ea3e84eaa47019465739992c -[pe]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html -[normalize_env_or_error]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/fn.normalize_param_env_or_error.html diff --git a/src/doc/rustc-dev-guide/src/param_env/param_env_summary.md b/src/doc/rustc-dev-guide/src/param_env/param_env_summary.md deleted file mode 100644 index 0ff6d8fc394..00000000000 --- a/src/doc/rustc-dev-guide/src/param_env/param_env_summary.md +++ /dev/null @@ -1,18 +0,0 @@ -# The `ParamEnv` type - -## Summary - -The [`ParamEnv`][pe] is used to store information about the environment that we are interacting with the type system from. For example the set of in-scope where-clauses is stored in `ParamEnv` as it differs between each item whereas the list of user written impls is not stored in the `ParamEnv` as this does not change for each item. - -This chapter of the dev guide covers: -- A high level summary of what a `ParamEnv` is and what it is used for -- Technical details about what the process of constructing a `ParamEnv` involves -- Guidance about how to acquire a `ParamEnv` when one is required - -## Bundling - -A useful API on `ParamEnv` is the [`and`][and] method which allows bundling a value with the `ParamEnv`. The `and` method produces a [`ParamEnvAnd<T>`][pea] making it clearer that using the inner value is intended to be done in that specific environment. - -[and]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html#method.and -[pe]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html -[pea]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnvAnd.html \ No newline at end of file diff --git a/src/doc/rustc-dev-guide/src/param_env/param_env_what_is_it.md b/src/doc/rustc-dev-guide/src/param_env/param_env_what_is_it.md deleted file mode 100644 index 5c2f4d59405..00000000000 --- a/src/doc/rustc-dev-guide/src/param_env/param_env_what_is_it.md +++ /dev/null @@ -1,59 +0,0 @@ - -# What is a `ParamEnv`? - -The type system relies on information in the environment in order for it to function correctly. This information is stored in the [`ParamEnv`][pe] type and it is important to use the correct `ParamEnv` when interacting with the type system. - -The information represented by `ParamEnv` is a list of in-scope where-clauses, and a `Reveal` (see linked docs for more information). A `ParamEnv` typically corresponds to a specific item's where clauses, some clauses are not explicitly written bounds and instead are implicitly added in [`predicates_of`][predicates_of] such as `ConstArgHasType` or some implied bounds. - -A `ParamEnv` can also be created with arbitrary data that is not derived from a specific item such as in [`compare_method_predicate_entailment`][method_pred_entailment] which creates a hybrid `ParamEnv` consisting of the impl's where clauses and the trait definition's function's where clauses. In most cases `ParamEnv`s are initially created via the [`param_env` query][query] which returns a `ParamEnv` derived from the provided item's where clauses. - -If we have a function such as: -```rust -// `foo` would have a `ParamEnv` of: -// `[T: Sized, T: Trait, <T as Trait>::Assoc: Clone]` -fn foo<T: Trait>() -where - <T as Trait>::Assoc: Clone, -{} -``` -If we were conceptually inside of `foo` (for example, type-checking or linting it) we would use this `ParamEnv` everywhere that we interact with the type system. This would allow things such as normalization (TODO: write a chapter about normalization and link it), evaluating generic constants, and proving where clauses/goals, to rely on `T` being sized, implementing `Trait`, etc. - -A more concrete example: -```rust -// `foo` would have a `ParamEnv` of: -// `[T: Sized, T: Clone]` -fn foo<T: Clone>(a: T) { - // when typechecking `foo` we require all the where clauses on `bar` - // to hold in order for it to be legal to call. This means we have to - // prove `T: Clone`. As we are type checking `foo` we use `foo`'s - // environment when trying to check that `T: Clone` holds. - // - // Trying to prove `T: Clone` with a `ParamEnv` of `[T: Sized, T: Clone]` - // will trivially succeed as bound we want to prove is in our environment. - requires_clone(a); -} -``` - -Or alternatively an example that would not compile: -```rust -// `foo2` would have a `ParamEnv` of: -// `[T: Sized]` -fn foo2<T>(a: T) { - // When typechecking `foo2` we attempt to prove `T: Clone`. - // As we are type checking `foo2` we use `foo2`'s environment - // when trying to prove `T: Clone`. - // - // Trying to prove `T: Clone` with a `ParamEnv` of `[T: Sized]` will - // fail as there is nothing in the environment telling the trait solver - // that `T` implements `Clone` and there exists no user written impl - // that could apply. - requires_clone(a); -} -``` - -It's very important to use the correct `ParamEnv` when interacting with the type system as otherwise it can lead to ICEs or things compiling when they shouldn't (or vice versa). See [#82159](https://github.com/rust-lang/rust/pull/82159) and [#82067](https://github.com/rust-lang/rust/pull/82067) as examples of PRs that changed rustc to use the correct param env to avoid ICE. Determining how to acquire the correct `ParamEnv` is explained later in this chapter. - -[predicates_of]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/collect/predicates_of/fn.predicates_of.html -[method_pred_entailment]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/compare_impl_item/fn.compare_method_predicate_entailment.html -[pe]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html -[query]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.param_env diff --git a/src/doc/rustc-dev-guide/src/rustc-driver/getting-diagnostics.md b/src/doc/rustc-dev-guide/src/rustc-driver/getting-diagnostics.md index 1043df6ecb6..518cf4e821a 100644 --- a/src/doc/rustc-dev-guide/src/rustc-driver/getting-diagnostics.md +++ b/src/doc/rustc-dev-guide/src/rustc-driver/getting-diagnostics.md @@ -7,7 +7,7 @@ otherwise be printed to stderr. To get diagnostics from the compiler, configure [`rustc_interface::Config`] to output diagnostic to a buffer, -and run [`TyCtxt.analysis`]. +and run [`rustc_hir_typeck::typeck`] for each item. ```rust {{#include ../../examples/rustc-interface-getting-diagnostics.rs}} @@ -16,3 +16,4 @@ and run [`TyCtxt.analysis`]. [`rustc_interface`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/index.html [`rustc_interface::Config`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/interface/struct.Config.html [`TyCtxt.analysis`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/passes/fn.analysis.html +[`rustc_hir_typeck::typeck`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/fn.typeck.html diff --git a/src/doc/rustc-dev-guide/src/rustc-driver/remarks-on-perma-unstable-features.md b/src/doc/rustc-dev-guide/src/rustc-driver/remarks-on-perma-unstable-features.md new file mode 100644 index 00000000000..b434cfc9cf1 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/rustc-driver/remarks-on-perma-unstable-features.md @@ -0,0 +1,54 @@ +# Remarks on perma unstable features + +## `rustc_private` + +### Overview + +The `rustc_private` feature allows external crates to use compiler internals. + +### Using `rustc-private` with Official Toolchains + +When using the `rustc_private` feature with official Rust toolchains distributed via rustup, you need to install two additional components: + +1. **`rustc-dev`**: Provides compiler libraries +2. **`llvm-tools`**: Provides LLVM libraries required for linking + +#### Installation Steps + +Install both components using rustup: + +```text +rustup component add rustc-dev llvm-tools +``` + +#### Common Error + +Without the `llvm-tools` component, you'll encounter linking errors like: + +```text +error: linking with `cc` failed: exit status: 1 + | + = note: rust-lld: error: unable to find library -lLLVM-{version} +``` + +### Using `rustc-private` with Custom Toolchains + +For custom-built toolchains or environments not using rustup, additional configuration is typically required: + +#### Requirements + +- LLVM libraries must be available in your system's library search paths +- The LLVM version must match the one used to build your Rust toolchain + +#### Troubleshooting Steps + +1. **Check LLVM installation**: Verify LLVM is installed and accessible +2. **Configure library paths**: You may need to set environment variables: + ```text + export LD_LIBRARY_PATH=/path/to/llvm/lib:$LD_LIBRARY_PATH + ``` +3. **Check version compatibility**: Ensure your LLVM version is compatible with your Rust toolchain + +### Additional Resources + +- [GitHub Issue #137421](https://github.com/rust-lang/rust/issues/137421): Explains that `rustc_private` linker failures often occur because `llvm-tools` is not installed diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md b/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md new file mode 100644 index 00000000000..169b95a7e1a --- /dev/null +++ b/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md @@ -0,0 +1,112 @@ +# The `rustdoc` test suite + +This page is specifically about the test suite named `rustdoc`. +For other test suites used for testing rustdoc, see [Rustdoc tests](../rustdoc.md#tests). + +The `rustdoc` test suite is specifically used to test the HTML output of rustdoc. + +This is achieved by means of `htmldocck.py`, a custom checker script that leverages [XPath]. + +[XPath]: https://en.wikipedia.org/wiki/XPath + +## Directives +Directives to htmldocck are similar to those given to `compiletest` in that they take the form of `//@` comments. + +In addition to the directives listed here, +`rustdoc` tests also support most +[compiletest directives](../tests/directives.html). + +All `PATH`s in directives are relative to the the rustdoc output directory (`build/TARGET/test/rustdoc/TESTNAME`), +so it is conventional to use a `#![crate_name = "foo"]` attribute to avoid +having to write a long crate name multiple times. +To avoid repetion, `-` can be used in any `PATH` argument to re-use the previous `PATH` argument. + +All arguments take the form of quoted strings +(both single and double quotes are supported), +with the exception of `COUNT` and the special `-` form of `PATH`. + +Directives are assertions that place constraints on the generated HTML. + +All directives (except `files`) can be negated by putting a `!` in front of their name. + +Similar to shell commands, +directives can extend across multiple lines if their last char is `\`. +In this case, the start of the next line should be `//`, with no `@`. + +For example, `//@ !has 'foo/struct.Bar.html'` checks that crate `foo` does not have a page for a struct named `Bar` in the crate root. + +### `has` + +Usage 1: `//@ has PATH` +Usage 2: `//@ has PATH XPATH PATTERN` + +In the first form, `has` checks that a given file exists. + +In the second form, `has` is an alias for `matches`, +except `PATTERN` is a whitespace-normalized[^1] string instead of a regex. + +### `matches` + +Usage: `//@ matches PATH XPATH PATTERN` + +Checks that the text of each element selected by `XPATH` in `PATH` matches the python-flavored regex `PATTERN`. + +### `matchesraw` + +Usage: `//@ matchesraw PATH PATTERN` + +Checks that the contents of the file `PATH` matches the regex `PATTERN`. + +### `hasraw` + +Usage: `//@ hasraw PATH PATTERN` + +Same as `matchesraw`, except `PATTERN` is a whitespace-normalized[^1] string instead of a regex. + +### `count` + +Usage: `//@ count PATH XPATH COUNT` + +Checks that there are exactly `COUNT` matches for `XPATH` within the file `PATH`. + +### `snapshot` + +Usage: `//@ snapshot NAME PATH XPATH` + +Creates a snapshot test named NAME. +A snapshot test captures a subtree of the DOM, at the location +determined by the XPath, and compares it to a pre-recorded value +in a file. The file's name is the test's name with the `.rs` extension +replaced with `.NAME.html`, where NAME is the snapshot's name. + +htmldocck supports the `--bless` option to accept the current subtree +as expected, saving it to the file determined by the snapshot's name. +compiletest's `--bless` flag is forwarded to htmldocck. + +### `has-dir` + +Usage: `//@ has-dir PATH` + +Checks for the existance of directory `PATH`. + +### `files` + +Usage: `//@ files PATH ENTRIES` + +Checks that the directory `PATH` contains exactly `ENTRIES`. +`ENTRIES` is a python list of strings inside a quoted string, +as if it were to be parsed by `eval`. +(note that the list is actually parsed by `shlex.split`, +so it cannot contain arbitrary python expressions). + +Example: `//@ files "foo/bar" '["index.html", "sidebar-items.js"]'` + +[^1]: Whitespace normalization means that all spans of consecutive whitespace are replaced with a single space. The files themselves are also whitespace-normalized. + +## Limitations +`htmldocck.py` uses the xpath implementation from the standard library. +This leads to several limitations: +* All `XPATH` arguments must start with `//` due to a flaw in the implemention. +* Many XPath features (functions, axies, etc.) are not supported. +* Only well-formed HTML can be parsed (hopefully rustdoc doesn't output mismatched tags). + diff --git a/src/doc/rustc-dev-guide/src/rustdoc.md b/src/doc/rustc-dev-guide/src/rustdoc.md index 356698148e4..320dc9d5825 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc.md +++ b/src/doc/rustc-dev-guide/src/rustdoc.md @@ -77,27 +77,27 @@ does is call the `main()` that's in this crate's `lib.rs`, though.) `doctest.rs`. * The Markdown renderer is loaded up in `html/markdown.rs`, including functions for extracting doctests from a given block of Markdown. -* The tests on the structure of rustdoc HTML output are located in `tests/rustdoc`, where - they're handled by the test runner of bootstrap and the supplementary script - `src/etc/htmldocck.py`. * Frontend CSS and JavaScript are stored in `html/static/`. ## Tests -* All paths in this section are relative to `tests` in the rust-lang/rust repository. -* Tests on search engine and index are located in `rustdoc-js` and `rustdoc-js-std`. +* Tests on search engine and index are located in `tests/rustdoc-js` and `tests/rustdoc-js-std`. The format is specified [in the search guide](rustdoc-internals/search.md#testing-the-search-engine). * Tests on the "UI" of rustdoc (the terminal output it produces when run) are in - `rustdoc-ui` + `tests/rustdoc-ui` * Tests on the "GUI" of rustdoc (the HTML, JS, and CSS as rendered in a browser) - are in `rustdoc-gui`. These use a [NodeJS tool called + are in `tests/rustdoc-gui`. These use a [NodeJS tool called browser-UI-test](https://github.com/GuillaumeGomez/browser-UI-test/) that uses puppeteer to run tests in a headless browser and check rendering and interactivity. * Additionally, JavaScript type annotations are written using [TypeScript-flavored JSDoc] comments and an external d.ts file. The code itself is plain, valid JavaScript; we only use tsc as a linter. +* The tests on the structure of rustdoc HTML output are located in `tests/rustdoc`, + where they're handled by the test runner of bootstrap and + the supplementary script `src/etc/htmldocck.py`. + [These tests have several extra directives available to them](./rustdoc-internals/rustdoc-test-suite.md). [TypeScript-flavored JSDoc]: https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html diff --git a/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/cg_clif.md b/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/cg_clif.md new file mode 100644 index 00000000000..030ddd7dff5 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/cg_clif.md @@ -0,0 +1,3 @@ +# Cranelift codegen backend tests + +TODO: please add some more information to this page. diff --git a/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/cg_gcc.md b/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/cg_gcc.md new file mode 100644 index 00000000000..4caf4c0e0ee --- /dev/null +++ b/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/cg_gcc.md @@ -0,0 +1,3 @@ +# GCC codegen backend tests + +TODO: please add some more information to this page. diff --git a/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/intro.md b/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/intro.md new file mode 100644 index 00000000000..6bf46ddcd21 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/intro.md @@ -0,0 +1,13 @@ +# Codegen backend testing + +See also the [Code generation](../../backend/codegen.md) chapter. + +In addition to the primary LLVM codegen backend, the rust-lang/rust CI also runs tests of the [cranelift][cg_clif] and [GCC][cg_gcc] codegen backends in certain test jobs. + +For more details on the tests involved, see: + +- [Cranelift codegen backend tests](./cg_clif.md) +- [GCC codegen backend tests](./cg_gcc.md) + +[cg_clif]: https://github.com/rust-lang/rustc_codegen_cranelift +[cg_gcc]: https://github.com/rust-lang/rustc_codegen_gcc diff --git a/src/doc/rustc-dev-guide/src/tests/fuchsia.md b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md index e96290b9215..b19d94d6ff7 100644 --- a/src/doc/rustc-dev-guide/src/tests/fuchsia.md +++ b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md @@ -4,6 +4,14 @@ million lines of Rust code.[^loc] It has caught a large number of [regressions] in the past and was subsequently included in CI. +## What to do if the Fuchsia job breaks? + +Please contact the [fuchsia][fuchsia-ping] ping group and ask them for help. + +```text +@rustbot ping fuchsia +``` + ## Building Fuchsia in CI Fuchsia builds as part of the suite of bors tests that run before a pull request @@ -32,7 +40,7 @@ using your local Rust toolchain. src/ci/docker/run.sh x86_64-fuchsia ``` -See the [Testing with Docker](docker.md) chapter for more details on how to run +See the [Testing with Docker](../docker.md) chapter for more details on how to run and debug jobs with Docker. Note that a Fuchsia checkout is *large* – as of this writing, a checkout and @@ -162,6 +170,7 @@ rustc book][platform-support]. [`public_configs`]: https://gn.googlesource.com/gn/+/main/docs/reference.md#var_public_configs [`//build/config:compiler`]: https://cs.opensource.google/fuchsia/fuchsia/+/main:build/config/BUILD.gn;l=121;drc=c26c473bef93b33117ae417893118907a026fec7 [build system]: https://fuchsia.dev/fuchsia-src/development/build/build_system +[fuchsia-ping]: ../../notification-groups/fuchsia.md [^loc]: As of June 2024, Fuchsia had about 2 million lines of first-party Rust code and a roughly equal amount of third-party code, as counted by tokei diff --git a/src/doc/rustc-dev-guide/src/tests/rust-for-linux.md b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/rust-for-linux.md index c674d1575b7..d549ec6fca5 100644 --- a/src/doc/rustc-dev-guide/src/tests/rust-for-linux.md +++ b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/rust-for-linux.md @@ -3,26 +3,7 @@ [Rust for Linux](https://rust-for-linux.com/) (RfL) is an effort for adding support for the Rust programming language into the Linux kernel. -## Building Rust for Linux in CI - -Rust for Linux builds as part of the suite of bors tests that run before a pull -request is merged. - -The workflow builds a stage1 sysroot of the Rust compiler, downloads the Linux -kernel, and tries to compile several Rust for Linux drivers and examples using -this sysroot. RfL uses several unstable compiler/language features, therefore -this workflow notifies us if a given compiler change would break it. - -If you are worried that a pull request might break the Rust for Linux builder -and want to test it out before submitting it to the bors queue, simply add this -line to your PR description: - -> try-job: x86_64-rust-for-linux - -Then when you `@bors try` it will pick the job that builds the Rust for Linux -integration. - -## What to do in case of failure +## What to do if the Rust for Linux job breaks? If a PR breaks the Rust for Linux CI job, then: @@ -48,4 +29,23 @@ ping group to ask for help: @rustbot ping rfl ``` -[rfl-ping]: ../notification-groups/rust-for-linux.md +## Building Rust for Linux in CI + +Rust for Linux builds as part of the suite of bors tests that run before a pull +request is merged. + +The workflow builds a stage1 sysroot of the Rust compiler, downloads the Linux +kernel, and tries to compile several Rust for Linux drivers and examples using +this sysroot. RfL uses several unstable compiler/language features, therefore +this workflow notifies us if a given compiler change would break it. + +If you are worried that a pull request might break the Rust for Linux builder +and want to test it out before submitting it to the bors queue, simply add this +line to your PR description: + +> try-job: x86_64-rust-for-linux + +Then when you `@bors try` it will pick the job that builds the Rust for Linux +integration. + +[rfl-ping]: ../../notification-groups/rust-for-linux.md diff --git a/src/doc/rustc-dev-guide/src/tests/ecosystem.md b/src/doc/rustc-dev-guide/src/tests/ecosystem.md index 08360140425..f4b93492e00 100644 --- a/src/doc/rustc-dev-guide/src/tests/ecosystem.md +++ b/src/doc/rustc-dev-guide/src/tests/ecosystem.md @@ -24,5 +24,5 @@ there aren't any significant regressions. We have CI jobs that build large open-source Rust projects that are used as regression tests in CI. Our integration jobs build the following projects: -- [Fuchsia](fuchsia.md) -- [Rust for Linux](rust-for-linux.md) +- [Fuchsia](./ecosystem-test-jobs/fuchsia.md) +- [Rust for Linux](./ecosystem-test-jobs/rust-for-linux.md) diff --git a/src/doc/rustc-dev-guide/src/tests/intro.md b/src/doc/rustc-dev-guide/src/tests/intro.md index ba44a969bf9..7bf30b106b4 100644 --- a/src/doc/rustc-dev-guide/src/tests/intro.md +++ b/src/doc/rustc-dev-guide/src/tests/intro.md @@ -38,7 +38,7 @@ directory, and `x` will essentially run `cargo test` on that package. Examples: | Command | Description | -| ----------------------------------------- | ------------------------------------- | +|-------------------------------------------|---------------------------------------| | `./x test library/std` | Runs tests on `std` only | | `./x test library/core` | Runs tests on `core` only | | `./x test compiler/rustc_data_structures` | Runs tests on `rustc_data_structures` | @@ -86,7 +86,7 @@ above. Examples: | Command | Description | -| ----------------------- | ------------------------------------------------------------------ | +|-------------------------|--------------------------------------------------------------------| | `./x fmt --check` | Checks formatting and exits with an error if formatting is needed. | | `./x fmt` | Runs rustfmt across the entire codebase. | | `./x test tidy --bless` | First runs rustfmt to format the codebase, then runs tidy checks. | @@ -155,6 +155,10 @@ chapter](ecosystem.md) for more details. A separate infrastructure is used for testing and tracking performance of the compiler. See the [Performance testing chapter](perf.md) for more details. +### Codegen backend testing + +See [Codegen backend testing](./codegen-backend-tests/intro.md). + ## Miscellaneous information There are some other useful testing-related info at [Misc info](misc.md). diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md index 1190c2646af..407862d48af 100644 --- a/src/doc/rustc-dev-guide/src/tests/ui.md +++ b/src/doc/rustc-dev-guide/src/tests/ui.md @@ -335,6 +335,9 @@ But for strict testing, try to use the `ERROR` annotation as much as possible, including `//~?` annotations for diagnostics without span. For compile time diagnostics `error-pattern` should very rarely be necessary. +Per-line annotations (`//~`) are still checked in tests using `error-pattern`, +to opt out of these checks in exceptional cases use `//@ compile-flags: --error-format=human`. + ### Error levels The error levels that you can have are: @@ -448,6 +451,14 @@ reasons, including: can alert the developer so they know that the associated issue has been fixed and can possibly be closed. +This directive takes comma-separated issue numbers as arguments, or `"unknown"`: + +- `//@ known-bug: #123, #456` (when the issues are on rust-lang/rust) +- `//@ known-bug: rust-lang/chalk#123456` + (allows arbitrary text before the `#`, which is useful when the issue is on another repo) +- `//@ known-bug: unknown` + (when there is no known issue yet; preferrably open one if it does not already exist) + Do not include [error annotations](#error-annotations) in a test with `known-bug`. The test should still include other normal directives and stdout/stderr files. diff --git a/src/doc/rustc-dev-guide/src/traits/caching.md b/src/doc/rustc-dev-guide/src/traits/caching.md index a9f20969b57..c44722a1d9a 100644 --- a/src/doc/rustc-dev-guide/src/traits/caching.md +++ b/src/doc/rustc-dev-guide/src/traits/caching.md @@ -61,7 +61,7 @@ to be pretty clearly safe and also still retains a very high hit rate **TODO**: it looks like `pick_candidate_cache` no longer exists. In general, is this section still accurate at all? -[`ParamEnv`]: ../param_env/param_env_summary.html +[`ParamEnv`]: ../typing_parameter_envs.html [`tcx`]: ../ty.html [#18290]: https://github.com/rust-lang/rust/issues/18290 [#22019]: https://github.com/rust-lang/rust/issues/22019 diff --git a/src/doc/rustc-dev-guide/src/traits/resolution.md b/src/doc/rustc-dev-guide/src/traits/resolution.md index 26eb7245886..c62b0593694 100644 --- a/src/doc/rustc-dev-guide/src/traits/resolution.md +++ b/src/doc/rustc-dev-guide/src/traits/resolution.md @@ -183,7 +183,7 @@ in that list. If so, it is considered satisfied. More precisely, we want to check whether there is a where-clause obligation that is for the same trait (or some subtrait) and which can match against the obligation. -[parameter environment]: ../param_env/param_env_summary.html +[parameter environment]: ../typing_parameter_envs.html Consider this simple example: diff --git a/src/doc/rustc-dev-guide/src/ty_module/binders.md b/src/doc/rustc-dev-guide/src/ty_module/binders.md index defb7cde514..71157eca9b1 100644 --- a/src/doc/rustc-dev-guide/src/ty_module/binders.md +++ b/src/doc/rustc-dev-guide/src/ty_module/binders.md @@ -40,7 +40,7 @@ We did not always explicitly track the set of bound vars introduced by each `Bin ``` Binder( fn(&'^1_0 &'^1 T/#0), - &[BoundVariarbleKind::Region(...)], + &[BoundVariableKind::Region(...)], ) ``` This would cause all kinds of issues as the region `'^1_0` refers to a binder at a higher level than the outermost binder i.e. it is an escaping bound var. The `'^1` region (also writeable as `'^0_1`) is also ill formed as the binder it refers to does not introduce a second parameter. Modern day rustc will ICE when constructing this binder due to both of those regions, in the past we would have simply allowed this to work and then ran into issues in other parts of the codebase. diff --git a/src/doc/rustc-dev-guide/src/typing_parameter_envs.md b/src/doc/rustc-dev-guide/src/typing_parameter_envs.md new file mode 100644 index 00000000000..757296d1f65 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/typing_parameter_envs.md @@ -0,0 +1,206 @@ +# Typing/Parameter Environments + +<!-- toc --> + +## Typing Environments + +When interacting with the type system there are a few variables to consider that can affect the results of trait solving. The the set of in-scope where clauses, and what phase of the compiler type system operations are being performed in (the [`ParamEnv`][penv] and [`TypingMode`][tmode] structs respectively). + +When an environment to perform type system operations in has not yet been created, the [`TypingEnv`][tenv] can be used to bundle all of the external context required into a single type. + +Once a context to perform type system operations in has been created (e.g. an [`ObligationCtxt`][ocx] or [`FnCtxt`][fnctxt]) a `TypingEnv` is typically not stored anywhere as only the `TypingMode` is a property of the whole environment, whereas different `ParamEnv`s can be used on a per-goal basis. + +[ocx]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/struct.ObligationCtxt.html +[fnctxt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/fn_ctxt/struct.FnCtxt.html + +## Parameter Environemnts + +### What is a `ParamEnv` + +The [`ParamEnv`][penv] is a list of in-scope where-clauses, it typically corresponds to a specific item's where clauses. Some clauses are not explicitly written but are instead are implicitly added in the [`predicates_of`][predicates_of] query, such as `ConstArgHasType` or (some) implied bounds. + +In most cases `ParamEnv`s are initially created via the [`param_env` query][query] which returns a `ParamEnv` derived from the provided item's where clauses. A `ParamEnv` can also be created with arbitrary sets of clauses that are not derived from a specific item, such as in [`compare_method_predicate_entailment`][method_pred_entailment] where we create a hybrid `ParamEnv` consisting of the impl's where clauses and the trait definition's function's where clauses. + +--- + +If we have a function such as: +```rust +// `foo` would have a `ParamEnv` of: +// `[T: Sized, T: Trait, <T as Trait>::Assoc: Clone]` +fn foo<T: Trait>() +where + <T as Trait>::Assoc: Clone, +{} +``` +If we were conceptually inside of `foo` (for example, type-checking or linting it) we would use this `ParamEnv` everywhere that we interact with the type system. This would allow things such as normalization (TODO: write a chapter about normalization and link it), evaluating generic constants, and proving where clauses/goals, to rely on `T` being sized, implementing `Trait`, etc. + +A more concrete example: +```rust +// `foo` would have a `ParamEnv` of: +// `[T: Sized, T: Clone]` +fn foo<T: Clone>(a: T) { + // when typechecking `foo` we require all the where clauses on `requires_clone` + // to hold in order for it to be legal to call. This means we have to + // prove `T: Clone`. As we are type checking `foo` we use `foo`'s + // environment when trying to check that `T: Clone` holds. + // + // Trying to prove `T: Clone` with a `ParamEnv` of `[T: Sized, T: Clone]` + // will trivially succeed as bound we want to prove is in our environment. + requires_clone(a); +} +``` + +Or alternatively an example that would not compile: +```rust +// `foo2` would have a `ParamEnv` of: +// `[T: Sized]` +fn foo2<T>(a: T) { + // When typechecking `foo2` we attempt to prove `T: Clone`. + // As we are type checking `foo2` we use `foo2`'s environment + // when trying to prove `T: Clone`. + // + // Trying to prove `T: Clone` with a `ParamEnv` of `[T: Sized]` will + // fail as there is nothing in the environment telling the trait solver + // that `T` implements `Clone` and there exists no user written impl + // that could apply. + requires_clone(a); +} +``` + +[predicates_of]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/collect/predicates_of/fn.predicates_of.html +[method_pred_entailment]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/compare_impl_item/fn.compare_method_predicate_entailment.html +[query]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.param_env + +### Acquiring a `ParamEnv` + +Using the wrong [`ParamEnv`][penv] when interacting with the type system can lead to ICEs, illformed programs compiling, or erroing when we shouldn't. See [#82159](https://github.com/rust-lang/rust/pull/82159) and [#82067](https://github.com/rust-lang/rust/pull/82067) as examples of PRs that modified the compiler to use the correct param env and in the process fixed ICEs. + +In the large majority of cases, when a `ParamEnv` is required it either already exists somewhere in scope, or above in the call stack and should be passed down. A non exhaustive list of places where you might find an existing `ParamEnv`: +- During typeck `FnCtxt` has a [`param_env` field][fnctxt_param_env] +- When writing late lints the `LateContext` has a [`param_env` field][latectxt_param_env] +- During well formedness checking the `WfCheckingCtxt` has a [`param_env` field][wfckctxt_param_env] +- The `TypeChecker` used for MIR Typeck has a [`param_env` field][mirtypeck_param_env] +- In the next-gen trait solver all `Goal`s have a [`param_env` field][goal_param_env] specifying what environment to prove the goal in +- When editing an existing [`TypeRelation`][typerelation] if it implements [`PredicateEmittingRelation`][predicate_emitting_relation] then a [`param_env` method][typerelation_param_env] will be available. + +If you aren't sure if there's a `ParamEnv` in scope somewhere that can be used it can be worth opening a thread in the [`#t-compiler/help`][compiler_help] zulip stream where someone may be able to point out where a `ParamEnv` can be acquired from. + +Manually constructing a `ParamEnv` is typically only needed at the start of some kind of top level analysis (e.g. hir typeck or borrow checking). In such cases there are three ways it can be done: +- Calling the [`tcx.param_env(def_id)` query][param_env_query] which returns the environment associated with a given definition. +- Creating an empty environment with [`ParamEnv::empty`][env_empty]. +- Using [`ParamEnv::new`][param_env_new] to construct an env with an arbitrary set of where clauses. Then calling [`traits::normalize_param_env_or_error`][normalize_env_or_error] to handle normalizing and elaborating all the where clauses in the env. + +Using the `param_env` query is by far the most common way to construct a `ParamEnv` as most of the time the compiler is performing an analysis as part of some specific definition. + +Creating an empty environment with `ParamEnv::empty` is typically only done either in codegen (indirectly via [`TypingEnv::fully_monomorphized`][tenv_mono]), or as part of some analysis that do not expect to ever encounter generic parameters (e.g. various parts of coherence/orphan check). + +Creating an env from an arbitrary set of where clauses is usually unnecessary and should only be done if the environment you need does not correspond to an actual item in the source code (e.g. [`compare_method_predicate_entailment`][method_pred_entailment]). + +[param_env_new]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html#method.new +[normalize_env_or_error]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/fn.normalize_param_env_or_error.html +[fnctxt_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/fn_ctxt/struct.FnCtxt.html#structfield.param_env +[latectxt_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/context/struct.LateContext.html#structfield.param_env +[wfckctxt_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/wfcheck/struct.WfCheckingCtxt.html#structfield.param_env +[goal_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/infer/canonical/ir/solve/struct.Goal.html#structfield.param_env +[typerelation_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/infer/trait.PredicateEmittingRelation.html#tymethod.param_env +[typerelation]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/relate/trait.TypeRelation.html +[mirtypeck_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/type_check/struct.TypeChecker.html#structfield.param_env +[env_empty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html#method.empty +[param_env_query]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/fn_ctxt/struct.FnCtxt.html#structfield.param_env +[method_pred_entailment]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/compare_impl_item/fn.compare_method_predicate_entailment.html +[predicate_emitting_relation]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/relate/combine/trait.PredicateEmittingRelation.html +[tenv_mono]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypingEnv.html#method.fully_monomorphized +[compiler_help]: https://rust-lang.zulipchat.com/#narrow/channel/182449-t-compiler.2Fhelp + +### How are `ParamEnv`s constructed + +Creating a [`ParamEnv`][pe] is more complicated than simply using the list of where clauses defined on an item as written by the user. We need to both elaborate supertraits into the env and fully normalize all aliases. This logic is handled by [`traits::normalize_param_env_or_error`][normalize_env_or_error] (even though it does not mention anything about elaboration). + +#### Elaborating supertraits + +When we have a function such as `fn foo<T: Copy>()` we would like to be able to prove `T: Clone` inside of the function as the `Copy` trait has a `Clone` supertrait. Constructing a `ParamEnv` looks at all of the trait bounds in the env and explicitly adds new where clauses to the `ParamEnv` for any supertraits found on the traits. + +A concrete example would be the following function: +```rust +trait Trait: SuperTrait {} +trait SuperTrait: SuperSuperTrait {} + +// `bar`'s unelaborated `ParamEnv` would be: +// `[T: Sized, T: Copy, T: Trait]` +fn bar<T: Copy + Trait>(a: T) { + requires_impl(a); +} + +fn requires_impl<T: Clone + SuperSuperTrait>(a: T) {} +``` + +If we did not elaborate the env then the `requires_impl` call would fail to typecheck as we would not be able to prove `T: Clone` or `T: SuperSuperTrait`. In practice we elaborate the env which means that `bar`'s `ParamEnv` is actually: +`[T: Sized, T: Copy, T: Clone, T: Trait, T: SuperTrait, T: SuperSuperTrait]` +This allows us to prove `T: Clone` and `T: SuperSuperTrait` when type checking `bar`. + +The `Clone` trait has a `Sized` supertrait however we do not end up with two `T: Sized` bounds in the env (one for the supertrait and one for the implicitly added `T: Sized` bound) as the elaboration process (implemented via [`util::elaborate`][elaborate]) deduplicates where clauses. + +A side effect of this is that even if no actual elaboration of supertraits takes place, the existing where clauses in the env are _also_ deduplicated. See the following example: +```rust +trait Trait {} +// The unelaborated `ParamEnv` would be: +// `[T: Sized, T: Trait, T: Trait]` +// but after elaboration it would be: +// `[T: Sized, T: Trait]` +fn foo<T: Trait + Trait>() {} +``` + +The [next-gen trait solver][next-gen-solver] also requires this elaboration to take place. + +[elaborate]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/traits/util/fn.elaborate.html +[next-gen-solver]: ./solve/trait-solving.md + +#### Normalizing all bounds + +In the old trait solver the where clauses stored in `ParamEnv` are required to be fully normalized as otherwise the trait solver will not function correctly. A concrete example of needing to normalize the `ParamEnv` is the following: +```rust +trait Trait<T> { + type Assoc; +} + +trait Other { + type Bar; +} + +impl<T> Other for T { + type Bar = u32; +} + +// `foo`'s unnormalized `ParamEnv` would be: +// `[T: Sized, U: Sized, U: Trait<T::Bar>]` +fn foo<T, U>(a: U) +where + U: Trait<<T as Other>::Bar>, +{ + requires_impl(a); +} + +fn requires_impl<U: Trait<u32>>(_: U) {} +``` + +As humans we can tell that `<T as Other>::Bar` is equal to `u32` so the trait bound on `U` is equivalent to `U: Trait<u32>`. In practice trying to prove `U: Trait<u32>` in the old solver in this environment would fail as it is unable to determine that `<T as Other>::Bar` is equal to `u32`. + +To work around this we normalize `ParamEnv`'s after constructing them so that `foo`'s `ParamEnv` is actually: `[T: Sized, U: Sized, U: Trait<u32>]` which means the trait solver is now able to use the `U: Trait<u32>` in the `ParamEnv` to determine that the trait bound `U: Trait<u32>` holds. + +This workaround does not work in all cases as normalizing associated types requires a `ParamEnv` which introduces a bootstrapping problem. We need a normalized `ParamEnv` in order for normalization to give correct results, but we need to normalize to get that `ParamEnv`. Currently we normalize the `ParamEnv` once using the unnormalized param env and it tends to give okay results in practice even though there are some examples where this breaks ([example]). + +In the next-gen trait solver the requirement for all where clauses in the `ParamEnv` to be fully normalized is not present and so we do not normalize when constructing `ParamEnv`s. + +[example]: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=e6933265ea3e84eaa47019465739992c +[pe]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html +[normalize_env_or_error]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/fn.normalize_param_env_or_error.html + +## Typing Modes + +Depending on what context we are performing type system operations in, different behaviour may be required. For example during coherence there are stronger requirements about when we can consider goals to not hold or when we can consider types to be unequal. + +Tracking which "phase" of the compiler type system operations are being performed in is done by the [`TypingMode`][tenv] enum. The documentation on the `TypingMode` enum is quite good so instead of repeating it here verbatim we would recommend reading the API documentation directly. + +[penv]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html +[tenv]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/infer_ctxt/enum.TypingMode.html +[tmode]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.TypingMode.html diff --git a/src/doc/unstable-book/src/language-features/import-trait-associated-functions.md b/src/doc/unstable-book/src/language-features/import-trait-associated-functions.md new file mode 100644 index 00000000000..0ae5915361e --- /dev/null +++ b/src/doc/unstable-book/src/language-features/import-trait-associated-functions.md @@ -0,0 +1,22 @@ +# import_trait_associated_functions + +The tracking issue for this feature is: [#134691] + +[#134691]: https://github.com/rust-lang/rust/issues/134691 + +------------------------ + +This feature allows importing associated functions and constants from traits and then using them like regular items. + +```rust +#![feature(import_trait_associated_functions)] + +use std::ops::Add::add; + +fn main() { + let numbers = vec![1, 2, 3, 4, 5, 6]; + let sum = numbers.into_iter().reduce(add); // instead of `.reduce(Add:add)` + + assert_eq!(sum, Some(21)); +} +``` diff --git a/src/librustdoc/doctest/runner.rs b/src/librustdoc/doctest/runner.rs index f891505d2a6..e34b8a53b07 100644 --- a/src/librustdoc/doctest/runner.rs +++ b/src/librustdoc/doctest/runner.rs @@ -144,7 +144,6 @@ let tests = {{ {ids} tests }}; -let test_marker = std::ffi::OsStr::new(__doctest_mod::RUN_OPTION); let test_args = &[{test_args}]; const ENV_BIN: &'static str = \"RUSTDOC_DOCTEST_BIN_PATH\"; diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 0ea4d8f1e39..aa8df35258d 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1446,6 +1446,9 @@ so that we can apply CSS-filters to change the arrow color in themes */ align-items: center; cursor: pointer; } +.setting-check input { + flex-shrink: 0, +} .setting-radio input:checked { box-shadow: inset 0 0 0 3px var(--main-background-color); diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index f8f670f575b..761282bde7c 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -5,7 +5,7 @@ use std::ops; use rustc_hir as hir; use rustc_lint::builtin::MISSING_DOCS; -use rustc_middle::lint::LintLevelSource; +use rustc_middle::lint::{LevelAndSource, LintLevelSource}; use rustc_session::lint; use rustc_span::FileName; use serde::Serialize; @@ -216,7 +216,8 @@ impl DocVisitor<'_> for CoverageCalculator<'_, '_> { let has_doc_example = tests.found_tests != 0; let hir_id = DocContext::as_local_hir_id(self.ctx.tcx, i.item_id).unwrap(); - let (level, source) = self.ctx.tcx.lint_level_at_node(MISSING_DOCS, hir_id); + let LevelAndSource { level, src, .. } = + self.ctx.tcx.lint_level_at_node(MISSING_DOCS, hir_id); // In case we have: // @@ -251,7 +252,7 @@ impl DocVisitor<'_> for CoverageCalculator<'_, '_> { // unless the user had an explicit `allow`. // let should_have_docs = !should_be_ignored - && (level != lint::Level::Allow || matches!(source, LintLevelSource::Default)); + && (level != lint::Level::Allow || matches!(src, LintLevelSource::Default)); if let Some(span) = i.span(self.ctx.tcx) { let filename = span.filename(self.ctx.sess()); diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs index 0fefd13f763..70dbb944d4c 100644 --- a/src/librustdoc/passes/check_doc_test_visibility.rs +++ b/src/librustdoc/passes/check_doc_test_visibility.rs @@ -6,7 +6,7 @@ //! - PRIVATE_DOC_TESTS: this lint is **STABLE** and looks for private items with doctests. use rustc_hir as hir; -use rustc_middle::lint::LintLevelSource; +use rustc_middle::lint::{LevelAndSource, LintLevelSource}; use rustc_session::lint; use tracing::debug; @@ -107,11 +107,11 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) - { return false; } - let (level, source) = cx.tcx.lint_level_at_node( + let LevelAndSource { level, src, .. } = cx.tcx.lint_level_at_node( crate::lint::MISSING_DOC_CODE_EXAMPLES, cx.tcx.local_def_id_to_hir_id(def_id), ); - level != lint::Level::Allow || matches!(source, LintLevelSource::Default) + level != lint::Level::Allow || matches!(src, LintLevelSource::Default) } pub(crate) fn look_for_tests(cx: &DocContext<'_>, dox: &str, item: &Item) { diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs index 48b5d4da888..7bb5dbee126 100644 --- a/src/tools/clippy/clippy_lints/src/booleans.rs +++ b/src/tools/clippy/clippy_lints/src/booleans.rs @@ -199,7 +199,7 @@ fn check_simplify_not(cx: &LateContext<'_>, msrv: Msrv, expr: &Expr<'_>) { && !expr.span.from_expansion() && !inner.span.from_expansion() && let Some(suggestion) = simplify_not(cx, msrv, inner) - && cx.tcx.lint_level_at_node(NONMINIMAL_BOOL, expr.hir_id).0 != Level::Allow + && cx.tcx.lint_level_at_node(NONMINIMAL_BOOL, expr.hir_id).level != Level::Allow { use clippy_utils::sugg::{Sugg, has_enclosing_paren}; let maybe_par = if let Some(sug) = Sugg::hir_opt(cx, inner) { @@ -605,7 +605,7 @@ impl<'tcx> NonminimalBoolVisitor<'_, 'tcx> { } } let nonminimal_bool_lint = |mut suggestions: Vec<_>| { - if self.cx.tcx.lint_level_at_node(NONMINIMAL_BOOL, e.hir_id).0 != Level::Allow { + if self.cx.tcx.lint_level_at_node(NONMINIMAL_BOOL, e.hir_id).level != Level::Allow { suggestions.sort(); span_lint_hir_and_then( self.cx, diff --git a/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs b/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs index 53c24a3faf1..d1a8590c59b 100644 --- a/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs +++ b/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs @@ -69,7 +69,7 @@ impl EarlyLintPass for DisallowedScriptIdents { // Implementation is heavily inspired by the implementation of [`non_ascii_idents`] lint: // https://github.com/rust-lang/rust/blob/master/compiler/rustc_lint/src/non_ascii_idents.rs - let check_disallowed_script_idents = cx.builder.lint_level(DISALLOWED_SCRIPT_IDENTS).0 != Level::Allow; + let check_disallowed_script_idents = cx.builder.lint_level(DISALLOWED_SCRIPT_IDENTS).level != Level::Allow; if !check_disallowed_script_idents { return; } diff --git a/src/tools/clippy/clippy_lints/src/duplicate_mod.rs b/src/tools/clippy/clippy_lints/src/duplicate_mod.rs index 243c99a19ce..ce551a64d99 100644 --- a/src/tools/clippy/clippy_lints/src/duplicate_mod.rs +++ b/src/tools/clippy/clippy_lints/src/duplicate_mod.rs @@ -2,6 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use rustc_ast::ast::{Crate, Inline, Item, ItemKind, ModKind}; use rustc_errors::MultiSpan; use rustc_lint::{EarlyContext, EarlyLintPass, Level, LintContext}; +use rustc_middle::lint::LevelAndSource; use rustc_session::impl_lint_pass; use rustc_span::{FileName, Span}; use std::collections::BTreeMap; @@ -45,11 +46,10 @@ declare_clippy_lint! { "file loaded as module multiple times" } -#[derive(PartialOrd, Ord, PartialEq, Eq)] struct Modules { local_path: PathBuf, spans: Vec<Span>, - lint_levels: Vec<Level>, + lint_levels: Vec<LevelAndSource>, } #[derive(Default)] @@ -95,11 +95,11 @@ impl EarlyLintPass for DuplicateMod { .iter() .zip(lint_levels) .filter_map(|(span, lvl)| { - if let Some(id) = lvl.get_expectation_id() { + if let Some(id) = lvl.lint_id { cx.fulfill_expectation(id); } - (!matches!(lvl, Level::Allow | Level::Expect(_))).then_some(*span) + (!matches!(lvl.level, Level::Allow | Level::Expect)).then_some(*span) }) .collect(); diff --git a/src/tools/clippy/clippy_lints/src/format_push_string.rs b/src/tools/clippy/clippy_lints/src/format_push_string.rs index 68cc50f3939..b64d608c0c7 100644 --- a/src/tools/clippy/clippy_lints/src/format_push_string.rs +++ b/src/tools/clippy/clippy_lints/src/format_push_string.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher; use clippy_utils::ty::is_type_lang_item; -use rustc_hir::{BinOpKind, Expr, ExprKind, LangItem, MatchSource}; +use rustc_hir::{AssignOpKind, Expr, ExprKind, LangItem, MatchSource}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; use rustc_span::sym; @@ -77,7 +77,7 @@ impl<'tcx> LateLintPass<'tcx> for FormatPushString { return; } }, - ExprKind::AssignOp(op, left, arg) if op.node == BinOpKind::Add && is_string(cx, left) => arg, + ExprKind::AssignOp(op, left, arg) if op.node == AssignOpKind::AddAssign && is_string(cx, left) => arg, _ => return, }; if is_format(cx, arg) { diff --git a/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs index 41d2b18803d..185fc2aa2d4 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs @@ -5,7 +5,7 @@ use clippy_utils::source::snippet_with_context; use rustc_ast::ast::{LitIntType, LitKind}; use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; -use rustc_hir::{BinOpKind, Block, Expr, ExprKind, Stmt, StmtKind}; +use rustc_hir::{AssignOpKind, BinOpKind, Block, Expr, ExprKind, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{IntTy, Ty, UintTy}; use rustc_session::declare_lint_pass; @@ -68,7 +68,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingAdd { && ex.span.ctxt() == ctxt && expr1.span.ctxt() == ctxt && clippy_utils::SpanlessEq::new(cx).eq_expr(l, target) - && BinOpKind::Add == op1.node + && AssignOpKind::AddAssign == op1.node && let ExprKind::Lit(lit) = value.kind && let LitKind::Int(Pu128(1), LitIntType::Unsuffixed) = lit.node && block.expr.is_none() diff --git a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs index cbc3e2ccd5b..5d7d3ae3f24 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs @@ -8,7 +8,7 @@ use clippy_utils::{ use rustc_ast::ast::LitKind; use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; -use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind, QPath}; +use rustc_hir::{AssignOpKind, BinOp, BinOpKind, Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; use rustc_span::Span; @@ -366,7 +366,7 @@ fn subtracts_one<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<&'a Exp match peel_blocks_with_stmt(expr).kind { ExprKind::AssignOp(ref op1, target, value) => { // Check if literal being subtracted is one - (BinOpKind::Sub == op1.node && is_integer_literal(value, 1)).then_some(target) + (AssignOpKind::SubAssign == op1.node && is_integer_literal(value, 1)).then_some(target) }, ExprKind::Assign(target, value, _) => { if let ExprKind::Binary(ref op1, left1, right1) = value.kind diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index cc3d972f017..3fe3cd67e16 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -408,9 +408,9 @@ mod zombie_processes; use clippy_config::{Conf, get_configuration_metadata, sanitize_explanation}; use clippy_utils::macros::FormatArgsStorage; -use utils::attr_collector::{AttrCollector, AttrStorage}; use rustc_data_structures::fx::FxHashSet; use rustc_lint::{Lint, LintId}; +use utils::attr_collector::{AttrCollector, AttrStorage}; /// Register all pre expansion lints /// diff --git a/src/tools/clippy/clippy_lints/src/loops/utils.rs b/src/tools/clippy/clippy_lints/src/loops/utils.rs index a5185d38e7c..3c6fbef2bda 100644 --- a/src/tools/clippy/clippy_lints/src/loops/utils.rs +++ b/src/tools/clippy/clippy_lints/src/loops/utils.rs @@ -3,7 +3,9 @@ use clippy_utils::{get_parent_expr, is_integer_const, path_to_local, path_to_loc use rustc_ast::ast::{LitIntType, LitKind}; use rustc_errors::Applicability; use rustc_hir::intravisit::{Visitor, walk_expr, walk_local}; -use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, HirId, HirIdMap, LetStmt, Mutability, PatKind}; +use rustc_hir::{ + AssignOpKind, BorrowKind, Expr, ExprKind, HirId, HirIdMap, LetStmt, Mutability, PatKind +}; use rustc_lint::LateContext; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{self, Ty}; @@ -58,7 +60,7 @@ impl<'tcx> Visitor<'tcx> for IncrementVisitor<'_, 'tcx> { match parent.kind { ExprKind::AssignOp(op, lhs, rhs) => { if lhs.hir_id == expr.hir_id { - *state = if op.node == BinOpKind::Add + *state = if op.node == AssignOpKind::AddAssign && is_integer_const(self.cx, rhs, 1) && *state == IncrementVisitorVarState::Initial && self.depth == 0 diff --git a/src/tools/clippy/clippy_lints/src/macro_use.rs b/src/tools/clippy/clippy_lints/src/macro_use.rs index b712b351d06..98ad1f6a160 100644 --- a/src/tools/clippy/clippy_lints/src/macro_use.rs +++ b/src/tools/clippy/clippy_lints/src/macro_use.rs @@ -153,9 +153,15 @@ impl LateLintPass<'_> for MacroUseImports { [] | [_] => return, [root, item] => { if !check_dup.contains(&(*item).to_string()) { - used.entry(((*root).to_string(), span, hir_id)) - .or_insert_with(Vec::new) - .push((*item).to_string()); + used.entry(( + (*root).to_string(), + span, + hir_id.local_id, + cx.tcx.def_path_hash(hir_id.owner.def_id.into()), + )) + .or_insert_with(|| (vec![], hir_id)) + .0 + .push((*item).to_string()); check_dup.push((*item).to_string()); } }, @@ -171,15 +177,27 @@ impl LateLintPass<'_> for MacroUseImports { } }) .collect::<Vec<_>>(); - used.entry(((*root).to_string(), span, hir_id)) - .or_insert_with(Vec::new) - .push(filtered.join("::")); + used.entry(( + (*root).to_string(), + span, + hir_id.local_id, + cx.tcx.def_path_hash(hir_id.owner.def_id.into()), + )) + .or_insert_with(|| (vec![], hir_id)) + .0 + .push(filtered.join("::")); check_dup.extend(filtered); } else { let rest = rest.to_vec(); - used.entry(((*root).to_string(), span, hir_id)) - .or_insert_with(Vec::new) - .push(rest.join("::")); + used.entry(( + (*root).to_string(), + span, + hir_id.local_id, + cx.tcx.def_path_hash(hir_id.owner.def_id.into()), + )) + .or_insert_with(|| (vec![], hir_id)) + .0 + .push(rest.join("::")); check_dup.extend(rest.iter().map(ToString::to_string)); } }, @@ -190,7 +208,7 @@ impl LateLintPass<'_> for MacroUseImports { // If mac_refs is not empty we have encountered an import we could not handle // such as `std::prelude::v1::foo` or some other macro that expands to an import. if self.mac_refs.is_empty() { - for ((root, span, hir_id), path) in used { + for ((root, span, ..), (path, hir_id)) in used { let import = if let [single] = &path[..] { format!("{root}::{single}") } else { diff --git a/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs b/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs index d78299fe08b..cdd6f4e5b03 100644 --- a/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs +++ b/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs @@ -10,7 +10,7 @@ use rustc_ast::{LitKind, RangeLimits}; use rustc_data_structures::packed::Pu128; use rustc_data_structures::unhash::UnindexMap; use rustc_errors::{Applicability, Diag}; -use rustc_hir::{BinOp, Block, Body, Expr, ExprKind, UnOp}; +use rustc_hir::{BinOpKind, Block, Body, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; use rustc_span::source_map::Spanned; @@ -97,7 +97,7 @@ enum LengthComparison { /// /// E.g. for `v.len() > 5` this returns `Some((LengthComparison::IntLessThanLength, 5, v.len()))` fn len_comparison<'hir>( - bin_op: BinOp, + bin_op: BinOpKind, left: &'hir Expr<'hir>, right: &'hir Expr<'hir>, ) -> Option<(LengthComparison, usize, &'hir Expr<'hir>)> { @@ -112,7 +112,7 @@ fn len_comparison<'hir>( // normalize comparison, `v.len() > 4` becomes `4 < v.len()` // this simplifies the logic a bit - let (op, left, right) = normalize_comparison(bin_op.node, left, right)?; + let (op, left, right) = normalize_comparison(bin_op, left, right)?; match (op, left.kind, right.kind) { (Rel::Lt, int_lit_pat!(left), _) => Some((LengthComparison::IntLessThanLength, left as usize, right)), (Rel::Lt, _, int_lit_pat!(right)) => Some((LengthComparison::LengthLessThanInt, right as usize, left)), @@ -138,7 +138,7 @@ fn assert_len_expr<'hir>( && let ExprKind::Unary(UnOp::Not, condition) = &cond.kind && let ExprKind::Binary(bin_op, left, right) = &condition.kind - && let Some((cmp, asserted_len, slice_len)) = len_comparison(*bin_op, left, right) + && let Some((cmp, asserted_len, slice_len)) = len_comparison(bin_op.node, left, right) && let ExprKind::MethodCall(method, recv, [], _) = &slice_len.kind && cx.typeck_results().expr_ty_adjusted(recv).peel_refs().is_slice() && method.ident.name == sym::len diff --git a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs index be728e6c8b7..fbd287f5285 100644 --- a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs +++ b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs @@ -261,10 +261,11 @@ fn check_expr<'tcx>(vis: &mut ReadVisitor<'_, 'tcx>, expr: &'tcx Expr<'_>) -> St | ExprKind::Assign(..) | ExprKind::Index(..) | ExprKind::Repeat(_, _) - | ExprKind::Struct(_, _, _) => { + | ExprKind::Struct(_, _, _) + | ExprKind::AssignOp(_, _, _) => { walk_expr(vis, expr); }, - ExprKind::Binary(op, _, _) | ExprKind::AssignOp(op, _, _) => { + ExprKind::Binary(op, _, _) => { if op.node == BinOpKind::And || op.node == BinOpKind::Or { // x && y and x || y always evaluate x first, so these are // strictly sequenced. diff --git a/src/tools/clippy/clippy_lints/src/module_style.rs b/src/tools/clippy/clippy_lints/src/module_style.rs index 676d608eb31..7287193326f 100644 --- a/src/tools/clippy/clippy_lints/src/module_style.rs +++ b/src/tools/clippy/clippy_lints/src/module_style.rs @@ -73,8 +73,8 @@ impl_lint_pass!(ModStyle => [MOD_MODULE_FILES, SELF_NAMED_MODULE_FILES]); impl EarlyLintPass for ModStyle { fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &ast::Crate) { - if cx.builder.lint_level(MOD_MODULE_FILES).0 == Level::Allow - && cx.builder.lint_level(SELF_NAMED_MODULE_FILES).0 == Level::Allow + if cx.builder.lint_level(MOD_MODULE_FILES).level == Level::Allow + && cx.builder.lint_level(SELF_NAMED_MODULE_FILES).level == Level::Allow { return; } diff --git a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs index 08fcd17e555..a78a342d4fe 100644 --- a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs +++ b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs @@ -335,9 +335,12 @@ impl<'tcx> LateLintPass<'tcx> for ArithmeticSideEffects { return; } match &expr.kind { - hir::ExprKind::AssignOp(op, lhs, rhs) | hir::ExprKind::Binary(op, lhs, rhs) => { + hir::ExprKind::Binary(op, lhs, rhs) => { self.manage_bin_ops(cx, expr, op.node, lhs, rhs); }, + hir::ExprKind::AssignOp(op, lhs, rhs) => { + self.manage_bin_ops(cx, expr, op.node.into(), lhs, rhs); + }, hir::ExprKind::MethodCall(ps, receiver, args, _) => { self.manage_method_call(args, cx, expr, ps, receiver); }, diff --git a/src/tools/clippy/clippy_lints/src/operators/mod.rs b/src/tools/clippy/clippy_lints/src/operators/mod.rs index f758d08d366..d32c062cf56 100644 --- a/src/tools/clippy/clippy_lints/src/operators/mod.rs +++ b/src/tools/clippy/clippy_lints/src/operators/mod.rs @@ -913,9 +913,10 @@ impl<'tcx> LateLintPass<'tcx> for Operators { ); }, ExprKind::AssignOp(op, lhs, rhs) => { - self.arithmetic_context.check_binary(cx, e, op.node, lhs, rhs); - misrefactored_assign_op::check(cx, e, op.node, lhs, rhs); - modulo_arithmetic::check(cx, e, op.node, lhs, rhs, false); + let bin_op = op.node.into(); + self.arithmetic_context.check_binary(cx, e, bin_op, lhs, rhs); + misrefactored_assign_op::check(cx, e, bin_op, lhs, rhs); + modulo_arithmetic::check(cx, e, bin_op, lhs, rhs, false); }, ExprKind::Assign(lhs, rhs, _) => { assign_op_pattern::check(cx, e, lhs, rhs); diff --git a/src/tools/clippy/clippy_lints/src/raw_strings.rs b/src/tools/clippy/clippy_lints/src/raw_strings.rs index c6e6e782f9d..6a79cae32a5 100644 --- a/src/tools/clippy/clippy_lints/src/raw_strings.rs +++ b/src/tools/clippy/clippy_lints/src/raw_strings.rs @@ -138,7 +138,7 @@ impl RawStrings { ); }, ); - if !matches!(cx.get_lint_level(NEEDLESS_RAW_STRINGS), rustc_lint::Allow) { + if !matches!(cx.get_lint_level(NEEDLESS_RAW_STRINGS).level, rustc_lint::Allow) { return; } } diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs index 4cb73df8b48..d8e8ead2912 100644 --- a/src/tools/clippy/clippy_lints/src/returns.rs +++ b/src/tools/clippy/clippy_lints/src/returns.rs @@ -404,7 +404,7 @@ fn check_final_expr<'tcx>( match cx.tcx.hir_attrs(expr.hir_id) { [] => {}, [attr] => { - if matches!(Level::from_attr(attr), Some(Level::Expect(_))) + if matches!(Level::from_attr(attr), Some((Level::Expect, _))) && let metas = attr.meta_item_list() && let Some(lst) = metas && let [MetaItemInner::MetaItem(meta_item), ..] = lst.as_slice() diff --git a/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs b/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs index fb426e91bf0..56bd8fefdb4 100644 --- a/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs +++ b/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs @@ -5,6 +5,7 @@ use core::ops::ControlFlow; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; +use rustc_span::Span; declare_clippy_lint! { /// ### What it does @@ -56,8 +57,27 @@ declare_lint_pass!(SuspiciousImpl => [SUSPICIOUS_ARITHMETIC_IMPL, SUSPICIOUS_OP_ impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { - if let hir::ExprKind::Binary(binop, _, _) | hir::ExprKind::AssignOp(binop, ..) = expr.kind - && let Some((binop_trait_lang, op_assign_trait_lang)) = binop_traits(binop.node) + match expr.kind { + hir::ExprKind::Binary(op, _, _) => { + self.check_expr_inner(cx, expr, op.node, op.span); + } + hir::ExprKind::AssignOp(op, _, _) => { + self.check_expr_inner(cx, expr, op.node.into(), op.span); + } + _ => {} + } + } +} + +impl<'tcx> SuspiciousImpl { + fn check_expr_inner( + &mut self, + cx: &LateContext<'tcx>, + expr: &'tcx hir::Expr<'_>, + binop: hir::BinOpKind, + span: Span, + ) { + if let Some((binop_trait_lang, op_assign_trait_lang)) = binop_traits(binop) && let Some(binop_trait_id) = cx.tcx.lang_items().get(binop_trait_lang) && let Some(op_assign_trait_id) = cx.tcx.lang_items().get(op_assign_trait_lang) @@ -82,10 +102,10 @@ impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl { span_lint( cx, lint, - binop.span, + span, format!( "suspicious use of `{}` in `{}` impl", - binop.node.as_str(), + binop.as_str(), cx.tcx.item_name(trait_id) ), ); diff --git a/src/tools/clippy/clippy_lints/src/swap.rs b/src/tools/clippy/clippy_lints/src/swap.rs index 7176d533b61..0337b74b4b1 100644 --- a/src/tools/clippy/clippy_lints/src/swap.rs +++ b/src/tools/clippy/clippy_lints/src/swap.rs @@ -10,7 +10,7 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_hir::intravisit::{Visitor, walk_expr}; use rustc_errors::Applicability; -use rustc_hir::{BinOpKind, Block, Expr, ExprKind, LetStmt, PatKind, QPath, Stmt, StmtKind}; +use rustc_hir::{AssignOpKind, Block, Expr, ExprKind, LetStmt, PatKind, QPath, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::ty; use rustc_session::declare_lint_pass; @@ -307,7 +307,7 @@ fn extract_sides_of_xor_assign<'a, 'hir>( if let StmtKind::Semi(expr) = stmt.kind && let ExprKind::AssignOp( Spanned { - node: BinOpKind::BitXor, + node: AssignOpKind::BitXorAssign, .. }, lhs, diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index dd149c4a29b..17751e824c0 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -15,7 +15,7 @@ use rustc_apfloat::ieee::{Half, Quad}; use rustc_ast::ast::{self, LitFloatType, LitKind}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{ - BinOp, BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item, ItemKind, Node, PatExpr, PatExprKind, QPath, UnOp, + BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item, ItemKind, Node, PatExpr, PatExprKind, QPath, UnOp, }; use rustc_lexer::tokenize; use rustc_lint::LateContext; @@ -506,7 +506,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> { UnOp::Deref => Some(if let Constant::Ref(r) = o { *r } else { o }), }), ExprKind::If(cond, then, ref otherwise) => self.ifthenelse(cond, then, *otherwise), - ExprKind::Binary(op, left, right) => self.binop(op, left, right), + ExprKind::Binary(op, left, right) => self.binop(op.node, left, right), ExprKind::Call(callee, []) => { // We only handle a few const functions for now. if let ExprKind::Path(qpath) = &callee.kind @@ -744,7 +744,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> { } } - fn binop(&self, op: BinOp, left: &Expr<'_>, right: &Expr<'_>) -> Option<Constant<'tcx>> { + fn binop(&self, op: BinOpKind, left: &Expr<'_>, right: &Expr<'_>) -> Option<Constant<'tcx>> { let l = self.expr(left)?; let r = self.expr(right); match (l, r) { @@ -757,7 +757,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> { // Using / or %, where the left-hand argument is the smallest integer of a signed integer type and // the right-hand argument is -1 always panics, even with overflow-checks disabled - if let BinOpKind::Div | BinOpKind::Rem = op.node + if let BinOpKind::Div | BinOpKind::Rem = op && l == ty_min_value && r == -1 { @@ -765,7 +765,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> { } let zext = |n: i128| Constant::Int(unsext(self.tcx, n, ity)); - match op.node { + match op { // When +, * or binary - create a value greater than the maximum value, or less than // the minimum value that can be stored, it panics. BinOpKind::Add => l.checked_add(r).and_then(|n| ity.ensure_fits(n)).map(zext), @@ -792,7 +792,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> { ty::Uint(ity) => { let bits = ity.bits(); - match op.node { + match op { BinOpKind::Add => l.checked_add(r).and_then(|n| ity.ensure_fits(n)).map(Constant::Int), BinOpKind::Sub => l.checked_sub(r).and_then(|n| ity.ensure_fits(n)).map(Constant::Int), BinOpKind::Mul => l.checked_mul(r).and_then(|n| ity.ensure_fits(n)).map(Constant::Int), @@ -815,7 +815,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> { _ => None, }, // FIXME(f16_f128): add these types when binary operations are available on all platforms - (Constant::F32(l), Some(Constant::F32(r))) => match op.node { + (Constant::F32(l), Some(Constant::F32(r))) => match op { BinOpKind::Add => Some(Constant::F32(l + r)), BinOpKind::Sub => Some(Constant::F32(l - r)), BinOpKind::Mul => Some(Constant::F32(l * r)), @@ -829,7 +829,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> { BinOpKind::Gt => Some(Constant::Bool(l > r)), _ => None, }, - (Constant::F64(l), Some(Constant::F64(r))) => match op.node { + (Constant::F64(l), Some(Constant::F64(r))) => match op { BinOpKind::Add => Some(Constant::F64(l + r)), BinOpKind::Sub => Some(Constant::F64(l - r)), BinOpKind::Mul => Some(Constant::F64(l * r)), @@ -843,7 +843,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> { BinOpKind::Gt => Some(Constant::Bool(l > r)), _ => None, }, - (l, r) => match (op.node, l, r) { + (l, r) => match (op, l, r) { (BinOpKind::And, Constant::Bool(false), _) => Some(Constant::Bool(false)), (BinOpKind::Or, Constant::Bool(true), _) => Some(Constant::Bool(true)), (BinOpKind::And, Constant::Bool(true), Some(r)) | (BinOpKind::Or, Constant::Bool(false), Some(r)) => { diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 8dc28fa3077..6d2c2a2d692 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -114,6 +114,7 @@ use rustc_hir::{ use rustc_lexer::{TokenKind, tokenize}; use rustc_lint::{LateContext, Level, Lint, LintContext}; use rustc_middle::hir::place::PlaceBase; +use rustc_middle::lint::LevelAndSource; use rustc_middle::mir::{AggregateKind, Operand, RETURN_PLACE, Rvalue, StatementKind, TerminatorKind}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow}; use rustc_middle::ty::fast_reject::SimplifiedType; @@ -1976,14 +1977,14 @@ pub fn fulfill_or_allowed(cx: &LateContext<'_>, lint: &'static Lint, ids: impl I let mut suppress_lint = false; for id in ids { - let (level, _) = cx.tcx.lint_level_at_node(lint, id); - if let Some(expectation) = level.get_expectation_id() { + let LevelAndSource { level, lint_id, .. } = cx.tcx.lint_level_at_node(lint, id); + if let Some(expectation) = lint_id { cx.fulfill_expectation(expectation); } match level { - Level::Allow | Level::Expect(_) => suppress_lint = true, - Level::Warn | Level::ForceWarn(_) | Level::Deny | Level::Forbid => {}, + Level::Allow | Level::Expect => suppress_lint = true, + Level::Warn | Level::ForceWarn | Level::Deny | Level::Forbid => {}, } } @@ -1998,7 +1999,7 @@ pub fn fulfill_or_allowed(cx: &LateContext<'_>, lint: &'static Lint, ids: impl I /// make sure to use `span_lint_hir` functions to emit the lint. This ensures that /// expectations at the checked nodes will be fulfilled. pub fn is_lint_allowed(cx: &LateContext<'_>, lint: &'static Lint, id: HirId) -> bool { - cx.tcx.lint_level_at_node(lint, id).0 == Level::Allow + cx.tcx.lint_level_at_node(lint, id).level == Level::Allow } pub fn strip_pat_refs<'hir>(mut pat: &'hir Pat<'hir>) -> &'hir Pat<'hir> { diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs index 065d48119a2..e92c0c79b25 100644 --- a/src/tools/clippy/clippy_utils/src/sugg.rs +++ b/src/tools/clippy/clippy_utils/src/sugg.rs @@ -357,7 +357,7 @@ fn binop_to_string(op: AssocOp, lhs: &str, rhs: &str) -> String { match op { AssocOp::Binary(op) => format!("{lhs} {} {rhs}", op.as_str()), AssocOp::Assign => format!("{lhs} = {rhs}"), - AssocOp::AssignOp(op) => format!("{lhs} {}= {rhs}", op.as_str()), + AssocOp::AssignOp(op) => format!("{lhs} {} {rhs}", op.as_str()), AssocOp::Cast => format!("{lhs} as {rhs}"), AssocOp::Range(limits) => format!("{lhs}{}{rhs}", limits.as_str()), } diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 08d3c1c343e..9e35d2b4667 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -9,9 +9,9 @@ use std::{fmt, iter}; use build_helper::git::GitConfig; use semver::Version; use serde::de::{Deserialize, Deserializer, Error as _}; -use test::{ColorConfig, OutputFormat}; pub use self::Mode::*; +use crate::executor::{ColorConfig, OutputFormat}; use crate::util::{PathBufExt, add_dylib_path}; macro_rules! string_enum { @@ -178,6 +178,10 @@ pub struct Config { /// `true` to overwrite stderr/stdout files instead of complaining about changes in output. pub bless: bool, + /// Stop as soon as possible after any test fails. + /// May run a few more tests before stopping, due to threading. + pub fail_fast: bool, + /// The library paths required for running the compiler. pub compile_lib_path: PathBuf, diff --git a/src/tools/compiletest/src/executor.rs b/src/tools/compiletest/src/executor.rs new file mode 100644 index 00000000000..7588fee2b2b --- /dev/null +++ b/src/tools/compiletest/src/executor.rs @@ -0,0 +1,156 @@ +//! This module encapsulates all of the code that interacts directly with +//! libtest, to execute the collected tests. +//! +//! This will hopefully make it easier to migrate away from libtest someday. + +use std::borrow::Cow; +use std::io; +use std::sync::Arc; + +use crate::common::{Config, TestPaths}; + +/// Delegates to libtest to run the list of collected tests. +/// +/// Returns `Ok(true)` if all tests passed, or `Ok(false)` if one or more tests failed. +pub(crate) fn execute_tests(config: &Config, tests: Vec<CollectedTest>) -> io::Result<bool> { + let opts = test_opts(config); + let tests = tests.into_iter().map(|t| t.into_libtest()).collect::<Vec<_>>(); + + test::run_tests_console(&opts, tests) +} + +/// Information needed to create a `test::TestDescAndFn`. +pub(crate) struct CollectedTest { + pub(crate) desc: CollectedTestDesc, + pub(crate) config: Arc<Config>, + pub(crate) testpaths: TestPaths, + pub(crate) revision: Option<String>, +} + +/// Information needed to create a `test::TestDesc`. +pub(crate) struct CollectedTestDesc { + pub(crate) name: String, + pub(crate) ignore: bool, + pub(crate) ignore_message: Option<Cow<'static, str>>, + pub(crate) should_panic: ShouldPanic, +} + +impl CollectedTest { + fn into_libtest(self) -> test::TestDescAndFn { + let Self { desc, config, testpaths, revision } = self; + let CollectedTestDesc { name, ignore, ignore_message, should_panic } = desc; + + // Libtest requires the ignore message to be a &'static str, so we might + // have to leak memory to create it. This is fine, as we only do so once + // per test, so the leak won't grow indefinitely. + let ignore_message = ignore_message.map(|msg| match msg { + Cow::Borrowed(s) => s, + Cow::Owned(s) => &*String::leak(s), + }); + + let desc = test::TestDesc { + name: test::DynTestName(name), + ignore, + ignore_message, + source_file: "", + start_line: 0, + start_col: 0, + end_line: 0, + end_col: 0, + should_panic: should_panic.to_libtest(), + compile_fail: false, + no_run: false, + test_type: test::TestType::Unknown, + }; + + // This closure is invoked when libtest returns control to compiletest + // to execute the test. + let testfn = test::DynTestFn(Box::new(move || { + crate::runtest::run(config, &testpaths, revision.as_deref()); + Ok(()) + })); + + test::TestDescAndFn { desc, testfn } + } +} + +/// Whether console output should be colored or not. +#[derive(Copy, Clone, Default, Debug)] +pub enum ColorConfig { + #[default] + AutoColor, + AlwaysColor, + NeverColor, +} + +impl ColorConfig { + fn to_libtest(self) -> test::ColorConfig { + match self { + Self::AutoColor => test::ColorConfig::AutoColor, + Self::AlwaysColor => test::ColorConfig::AlwaysColor, + Self::NeverColor => test::ColorConfig::NeverColor, + } + } +} + +/// Format of the test results output. +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] +pub enum OutputFormat { + /// Verbose output + Pretty, + /// Quiet output + #[default] + Terse, + /// JSON output + Json, +} + +impl OutputFormat { + fn to_libtest(self) -> test::OutputFormat { + match self { + Self::Pretty => test::OutputFormat::Pretty, + Self::Terse => test::OutputFormat::Terse, + Self::Json => test::OutputFormat::Json, + } + } +} + +/// Whether test is expected to panic or not. +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub(crate) enum ShouldPanic { + No, + Yes, +} + +impl ShouldPanic { + fn to_libtest(self) -> test::ShouldPanic { + match self { + Self::No => test::ShouldPanic::No, + Self::Yes => test::ShouldPanic::Yes, + } + } +} + +fn test_opts(config: &Config) -> test::TestOpts { + test::TestOpts { + exclude_should_panic: false, + filters: config.filters.clone(), + filter_exact: config.filter_exact, + run_ignored: if config.run_ignored { test::RunIgnored::Yes } else { test::RunIgnored::No }, + format: config.format.to_libtest(), + logfile: config.logfile.clone(), + run_tests: true, + bench_benchmarks: true, + nocapture: config.nocapture, + color: config.color.to_libtest(), + shuffle: false, + shuffle_seed: None, + test_threads: None, + skip: config.skip.clone(), + list: false, + options: test::Options::new(), + time_options: None, + force_run_in_process: false, + fail_fast: config.fail_fast, + } +} diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index f654bd9c90b..a0178f4bcc5 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -11,6 +11,7 @@ use tracing::*; use crate::common::{Config, Debugger, FailMode, Mode, PassMode}; use crate::debuggers::{extract_cdb_version, extract_gdb_version}; +use crate::executor::{CollectedTestDesc, ShouldPanic}; use crate::header::auxiliary::{AuxProps, parse_and_update_aux}; use crate::header::needs::CachedNeedsConditions; use crate::util::static_regex; @@ -1355,15 +1356,15 @@ where Some((min, max)) } -pub fn make_test_description<R: Read>( +pub(crate) fn make_test_description<R: Read>( config: &Config, cache: &HeadersCache, - name: test::TestName, + name: String, path: &Path, src: R, test_revision: Option<&str>, poisoned: &mut bool, -) -> test::TestDesc { +) -> CollectedTestDesc { let mut ignore = false; let mut ignore_message = None; let mut should_fail = false; @@ -1387,10 +1388,7 @@ pub fn make_test_description<R: Read>( match $e { IgnoreDecision::Ignore { reason } => { ignore = true; - // The ignore reason must be a &'static str, so we have to leak memory to - // create it. This is fine, as the header is parsed only at the start of - // compiletest so it won't grow indefinitely. - ignore_message = Some(&*Box::leak(Box::<str>::from(reason))); + ignore_message = Some(reason.into()); } IgnoreDecision::Error { message } => { eprintln!("error: {}:{line_number}: {message}", path.display()); @@ -1431,25 +1429,12 @@ pub fn make_test_description<R: Read>( // since we run the pretty printer across all tests by default. // If desired, we could add a `should-fail-pretty` annotation. let should_panic = match config.mode { - crate::common::Pretty => test::ShouldPanic::No, - _ if should_fail => test::ShouldPanic::Yes, - _ => test::ShouldPanic::No, + crate::common::Pretty => ShouldPanic::No, + _ if should_fail => ShouldPanic::Yes, + _ => ShouldPanic::No, }; - test::TestDesc { - name, - ignore, - ignore_message, - source_file: "", - start_line: 0, - start_col: 0, - end_line: 0, - end_col: 0, - should_panic, - compile_fail: false, - no_run: false, - test_type: test::TestType::Unknown, - } + CollectedTestDesc { name, ignore, ignore_message, should_panic } } fn ignore_cdb(config: &Config, line: &str) -> IgnoreDecision { diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 4d90f152ee2..ff6bc49b72a 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -8,14 +8,15 @@ use super::{ parse_normalize_rule, }; use crate::common::{Config, Debugger, Mode}; +use crate::executor::{CollectedTestDesc, ShouldPanic}; fn make_test_description<R: Read>( config: &Config, - name: test::TestName, + name: String, path: &Path, src: R, revision: Option<&str>, -) -> test::TestDesc { +) -> CollectedTestDesc { let cache = HeadersCache::load(config); let mut poisoned = false; let test = crate::header::make_test_description( @@ -233,7 +234,7 @@ fn parse_rs(config: &Config, contents: &str) -> EarlyProps { } fn check_ignore(config: &Config, contents: &str) -> bool { - let tn = test::DynTestName(String::new()); + let tn = String::new(); let p = Path::new("a.rs"); let d = make_test_description(&config, tn, p, std::io::Cursor::new(contents), None); d.ignore @@ -242,13 +243,13 @@ fn check_ignore(config: &Config, contents: &str) -> bool { #[test] fn should_fail() { let config: Config = cfg().build(); - let tn = test::DynTestName(String::new()); + let tn = String::new(); let p = Path::new("a.rs"); let d = make_test_description(&config, tn.clone(), p, std::io::Cursor::new(""), None); - assert_eq!(d.should_panic, test::ShouldPanic::No); + assert_eq!(d.should_panic, ShouldPanic::No); let d = make_test_description(&config, tn, p, std::io::Cursor::new("//@ should-fail"), None); - assert_eq!(d.should_panic, test::ShouldPanic::Yes); + assert_eq!(d.should_panic, ShouldPanic::Yes); } #[test] diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 950566b2582..8145ae1c1bc 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -12,6 +12,7 @@ pub mod common; pub mod compute_diff; mod debuggers; pub mod errors; +mod executor; pub mod header; mod json; mod raise_fd_limit; @@ -32,7 +33,6 @@ use std::{env, fs, vec}; use build_helper::git::{get_git_modified_files, get_git_untracked_files}; use getopts::Options; -use test::ColorConfig; use tracing::*; use walkdir::WalkDir; @@ -41,6 +41,7 @@ use crate::common::{ CompareMode, Config, Debugger, Mode, PassMode, TestPaths, UI_EXTENSIONS, expected_output_path, output_base_dir, output_relative_path, }; +use crate::executor::{CollectedTest, ColorConfig, OutputFormat}; use crate::header::HeadersCache; use crate::util::logv; @@ -50,6 +51,12 @@ use crate::util::logv; /// some code here that inspects environment variables or even runs executables /// (e.g. when discovering debugger versions). pub fn parse_config(args: Vec<String>) -> Config { + if env::var("RUST_TEST_NOCAPTURE").is_ok() { + eprintln!( + "WARNING: RUST_TEST_NOCAPTURE is not supported. Use the `--no-capture` flag instead." + ); + } + let mut opts = Options::new(); opts.reqopt("", "compile-lib-path", "path to host shared libraries", "PATH") .reqopt("", "run-lib-path", "path to target shared libraries", "PATH") @@ -128,6 +135,7 @@ pub fn parse_config(args: Vec<String>) -> Config { "bless", "overwrite stderr/stdout files instead of complaining about a mismatch", ) + .optflag("", "fail-fast", "stop as soon as possible after any test fails") .optflag("", "quiet", "print one character per test instead of one line") .optopt("", "color", "coloring: auto, always, never", "WHEN") .optflag("", "json", "emit json output instead of plaintext output") @@ -319,6 +327,9 @@ pub fn parse_config(args: Vec<String>) -> Config { Config { bless: matches.opt_present("bless"), + fail_fast: matches.opt_present("fail-fast") + || env::var_os("RUSTC_TEST_FAIL_FAST").is_some(), + compile_lib_path: make_absolute(opt_path(matches, "compile-lib-path")), run_lib_path: make_absolute(opt_path(matches, "run-lib-path")), rustc_path: opt_path(matches, "rustc-path"), @@ -392,9 +403,9 @@ pub fn parse_config(args: Vec<String>) -> Config { verbose: matches.opt_present("verbose"), format: match (matches.opt_present("quiet"), matches.opt_present("json")) { (true, true) => panic!("--quiet and --json are incompatible"), - (true, false) => test::OutputFormat::Terse, - (false, true) => test::OutputFormat::Json, - (false, false) => test::OutputFormat::Pretty, + (true, false) => OutputFormat::Terse, + (false, true) => OutputFormat::Json, + (false, false) => OutputFormat::Pretty, }, only_modified: matches.opt_present("only-modified"), color, @@ -525,8 +536,6 @@ pub fn run_tests(config: Arc<Config>) { // Let tests know which target they're running as env::set_var("TARGET", &config.target); - let opts = test_opts(&config); - let mut configs = Vec::new(); if let Mode::DebugInfo = config.mode { // Debugging emscripten code doesn't make sense today @@ -553,12 +562,12 @@ pub fn run_tests(config: Arc<Config>) { tests.extend(collect_and_make_tests(c)); } - tests.sort_by(|a, b| a.desc.name.as_slice().cmp(&b.desc.name.as_slice())); + tests.sort_by(|a, b| Ord::cmp(&a.desc.name, &b.desc.name)); // Delegate to libtest to filter and run the big list of structures created - // during test discovery. When libtest decides to run a test, it will invoke - // the corresponding closure created by `make_test_closure`. - let res = test::run_tests_console(&opts, tests); + // during test discovery. When libtest decides to run a test, it will + // return control to compiletest by invoking a closure. + let res = crate::executor::execute_tests(&config, tests); // Check the outcome reported by libtest. match res { @@ -602,37 +611,6 @@ pub fn run_tests(config: Arc<Config>) { } } -pub fn test_opts(config: &Config) -> test::TestOpts { - if env::var("RUST_TEST_NOCAPTURE").is_ok() { - eprintln!( - "WARNING: RUST_TEST_NOCAPTURE is no longer used. \ - Use the `--nocapture` flag instead." - ); - } - - test::TestOpts { - exclude_should_panic: false, - filters: config.filters.clone(), - filter_exact: config.filter_exact, - run_ignored: if config.run_ignored { test::RunIgnored::Yes } else { test::RunIgnored::No }, - format: config.format, - logfile: config.logfile.clone(), - run_tests: true, - bench_benchmarks: true, - nocapture: config.nocapture, - color: config.color, - shuffle: false, - shuffle_seed: None, - test_threads: None, - skip: config.skip.clone(), - list: false, - options: test::Options::new(), - time_options: None, - force_run_in_process: false, - fail_fast: std::env::var_os("RUSTC_TEST_FAIL_FAST").is_some(), - } -} - /// Read-only context data used during test collection. struct TestCollectorCx { config: Arc<Config>, @@ -643,17 +621,17 @@ struct TestCollectorCx { /// Mutable state used during test collection. struct TestCollector { - tests: Vec<test::TestDescAndFn>, + tests: Vec<CollectedTest>, found_path_stems: HashSet<PathBuf>, poisoned: bool, } -/// Creates libtest structures for every test/revision in the test suite directory. +/// Creates test structures for every test/revision in the test suite directory. /// /// This always inspects _all_ test files in the suite (e.g. all 17k+ ui tests), /// regardless of whether any filters/tests were specified on the command-line, /// because filtering is handled later by libtest. -pub fn collect_and_make_tests(config: Arc<Config>) -> Vec<test::TestDescAndFn> { +pub(crate) fn collect_and_make_tests(config: Arc<Config>) -> Vec<CollectedTest> { debug!("making tests from {}", config.src_test_suite_root.display()); let common_inputs_stamp = common_inputs_stamp(&config); let modified_tests = @@ -882,7 +860,7 @@ fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &Te }; // For each revision (or the sole dummy revision), create and append a - // `test::TestDescAndFn` that can be handed over to libtest. + // `CollectedTest` that can be handed over to the test executor. collector.tests.extend(revisions.into_iter().map(|revision| { // Create a test name and description to hand over to libtest. let src_file = fs::File::open(&test_path).expect("open test file to parse ignores"); @@ -905,13 +883,14 @@ fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &Te if !cx.config.force_rerun && is_up_to_date(cx, testpaths, &early_props, revision) { desc.ignore = true; // Keep this in sync with the "up-to-date" message detected by bootstrap. - desc.ignore_message = Some("up-to-date"); + desc.ignore_message = Some("up-to-date".into()); } - // Create the callback that will run this test/revision when libtest calls it. - let testfn = make_test_closure(Arc::clone(&cx.config), testpaths, revision); + let config = Arc::clone(&cx.config); + let testpaths = testpaths.clone(); + let revision = revision.map(str::to_owned); - test::TestDescAndFn { desc, testfn } + CollectedTest { desc, config, testpaths, revision } })); } @@ -1043,11 +1022,7 @@ impl Stamp { } /// Creates a name for this test/revision that can be handed over to libtest. -fn make_test_name( - config: &Config, - testpaths: &TestPaths, - revision: Option<&str>, -) -> test::TestName { +fn make_test_name(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> String { // Print the name of the file, relative to the sources root. let path = testpaths.file.strip_prefix(&config.src_root).unwrap(); let debugger = match config.debugger { @@ -1059,32 +1034,14 @@ fn make_test_name( None => String::new(), }; - test::DynTestName(format!( + format!( "[{}{}{}] {}{}", config.mode, debugger, mode_suffix, path.display(), revision.map_or("".to_string(), |rev| format!("#{}", rev)) - )) -} - -/// Creates a callback for this test/revision that libtest will call when it -/// decides to actually run the underlying test. -fn make_test_closure( - config: Arc<Config>, - testpaths: &TestPaths, - revision: Option<&str>, -) -> test::TestFn { - let testpaths = testpaths.clone(); - let revision = revision.map(str::to_owned); - - // This callback is the link between compiletest's test discovery code, - // and the parts of compiletest that know how to run an individual test. - test::DynTestFn(Box::new(move || { - runtest::run(config, &testpaths, revision.as_deref()); - Ok(()) - })) + ) } /// Checks that test discovery didn't find any tests whose name stem is a prefix diff --git a/src/tools/compiletest/src/runtest/ui.rs b/src/tools/compiletest/src/runtest/ui.rs index 9b5b8b56b60..974e5170465 100644 --- a/src/tools/compiletest/src/runtest/ui.rs +++ b/src/tools/compiletest/src/runtest/ui.rs @@ -169,16 +169,9 @@ impl TestCx<'_> { self.props.error_patterns ); - let check_patterns = should_run == WillExecute::No - && (!self.props.error_patterns.is_empty() - || !self.props.regex_error_patterns.is_empty()); if !explicit && self.config.compare_mode.is_none() { - let check_annotations = !check_patterns || !expected_errors.is_empty(); - - if check_annotations { - // "//~ERROR comments" - self.check_expected_errors(expected_errors, &proc_res); - } + // "//~ERROR comments" + self.check_expected_errors(expected_errors, &proc_res); } else if explicit && !expected_errors.is_empty() { let msg = format!( "line {}: cannot combine `--error-format` with {} annotations; use `error-pattern` instead", @@ -188,7 +181,10 @@ impl TestCx<'_> { self.fatal(&msg); } let output_to_check = self.get_output(&proc_res); - if check_patterns { + if should_run == WillExecute::No + && (!self.props.error_patterns.is_empty() + || !self.props.regex_error_patterns.is_empty()) + { // "// error-pattern" comments self.check_all_error_patterns(&output_to_check, &proc_res, pm); } diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs index 65120770edd..be6b483bfff 100644 --- a/src/tools/rustfmt/src/expr.rs +++ b/src/tools/rustfmt/src/expr.rs @@ -2058,7 +2058,7 @@ fn rewrite_assignment( context: &RewriteContext<'_>, lhs: &ast::Expr, rhs: &ast::Expr, - op: Option<&ast::BinOp>, + op: Option<&ast::AssignOp>, shape: Shape, ) -> RewriteResult { let operator_str = match op { diff --git a/tests/codegen/clone_as_copy.rs b/tests/codegen/clone_as_copy.rs index c39f120044c..ef834ef5912 100644 --- a/tests/codegen/clone_as_copy.rs +++ b/tests/codegen/clone_as_copy.rs @@ -1,6 +1,4 @@ //@ revisions: DEBUGINFO NODEBUGINFO -//@ compile-flags: -Zunsound-mir-opts -// FIXME: see <https://github.com/rust-lang/rust/issues/132353> //@ compile-flags: -Copt-level=3 -Cno-prepopulate-passes //@ [DEBUGINFO] compile-flags: -Cdebuginfo=full diff --git a/tests/codegen/slice-split-at.rs b/tests/codegen/slice-split-at.rs new file mode 100644 index 00000000000..07018cf9c91 --- /dev/null +++ b/tests/codegen/slice-split-at.rs @@ -0,0 +1,24 @@ +//@ compile-flags: -Copt-level=3 +#![crate_type = "lib"] + +// Check that no panic is generated in `split_at` when calculating the index for +// the tail chunk using `checked_sub`. +// +// Tests written for refactored implementations of: +// `<[T]>::{split_last_chunk, split_last_chunk_mut, last_chunk, last_chunk_mut}` + +// CHECK-LABEL: @split_at_last_chunk +#[no_mangle] +pub fn split_at_last_chunk(s: &[u8], chunk_size: usize) -> Option<(&[u8], &[u8])> { + // CHECK-NOT: panic + let Some(index) = s.len().checked_sub(chunk_size) else { return None }; + Some(s.split_at(index)) +} + +// CHECK-LABEL: @split_at_mut_last_chunk +#[no_mangle] +pub fn split_at_mut_last_chunk(s: &mut [u8], chunk_size: usize) -> Option<(&mut [u8], &mut [u8])> { + // CHECK-NOT: panic + let Some(index) = s.len().checked_sub(chunk_size) else { return None }; + Some(s.split_at_mut(index)) +} diff --git a/tests/codegen/try_question_mark_nop.rs b/tests/codegen/try_question_mark_nop.rs index 3a3453b22b4..9430465a286 100644 --- a/tests/codegen/try_question_mark_nop.rs +++ b/tests/codegen/try_question_mark_nop.rs @@ -16,12 +16,17 @@ use std::ptr::NonNull; #[no_mangle] pub fn option_nop_match_32(x: Option<u32>) -> Option<u32> { // CHECK: start: - // TWENTY-NEXT: %[[IS_SOME:.+]] = trunc nuw i32 %0 to i1 - // TWENTY-NEXT: %[[PAYLOAD:.+]] = select i1 %[[IS_SOME]], i32 %1, i32 undef - // CHECK-NEXT: [[REG1:%.*]] = insertvalue { i32, i32 } poison, i32 %0, 0 - // NINETEEN-NEXT: [[REG2:%.*]] = insertvalue { i32, i32 } [[REG1]], i32 %1, 1 - // TWENTY-NEXT: [[REG2:%.*]] = insertvalue { i32, i32 } [[REG1]], i32 %[[PAYLOAD]], 1 - // CHECK-NEXT: ret { i32, i32 } [[REG2]] + // CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw i32 %0 to i1 + + // NINETEEN-NEXT: [[SELECT:%.*]] = select i1 [[TRUNC]], i32 %0, i32 0 + // NINETEEN-NEXT: [[REG2:%.*]] = insertvalue { i32, i32 } poison, i32 [[SELECT]], 0 + // NINETEEN-NEXT: [[REG3:%.*]] = insertvalue { i32, i32 } [[REG2]], i32 %1, 1 + + // TWENTY-NEXT: [[SELECT:%.*]] = select i1 [[TRUNC]], i32 %1, i32 undef + // TWENTY-NEXT: [[REG2:%.*]] = insertvalue { i32, i32 } poison, i32 %0, 0 + // TWENTY-NEXT: [[REG3:%.*]] = insertvalue { i32, i32 } [[REG2]], i32 [[SELECT]], 1 + + // CHECK-NEXT: ret { i32, i32 } [[REG3]] match x { Some(x) => Some(x), None => None, @@ -90,12 +95,17 @@ pub fn control_flow_nop_traits_32(x: ControlFlow<i32, u32>) -> ControlFlow<i32, #[no_mangle] pub fn option_nop_match_64(x: Option<u64>) -> Option<u64> { // CHECK: start: - // TWENTY-NEXT: %[[TRUNC:[0-9]+]] = trunc nuw i64 %0 to i1 - // TWENTY-NEXT: %[[SEL:\.[0-9]+]] = select i1 %[[TRUNC]], i64 %1, i64 undef - // CHECK-NEXT: [[REG1:%[0-9a-zA-Z_.]+]] = insertvalue { i64, i64 } poison, i64 %0, 0 - // NINETEEN-NEXT: [[REG2:%[0-9a-zA-Z_.]+]] = insertvalue { i64, i64 } [[REG1]], i64 %1, 1 - // TWENTY-NEXT: [[REG2:%[0-9a-zA-Z_.]+]] = insertvalue { i64, i64 } [[REG1]], i64 %[[SEL]], 1 - // CHECK-NEXT: ret { i64, i64 } [[REG2]] + // CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw i64 %0 to i1 + + // NINETEEN-NEXT: [[SELECT:%.*]] = select i1 [[TRUNC]], i64 %0, i64 0 + // NINETEEN-NEXT: [[REG2:%.*]] = insertvalue { i64, i64 } poison, i64 [[SELECT]], 0 + // NINETEEN-NEXT: [[REG3:%.*]] = insertvalue { i64, i64 } [[REG2]], i64 %1, 1 + + // TWENTY-NEXT: [[SELECT:%.*]] = select i1 [[TRUNC]], i64 %1, i64 undef + // TWENTY-NEXT: [[REG2:%.*]] = insertvalue { i64, i64 } poison, i64 %0, 0 + // TWENTY-NEXT: [[REG3:%.*]] = insertvalue { i64, i64 } [[REG2]], i64 [[SELECT]], 1 + + // CHECK-NEXT: ret { i64, i64 } [[REG3]] match x { Some(x) => Some(x), None => None, @@ -164,8 +174,8 @@ pub fn control_flow_nop_traits_64(x: ControlFlow<i64, u64>) -> ControlFlow<i64, #[no_mangle] pub fn result_nop_match_128(x: Result<i128, u128>) -> Result<i128, u128> { // CHECK: start: - // CHECK-NEXT: getelementptr inbounds {{(nuw )?}}i8 // CHECK-NEXT: store i128 + // CHECK-NEXT: getelementptr inbounds {{(nuw )?}}i8 // CHECK-NEXT: store i128 // CHECK-NEXT: ret void match x { @@ -189,8 +199,8 @@ pub fn result_nop_traits_128(x: Result<i128, u128>) -> Result<i128, u128> { #[no_mangle] pub fn control_flow_nop_match_128(x: ControlFlow<i128, u128>) -> ControlFlow<i128, u128> { // CHECK: start: - // CHECK-NEXT: getelementptr inbounds {{(nuw )?}}i8 // CHECK-NEXT: store i128 + // CHECK-NEXT: getelementptr inbounds {{(nuw )?}}i8 // CHECK-NEXT: store i128 // CHECK-NEXT: ret void match x { diff --git a/tests/coverage/issue-84561.cov-map b/tests/coverage/issue-84561.cov-map index 3bd4e7d2a36..47e2922a805 100644 --- a/tests/coverage/issue-84561.cov-map +++ b/tests/coverage/issue-84561.cov-map @@ -59,109 +59,80 @@ Number of file 0 mappings: 1 Highest counter ID seen: c0 Function name: issue_84561::test3 -Raw bytes (315): 0x[01, 01, 1b, 1d, 21, 25, 29, 21, 25, 2d, 31, 21, 17, 25, 2d, 41, 45, 49, 4d, 51, 55, 33, 51, 49, 4d, 33, 37, 49, 4d, 51, 59, 55, 59, 55, 59, 47, 5d, 55, 59, 61, 65, 71, 75, 69, 6d, 69, 6d, 69, 6d, 63, 79, 71, 75, 79, 7d, 7d, 81, 01, 33, 01, 08, 01, 03, 0f, 05, 04, 09, 01, 0f, 09, 02, 05, 04, 0f, 0d, 05, 05, 00, 0f, 11, 01, 05, 00, 0f, 15, 01, 09, 01, 0f, 19, 02, 05, 00, 0f, 1d, 01, 05, 00, 0f, 02, 00, 20, 00, 30, 21, 01, 05, 03, 0f, 25, 03, 20, 00, 30, 29, 00, 33, 00, 41, 06, 00, 4b, 00, 5a, 0a, 01, 05, 00, 0f, 2d, 05, 09, 03, 10, 31, 05, 0d, 00, 1b, 0e, 02, 0d, 00, 1c, 12, 04, 09, 02, 0f, 35, 06, 05, 00, 0f, 39, 04, 05, 00, 0f, 3d, 04, 09, 01, 0f, 41, 05, 08, 00, 0f, 45, 01, 09, 00, 13, 1a, 05, 09, 00, 13, 33, 05, 08, 00, 0f, 51, 01, 09, 00, 13, 22, 03, 0d, 00, 1d, 26, 03, 09, 00, 13, 2e, 03, 0d, 00, 1d, 47, 03, 05, 00, 0f, 47, 01, 0c, 00, 13, 5d, 01, 0d, 00, 13, 42, 02, 0d, 00, 13, 61, 04, 05, 02, 13, 65, 03, 0d, 00, 13, 4a, 02, 0d, 00, 13, 63, 03, 05, 00, 0f, 69, 01, 0c, 00, 13, 6d, 01, 0d, 00, 17, 71, 04, 0d, 00, 13, 5a, 02, 0d, 00, 17, 5a, 01, 14, 00, 1b, 00, 01, 15, 00, 1b, 5a, 02, 15, 00, 1b, 75, 04, 0d, 00, 13, 5e, 03, 09, 00, 19, 79, 02, 05, 00, 0f, 66, 03, 09, 00, 22, 7d, 02, 05, 00, 0f, 6a, 03, 09, 00, 2c, 81, 01, 02, 01, 00, 02] +Raw bytes (279): 0x[01, 01, 0a, 0d, 11, 0d, 15, 0d, 19, 1d, 21, 29, 2d, 25, 29, 25, 29, 25, 29, 27, 31, 29, 2d, 33, 01, 08, 01, 03, 0f, 05, 04, 09, 01, 0f, 09, 02, 05, 04, 0f, 09, 05, 05, 00, 0f, 09, 01, 05, 00, 0f, 09, 01, 09, 01, 0f, 0d, 02, 05, 00, 0f, 0d, 01, 05, 00, 0f, 00, 00, 20, 00, 30, 0d, 01, 05, 03, 0f, 00, 03, 20, 00, 30, 00, 00, 33, 00, 41, 00, 00, 4b, 00, 5a, 0d, 01, 05, 00, 0f, 00, 05, 09, 03, 10, 00, 05, 0d, 00, 1b, 00, 02, 0d, 00, 1c, 0d, 04, 09, 02, 0f, 0d, 06, 05, 00, 0f, 0d, 04, 05, 00, 0f, 0d, 04, 09, 01, 0f, 0d, 05, 08, 00, 0f, 11, 01, 09, 00, 13, 02, 05, 09, 00, 13, 0d, 05, 08, 00, 0f, 15, 01, 09, 00, 13, 00, 03, 0d, 00, 1d, 06, 03, 09, 00, 13, 00, 03, 0d, 00, 1d, 0d, 03, 05, 00, 0f, 0d, 01, 0c, 00, 13, 19, 01, 0d, 00, 13, 0a, 02, 0d, 00, 13, 1d, 04, 05, 02, 13, 21, 03, 0d, 00, 13, 0e, 02, 0d, 00, 13, 27, 03, 05, 00, 0f, 25, 01, 0c, 00, 13, 29, 01, 0d, 00, 17, 29, 04, 0d, 00, 13, 1e, 02, 0d, 00, 17, 1e, 01, 14, 00, 1b, 00, 01, 15, 00, 1b, 1e, 02, 15, 00, 1b, 2d, 04, 0d, 00, 13, 22, 03, 09, 00, 19, 31, 02, 05, 00, 0f, 31, 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: 27 -- expression 0 operands: lhs = Counter(7), rhs = Counter(8) -- expression 1 operands: lhs = Counter(9), rhs = Counter(10) -- expression 2 operands: lhs = Counter(8), rhs = Counter(9) -- expression 3 operands: lhs = Counter(11), rhs = Counter(12) -- expression 4 operands: lhs = Counter(8), rhs = Expression(5, Add) -- expression 5 operands: lhs = Counter(9), rhs = Counter(11) -- expression 6 operands: lhs = Counter(16), rhs = Counter(17) -- expression 7 operands: lhs = Counter(18), rhs = Counter(19) -- expression 8 operands: lhs = Counter(20), rhs = Counter(21) -- expression 9 operands: lhs = Expression(12, Add), rhs = Counter(20) -- expression 10 operands: lhs = Counter(18), rhs = Counter(19) -- expression 11 operands: lhs = Expression(12, Add), rhs = Expression(13, Add) -- expression 12 operands: lhs = Counter(18), rhs = Counter(19) -- expression 13 operands: lhs = Counter(20), rhs = Counter(22) -- expression 14 operands: lhs = Counter(21), rhs = Counter(22) -- expression 15 operands: lhs = Counter(21), rhs = Counter(22) -- expression 16 operands: lhs = Expression(17, Add), rhs = Counter(23) -- expression 17 operands: lhs = Counter(21), rhs = Counter(22) -- expression 18 operands: lhs = Counter(24), rhs = Counter(25) -- expression 19 operands: lhs = Counter(28), rhs = Counter(29) -- expression 20 operands: lhs = Counter(26), rhs = Counter(27) -- expression 21 operands: lhs = Counter(26), rhs = Counter(27) -- expression 22 operands: lhs = Counter(26), rhs = Counter(27) -- expression 23 operands: lhs = Expression(24, Add), rhs = Counter(30) -- expression 24 operands: lhs = Counter(28), rhs = Counter(29) -- expression 25 operands: lhs = Counter(30), rhs = Counter(31) -- expression 26 operands: lhs = Counter(31), rhs = Counter(32) +Number of expressions: 10 +- expression 0 operands: lhs = Counter(3), rhs = Counter(4) +- expression 1 operands: lhs = Counter(3), rhs = Counter(5) +- expression 2 operands: lhs = Counter(3), rhs = Counter(6) +- expression 3 operands: lhs = Counter(7), rhs = Counter(8) +- expression 4 operands: lhs = Counter(10), rhs = Counter(11) +- expression 5 operands: lhs = Counter(9), rhs = Counter(10) +- expression 6 operands: lhs = Counter(9), rhs = Counter(10) +- expression 7 operands: lhs = Counter(9), rhs = Counter(10) +- expression 8 operands: lhs = Expression(9, Add), rhs = Counter(12) +- expression 9 operands: lhs = Counter(10), rhs = Counter(11) Number of file 0 mappings: 51 - Code(Counter(0)) at (prev + 8, 1) to (start + 3, 15) - Code(Counter(1)) at (prev + 4, 9) to (start + 1, 15) - Code(Counter(2)) at (prev + 2, 5) to (start + 4, 15) -- Code(Counter(3)) at (prev + 5, 5) to (start + 0, 15) -- Code(Counter(4)) at (prev + 1, 5) to (start + 0, 15) -- Code(Counter(5)) at (prev + 1, 9) to (start + 1, 15) -- Code(Counter(6)) at (prev + 2, 5) to (start + 0, 15) -- Code(Counter(7)) at (prev + 1, 5) to (start + 0, 15) -- Code(Expression(0, Sub)) at (prev + 0, 32) to (start + 0, 48) +- Code(Counter(2)) at (prev + 5, 5) to (start + 0, 15) +- Code(Counter(2)) at (prev + 1, 5) to (start + 0, 15) +- Code(Counter(2)) at (prev + 1, 9) to (start + 1, 15) +- Code(Counter(3)) at (prev + 2, 5) to (start + 0, 15) +- Code(Counter(3)) at (prev + 1, 5) to (start + 0, 15) +- Code(Zero) at (prev + 0, 32) to (start + 0, 48) +- Code(Counter(3)) at (prev + 1, 5) to (start + 3, 15) +- Code(Zero) at (prev + 3, 32) to (start + 0, 48) +- Code(Zero) at (prev + 0, 51) to (start + 0, 65) +- Code(Zero) at (prev + 0, 75) to (start + 0, 90) +- Code(Counter(3)) at (prev + 1, 5) to (start + 0, 15) +- Code(Zero) at (prev + 5, 9) to (start + 3, 16) +- Code(Zero) at (prev + 5, 13) to (start + 0, 27) +- Code(Zero) at (prev + 2, 13) to (start + 0, 28) +- Code(Counter(3)) at (prev + 4, 9) to (start + 2, 15) +- Code(Counter(3)) at (prev + 6, 5) to (start + 0, 15) +- Code(Counter(3)) at (prev + 4, 5) to (start + 0, 15) +- Code(Counter(3)) at (prev + 4, 9) to (start + 1, 15) +- Code(Counter(3)) at (prev + 5, 8) to (start + 0, 15) +- Code(Counter(4)) at (prev + 1, 9) to (start + 0, 19) +- Code(Expression(0, Sub)) at (prev + 5, 9) to (start + 0, 19) + = (c3 - c4) +- Code(Counter(3)) at (prev + 5, 8) to (start + 0, 15) +- Code(Counter(5)) at (prev + 1, 9) to (start + 0, 19) +- Code(Zero) at (prev + 3, 13) to (start + 0, 29) +- Code(Expression(1, Sub)) at (prev + 3, 9) to (start + 0, 19) + = (c3 - c5) +- Code(Zero) at (prev + 3, 13) to (start + 0, 29) +- Code(Counter(3)) at (prev + 3, 5) to (start + 0, 15) +- Code(Counter(3)) at (prev + 1, 12) to (start + 0, 19) +- Code(Counter(6)) at (prev + 1, 13) to (start + 0, 19) +- Code(Expression(2, Sub)) at (prev + 2, 13) to (start + 0, 19) + = (c3 - c6) +- Code(Counter(7)) at (prev + 4, 5) to (start + 2, 19) +- Code(Counter(8)) at (prev + 3, 13) to (start + 0, 19) +- Code(Expression(3, Sub)) at (prev + 2, 13) to (start + 0, 19) = (c7 - c8) -- Code(Counter(8)) at (prev + 1, 5) to (start + 3, 15) -- Code(Counter(9)) at (prev + 3, 32) to (start + 0, 48) -- Code(Counter(10)) at (prev + 0, 51) to (start + 0, 65) -- Code(Expression(1, Sub)) at (prev + 0, 75) to (start + 0, 90) +- Code(Expression(9, Add)) at (prev + 3, 5) to (start + 0, 15) + = (c10 + c11) +- Code(Counter(9)) at (prev + 1, 12) to (start + 0, 19) +- Code(Counter(10)) at (prev + 1, 13) to (start + 0, 23) +- Code(Counter(10)) at (prev + 4, 13) to (start + 0, 19) +- Code(Expression(7, Sub)) at (prev + 2, 13) to (start + 0, 23) + = (c9 - c10) +- Code(Expression(7, Sub)) at (prev + 1, 20) to (start + 0, 27) = (c9 - c10) -- Code(Expression(2, Sub)) at (prev + 1, 5) to (start + 0, 15) - = (c8 - c9) -- Code(Counter(11)) at (prev + 5, 9) to (start + 3, 16) -- Code(Counter(12)) at (prev + 5, 13) to (start + 0, 27) -- Code(Expression(3, Sub)) at (prev + 2, 13) to (start + 0, 28) - = (c11 - c12) -- Code(Expression(4, Sub)) at (prev + 4, 9) to (start + 2, 15) - = (c8 - (c9 + c11)) -- Code(Counter(13)) at (prev + 6, 5) to (start + 0, 15) -- Code(Counter(14)) at (prev + 4, 5) to (start + 0, 15) -- Code(Counter(15)) at (prev + 4, 9) to (start + 1, 15) -- Code(Counter(16)) at (prev + 5, 8) to (start + 0, 15) -- Code(Counter(17)) at (prev + 1, 9) to (start + 0, 19) -- Code(Expression(6, Sub)) at (prev + 5, 9) to (start + 0, 19) - = (c16 - c17) -- Code(Expression(12, Add)) at (prev + 5, 8) to (start + 0, 15) - = (c18 + c19) -- Code(Counter(20)) at (prev + 1, 9) to (start + 0, 19) -- Code(Expression(8, Sub)) at (prev + 3, 13) to (start + 0, 29) - = (c20 - c21) -- Code(Expression(9, Sub)) at (prev + 3, 9) to (start + 0, 19) - = ((c18 + c19) - c20) -- Code(Expression(11, Sub)) at (prev + 3, 13) to (start + 0, 29) - = ((c18 + c19) - (c20 + c22)) -- Code(Expression(17, Add)) at (prev + 3, 5) to (start + 0, 15) - = (c21 + c22) -- Code(Expression(17, Add)) at (prev + 1, 12) to (start + 0, 19) - = (c21 + c22) -- Code(Counter(23)) at (prev + 1, 13) to (start + 0, 19) -- Code(Expression(16, Sub)) at (prev + 2, 13) to (start + 0, 19) - = ((c21 + c22) - c23) -- Code(Counter(24)) at (prev + 4, 5) to (start + 2, 19) -- Code(Counter(25)) at (prev + 3, 13) to (start + 0, 19) -- Code(Expression(18, Sub)) at (prev + 2, 13) to (start + 0, 19) - = (c24 - c25) -- Code(Expression(24, Add)) at (prev + 3, 5) to (start + 0, 15) - = (c28 + c29) -- Code(Counter(26)) at (prev + 1, 12) to (start + 0, 19) -- Code(Counter(27)) at (prev + 1, 13) to (start + 0, 23) -- Code(Counter(28)) at (prev + 4, 13) to (start + 0, 19) -- Code(Expression(22, Sub)) at (prev + 2, 13) to (start + 0, 23) - = (c26 - c27) -- Code(Expression(22, Sub)) at (prev + 1, 20) to (start + 0, 27) - = (c26 - c27) - Code(Zero) at (prev + 1, 21) to (start + 0, 27) -- Code(Expression(22, Sub)) at (prev + 2, 21) to (start + 0, 27) - = (c26 - c27) -- Code(Counter(29)) at (prev + 4, 13) to (start + 0, 19) -- Code(Expression(23, Sub)) at (prev + 3, 9) to (start + 0, 25) - = ((c28 + c29) - c30) -- Code(Counter(30)) at (prev + 2, 5) to (start + 0, 15) -- Code(Expression(25, Sub)) at (prev + 3, 9) to (start + 0, 34) - = (c30 - c31) -- Code(Counter(31)) at (prev + 2, 5) to (start + 0, 15) -- Code(Expression(26, Sub)) at (prev + 3, 9) to (start + 0, 44) - = (c31 - c32) -- Code(Counter(32)) at (prev + 2, 1) to (start + 0, 2) -Highest counter ID seen: c32 +- Code(Expression(7, Sub)) at (prev + 2, 21) to (start + 0, 27) + = (c9 - c10) +- Code(Counter(11)) at (prev + 4, 13) to (start + 0, 19) +- Code(Expression(8, Sub)) at (prev + 3, 9) to (start + 0, 25) + = ((c10 + c11) - c12) +- Code(Counter(12)) at (prev + 2, 5) to (start + 0, 15) +- Code(Counter(12)) at (prev + 3, 9) to (start + 0, 34) +- Code(Zero) at (prev + 2, 5) to (start + 0, 15) +- Code(Zero) at (prev + 3, 9) to (start + 0, 44) +- Code(Zero) at (prev + 2, 1) to (start + 0, 2) +Highest counter ID seen: c12 diff --git a/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-abort.diff b/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-abort.diff index 886f9a68dd9..417406de39b 100644 --- a/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-abort.diff +++ b/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-abort.diff @@ -8,8 +8,9 @@ bb0: { StorageLive(_1); - _1 = const <bool as NeedsDrop>::NEEDS; +- _1 = const <bool as NeedsDrop>::NEEDS; - switchInt(move _1) -> [0: bb2, otherwise: bb1]; ++ _1 = const false; + switchInt(const false) -> [0: bb2, otherwise: bb1]; } diff --git a/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-unwind.diff b/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-unwind.diff index cc53b213397..63ba2c6865f 100644 --- a/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-unwind.diff +++ b/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-unwind.diff @@ -8,8 +8,9 @@ bb0: { StorageLive(_1); - _1 = const <bool as NeedsDrop>::NEEDS; +- _1 = const <bool as NeedsDrop>::NEEDS; - switchInt(move _1) -> [0: bb2, otherwise: bb1]; ++ _1 = const false; + switchInt(const false) -> [0: bb2, otherwise: bb1]; } diff --git a/tests/mir-opt/const_prop/read_immutable_static.main.GVN.diff b/tests/mir-opt/const_prop/read_immutable_static.main.GVN.diff index 23928337bf7..8df262b351f 100644 --- a/tests/mir-opt/const_prop/read_immutable_static.main.GVN.diff +++ b/tests/mir-opt/const_prop/read_immutable_static.main.GVN.diff @@ -14,19 +14,23 @@ bb0: { StorageLive(_1); - StorageLive(_2); +- StorageLive(_2); - StorageLive(_3); + nop; ++ nop; _3 = const {ALLOC0: &u8}; - _2 = copy (*_3); +- _2 = copy (*_3); ++ _2 = const 2_u8; StorageLive(_4); StorageLive(_5); _5 = const {ALLOC0: &u8}; - _4 = copy (*_5); -+ _4 = copy (*_3); - _1 = Add(move _2, move _4); +- _1 = Add(move _2, move _4); ++ _4 = const 2_u8; ++ _1 = const 4_u8; StorageDead(_4); - StorageDead(_2); +- StorageDead(_2); ++ nop; StorageDead(_5); - StorageDead(_3); + nop; diff --git a/tests/mir-opt/const_prop/read_immutable_static.rs b/tests/mir-opt/const_prop/read_immutable_static.rs index 98ba76fb765..05fec2f3303 100644 --- a/tests/mir-opt/const_prop/read_immutable_static.rs +++ b/tests/mir-opt/const_prop/read_immutable_static.rs @@ -6,7 +6,6 @@ static FOO: u8 = 2; fn main() { // CHECK-LABEL: fn main( // CHECK: debug x => [[x:_.*]]; - // Disabled due to <https://github.com/rust-lang/rust/issues/130853> - // COM: CHECK: [[x]] = const 4_u8; + // CHECK: [[x]] = const 4_u8; let x = FOO + FOO; } 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 4477b4b005b..b9e269266b0 100644 --- a/tests/mir-opt/const_prop/ref_deref.main.GVN.diff +++ b/tests/mir-opt/const_prop/ref_deref.main.GVN.diff @@ -16,7 +16,8 @@ StorageLive(_2); _4 = const main::promoted[0]; _2 = &(*_4); - _1 = copy (*_2); +- _1 = copy (*_2); ++ _1 = const 4_i32; StorageDead(_2); _0 = const (); StorageDead(_1); 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 bbfd70bea16..dcc13c9251c 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 @@ -16,7 +16,8 @@ StorageLive(_2); _4 = const main::promoted[0]; _2 = &((*_4).1: i32); - _1 = copy (*_2); +- _1 = copy (*_2); ++ _1 = const 5_i32; StorageDead(_2); _0 = const (); StorageDead(_1); diff --git a/tests/mir-opt/const_prop/ref_deref_project.rs b/tests/mir-opt/const_prop/ref_deref_project.rs index 31108e1a57f..5a48a887f93 100644 --- a/tests/mir-opt/const_prop/ref_deref_project.rs +++ b/tests/mir-opt/const_prop/ref_deref_project.rs @@ -5,7 +5,6 @@ fn main() { // CHECK-LABEL: fn main( // CHECK: debug a => [[a:_.*]]; - // Disabled due to <https://github.com/rust-lang/rust/issues/130853> - // COM: CHECK: [[a]] = const 5_i32; + // CHECK: [[a]] = const 5_i32; let a = *(&(4, 5).1); } 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 0798b303929..d6e81debccd 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 @@ -40,7 +40,7 @@ bb1: { - _1 = copy (*_2)[_6]; -+ _1 = copy (*_2)[1 of 2]; ++ _1 = const 2_u32; StorageDead(_6); StorageDead(_4); StorageDead(_2); 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 c0b3d4d3219..6713e531892 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 @@ -40,7 +40,7 @@ bb1: { - _1 = copy (*_2)[_6]; -+ _1 = copy (*_2)[1 of 2]; ++ _1 = const 2_u32; StorageDead(_6); StorageDead(_4); StorageDead(_2); 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 0798b303929..d6e81debccd 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 @@ -40,7 +40,7 @@ bb1: { - _1 = copy (*_2)[_6]; -+ _1 = copy (*_2)[1 of 2]; ++ _1 = const 2_u32; StorageDead(_6); StorageDead(_4); StorageDead(_2); 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 c0b3d4d3219..6713e531892 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 @@ -40,7 +40,7 @@ bb1: { - _1 = copy (*_2)[_6]; -+ _1 = copy (*_2)[1 of 2]; ++ _1 = const 2_u32; StorageDead(_6); StorageDead(_4); StorageDead(_2); diff --git a/tests/mir-opt/const_prop/slice_len.rs b/tests/mir-opt/const_prop/slice_len.rs index 498e09fbb65..ebd3c9e792d 100644 --- a/tests/mir-opt/const_prop/slice_len.rs +++ b/tests/mir-opt/const_prop/slice_len.rs @@ -8,8 +8,7 @@ fn main() { // CHECK-LABEL: fn main( // CHECK: debug a => [[a:_.*]]; // CHECK: [[slice:_.*]] = copy {{.*}} as &[u32] (PointerCoercion(Unsize, AsCast)); - // Disabled due to <https://github.com/rust-lang/rust/issues/130853> - // COM: CHECK: assert(const true, - // COM: CHECK: [[a]] = const 2_u32; + // CHECK: assert(const true, + // CHECK: [[a]] = const 2_u32; let a = (&[1u32, 2, 3] as &[u32])[1]; } diff --git a/tests/mir-opt/const_prop/transmute.undef_union_as_integer.GVN.32bit.diff b/tests/mir-opt/const_prop/transmute.undef_union_as_integer.GVN.32bit.diff index febb6bfb0a4..2ac9769a0e7 100644 --- a/tests/mir-opt/const_prop/transmute.undef_union_as_integer.GVN.32bit.diff +++ b/tests/mir-opt/const_prop/transmute.undef_union_as_integer.GVN.32bit.diff @@ -10,8 +10,9 @@ StorageLive(_1); StorageLive(_2); - _2 = (); +- _1 = Union32 { value: move _2 }; + _2 = const (); - _1 = Union32 { value: move _2 }; ++ _1 = Union32 { value: const () }; StorageDead(_2); _0 = move _1 as u32 (Transmute); StorageDead(_1); diff --git a/tests/mir-opt/const_prop/transmute.undef_union_as_integer.GVN.64bit.diff b/tests/mir-opt/const_prop/transmute.undef_union_as_integer.GVN.64bit.diff index febb6bfb0a4..2ac9769a0e7 100644 --- a/tests/mir-opt/const_prop/transmute.undef_union_as_integer.GVN.64bit.diff +++ b/tests/mir-opt/const_prop/transmute.undef_union_as_integer.GVN.64bit.diff @@ -10,8 +10,9 @@ StorageLive(_1); StorageLive(_2); - _2 = (); +- _1 = Union32 { value: move _2 }; + _2 = const (); - _1 = Union32 { value: move _2 }; ++ _1 = Union32 { value: const () }; StorageDead(_2); _0 = move _1 as u32 (Transmute); StorageDead(_1); 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 557320f0179..ef418798faa 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,11 +5,10 @@ let mut _0: (); let _1: main::Un; let mut _2: u32; - let mut _3: u32; scope 1 { debug un => _1; scope 3 (inlined std::mem::drop::<u32>) { - debug _x => _3; + debug _x => _2; } } scope 2 (inlined val) { @@ -17,13 +16,10 @@ bb0: { StorageLive(_1); - StorageLive(_2); - nop; _1 = Un { us: const 1_u32 }; + StorageLive(_2); + _2 = copy (_1.0: u32); StorageDead(_2); - StorageLive(_3); - _3 = copy (_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 557320f0179..ef418798faa 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,11 +5,10 @@ let mut _0: (); let _1: main::Un; let mut _2: u32; - let mut _3: u32; scope 1 { debug un => _1; scope 3 (inlined std::mem::drop::<u32>) { - debug _x => _3; + debug _x => _2; } } scope 2 (inlined val) { @@ -17,13 +16,10 @@ bb0: { StorageLive(_1); - StorageLive(_2); - nop; _1 = Un { us: const 1_u32 }; + StorageLive(_2); + _2 = copy (_1.0: u32); StorageDead(_2); - StorageLive(_3); - _3 = copy (_1.0: u32); - StorageDead(_3); StorageDead(_1); return; } diff --git a/tests/mir-opt/gvn.borrowed.GVN.panic-abort.diff b/tests/mir-opt/gvn.borrowed.GVN.panic-abort.diff index acbea13642c..b0702696e18 100644 --- a/tests/mir-opt/gvn.borrowed.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.borrowed.GVN.panic-abort.diff @@ -18,7 +18,8 @@ } bb2: { - _0 = opaque::<T>(copy (*_3)) -> [return: bb3, unwind unreachable]; +- _0 = opaque::<T>(copy (*_3)) -> [return: bb3, unwind unreachable]; ++ _0 = opaque::<T>(copy _1) -> [return: bb3, unwind unreachable]; } bb3: { diff --git a/tests/mir-opt/gvn.borrowed.GVN.panic-unwind.diff b/tests/mir-opt/gvn.borrowed.GVN.panic-unwind.diff index ba080bfdb07..fe05d4deeed 100644 --- a/tests/mir-opt/gvn.borrowed.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.borrowed.GVN.panic-unwind.diff @@ -18,7 +18,8 @@ } bb2: { - _0 = opaque::<T>(copy (*_3)) -> [return: bb3, unwind continue]; +- _0 = opaque::<T>(copy (*_3)) -> [return: bb3, unwind continue]; ++ _0 = opaque::<T>(copy _1) -> [return: bb3, unwind continue]; } bb3: { 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 7f99b83d937..3cce35d34e9 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:615:19: 615:21}; + let mut _9: {closure@$DIR/gvn.rs:620:19: 620:21}; let _10: (); let mut _11: fn(); - let mut _13: {closure@$DIR/gvn.rs:615:19: 615:21}; + let mut _13: {closure@$DIR/gvn.rs:620:19: 620: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:615:19: 615:21}; + let _7: {closure@$DIR/gvn.rs:620:19: 620:21}; scope 3 { debug closure => _7; let _8: fn(); @@ -62,16 +62,16 @@ StorageDead(_6); StorageDead(_5); - StorageLive(_7); -- _7 = {closure@$DIR/gvn.rs:615:19: 615:21}; +- _7 = {closure@$DIR/gvn.rs:620:19: 620:21}; - StorageLive(_8); + nop; -+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21}; ++ _7 = const ZeroSized: {closure@$DIR/gvn.rs:620:19: 620:21}; + nop; StorageLive(_9); - _9 = copy _7; - _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); -+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21}; -+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); ++ _9 = const ZeroSized: {closure@$DIR/gvn.rs:620:19: 620:21}; ++ _8 = const ZeroSized: {closure@$DIR/gvn.rs:620:19: 620:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); StorageDead(_9); StorageLive(_10); StorageLive(_11); @@ -88,8 +88,8 @@ StorageLive(_13); - _13 = copy _7; - _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); -+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21}; -+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); ++ _13 = const ZeroSized: {closure@$DIR/gvn.rs:620:19: 620:21}; ++ _12 = const ZeroSized: {closure@$DIR/gvn.rs:620:19: 620:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); 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 06dd0502f30..d85aca040fe 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:615:19: 615:21}; + let mut _9: {closure@$DIR/gvn.rs:620:19: 620:21}; let _10: (); let mut _11: fn(); - let mut _13: {closure@$DIR/gvn.rs:615:19: 615:21}; + let mut _13: {closure@$DIR/gvn.rs:620:19: 620: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:615:19: 615:21}; + let _7: {closure@$DIR/gvn.rs:620:19: 620:21}; scope 3 { debug closure => _7; let _8: fn(); @@ -62,16 +62,16 @@ StorageDead(_6); StorageDead(_5); - StorageLive(_7); -- _7 = {closure@$DIR/gvn.rs:615:19: 615:21}; +- _7 = {closure@$DIR/gvn.rs:620:19: 620:21}; - StorageLive(_8); + nop; -+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21}; ++ _7 = const ZeroSized: {closure@$DIR/gvn.rs:620:19: 620:21}; + nop; StorageLive(_9); - _9 = copy _7; - _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); -+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21}; -+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); ++ _9 = const ZeroSized: {closure@$DIR/gvn.rs:620:19: 620:21}; ++ _8 = const ZeroSized: {closure@$DIR/gvn.rs:620:19: 620:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); StorageDead(_9); StorageLive(_10); StorageLive(_11); @@ -88,8 +88,8 @@ StorageLive(_13); - _13 = copy _7; - _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); -+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21}; -+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:615:19: 615:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); ++ _13 = const ZeroSized: {closure@$DIR/gvn.rs:620:19: 620:21}; ++ _12 = const ZeroSized: {closure@$DIR/gvn.rs:620:19: 620:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); StorageDead(_13); StorageLive(_14); StorageLive(_15); diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs index c895a579259..6ef320c90de 100644 --- a/tests/mir-opt/gvn.rs +++ b/tests/mir-opt/gvn.rs @@ -100,17 +100,18 @@ fn subexpression_elimination(x: u64, y: u64, mut z: u64) { opaque((x * y) - y); // We cannot substitute through an immutable reference. - // (Disabled due to <https://github.com/rust-lang/rust/issues/130853>) // CHECK: [[ref:_.*]] = &_3; // CHECK: [[deref:_.*]] = copy (*[[ref]]); - // COM: CHECK: [[addref:_.*]] = Add(copy [[deref]], copy _1); - // COM: CHECK: opaque::<u64>(copy [[addref]]) - // COM: CHECK: opaque::<u64>(copy [[addref]]) + // CHECK: [[addref:_.*]] = Add(move [[deref]], copy _1); + // CHECK: opaque::<u64>(move [[addref]]) + // CHECK: [[deref2:_.*]] = copy (*[[ref]]); + // CHECK: [[addref2:_.*]] = Add(move [[deref2]], copy _1); + // CHECK: opaque::<u64>(move [[addref2]]) let a = &z; opaque(*a + x); opaque(*a + x); - // And certainly not through a mutable reference or a pointer. + // But not through a mutable reference or a pointer. // CHECK: [[mut:_.*]] = &mut _3; // CHECK: [[addmut:_.*]] = Add( // CHECK: opaque::<u64>(move [[addmut]]) @@ -142,9 +143,11 @@ fn subexpression_elimination(x: u64, y: u64, mut z: u64) { // Important: `e` is not `a`! // CHECK: [[ref2:_.*]] = &_3; // CHECK: [[deref2:_.*]] = copy (*[[ref2]]); - // COM: CHECK: [[addref2:_.*]] = Add(copy [[deref2]], copy _1); - // COM: CHECK: opaque::<u64>(copy [[addref2]]) - // COM: CHECK: opaque::<u64>(copy [[addref2]]) + // CHECK: [[addref2:_.*]] = Add(move [[deref2]], copy _1); + // CHECK: opaque::<u64>(move [[addref2]]) + // CHECK: [[deref3:_.*]] = copy (*[[ref2]]); + // CHECK: [[addref3:_.*]] = Add(move [[deref3]], copy _1); + // CHECK: opaque::<u64>(move [[addref3]]) let e = &z; opaque(*e + x); opaque(*e + x); @@ -499,8 +502,9 @@ fn dereferences(t: &mut u32, u: &impl Copy, s: &S<u32>) { // Do not reuse dereferences of `&Freeze`. // CHECK: [[ref:_.*]] = &(*_1); // CHECK: [[st7:_.*]] = copy (*[[ref]]); - // COM: CHECK: opaque::<u32>(copy [[st7]]) - // COM: CHECK: opaque::<u32>(copy [[st7]]) + // CHECK: opaque::<u32>(move [[st7]]) + // CHECK: [[st8:_.*]] = copy (*[[ref]]); + // CHECK: opaque::<u32>(move [[st8]]) let z = &*t; opaque(*z); opaque(*z); @@ -519,8 +523,9 @@ fn dereferences(t: &mut u32, u: &impl Copy, s: &S<u32>) { // `*s` is not Copy, but `(*s).0` is, but we still cannot reuse. // CHECK: [[st10:_.*]] = copy ((*_3).0: u32); - // COM: CHECK: opaque::<u32>(copy [[st10]]) - // COM: CHECK: opaque::<u32>(copy [[st10]]) + // CHECK: opaque::<u32>(move [[st10]]) + // CHECK: [[st11:_.*]] = copy ((*_3).0: u32); + // CHECK: opaque::<u32>(move [[st11]]) opaque(s.0); opaque(s.0); } @@ -737,7 +742,7 @@ fn borrowed<T: Copy + Freeze>(x: T) { // CHECK: bb1: { // CHECK-NEXT: _0 = opaque::<T>(copy _1) // CHECK: bb2: { - // COM: CHECK-NEXT: _0 = opaque::<T>(copy _1) + // CHECK-NEXT: _0 = opaque::<T>(copy _1) mir! { { let a = x; diff --git a/tests/mir-opt/gvn.slices.GVN.panic-abort.diff b/tests/mir-opt/gvn.slices.GVN.panic-abort.diff index 43efcbdfb1e..e8e99b44e72 100644 --- a/tests/mir-opt/gvn.slices.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.slices.GVN.panic-abort.diff @@ -111,8 +111,9 @@ StorageLive(_7); StorageLive(_8); - StorageLive(_9); +- StorageLive(_10); ++ nop; + nop; - StorageLive(_10); StorageLive(_11); _11 = &(*_1); _10 = core::str::<impl str>::as_ptr(move _11) -> [return: bb3, unwind unreachable]; @@ -122,8 +123,9 @@ StorageDead(_11); _9 = &_10; - StorageLive(_12); +- StorageLive(_13); ++ nop; + nop; - StorageLive(_13); StorageLive(_14); - _14 = &(*_4); + _14 = &(*_1); @@ -148,11 +150,12 @@ StorageLive(_17); StorageLive(_18); - _18 = copy (*_15); -+ _18 = copy (*_9); ++ _18 = copy _10; StorageLive(_19); - _19 = copy (*_16); -+ _19 = copy (*_12); - _17 = Eq(move _18, move _19); +- _17 = Eq(move _18, move _19); ++ _19 = copy _13; ++ _17 = Eq(copy _10, copy _13); switchInt(move _17) -> [0: bb6, otherwise: bb5]; } @@ -163,8 +166,10 @@ StorageDead(_17); StorageDead(_16); StorageDead(_15); - StorageDead(_13); - StorageDead(_10); +- StorageDead(_13); +- StorageDead(_10); ++ nop; ++ nop; StorageDead(_8); StorageDead(_7); - StorageLive(_29); @@ -213,8 +218,9 @@ StorageLive(_33); StorageLive(_34); - StorageLive(_35); +- StorageLive(_36); ++ nop; + nop; - StorageLive(_36); StorageLive(_37); _37 = &(*_1); _36 = core::str::<impl str>::as_ptr(move _37) -> [return: bb8, unwind unreachable]; @@ -224,8 +230,9 @@ StorageDead(_37); _35 = &_36; - StorageLive(_38); +- StorageLive(_39); ++ nop; + nop; - StorageLive(_39); StorageLive(_40); _40 = &(*_29); _39 = core::slice::<impl [u8]>::as_ptr(move _40) -> [return: bb9, unwind unreachable]; @@ -249,11 +256,12 @@ StorageLive(_43); StorageLive(_44); - _44 = copy (*_41); -+ _44 = copy (*_35); ++ _44 = copy _36; StorageLive(_45); - _45 = copy (*_42); -+ _45 = copy (*_38); - _43 = Eq(move _44, move _45); +- _43 = Eq(move _44, move _45); ++ _45 = copy _39; ++ _43 = Eq(copy _36, copy _39); switchInt(move _43) -> [0: bb11, otherwise: bb10]; } @@ -264,8 +272,10 @@ StorageDead(_43); StorageDead(_42); StorageDead(_41); - StorageDead(_39); - StorageDead(_36); +- StorageDead(_39); +- StorageDead(_36); ++ nop; ++ nop; StorageDead(_34); StorageDead(_33); _0 = const (); diff --git a/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff b/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff index 8572f538c0f..4296d4d4a59 100644 --- a/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff @@ -111,8 +111,9 @@ StorageLive(_7); StorageLive(_8); - StorageLive(_9); +- StorageLive(_10); ++ nop; + nop; - StorageLive(_10); StorageLive(_11); _11 = &(*_1); _10 = core::str::<impl str>::as_ptr(move _11) -> [return: bb3, unwind continue]; @@ -122,8 +123,9 @@ StorageDead(_11); _9 = &_10; - StorageLive(_12); +- StorageLive(_13); ++ nop; + nop; - StorageLive(_13); StorageLive(_14); - _14 = &(*_4); + _14 = &(*_1); @@ -148,11 +150,12 @@ StorageLive(_17); StorageLive(_18); - _18 = copy (*_15); -+ _18 = copy (*_9); ++ _18 = copy _10; StorageLive(_19); - _19 = copy (*_16); -+ _19 = copy (*_12); - _17 = Eq(move _18, move _19); +- _17 = Eq(move _18, move _19); ++ _19 = copy _13; ++ _17 = Eq(copy _10, copy _13); switchInt(move _17) -> [0: bb6, otherwise: bb5]; } @@ -163,8 +166,10 @@ StorageDead(_17); StorageDead(_16); StorageDead(_15); - StorageDead(_13); - StorageDead(_10); +- StorageDead(_13); +- StorageDead(_10); ++ nop; ++ nop; StorageDead(_8); StorageDead(_7); - StorageLive(_29); @@ -213,8 +218,9 @@ StorageLive(_33); StorageLive(_34); - StorageLive(_35); +- StorageLive(_36); ++ nop; + nop; - StorageLive(_36); StorageLive(_37); _37 = &(*_1); _36 = core::str::<impl str>::as_ptr(move _37) -> [return: bb8, unwind continue]; @@ -224,8 +230,9 @@ StorageDead(_37); _35 = &_36; - StorageLive(_38); +- StorageLive(_39); ++ nop; + nop; - StorageLive(_39); StorageLive(_40); _40 = &(*_29); _39 = core::slice::<impl [u8]>::as_ptr(move _40) -> [return: bb9, unwind continue]; @@ -249,11 +256,12 @@ StorageLive(_43); StorageLive(_44); - _44 = copy (*_41); -+ _44 = copy (*_35); ++ _44 = copy _36; StorageLive(_45); - _45 = copy (*_42); -+ _45 = copy (*_38); - _43 = Eq(move _44, move _45); +- _43 = Eq(move _44, move _45); ++ _45 = copy _39; ++ _43 = Eq(copy _36, copy _39); switchInt(move _43) -> [0: bb11, otherwise: bb10]; } @@ -264,8 +272,10 @@ StorageDead(_43); StorageDead(_42); StorageDead(_41); - StorageDead(_39); - StorageDead(_36); +- StorageDead(_39); +- StorageDead(_36); ++ nop; ++ nop; StorageDead(_34); StorageDead(_33); _0 = const (); diff --git a/tests/mir-opt/gvn_clone.rs b/tests/mir-opt/gvn_clone.rs index c16b665fbd3..08938c0e1b4 100644 --- a/tests/mir-opt/gvn_clone.rs +++ b/tests/mir-opt/gvn_clone.rs @@ -1,5 +1,3 @@ -//@ compile-flags: -Zunsound-mir-opts -// FIXME: see <https://github.com/rust-lang/rust/issues/132353> //@ test-mir-pass: GVN //@ compile-flags: -Zmir-enable-passes=+InstSimplify-before-inline diff --git a/tests/mir-opt/gvn_clone.{impl#0}-clone.GVN.diff b/tests/mir-opt/gvn_clone.{impl#0}-clone.GVN.diff index 2a672e82970..0f23415ec53 100644 --- a/tests/mir-opt/gvn_clone.{impl#0}-clone.GVN.diff +++ b/tests/mir-opt/gvn_clone.{impl#0}-clone.GVN.diff @@ -1,7 +1,7 @@ -- // MIR for `<impl at $DIR/gvn_clone.rs:14:10: 14:15>::clone` before GVN -+ // MIR for `<impl at $DIR/gvn_clone.rs:14:10: 14:15>::clone` after GVN +- // MIR for `<impl at $DIR/gvn_clone.rs:12:10: 12:15>::clone` before GVN ++ // MIR for `<impl at $DIR/gvn_clone.rs:12:10: 12:15>::clone` after GVN - fn <impl at $DIR/gvn_clone.rs:14:10: 14:15>::clone(_1: &AllCopy) -> AllCopy { + fn <impl at $DIR/gvn_clone.rs:12:10: 12:15>::clone(_1: &AllCopy) -> AllCopy { debug self => _1; let mut _0: AllCopy; let mut _2: i32; diff --git a/tests/mir-opt/gvn_copy_aggregate.rs b/tests/mir-opt/gvn_copy_aggregate.rs index 7c181d1ad37..c9473025a15 100644 --- a/tests/mir-opt/gvn_copy_aggregate.rs +++ b/tests/mir-opt/gvn_copy_aggregate.rs @@ -1,5 +1,3 @@ -//@ compile-flags: -Zunsound-mir-opts -// FIXME: see <https://github.com/rust-lang/rust/issues/132353. //@ test-mir-pass: GVN //@ compile-flags: -Cpanic=abort diff --git a/tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff index 881b629803a..a3e4796d088 100644 --- a/tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff @@ -17,15 +17,16 @@ StorageLive(_3); _5 = const f::promoted[0]; _3 = &(*_5); - _2 = copy ((*_3).1: E); -- StorageLive(_1); -+ nop; - _1 = copy ((_2 as A).1: u32); +- _2 = copy ((*_3).1: E); ++ _2 = const Scalar(0x00000000): E; + StorageLive(_1); +- _1 = copy ((_2 as A).1: u32); ++ _1 = const 0_u32; StorageDead(_3); StorageDead(_2); - _0 = copy _1; -- StorageDead(_1); -+ nop; +- _0 = copy _1; ++ _0 = const 0_u32; + StorageDead(_1); return; } } diff --git a/tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff index 881b629803a..a3e4796d088 100644 --- a/tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff @@ -17,15 +17,16 @@ StorageLive(_3); _5 = const f::promoted[0]; _3 = &(*_5); - _2 = copy ((*_3).1: E); -- StorageLive(_1); -+ nop; - _1 = copy ((_2 as A).1: u32); +- _2 = copy ((*_3).1: E); ++ _2 = const Scalar(0x00000000): E; + StorageLive(_1); +- _1 = copy ((_2 as A).1: u32); ++ _1 = const 0_u32; StorageDead(_3); StorageDead(_2); - _0 = copy _1; -- StorageDead(_1); -+ nop; +- _0 = copy _1; ++ _0 = const 0_u32; + StorageDead(_1); return; } } diff --git a/tests/mir-opt/pre-codegen/clone_as_copy.rs b/tests/mir-opt/pre-codegen/clone_as_copy.rs index ae4661e93fd..f5ff1854d38 100644 --- a/tests/mir-opt/pre-codegen/clone_as_copy.rs +++ b/tests/mir-opt/pre-codegen/clone_as_copy.rs @@ -1,5 +1,3 @@ -//@ compile-flags: -Zunsound-mir-opts -// FIXME: see <https://github.com/rust-lang/rust/issues/132353> //@ compile-flags: -Cdebuginfo=full // Check if we have transformed the nested clone to the copy in the complete pipeline. diff --git a/tests/mir-opt/pre-codegen/deref_nested_borrows.rs b/tests/mir-opt/pre-codegen/deref_nested_borrows.rs index 4f70ec36bc9..738cd981ae6 100644 --- a/tests/mir-opt/pre-codegen/deref_nested_borrows.rs +++ b/tests/mir-opt/pre-codegen/deref_nested_borrows.rs @@ -1,4 +1,3 @@ -//! Regression test for <https://github.com/rust-lang/rust/issues/130853> // EMIT_MIR_FOR_EACH_PANIC_STRATEGY fn src(x: &&u8) -> bool { diff --git a/tests/mir-opt/pre-codegen/no_inlined_clone.{impl#0}-clone.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/no_inlined_clone.{impl#0}-clone.PreCodegen.after.mir index 62a9cd9131f..9020cf1ef37 100644 --- a/tests/mir-opt/pre-codegen/no_inlined_clone.{impl#0}-clone.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/no_inlined_clone.{impl#0}-clone.PreCodegen.after.mir @@ -3,13 +3,9 @@ fn <impl at $DIR/no_inlined_clone.rs:9:10: 9:15>::clone(_1: &Foo) -> Foo { debug self => _1; let mut _0: Foo; - let mut _2: i32; bb0: { - StorageLive(_2); - _2 = copy ((*_1).0: i32); - _0 = Foo { a: move _2 }; - StorageDead(_2); + _0 = copy (*_1); return; } } 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 5a269717f82..cbdd194afd3 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 @@ -4,70 +4,65 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2 let mut _0: bool; let mut _3: &(usize, usize, usize, usize); let _4: &usize; - let mut _5: &(usize, usize, usize, usize); + let _5: &usize; let _6: &usize; - let mut _7: &(usize, usize, usize, usize); - let _8: &usize; - let mut _9: &(usize, usize, usize, usize); - let _10: &usize; - let mut _11: &&usize; - let _12: &usize; - let mut _13: &&usize; - let mut _16: bool; - let mut _17: &&usize; - let _18: &usize; - let mut _19: &&usize; - let mut _22: bool; - let mut _23: &&usize; - let _24: &usize; - let mut _25: &&usize; - let mut _28: bool; - let mut _29: &&usize; - let _30: &usize; - let mut _31: &&usize; + let _7: &usize; + let mut _8: &&usize; + let _9: &usize; + let mut _10: &&usize; + let mut _13: bool; + let mut _14: &&usize; + let _15: &usize; + let mut _16: &&usize; + let mut _19: bool; + let mut _20: &&usize; + let _21: &usize; + let mut _22: &&usize; + let mut _23: bool; + let mut _24: &&usize; + let _25: &usize; + let mut _26: &&usize; scope 1 { debug a => _4; - debug b => _6; - debug c => _8; - debug d => _10; + debug b => _5; + debug c => _6; + debug d => _7; scope 2 (inlined std::cmp::impls::<impl PartialOrd for &usize>::le) { - debug self => _11; - debug other => _13; + debug self => _8; + debug other => _10; scope 3 (inlined std::cmp::impls::<impl PartialOrd for usize>::le) { debug self => _4; - debug other => _8; - let mut _14: usize; - let mut _15: usize; + debug other => _6; + let mut _11: usize; + let mut _12: usize; } } scope 4 (inlined std::cmp::impls::<impl PartialOrd for &usize>::le) { - debug self => _17; - debug other => _19; + debug self => _14; + debug other => _16; scope 5 (inlined std::cmp::impls::<impl PartialOrd for usize>::le) { - debug self => _10; - debug other => _6; - let mut _20: usize; - let mut _21: usize; + debug self => _7; + debug other => _5; + let mut _17: usize; + let mut _18: usize; } } scope 6 (inlined std::cmp::impls::<impl PartialOrd for &usize>::le) { - debug self => _23; - debug other => _25; + debug self => _20; + debug other => _22; scope 7 (inlined std::cmp::impls::<impl PartialOrd for usize>::le) { - debug self => _8; + debug self => _6; debug other => _4; - let mut _26: usize; - let mut _27: usize; } } scope 8 (inlined std::cmp::impls::<impl PartialOrd for &usize>::le) { - debug self => _29; - debug other => _31; + debug self => _24; + debug other => _26; scope 9 (inlined std::cmp::impls::<impl PartialOrd for usize>::le) { - debug self => _6; - debug other => _10; - let mut _32: usize; - let mut _33: usize; + debug self => _5; + debug other => _7; + let mut _27: usize; + let mut _28: usize; } } } @@ -75,129 +70,116 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2 bb0: { _3 = copy (*_2); _4 = &((*_3).0: usize); - _5 = copy (*_2); - _6 = &((*_5).1: usize); - _7 = copy (*_2); - _8 = &((*_7).2: usize); - _9 = copy (*_2); - _10 = &((*_9).3: usize); - StorageLive(_16); - StorageLive(_11); - _11 = &_4; + _5 = &((*_3).1: usize); + _6 = &((*_3).2: usize); + _7 = &((*_3).3: usize); StorageLive(_13); - StorageLive(_12); - _12 = copy _8; - _13 = &_12; - StorageLive(_14); - _14 = copy ((*_3).0: usize); - StorageLive(_15); - _15 = copy ((*_7).2: usize); - _16 = Le(move _14, move _15); - StorageDead(_15); - StorageDead(_14); - switchInt(move _16) -> [0: bb1, otherwise: bb2]; + StorageLive(_8); + _8 = &_4; + StorageLive(_10); + StorageLive(_9); + _9 = copy _6; + _10 = &_9; + _11 = copy ((*_3).0: usize); + _12 = copy ((*_3).2: usize); + _13 = Le(copy _11, copy _12); + switchInt(move _13) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageDead(_12); - StorageDead(_13); - StorageDead(_11); + StorageDead(_9); + StorageDead(_10); + StorageDead(_8); goto -> bb4; } bb2: { - StorageDead(_12); - StorageDead(_13); - StorageDead(_11); - StorageLive(_22); - StorageLive(_17); - _17 = &_10; + StorageDead(_9); + StorageDead(_10); + StorageDead(_8); StorageLive(_19); + StorageLive(_14); + _14 = &_7; + StorageLive(_16); + StorageLive(_15); + _15 = copy _5; + _16 = &_15; + StorageLive(_17); + _17 = copy ((*_3).3: usize); StorageLive(_18); - _18 = copy _6; - _19 = &_18; - StorageLive(_20); - _20 = copy ((*_9).3: usize); - StorageLive(_21); - _21 = copy ((*_5).1: usize); - _22 = Le(move _20, move _21); - StorageDead(_21); - StorageDead(_20); - switchInt(move _22) -> [0: bb3, otherwise: bb8]; + _18 = copy ((*_3).1: usize); + _19 = Le(move _17, move _18); + StorageDead(_18); + StorageDead(_17); + switchInt(move _19) -> [0: bb3, otherwise: bb8]; } bb3: { - StorageDead(_18); - StorageDead(_19); - StorageDead(_17); + StorageDead(_15); + StorageDead(_16); + StorageDead(_14); goto -> bb4; } bb4: { - StorageLive(_28); StorageLive(_23); - _23 = &_8; - StorageLive(_25); - StorageLive(_24); - _24 = copy _4; - _25 = &_24; - StorageLive(_26); - _26 = copy ((*_7).2: usize); - StorageLive(_27); - _27 = copy ((*_3).0: usize); - _28 = Le(move _26, move _27); - StorageDead(_27); - StorageDead(_26); - switchInt(move _28) -> [0: bb5, otherwise: bb6]; + StorageLive(_20); + _20 = &_6; + StorageLive(_22); + StorageLive(_21); + _21 = copy _4; + _22 = &_21; + _23 = Le(copy _12, copy _11); + switchInt(move _23) -> [0: bb5, otherwise: bb6]; } bb5: { - StorageDead(_24); - StorageDead(_25); - StorageDead(_23); + StorageDead(_21); + StorageDead(_22); + StorageDead(_20); _0 = const false; goto -> bb7; } bb6: { - StorageDead(_24); + StorageDead(_21); + StorageDead(_22); + StorageDead(_20); + StorageLive(_24); + _24 = &_5; + StorageLive(_26); + StorageLive(_25); + _25 = copy _7; + _26 = &_25; + StorageLive(_27); + _27 = copy ((*_3).1: usize); + StorageLive(_28); + _28 = copy ((*_3).3: usize); + _0 = Le(move _27, move _28); + StorageDead(_28); + StorageDead(_27); StorageDead(_25); - StorageDead(_23); - StorageLive(_29); - _29 = &_6; - StorageLive(_31); - StorageLive(_30); - _30 = copy _10; - _31 = &_30; - StorageLive(_32); - _32 = copy ((*_5).1: usize); - StorageLive(_33); - _33 = copy ((*_9).3: usize); - _0 = Le(move _32, move _33); - StorageDead(_33); - StorageDead(_32); - StorageDead(_30); - StorageDead(_31); - StorageDead(_29); + StorageDead(_26); + StorageDead(_24); goto -> bb7; } bb7: { - StorageDead(_28); + StorageDead(_23); goto -> bb9; } bb8: { - StorageDead(_18); - StorageDead(_19); - StorageDead(_17); + StorageDead(_15); + StorageDead(_16); + StorageDead(_14); _0 = const true; goto -> bb9; } bb9: { - StorageDead(_22); - StorageDead(_16); + StorageDead(_19); + StorageDead(_13); return; } } diff --git a/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir index f93f7264dec..bc7a31d5219 100644 --- a/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir @@ -4,46 +4,40 @@ fn variant_b::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:11:25: 11:41}, let mut _0: bool; let mut _3: &(usize, usize, usize, usize); let _4: usize; - let mut _5: &(usize, usize, usize, usize); + let _5: usize; let _6: usize; - let mut _7: &(usize, usize, usize, usize); - let _8: usize; - let mut _9: &(usize, usize, usize, usize); - let _10: usize; - let mut _11: bool; - let mut _12: bool; - let mut _13: bool; + let _7: usize; + let mut _8: bool; + let mut _9: bool; + let mut _10: bool; scope 1 { debug a => _4; - debug b => _6; - debug c => _8; - debug d => _10; + debug b => _5; + debug c => _6; + debug d => _7; } bb0: { _3 = copy (*_2); _4 = copy ((*_3).0: usize); - _5 = copy (*_2); - _6 = copy ((*_5).1: usize); - _7 = copy (*_2); - _8 = copy ((*_7).2: usize); - _9 = copy (*_2); - _10 = copy ((*_9).3: usize); - StorageLive(_11); - _11 = Le(copy _4, copy _8); - switchInt(move _11) -> [0: bb2, otherwise: bb1]; + _5 = copy ((*_3).1: usize); + _6 = copy ((*_3).2: usize); + _7 = copy ((*_3).3: usize); + StorageLive(_8); + _8 = Le(copy _4, copy _6); + switchInt(move _8) -> [0: bb2, otherwise: bb1]; } bb1: { - StorageLive(_12); - _12 = Le(copy _10, copy _6); - switchInt(move _12) -> [0: bb2, otherwise: bb6]; + StorageLive(_9); + _9 = Le(copy _7, copy _5); + switchInt(move _9) -> [0: bb2, otherwise: bb6]; } bb2: { - StorageLive(_13); - _13 = Le(copy _8, copy _4); - switchInt(move _13) -> [0: bb3, otherwise: bb4]; + StorageLive(_10); + _10 = Le(copy _6, copy _4); + switchInt(move _10) -> [0: bb3, otherwise: bb4]; } bb3: { @@ -52,12 +46,12 @@ fn variant_b::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:11:25: 11:41}, } bb4: { - _0 = Le(copy _6, copy _10); + _0 = Le(copy _5, copy _7); goto -> bb5; } bb5: { - StorageDead(_13); + StorageDead(_10); goto -> bb7; } @@ -67,8 +61,8 @@ fn variant_b::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:11:25: 11:41}, } bb7: { - StorageDead(_12); - StorageDead(_11); + StorageDead(_9); + StorageDead(_8); return; } } 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 ac485f485b1..889e80d26e1 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 @@ -19,14 +19,14 @@ fn old(_1: Result<T, E>) -> Result<T, E> { } bb1: { - _3 = move ((_1 as Ok).0: T); - _0 = Result::<T, E>::Ok(copy _3); + _3 = copy ((_1 as Ok).0: T); + _0 = copy _1; goto -> bb3; } bb2: { - _4 = move ((_1 as Err).0: E); - _0 = Result::<T, E>::Err(copy _4); + _4 = copy ((_1 as Err).0: E); + _0 = copy _1; goto -> bb3; } diff --git a/tests/mir-opt/simplify_aggregate_to_copy_miscompile.foo.GVN.diff b/tests/mir-opt/simplify_aggregate_to_copy_miscompile.foo.GVN.diff index 22d4277ee45..54c11679f0c 100644 --- a/tests/mir-opt/simplify_aggregate_to_copy_miscompile.foo.GVN.diff +++ b/tests/mir-opt/simplify_aggregate_to_copy_miscompile.foo.GVN.diff @@ -6,62 +6,52 @@ let mut _0: std::option::Option<i32>; let mut _2: &std::option::Option<i32>; let mut _3: &std::option::Option<i32>; - let _4: &&mut std::option::Option<i32>; - let mut _5: isize; - let mut _7: !; - let mut _8: std::option::Option<i32>; - let mut _9: i32; - let mut _10: !; - let mut _11: &mut std::option::Option<i32>; + let mut _4: isize; + let mut _6: !; + let mut _7: std::option::Option<i32>; + let mut _8: i32; + let mut _9: !; scope 1 { - debug col => _6; - let _6: i32; + debug col => _5; + let _5: i32; } bb0: { -- StorageLive(_2); -+ nop; + StorageLive(_2); StorageLive(_3); - StorageLive(_4); - _4 = &_1; -- _11 = deref_copy (*_4); -- _3 = &(*_11); -+ _11 = copy _1; -+ _3 = &(*_1); - _2 = get(move _3) -> [return: bb1, unwind unreachable]; + _3 = &(*_1); + _2 = get::<Option<i32>>(move _3) -> [return: bb1, unwind unreachable]; } bb1: { StorageDead(_3); - _5 = discriminant((*_2)); - switchInt(move _5) -> [1: bb2, otherwise: bb3]; + _4 = discriminant((*_2)); + switchInt(move _4) -> [1: bb2, otherwise: bb3]; } bb2: { -- StorageLive(_6); +- StorageLive(_5); + nop; - _6 = copy (((*_2) as Some).0: i32); - StorageLive(_8); -- _8 = Option::<i32>::None; -- (*_1) = move _8; -+ _8 = const Option::<i32>::None; + _5 = copy (((*_2) as Some).0: i32); + StorageLive(_7); +- _7 = Option::<i32>::None; +- (*_1) = move _7; ++ _7 = const Option::<i32>::None; + (*_1) = const Option::<i32>::None; + StorageDead(_7); + StorageLive(_8); + _8 = copy _5; +- _0 = Option::<i32>::Some(move _8); ++ _0 = Option::<i32>::Some(copy _5); StorageDead(_8); - StorageLive(_9); - _9 = copy _6; -- _0 = Option::<i32>::Some(move _9); -+ _0 = copy (*_2); - StorageDead(_9); -- StorageDead(_6); -+ nop; - StorageDead(_4); -- StorageDead(_2); +- StorageDead(_5); + nop; + StorageDead(_2); return; } bb3: { - StorageLive(_10); + StorageLive(_9); unreachable; } + } diff --git a/tests/mir-opt/simplify_aggregate_to_copy_miscompile.rs b/tests/mir-opt/simplify_aggregate_to_copy_miscompile.rs index 47721b768be..33e31b56977 100644 --- a/tests/mir-opt/simplify_aggregate_to_copy_miscompile.rs +++ b/tests/mir-opt/simplify_aggregate_to_copy_miscompile.rs @@ -7,16 +7,23 @@ //! This test demonstrates the behavior, and should be adjusted or removed when fixing and relanding //! the mir-opt. #![crate_type = "lib"] -// skip-filecheck -//@ compile-flags: -O -Zunsound-mir-opts //@ test-mir-pass: GVN #![allow(internal_features)] -#![feature(rustc_attrs, core_intrinsics)] +#![feature(core_intrinsics, custom_mir, rustc_attrs)] + +use std::intrinsics::mir::*; // EMIT_MIR simplify_aggregate_to_copy_miscompile.foo.GVN.diff -#[no_mangle] fn foo(v: &mut Option<i32>) -> Option<i32> { - if let &Some(col) = get(&v) { + // CHECK-LABEL: fn foo( + // CHECK-SAME: [[v:_.*]]: &mut Option<i32> + // CHECK: [[v_alias_1:_.*]] = &(*_1) + // CHECK-NEXT: [[v_alias_2:_.*]] = get::<Option<i32>>(move [[v_alias_1]]) + // CHECK: (*[[v]]) = const Option::<i32>::None; + // CHECK-NOT: _0 = copy (*[[v_alias_2]]) + // CHECK: _0 = Option::<i32>::Some + // CHECK-NOT: _0 = copy (*[[v_alias_2]]) + if let &Some(col) = get(v) { *v = None; return Some(col); } else { @@ -24,9 +31,31 @@ fn foo(v: &mut Option<i32>) -> Option<i32> { } } -#[no_mangle] +pub enum Value { + V0(i32), + V1(i32), +} + +// EMIT_MIR simplify_aggregate_to_copy_miscompile.set_discriminant.GVN.diff +#[custom_mir(dialect = "runtime", phase = "initial")] +fn set_discriminant(v: &mut Value) -> Value { + // CHECK-LABEL: fn set_discriminant( + mir! { + let v_: &Value; + { + Call(v_ = get(v), ReturnTo(ret), UnwindUnreachable()) + } + ret = { + let col: i32 = Field(Variant(*v_, 0), 0); + SetDiscriminant(*v, 1); + RET = Value::V0(col); + Return() + } + } +} + #[inline(never)] #[rustc_nounwind] -fn get(v: &Option<i32>) -> &Option<i32> { +fn get<T>(v: &T) -> &T { v } diff --git a/tests/mir-opt/simplify_aggregate_to_copy_miscompile.set_discriminant.GVN.diff b/tests/mir-opt/simplify_aggregate_to_copy_miscompile.set_discriminant.GVN.diff new file mode 100644 index 00000000000..41f9763d024 --- /dev/null +++ b/tests/mir-opt/simplify_aggregate_to_copy_miscompile.set_discriminant.GVN.diff @@ -0,0 +1,20 @@ +- // MIR for `set_discriminant` before GVN ++ // MIR for `set_discriminant` after GVN + + fn set_discriminant(_1: &mut Value) -> Value { + let mut _0: Value; + let mut _2: &Value; + let mut _3: i32; + + bb0: { + _2 = get::<Value>(copy _1) -> [return: bb1, unwind unreachable]; + } + + bb1: { + _3 = copy (((*_2) as variant#0).0: i32); + discriminant((*_1)) = 1; + _0 = Value::V0(copy _3); + return; + } + } + diff --git a/tests/rustdoc-ui/doctest/no-run-flag-error.rs b/tests/rustdoc-ui/doctest/no-run-flag-error.rs index 896d7729b8d..3f9016b23db 100644 --- a/tests/rustdoc-ui/doctest/no-run-flag-error.rs +++ b/tests/rustdoc-ui/doctest/no-run-flag-error.rs @@ -1,6 +1,7 @@ // test the behavior of the --no-run flag without the --test flag //@ compile-flags:-Z unstable-options --no-run --test-args=--test-threads=1 -//@ error-pattern: the `--test` flag must be passed pub fn f() {} + +//~? ERROR the `--test` flag must be passed to enable `--no-run` diff --git a/tests/rustdoc-ui/invalid-theme-name.rs b/tests/rustdoc-ui/invalid-theme-name.rs index d632a08ebc8..7f1d191c89d 100644 --- a/tests/rustdoc-ui/invalid-theme-name.rs +++ b/tests/rustdoc-ui/invalid-theme-name.rs @@ -1,3 +1,4 @@ //@ compile-flags:--theme {{src-base}}/invalid-theme-name.rs -//@ error-pattern: invalid argument //@ error-pattern: must have a .css extension + +//~? ERROR invalid argument: "$DIR/invalid-theme-name.rs" diff --git a/tests/rustdoc-ui/issues/issue-91713.rs b/tests/rustdoc-ui/issues/issue-91713.rs index 9875b5d4ad6..68240726007 100644 --- a/tests/rustdoc-ui/issues/issue-91713.rs +++ b/tests/rustdoc-ui/issues/issue-91713.rs @@ -1,3 +1,4 @@ //@ check-pass //@ compile-flags: --passes list -//@ error-pattern: the `passes` flag no longer functions + +//~? WARN the `passes` flag no longer functions diff --git a/tests/rustdoc-ui/lints/no-crate-level-doc-lint.rs b/tests/rustdoc-ui/lints/no-crate-level-doc-lint.rs index 6e631061e8a..5e7dc377f5d 100644 --- a/tests/rustdoc-ui/lints/no-crate-level-doc-lint.rs +++ b/tests/rustdoc-ui/lints/no-crate-level-doc-lint.rs @@ -1,6 +1,7 @@ -//@ error-pattern: no documentation found //@ normalize-stderr: "nightly|beta|1\.[0-9][0-9]\.[0-9]" -> "$$CHANNEL" #![deny(rustdoc::missing_crate_level_docs)] //^~ NOTE defined here pub fn foo() {} + +//~? ERROR no documentation found for this crate's top-level module diff --git a/tests/rustdoc-ui/lints/no-crate-level-doc-lint.stderr b/tests/rustdoc-ui/lints/no-crate-level-doc-lint.stderr index 3a748335ea8..721d3662c93 100644 --- a/tests/rustdoc-ui/lints/no-crate-level-doc-lint.stderr +++ b/tests/rustdoc-ui/lints/no-crate-level-doc-lint.stderr @@ -3,7 +3,7 @@ error: no documentation found for this crate's top-level module = help: The following guide may be of use: https://doc.rust-lang.org/$CHANNEL/rustdoc/how-to-write-documentation.html note: the lint level is defined here - --> $DIR/no-crate-level-doc-lint.rs:3:9 + --> $DIR/no-crate-level-doc-lint.rs:2:9 | LL | #![deny(rustdoc::missing_crate_level_docs)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/rustdoc-ui/track-diagnostics.rs b/tests/rustdoc-ui/track-diagnostics.rs index 27781f47e0d..d18d26bf794 100644 --- a/tests/rustdoc-ui/track-diagnostics.rs +++ b/tests/rustdoc-ui/track-diagnostics.rs @@ -8,4 +8,4 @@ struct A; struct B; -pub const S: A = B; +pub const S: A = B; //~ ERROR mismatched types diff --git a/tests/ui-fulldeps/missing-rustc-driver-error.rs b/tests/ui-fulldeps/missing-rustc-driver-error.rs index 03ab5ce7b25..d582efada90 100644 --- a/tests/ui-fulldeps/missing-rustc-driver-error.rs +++ b/tests/ui-fulldeps/missing-rustc-driver-error.rs @@ -1,6 +1,6 @@ // Test that we get the following hint when trying to use a compiler crate without rustc_driver. //@ error-pattern: try adding `extern crate rustc_driver;` at the top level of this crate -//@ compile-flags: --emit link +//@ compile-flags: --emit link --error-format=human //@ normalize-stderr: ".*crate .* required.*\n\n" -> "" //@ normalize-stderr: "aborting due to [0-9]+" -> "aborting due to NUMBER" diff --git a/tests/ui/abi/fixed_x18.rs b/tests/ui/abi/fixed_x18.rs index f1ff3e1d534..d373468f68f 100644 --- a/tests/ui/abi/fixed_x18.rs +++ b/tests/ui/abi/fixed_x18.rs @@ -23,3 +23,5 @@ #[lang = "sized"] trait Sized {} + +//~? ERROR the `-Zfixed-x18` flag is not supported on the ` diff --git a/tests/ui/abi/shadow-call-stack-without-fixed-x18.rs b/tests/ui/abi/shadow-call-stack-without-fixed-x18.rs index d758c903087..74882fb5c55 100644 --- a/tests/ui/abi/shadow-call-stack-without-fixed-x18.rs +++ b/tests/ui/abi/shadow-call-stack-without-fixed-x18.rs @@ -1,5 +1,4 @@ //@ compile-flags: --target aarch64-unknown-none -Zsanitizer=shadow-call-stack -//@ error-pattern: shadow-call-stack sanitizer is not supported for this target //@ dont-check-compiler-stderr //@ needs-llvm-components: aarch64 @@ -13,3 +12,5 @@ trait Sized {} #[no_mangle] pub fn foo() {} + +//~? ERROR shadow-call-stack sanitizer is not supported for this target diff --git a/tests/ui/allocator/two-allocators2.rs b/tests/ui/allocator/two-allocators2.rs index b3bb4598c77..6efb297054b 100644 --- a/tests/ui/allocator/two-allocators2.rs +++ b/tests/ui/allocator/two-allocators2.rs @@ -1,6 +1,5 @@ //@ aux-build:system-allocator.rs //@ no-prefer-dynamic -//@ error-pattern: the `#[global_allocator]` in extern crate system_allocator; @@ -10,3 +9,5 @@ use std::alloc::System; static A: System = System; fn main() {} + +//~? ERROR the `#[global_allocator]` in this crate conflicts with global allocator in: system_allocator diff --git a/tests/ui/allocator/two-allocators3.rs b/tests/ui/allocator/two-allocators3.rs index 0cb3879666d..3aba96068de 100644 --- a/tests/ui/allocator/two-allocators3.rs +++ b/tests/ui/allocator/two-allocators3.rs @@ -1,10 +1,10 @@ //@ aux-build:system-allocator.rs //@ aux-build:system-allocator2.rs //@ no-prefer-dynamic -//@ error-pattern: the `#[global_allocator]` in - extern crate system_allocator; extern crate system_allocator2; fn main() {} + +//~? ERROR the `#[global_allocator]` in system_allocator conflicts with global allocator in: system_allocator2 diff --git a/tests/ui/amdgpu-require-explicit-cpu.rs b/tests/ui/amdgpu-require-explicit-cpu.rs index 46778a1094f..d40cb97977d 100644 --- a/tests/ui/amdgpu-require-explicit-cpu.rs +++ b/tests/ui/amdgpu-require-explicit-cpu.rs @@ -3,7 +3,6 @@ //@ compile-flags: --crate-type=cdylib --target=amdgcn-amd-amdhsa //@ needs-llvm-components: amdgpu //@ needs-rust-lld -//@[nocpu] error-pattern: target requires explicitly specifying a cpu //@[nocpu] build-fail //@[cpu] compile-flags: -Ctarget-cpu=gfx900 //@[cpu] build-pass @@ -15,3 +14,5 @@ trait Sized {} pub fn foo() {} + +//[nocpu]~? ERROR target requires explicitly specifying a cpu with `-C target-cpu` diff --git a/tests/ui/associated-types/issue-36499.rs b/tests/ui/associated-types/issue-36499.rs index 25f4060fa6f..606918b40b7 100644 --- a/tests/ui/associated-types/issue-36499.rs +++ b/tests/ui/associated-types/issue-36499.rs @@ -1,5 +1,5 @@ //@ error-pattern: aborting due to 1 previous error fn main() { - 2 + +2; + 2 + +2; //~ ERROR leading `+` is not supported } diff --git a/tests/ui/attributes/attr-bad-crate-attr.rs b/tests/ui/attributes/attr-bad-crate-attr.rs index 9de0abca9a7..d37d349026a 100644 --- a/tests/ui/attributes/attr-bad-crate-attr.rs +++ b/tests/ui/attributes/attr-bad-crate-attr.rs @@ -3,7 +3,6 @@ //! //! See <https://doc.rust-lang.org/reference/attributes.html>. -//@ error-pattern: expected item - #![attr = "val"] #[attr = "val"] // Unterminated +//~^ ERROR expected item after attributes diff --git a/tests/ui/attributes/attr-bad-crate-attr.stderr b/tests/ui/attributes/attr-bad-crate-attr.stderr index 69eabd32230..22522896bd1 100644 --- a/tests/ui/attributes/attr-bad-crate-attr.stderr +++ b/tests/ui/attributes/attr-bad-crate-attr.stderr @@ -1,5 +1,5 @@ error: expected item after attributes - --> $DIR/attr-bad-crate-attr.rs:9:1 + --> $DIR/attr-bad-crate-attr.rs:7:1 | LL | #[attr = "val"] // Unterminated | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/attributes/z-crate-attr/garbage.rs b/tests/ui/attributes/z-crate-attr/garbage.rs index ec81dd1bcaa..69444e1935a 100644 --- a/tests/ui/attributes/z-crate-attr/garbage.rs +++ b/tests/ui/attributes/z-crate-attr/garbage.rs @@ -1,4 +1,7 @@ // Show diagnostics for invalid tokens //@ compile-flags: -Zcrate-attr=`%~@$# -//@ error-pattern:unknown start of token + fn main() {} + +//~? ERROR unknown start of token: ` +//~? ERROR expected identifier, found `%` diff --git a/tests/ui/attributes/z-crate-attr/injection.rs b/tests/ui/attributes/z-crate-attr/injection.rs index 0c5c81ca71a..a91f9d2886e 100644 --- a/tests/ui/attributes/z-crate-attr/injection.rs +++ b/tests/ui/attributes/z-crate-attr/injection.rs @@ -1,3 +1,5 @@ //@ compile-flags: '-Zcrate-attr=feature(yeet_expr)]fn main(){}#[inline' -//@ error-pattern:unexpected closing delimiter + fn foo() {} + +//~? ERROR unexpected closing delimiter: `]` diff --git a/tests/ui/attributes/z-crate-attr/inner-attr.rs b/tests/ui/attributes/z-crate-attr/inner-attr.rs index 522c906dcd8..47ecad70062 100644 --- a/tests/ui/attributes/z-crate-attr/inner-attr.rs +++ b/tests/ui/attributes/z-crate-attr/inner-attr.rs @@ -1,4 +1,5 @@ //@ compile-flags: -Zcrate-attr=#![feature(foo)] -//@ error-pattern:expected identifier fn main() {} + +//~? ERROR expected identifier, found `#` diff --git a/tests/ui/attributes/z-crate-attr/multiple.rs b/tests/ui/attributes/z-crate-attr/multiple.rs index ee13253f625..47d35d2c3fd 100644 --- a/tests/ui/attributes/z-crate-attr/multiple.rs +++ b/tests/ui/attributes/z-crate-attr/multiple.rs @@ -1,3 +1,5 @@ //@ compile-flags: -Zcrate-attr=feature(foo),feature(bar) -//@ error-pattern:invalid crate attr + fn main() {} + +//~? ERROR invalid crate attribute diff --git a/tests/ui/attributes/z-crate-attr/unbalanced-paren.rs b/tests/ui/attributes/z-crate-attr/unbalanced-paren.rs index fc1d7f39a59..77d5d698f65 100644 --- a/tests/ui/attributes/z-crate-attr/unbalanced-paren.rs +++ b/tests/ui/attributes/z-crate-attr/unbalanced-paren.rs @@ -1,4 +1,6 @@ // Show diagnostics for unbalanced parens. //@ compile-flags: -Zcrate-attr=( -//@ error-pattern:unclosed delimiter + fn main() {} + +//~? ERROR this file contains an unclosed delimiter diff --git a/tests/ui/binop/binop-bitxor-str.rs b/tests/ui/binop/binop-bitxor-str.rs index d59e46167fe..3072fa6ae90 100644 --- a/tests/ui/binop/binop-bitxor-str.rs +++ b/tests/ui/binop/binop-bitxor-str.rs @@ -1,3 +1,2 @@ -//@ error-pattern:no implementation for `String ^ String` - fn main() { let x = "a".to_string() ^ "b".to_string(); } +//~^ ERROR no implementation for `String ^ String` diff --git a/tests/ui/binop/binop-bitxor-str.stderr b/tests/ui/binop/binop-bitxor-str.stderr index 9d9ec6c5af6..d4bb0c17bfa 100644 --- a/tests/ui/binop/binop-bitxor-str.stderr +++ b/tests/ui/binop/binop-bitxor-str.stderr @@ -1,5 +1,5 @@ error[E0369]: no implementation for `String ^ String` - --> $DIR/binop-bitxor-str.rs:3:37 + --> $DIR/binop-bitxor-str.rs:1:37 | LL | fn main() { let x = "a".to_string() ^ "b".to_string(); } | --------------- ^ --------------- String diff --git a/tests/ui/binop/binop-mul-bool.rs b/tests/ui/binop/binop-mul-bool.rs index 0b4ed21a12d..706195d215c 100644 --- a/tests/ui/binop/binop-mul-bool.rs +++ b/tests/ui/binop/binop-mul-bool.rs @@ -1,3 +1 @@ -//@ error-pattern:cannot multiply `bool` by `bool` - -fn main() { let x = true * false; } +fn main() { let x = true * false; } //~ ERROR cannot multiply `bool` by `bool` diff --git a/tests/ui/binop/binop-mul-bool.stderr b/tests/ui/binop/binop-mul-bool.stderr index 82d066f45a4..7fa70f65f56 100644 --- a/tests/ui/binop/binop-mul-bool.stderr +++ b/tests/ui/binop/binop-mul-bool.stderr @@ -1,5 +1,5 @@ error[E0369]: cannot multiply `bool` by `bool` - --> $DIR/binop-mul-bool.rs:3:26 + --> $DIR/binop-mul-bool.rs:1:26 | LL | fn main() { let x = true * false; } | ---- ^ ----- bool diff --git a/tests/ui/borrowck/mut-borrow-in-loop-2.stderr b/tests/ui/borrowck/mut-borrow-in-loop-2.stderr index 4f32df1eb24..46e06bc91b9 100644 --- a/tests/ui/borrowck/mut-borrow-in-loop-2.stderr +++ b/tests/ui/borrowck/mut-borrow-in-loop-2.stderr @@ -12,10 +12,6 @@ help: consider creating a fresh reborrow of `value` here | LL | Other::handle(&mut *value); | ++++++ -help: consider creating a fresh reborrow of `value` here - | -LL | Other::handle(&mut *value); - | ++++++ error: aborting due to 1 previous error diff --git a/tests/ui/c-variadic/issue-86053-1.rs b/tests/ui/c-variadic/issue-86053-1.rs index f952235be98..8eeb99a4cc1 100644 --- a/tests/ui/c-variadic/issue-86053-1.rs +++ b/tests/ui/c-variadic/issue-86053-1.rs @@ -1,12 +1,18 @@ // Regression test for the ICE described in issue #86053. -//@ error-pattern:unexpected `self` parameter in function -//@ error-pattern:`...` must be the last argument of a C-variadic function -//@ error-pattern:cannot find type `F` in this scope - #![feature(c_variadic)] #![crate_type="lib"] fn ordering4 < 'a , 'b > ( a : , self , self , self , + //~^ ERROR expected type, found `,` + //~| ERROR unexpected `self` parameter in function + //~| ERROR unexpected `self` parameter in function + //~| ERROR unexpected `self` parameter in function self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { + //~^ ERROR unexpected `self` parameter in function + //~| ERROR unexpected `self` parameter in function + //~| ERROR unexpected `self` parameter in function + //~| ERROR `...` must be the last argument of a C-variadic function + //~| ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg + //~| ERROR cannot find type `F` in this scope } diff --git a/tests/ui/c-variadic/issue-86053-1.stderr b/tests/ui/c-variadic/issue-86053-1.stderr index ce31f0d300f..dc323f9a234 100644 --- a/tests/ui/c-variadic/issue-86053-1.stderr +++ b/tests/ui/c-variadic/issue-86053-1.stderr @@ -1,23 +1,23 @@ error: expected type, found `,` - --> $DIR/issue-86053-1.rs:10:47 + --> $DIR/issue-86053-1.rs:6:47 | LL | fn ordering4 < 'a , 'b > ( a : , self , self , self , | ^ expected type error: unexpected `self` parameter in function - --> $DIR/issue-86053-1.rs:10:51 + --> $DIR/issue-86053-1.rs:6:51 | LL | fn ordering4 < 'a , 'b > ( a : , self , self , self , | ^^^^ must be the first parameter of an associated function error: unexpected `self` parameter in function - --> $DIR/issue-86053-1.rs:10:58 + --> $DIR/issue-86053-1.rs:6:58 | LL | fn ordering4 < 'a , 'b > ( a : , self , self , self , | ^^^^ must be the first parameter of an associated function error: unexpected `self` parameter in function - --> $DIR/issue-86053-1.rs:10:67 + --> $DIR/issue-86053-1.rs:6:67 | LL | fn ordering4 < 'a , 'b > ( a : , self , self , self , | ^^^^ must be the first parameter of an associated function diff --git a/tests/ui/capture1.rs b/tests/ui/capture1.rs index 9bf6532a7d3..4f8c04e3fa9 100644 --- a/tests/ui/capture1.rs +++ b/tests/ui/capture1.rs @@ -1,6 +1,4 @@ -//@ error-pattern: can't capture dynamic environment in a fn item - fn main() { let bar: isize = 5; - fn foo() -> isize { return bar; } + fn foo() -> isize { return bar; } //~ ERROR can't capture dynamic environment in a fn item } diff --git a/tests/ui/capture1.stderr b/tests/ui/capture1.stderr index 067b85ba619..8027430de52 100644 --- a/tests/ui/capture1.stderr +++ b/tests/ui/capture1.stderr @@ -1,5 +1,5 @@ error[E0434]: can't capture dynamic environment in a fn item - --> $DIR/capture1.rs:5:32 + --> $DIR/capture1.rs:3:32 | LL | fn foo() -> isize { return bar; } | ^^^ diff --git a/tests/ui/cast/cast-from-nil.rs b/tests/ui/cast/cast-from-nil.rs index 8a677603aa9..65e1eb31b21 100644 --- a/tests/ui/cast/cast-from-nil.rs +++ b/tests/ui/cast/cast-from-nil.rs @@ -1,2 +1 @@ -//@ error-pattern: non-primitive cast: `()` as `u32` -fn main() { let u = (assert!(true) as u32); } +fn main() { let u = (assert!(true) as u32); } //~ ERROR non-primitive cast: `()` as `u32` diff --git a/tests/ui/cast/cast-from-nil.stderr b/tests/ui/cast/cast-from-nil.stderr index 991ff93a8bd..82c53d71e78 100644 --- a/tests/ui/cast/cast-from-nil.stderr +++ b/tests/ui/cast/cast-from-nil.stderr @@ -1,5 +1,5 @@ error[E0605]: non-primitive cast: `()` as `u32` - --> $DIR/cast-from-nil.rs:2:21 + --> $DIR/cast-from-nil.rs:1:21 | LL | fn main() { let u = (assert!(true) as u32); } | ^^^^^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object diff --git a/tests/ui/cast/cast-to-nil.rs b/tests/ui/cast/cast-to-nil.rs index d91f9a16a07..7cd864471dd 100644 --- a/tests/ui/cast/cast-to-nil.rs +++ b/tests/ui/cast/cast-to-nil.rs @@ -1,2 +1 @@ -//@ error-pattern: non-primitive cast: `u32` as `()` -fn main() { let u = 0u32 as (); } +fn main() { let u = 0u32 as (); } //~ ERROR non-primitive cast: `u32` as `()` diff --git a/tests/ui/cast/cast-to-nil.stderr b/tests/ui/cast/cast-to-nil.stderr index 14c75983b94..d7121a7adba 100644 --- a/tests/ui/cast/cast-to-nil.stderr +++ b/tests/ui/cast/cast-to-nil.stderr @@ -1,5 +1,5 @@ error[E0605]: non-primitive cast: `u32` as `()` - --> $DIR/cast-to-nil.rs:2:21 + --> $DIR/cast-to-nil.rs:1:21 | LL | fn main() { let u = 0u32 as (); } | ^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object diff --git a/tests/ui/cfg/cfg_false_no_std-2.rs b/tests/ui/cfg/cfg_false_no_std-2.rs index cd337565872..35e545aae34 100644 --- a/tests/ui/cfg/cfg_false_no_std-2.rs +++ b/tests/ui/cfg/cfg_false_no_std-2.rs @@ -1,7 +1,8 @@ // Error, the linked empty library is `no_std` and doesn't provide a panic handler. -//@ dont-check-compiler-stderr +//@ compile-flags: --error-format=human //@ error-pattern: `#[panic_handler]` function required, but not found +//@ dont-check-compiler-stderr //@ aux-build: cfg_false_lib_no_std_before.rs #![no_std] @@ -9,3 +10,7 @@ extern crate cfg_false_lib_no_std_before as _; fn main() {} + +// FIXME: The second error is target-dependent. +//FIXME~? ERROR `#[panic_handler]` function required, but not found +//FIXME~? ERROR unwinding panics are not supported without std diff --git a/tests/ui/cfg/raw-true-false.rs b/tests/ui/cfg/raw-true-false.rs index 4cb8bb71c92..c92672fc144 100644 --- a/tests/ui/cfg/raw-true-false.rs +++ b/tests/ui/cfg/raw-true-false.rs @@ -1,19 +1,11 @@ //@ check-pass -//@ compile-flags: --cfg false --check-cfg=cfg(r#false) - -#![deny(warnings)] - -#[expect(unexpected_cfgs)] -mod a { - #[cfg(r#true)] - pub fn foo() {} -} - -mod b { - #[cfg(r#false)] - pub fn bar() {} -} - +//@ revisions: r0x0 r0x1 r1x0 r1x1 +//@[r0x0] compile-flags: --cfg false --check-cfg=cfg(false) +//@[r0x1] compile-flags: --cfg false --check-cfg=cfg(r#false) +//@[r1x0] compile-flags: --cfg r#false --check-cfg=cfg(false) +//@[r1x1] compile-flags: --cfg r#false --check-cfg=cfg(r#false) +#![deny(unexpected_cfgs)] fn main() { - b::bar() + #[cfg(not(r#false))] + compile_error!(""); } diff --git a/tests/ui/check-cfg/invalid-arguments.boolean.stderr b/tests/ui/check-cfg/invalid-arguments.boolean.stderr deleted file mode 100644 index 18734de9dac..00000000000 --- a/tests/ui/check-cfg/invalid-arguments.boolean.stderr +++ /dev/null @@ -1,6 +0,0 @@ -error: invalid `--check-cfg` argument: `cfg(true)` - | - = note: `true` is a boolean literal - = note: `cfg()` arguments must be simple identifiers, `any()` or `values(...)` - = note: visit <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details - diff --git a/tests/ui/check-cfg/invalid-arguments.boolean_after_values.stderr b/tests/ui/check-cfg/invalid-arguments.boolean_after_values.stderr new file mode 100644 index 00000000000..3aa2205d3b1 --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.boolean_after_values.stderr @@ -0,0 +1,5 @@ +error: invalid `--check-cfg` argument: `cfg(values(),true)` + | + = note: `values()` cannot be specified before the names + = note: visit <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details + diff --git a/tests/ui/check-cfg/invalid-arguments.rs b/tests/ui/check-cfg/invalid-arguments.rs index 3bea128e3e4..279b13b6972 100644 --- a/tests/ui/check-cfg/invalid-arguments.rs +++ b/tests/ui/check-cfg/invalid-arguments.rs @@ -2,7 +2,7 @@ // //@ check-fail //@ no-auto-check-cfg -//@ revisions: anything_else boolean +//@ revisions: anything_else boolean_after_values //@ revisions: string_for_name_1 string_for_name_2 multiple_any multiple_values //@ revisions: multiple_values_any not_empty_any not_empty_values_any //@ revisions: values_any_missing_values values_any_before_ident ident_in_values_1 @@ -11,7 +11,7 @@ //@ revisions: none_not_empty cfg_none unsafe_attr // //@ [anything_else]compile-flags: --check-cfg=anything_else(...) -//@ [boolean]compile-flags: --check-cfg=cfg(true) +//@ [boolean_after_values]compile-flags: --check-cfg=cfg(values(),true) //@ [string_for_name_1]compile-flags: --check-cfg=cfg("NOT_IDENT") //@ [string_for_name_2]compile-flags: --check-cfg=cfg(foo,"NOT_IDENT",bar) //@ [multiple_any]compile-flags: --check-cfg=cfg(any(),any()) diff --git a/tests/ui/codegen/mismatched-data-layouts.rs b/tests/ui/codegen/mismatched-data-layouts.rs index 955f917ee33..194bcaa307f 100644 --- a/tests/ui/codegen/mismatched-data-layouts.rs +++ b/tests/ui/codegen/mismatched-data-layouts.rs @@ -3,7 +3,6 @@ //@ build-fail //@ needs-llvm-components: x86 //@ compile-flags: --crate-type=lib --target={{src-base}}/codegen/mismatched-data-layout.json -Z unstable-options -//@ error-pattern: differs from LLVM target's //@ normalize-stderr: "`, `[A-Za-z0-9-:]*`" -> "`, `normalized data layout`" //@ normalize-stderr: "layout, `[A-Za-z0-9-:]*`" -> "layout, `normalized data layout`" @@ -12,3 +11,5 @@ #[lang = "sized"] trait Sized {} + +//~? ERROR differs from LLVM target's diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-3.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-3.rs index c086b8d8c3f..ba55b1c08b1 100644 --- a/tests/ui/conditional-compilation/cfg-arg-invalid-3.rs +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-3.rs @@ -1,3 +1,5 @@ //@ compile-flags: --cfg a::b -//@ error-pattern: invalid `--cfg` argument: `a::b` (argument key must be an identifier) + fn main() {} + +//~? ERROR invalid `--cfg` argument: `a::b` (argument key must be an identifier) diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-5.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-5.rs index 6f0bf8cf5fe..d64aeead79c 100644 --- a/tests/ui/conditional-compilation/cfg-arg-invalid-5.rs +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-5.rs @@ -1,3 +1,5 @@ //@ compile-flags: --cfg a=10 -//@ error-pattern: invalid `--cfg` argument: `a=10` (argument value must be a string) + fn main() {} + +//~? ERROR invalid `--cfg` argument: `a=10` (argument value must be a string) diff --git a/tests/ui/conditional-compilation/cfg-attr-cfg-2.rs b/tests/ui/conditional-compilation/cfg-attr-cfg-2.rs index c801bbccedd..80735990015 100644 --- a/tests/ui/conditional-compilation/cfg-attr-cfg-2.rs +++ b/tests/ui/conditional-compilation/cfg-attr-cfg-2.rs @@ -1,8 +1,7 @@ -//@ error-pattern: `main` function not found //@ compile-flags: --cfg foo --check-cfg=cfg(foo,bar) // main is conditionally compiled, but the conditional compilation // is conditional too! #[cfg_attr(foo, cfg(bar))] -fn main() { } +fn main() { } //~ ERROR `main` function not found in crate `cfg_attr_cfg_2` diff --git a/tests/ui/conditional-compilation/cfg-attr-cfg-2.stderr b/tests/ui/conditional-compilation/cfg-attr-cfg-2.stderr index 64595241dc7..1febb430863 100644 --- a/tests/ui/conditional-compilation/cfg-attr-cfg-2.stderr +++ b/tests/ui/conditional-compilation/cfg-attr-cfg-2.stderr @@ -1,5 +1,5 @@ error[E0601]: `main` function not found in crate `cfg_attr_cfg_2` - --> $DIR/cfg-attr-cfg-2.rs:8:14 + --> $DIR/cfg-attr-cfg-2.rs:7:14 | LL | fn main() { } | ^ consider adding a `main` function to `$DIR/cfg-attr-cfg-2.rs` diff --git a/tests/ui/conditional-compilation/cfg-in-crate-1.rs b/tests/ui/conditional-compilation/cfg-in-crate-1.rs index ecd3722bf4c..a1faa2397a3 100644 --- a/tests/ui/conditional-compilation/cfg-in-crate-1.rs +++ b/tests/ui/conditional-compilation/cfg-in-crate-1.rs @@ -1,3 +1 @@ -//@ error-pattern: `main` function not found - -#![cfg(FALSE)] +#![cfg(FALSE)] //~ ERROR `main` function not found in crate `cfg_in_crate_1` diff --git a/tests/ui/conditional-compilation/cfg-in-crate-1.stderr b/tests/ui/conditional-compilation/cfg-in-crate-1.stderr index 6067a3a921c..126e10cf040 100644 --- a/tests/ui/conditional-compilation/cfg-in-crate-1.stderr +++ b/tests/ui/conditional-compilation/cfg-in-crate-1.stderr @@ -1,5 +1,5 @@ error[E0601]: `main` function not found in crate `cfg_in_crate_1` - --> $DIR/cfg-in-crate-1.rs:3:15 + --> $DIR/cfg-in-crate-1.rs:1:15 | LL | #![cfg(FALSE)] | ^ consider adding a `main` function to `$DIR/cfg-in-crate-1.rs` diff --git a/tests/ui/const-ptr/out_of_bounds_read.rs b/tests/ui/const-ptr/out_of_bounds_read.rs index 312b53432b4..ccf45bf324a 100644 --- a/tests/ui/const-ptr/out_of_bounds_read.rs +++ b/tests/ui/const-ptr/out_of_bounds_read.rs @@ -1,5 +1,3 @@ -//@ error-pattern: evaluation of constant value failed - fn main() { use std::ptr; @@ -8,6 +6,9 @@ fn main() { const PAST_END_PTR: *const u32 = unsafe { DATA.as_ptr().add(1) }; const _READ: u32 = unsafe { ptr::read(PAST_END_PTR) }; + //~^ ERROR evaluation of constant value failed const _CONST_READ: u32 = unsafe { PAST_END_PTR.read() }; + //~^ ERROR evaluation of constant value failed const _MUT_READ: u32 = unsafe { (PAST_END_PTR as *mut u32).read() }; + //~^ ERROR evaluation of constant value failed } diff --git a/tests/ui/const-ptr/out_of_bounds_read.stderr b/tests/ui/const-ptr/out_of_bounds_read.stderr index 899e151c9b8..b396fc4d71b 100644 --- a/tests/ui/const-ptr/out_of_bounds_read.stderr +++ b/tests/ui/const-ptr/out_of_bounds_read.stderr @@ -1,5 +1,5 @@ error[E0080]: evaluation of constant value failed - --> $DIR/out_of_bounds_read.rs:10:33 + --> $DIR/out_of_bounds_read.rs:8:33 | LL | const _READ: u32 = unsafe { ptr::read(PAST_END_PTR) }; | ^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC0+0x4 which is at or beyond the end of the allocation of size 4 bytes @@ -8,7 +8,7 @@ note: inside `std::ptr::read::<u32>` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL error[E0080]: evaluation of constant value failed - --> $DIR/out_of_bounds_read.rs:11:39 + --> $DIR/out_of_bounds_read.rs:10:39 | LL | const _CONST_READ: u32 = unsafe { PAST_END_PTR.read() }; | ^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC0+0x4 which is at or beyond the end of the allocation of size 4 bytes diff --git a/tests/ui/consts/const-size_of-cycle.rs b/tests/ui/consts/const-size_of-cycle.rs index cfb2294c445..f45d96d43f8 100644 --- a/tests/ui/consts/const-size_of-cycle.rs +++ b/tests/ui/consts/const-size_of-cycle.rs @@ -1,7 +1,6 @@ -//@ error-pattern: cycle detected - struct Foo { bytes: [u8; std::mem::size_of::<Foo>()] + //~^ ERROR cycle detected when evaluating type-level constant } fn main() {} diff --git a/tests/ui/consts/const-size_of-cycle.stderr b/tests/ui/consts/const-size_of-cycle.stderr index cd0ea556425..bf17d76a092 100644 --- a/tests/ui/consts/const-size_of-cycle.stderr +++ b/tests/ui/consts/const-size_of-cycle.stderr @@ -1,11 +1,11 @@ error[E0391]: cycle detected when evaluating type-level constant - --> $DIR/const-size_of-cycle.rs:4:17 + --> $DIR/const-size_of-cycle.rs:2:17 | LL | bytes: [u8; std::mem::size_of::<Foo>()] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`... - --> $DIR/const-size_of-cycle.rs:4:17 + --> $DIR/const-size_of-cycle.rs:2:17 | LL | bytes: [u8; std::mem::size_of::<Foo>()] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,7 +14,7 @@ LL | bytes: [u8; std::mem::size_of::<Foo>()] = note: ...which requires normalizing `[u8; std::mem::size_of::<Foo>()]`... = note: ...which again requires evaluating type-level constant, completing the cycle note: cycle used when checking that `Foo` is well-formed - --> $DIR/const-size_of-cycle.rs:3:1 + --> $DIR/const-size_of-cycle.rs:1:1 | LL | struct Foo { | ^^^^^^^^^^ diff --git a/tests/ui/consts/miri_unleashed/drop.rs b/tests/ui/consts/miri_unleashed/drop.rs index 45ade4906b8..17d089222d9 100644 --- a/tests/ui/consts/miri_unleashed/drop.rs +++ b/tests/ui/consts/miri_unleashed/drop.rs @@ -14,4 +14,6 @@ static TEST_OK: () = { // The actual error is tested by the error-pattern above. static TEST_BAD: () = { let _v: Vec<i32> = Vec::new(); -}; +}; //~ ERROR could not evaluate static initializer + +//~? WARN skipping const checks diff --git a/tests/ui/consts/timeout.rs b/tests/ui/consts/timeout.rs index c4fb8bab663..8dab87ac8e1 100644 --- a/tests/ui/consts/timeout.rs +++ b/tests/ui/consts/timeout.rs @@ -3,7 +3,6 @@ //! ICE. //@ compile-flags: --crate-type=lib -Ztiny-const-eval-limit -//@ error-pattern: constant evaluation is taking a long time static ROOK_ATTACKS_TABLE: () = { 0_u64.count_ones(); @@ -23,3 +22,5 @@ static ROOK_ATTACKS_TABLE: () = { 0_u64.count_ones(); 0_u64.count_ones(); }; + +//~? ERROR constant evaluation is taking a long time diff --git a/tests/ui/consts/timeout.stderr b/tests/ui/consts/timeout.stderr index 6bfa06d86d1..ecefeff76e9 100644 --- a/tests/ui/consts/timeout.stderr +++ b/tests/ui/consts/timeout.stderr @@ -4,7 +4,7 @@ error: constant evaluation is taking a long time = 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/timeout.rs:8:1 + --> $DIR/timeout.rs:7:1 | LL | static ROOK_ATTACKS_TABLE: () = { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/crate_type_flag.rs b/tests/ui/crate_type_flag.rs index 4f3cfbae45d..03bea3638e1 100644 --- a/tests/ui/crate_type_flag.rs +++ b/tests/ui/crate_type_flag.rs @@ -1,4 +1,5 @@ //@ compile-flags: --crate-type dynlib -//@ error-pattern: unknown crate type: `dynlib`, expected one of: `lib`, `rlib`, `staticlib`, `dylib`, `cdylib`, `bin`, `proc-macro` fn main() {} + +//~? ERROR unknown crate type: `dynlib` diff --git a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.rs b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.rs index 3bff4471698..7f85cbf227a 100644 --- a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.rs +++ b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.rs @@ -1,9 +1,9 @@ +//~ ERROR values of the type `[u8; usize::MAX]` are too big for the target architecture // Make sure the compiler does not ICE when trying to generate the debuginfo name of a type that // causes a layout error. See https://github.com/rust-lang/rust/issues/94961. //@ compile-flags:-C debuginfo=2 //@ build-fail -//@ error-pattern: too big for the target architecture #![crate_type = "rlib"] diff --git a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.rs b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.rs index 6a3f8f4c249..b79b5ff6fdb 100644 --- a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.rs +++ b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.rs @@ -1,11 +1,12 @@ +//FIXME~ ERROR values of the type `[u8; usize::MAX]` are too big for the target architecture // Make sure the compiler does not ICE when trying to generate the debuginfo name of a type that // causes a layout error. // This version of the test already ICE'd before the commit that introduce the ICE described in // https://github.com/rust-lang/rust/issues/94961. -//@ compile-flags:-C debuginfo=2 +//@ compile-flags:-C debuginfo=2 --error-format=human //@ build-fail -//@ error-pattern: too big for the target architecture +//@ error-pattern: values of the type `[u8; usize::MAX]` are too big for the target architecture #![crate_type = "rlib"] @@ -16,3 +17,6 @@ pub enum Foo<T> { pub fn foo() -> usize { std::mem::size_of::<Foo<u8>>() } + +// FIXME: the error is reported on different lines on different targets +//FIXME~? ERROR values of the type `[u8; usize::MAX]` are too big for the target architecture diff --git a/tests/ui/debuginfo/dwarf-versions.rs b/tests/ui/debuginfo/dwarf-versions.rs index 806ade51a99..6030b2fcf3c 100644 --- a/tests/ui/debuginfo/dwarf-versions.rs +++ b/tests/ui/debuginfo/dwarf-versions.rs @@ -4,7 +4,6 @@ //@ revisions: zero one two three four five six //@[zero] compile-flags: -Zdwarf-version=0 -//@[zero] error-pattern: requested DWARF version 0 is not supported //@[one] compile-flags: -Zdwarf-version=1 //@[one] error-pattern: requested DWARF version 1 is not supported @@ -22,7 +21,6 @@ //@[five] check-pass //@[six] compile-flags: -Zdwarf-version=6 -//@[six] error-pattern: requested DWARF version 6 is not supported //@ compile-flags: -g --target x86_64-unknown-linux-gnu --crate-type cdylib //@ needs-llvm-components: x86 @@ -36,3 +34,7 @@ pub trait Sized {} pub fn foo() {} + +//[zero]~? ERROR requested DWARF version 0 is not supported +//[one]~? ERROR requested DWARF version 1 is not supported +//[six]~? ERROR requested DWARF version 6 is not supported diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.rs b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.rs index 896bbac7d8e..75b8141cc38 100644 --- a/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.rs +++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.rs @@ -1,6 +1,5 @@ //@ revisions: aarch64_gl i686_g i686_gl i686_uwp_g x86_64_g x86_64_gl x86_64_uwp_g //@ compile-flags: --crate-type cdylib -Csplit-debuginfo=packed -//@ error-pattern: error: `-Csplit-debuginfo=packed` is unstable on this platform //@[aarch64_gl] compile-flags: --target aarch64-pc-windows-gnullvm //@[aarch64_gl] needs-llvm-components: aarch64 @@ -27,3 +26,5 @@ #![no_core] #![no_std] + +//~? ERROR `-Csplit-debuginfo=packed` is unstable on this platform diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.rs b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.rs index 54a88c91217..3f4da555aad 100644 --- a/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.rs +++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.rs @@ -1,6 +1,5 @@ //@ revisions: aarch64_gl i686_g i686_gl i686_uwp_g x86_64_g x86_64_gl x86_64_uwp_g //@ compile-flags: --crate-type cdylib -Csplit-debuginfo=unpacked -//@ error-pattern: error: `-Csplit-debuginfo=unpacked` is unstable on this platform //@[aarch64_gl] compile-flags: --target aarch64-pc-windows-gnullvm //@[aarch64_gl] needs-llvm-components: aarch64 @@ -27,3 +26,5 @@ #![no_core] #![no_std] + +//~? ERROR `-Csplit-debuginfo=unpacked` is unstable on this platform diff --git a/tests/ui/deprecation/deprecation-lint-2.rs b/tests/ui/deprecation/deprecation-lint-2.rs index 553b1afe45c..f22eebb53a0 100644 --- a/tests/ui/deprecation/deprecation-lint-2.rs +++ b/tests/ui/deprecation/deprecation-lint-2.rs @@ -1,5 +1,4 @@ //@ aux-build:deprecation-lint.rs -//@ error-pattern: use of deprecated function #![deny(deprecated)] @@ -9,5 +8,5 @@ extern crate deprecation_lint; use deprecation_lint::*; fn main() { - macro_test!(); + macro_test!(); //~ ERROR use of deprecated function `deprecation_lint::deprecated`: text } diff --git a/tests/ui/deprecation/deprecation-lint-2.stderr b/tests/ui/deprecation/deprecation-lint-2.stderr index 7d411c00445..ebc760bfe7b 100644 --- a/tests/ui/deprecation/deprecation-lint-2.stderr +++ b/tests/ui/deprecation/deprecation-lint-2.stderr @@ -1,11 +1,11 @@ error: use of deprecated function `deprecation_lint::deprecated`: text - --> $DIR/deprecation-lint-2.rs:12:5 + --> $DIR/deprecation-lint-2.rs:11:5 | LL | macro_test!(); | ^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/deprecation-lint-2.rs:4:9 + --> $DIR/deprecation-lint-2.rs:3:9 | LL | #![deny(deprecated)] | ^^^^^^^^^^ diff --git a/tests/ui/deprecation/deprecation-lint-3.rs b/tests/ui/deprecation/deprecation-lint-3.rs index f01fc924457..5a9ca9a2d0a 100644 --- a/tests/ui/deprecation/deprecation-lint-3.rs +++ b/tests/ui/deprecation/deprecation-lint-3.rs @@ -1,5 +1,4 @@ //@ aux-build:deprecation-lint.rs -//@ error-pattern: use of deprecated function #![deny(deprecated)] #![allow(warnings)] @@ -11,4 +10,5 @@ use deprecation_lint::*; fn main() { macro_test_arg_nested!(deprecated_text); + //~^ ERROR use of deprecated function `deprecation_lint::deprecated_text`: text } diff --git a/tests/ui/deprecation/deprecation-lint-3.stderr b/tests/ui/deprecation/deprecation-lint-3.stderr index 1723b7bbd05..8bfe08cf6d5 100644 --- a/tests/ui/deprecation/deprecation-lint-3.stderr +++ b/tests/ui/deprecation/deprecation-lint-3.stderr @@ -1,11 +1,11 @@ error: use of deprecated function `deprecation_lint::deprecated_text`: text - --> $DIR/deprecation-lint-3.rs:13:28 + --> $DIR/deprecation-lint-3.rs:12:28 | LL | macro_test_arg_nested!(deprecated_text); | ^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/deprecation-lint-3.rs:4:9 + --> $DIR/deprecation-lint-3.rs:3:9 | LL | #![deny(deprecated)] | ^^^^^^^^^^ diff --git a/tests/ui/duplicate/dupe-symbols-4.rs b/tests/ui/duplicate/dupe-symbols-4.rs index a9b7d689ad4..d961ba10e72 100644 --- a/tests/ui/duplicate/dupe-symbols-4.rs +++ b/tests/ui/duplicate/dupe-symbols-4.rs @@ -1,7 +1,5 @@ //@ build-fail -// -//@ error-pattern: symbol `fail` is already defined #![crate_type="rlib"] #![allow(warnings)] @@ -20,5 +18,5 @@ impl A for B { impl A for C { #[no_mangle] - fn fail(self) {} + fn fail(self) {} //~ ERROR symbol `fail` is already defined } diff --git a/tests/ui/duplicate/dupe-symbols-4.stderr b/tests/ui/duplicate/dupe-symbols-4.stderr index 4c5f1e7867f..e85d3f2b063 100644 --- a/tests/ui/duplicate/dupe-symbols-4.stderr +++ b/tests/ui/duplicate/dupe-symbols-4.stderr @@ -1,5 +1,5 @@ error: symbol `fail` is already defined - --> $DIR/dupe-symbols-4.rs:23:5 + --> $DIR/dupe-symbols-4.rs:21:5 | LL | fn fail(self) {} | ^^^^^^^^^^^^^ diff --git a/tests/ui/duplicate/dupe-symbols-7.rs b/tests/ui/duplicate/dupe-symbols-7.rs index 162c3c40446..ea17942493c 100644 --- a/tests/ui/duplicate/dupe-symbols-7.rs +++ b/tests/ui/duplicate/dupe-symbols-7.rs @@ -1,10 +1,7 @@ //@ build-fail //@ ignore-wasi wasi does different things with the `main` symbol -// -//@ error-pattern: entry symbol `main` declared multiple times - #![allow(warnings)] #[no_mangle] -fn main(){} +fn main(){} //~ ERROR entry symbol `main` declared multiple times diff --git a/tests/ui/duplicate/dupe-symbols-7.stderr b/tests/ui/duplicate/dupe-symbols-7.stderr index aa6213af2e4..d7503856939 100644 --- a/tests/ui/duplicate/dupe-symbols-7.stderr +++ b/tests/ui/duplicate/dupe-symbols-7.stderr @@ -1,5 +1,5 @@ error: entry symbol `main` declared multiple times - --> $DIR/dupe-symbols-7.rs:10:1 + --> $DIR/dupe-symbols-7.rs:7:1 | LL | fn main(){} | ^^^^^^^^^ diff --git a/tests/ui/duplicate/dupe-symbols-8.rs b/tests/ui/duplicate/dupe-symbols-8.rs index 258e91fa8c8..b3c635f38ed 100644 --- a/tests/ui/duplicate/dupe-symbols-8.rs +++ b/tests/ui/duplicate/dupe-symbols-8.rs @@ -1,11 +1,10 @@ //@ build-fail -//@ error-pattern: entry symbol `main` declared multiple times //@ ignore-wasi wasi does different things with the `main` symbol // // See #67946. #![allow(warnings)] -fn main() { +fn main() { //~ ERROR entry symbol `main` declared multiple times extern "Rust" { fn main(); } diff --git a/tests/ui/duplicate/dupe-symbols-8.stderr b/tests/ui/duplicate/dupe-symbols-8.stderr index 0f47d3683b5..494fdcca327 100644 --- a/tests/ui/duplicate/dupe-symbols-8.stderr +++ b/tests/ui/duplicate/dupe-symbols-8.stderr @@ -1,5 +1,5 @@ error: entry symbol `main` declared multiple times - --> $DIR/dupe-symbols-8.rs:8:1 + --> $DIR/dupe-symbols-8.rs:7:1 | LL | fn main() { | ^^^^^^^^^ diff --git a/tests/ui/elided-test.rs b/tests/ui/elided-test.rs index 025b75c1b5c..2bedc25e17b 100644 --- a/tests/ui/elided-test.rs +++ b/tests/ui/elided-test.rs @@ -1,7 +1,5 @@ -//@ error-pattern: `main` function not found - // Since we're not compiling a test runner this function should be elided // and the build will fail because main doesn't exist #[test] fn main() { -} +} //~ ERROR `main` function not found in crate `elided_test` diff --git a/tests/ui/elided-test.stderr b/tests/ui/elided-test.stderr index e323b8ba7ea..7aebe5d8264 100644 --- a/tests/ui/elided-test.stderr +++ b/tests/ui/elided-test.stderr @@ -1,5 +1,5 @@ error[E0601]: `main` function not found in crate `elided_test` - --> $DIR/elided-test.rs:7:2 + --> $DIR/elided-test.rs:5:2 | LL | } | ^ consider adding a `main` function to `$DIR/elided-test.rs` diff --git a/tests/ui/error-codes/E0602.rs b/tests/ui/error-codes/E0602.rs index 1849fd2d895..cba15bb92d4 100644 --- a/tests/ui/error-codes/E0602.rs +++ b/tests/ui/error-codes/E0602.rs @@ -1,8 +1,11 @@ //@ compile-flags:-D bogus //@ check-pass -//@ error-pattern:E0602 //@ error-pattern:requested on the command line with `-D bogus` //@ error-pattern:`#[warn(unknown_lints)]` on by default fn main() {} + +//~? WARN unknown lint: `bogus` +//~? WARN unknown lint: `bogus` +//~? WARN unknown lint: `bogus` diff --git a/tests/ui/errors/remap-path-prefix-reverse.local-self.stderr b/tests/ui/errors/remap-path-prefix-reverse.local-self.stderr index 7aa66be0d09..b4f83f6bfc0 100644 --- a/tests/ui/errors/remap-path-prefix-reverse.local-self.stderr +++ b/tests/ui/errors/remap-path-prefix-reverse.local-self.stderr @@ -1,7 +1,7 @@ error[E0423]: expected value, found struct `remapped_dep::SomeStruct` --> $DIR/remap-path-prefix-reverse.rs:16:13 | -LL | let _ = remapped_dep::SomeStruct; // ~ERROR E0423 +LL | let _ = remapped_dep::SomeStruct; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use struct literal syntax instead: `remapped_dep::SomeStruct {}` | ::: remapped-aux/remapped_dep.rs:4:1 diff --git a/tests/ui/errors/remap-path-prefix-reverse.remapped-self.stderr b/tests/ui/errors/remap-path-prefix-reverse.remapped-self.stderr index 7aa66be0d09..b4f83f6bfc0 100644 --- a/tests/ui/errors/remap-path-prefix-reverse.remapped-self.stderr +++ b/tests/ui/errors/remap-path-prefix-reverse.remapped-self.stderr @@ -1,7 +1,7 @@ error[E0423]: expected value, found struct `remapped_dep::SomeStruct` --> $DIR/remap-path-prefix-reverse.rs:16:13 | -LL | let _ = remapped_dep::SomeStruct; // ~ERROR E0423 +LL | let _ = remapped_dep::SomeStruct; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use struct literal syntax instead: `remapped_dep::SomeStruct {}` | ::: remapped-aux/remapped_dep.rs:4:1 diff --git a/tests/ui/errors/remap-path-prefix-reverse.rs b/tests/ui/errors/remap-path-prefix-reverse.rs index 7743e38f50f..28fdabb8f4d 100644 --- a/tests/ui/errors/remap-path-prefix-reverse.rs +++ b/tests/ui/errors/remap-path-prefix-reverse.rs @@ -13,5 +13,6 @@ extern crate remapped_dep; fn main() { // The actual error is irrelevant. The important part it that is should show // a snippet of the dependency's source. - let _ = remapped_dep::SomeStruct; // ~ERROR E0423 + let _ = remapped_dep::SomeStruct; + //~^ ERROR expected value, found struct `remapped_dep::SomeStruct` } diff --git a/tests/ui/errors/remap-path-prefix-sysroot.rs b/tests/ui/errors/remap-path-prefix-sysroot.rs index 7281e6da094..5e2e4fab51d 100644 --- a/tests/ui/errors/remap-path-prefix-sysroot.rs +++ b/tests/ui/errors/remap-path-prefix-sysroot.rs @@ -3,7 +3,6 @@ //@ [with-remap]compile-flags: --remap-path-prefix={{rust-src-base}}=remapped //@ [with-remap]compile-flags: --remap-path-prefix={{src-base}}=remapped-tests-ui //@ [without-remap]compile-flags: -//@ error-pattern: E0507 // The $SRC_DIR*.rs:LL:COL normalisation doesn't kick in automatically // as the remapped revision will not begin with $SRC_DIR_REAL, @@ -18,7 +17,10 @@ struct Worker { impl Drop for Worker { fn drop(&mut self) { self.thread.join().unwrap(); + //[without-remap]~^ ERROR cannot move out of `self.thread` which is behind a mutable reference } } pub fn main(){} + +//[with-remap]~? ERROR cannot move out of `self.thread` which is behind a mutable reference diff --git a/tests/ui/errors/remap-path-prefix.normal.stderr b/tests/ui/errors/remap-path-prefix.normal.stderr index 46d33d26052..5a125a7024a 100644 --- a/tests/ui/errors/remap-path-prefix.normal.stderr +++ b/tests/ui/errors/remap-path-prefix.normal.stderr @@ -1,5 +1,5 @@ error[E0425]: cannot find value `ferris` in this scope - --> remapped/errors/remap-path-prefix.rs:19:5 + --> remapped/errors/remap-path-prefix.rs:15:5 | LL | ferris | ^^^^^^ not found in this scope diff --git a/tests/ui/errors/remap-path-prefix.rs b/tests/ui/errors/remap-path-prefix.rs index 8809caa4d4f..7e38e16280f 100644 --- a/tests/ui/errors/remap-path-prefix.rs +++ b/tests/ui/errors/remap-path-prefix.rs @@ -7,14 +7,13 @@ // The remapped paths are not normalized by compiletest. //@ normalize-stderr: "\\(errors)" -> "/$1" -// The remapped paths aren't recognized by compiletest, so we -// cannot use line-specific patterns. -//@ error-pattern: E0425 - fn main() { // We cannot actually put an ERROR marker here because // the file name in the error message is not what the // test framework expects (since the filename gets remapped). // We still test the expected error in the stderr file. - ferris + ferris //[without-diagnostic-scope]~ ERROR cannot find value `ferris` in this scope } + +//[normal]~? ERROR cannot find value `ferris` in this scope +//[with-diagnostic-scope]~? ERROR cannot find value `ferris` in this scope diff --git a/tests/ui/errors/remap-path-prefix.with-diagnostic-scope.stderr b/tests/ui/errors/remap-path-prefix.with-diagnostic-scope.stderr index 46d33d26052..5a125a7024a 100644 --- a/tests/ui/errors/remap-path-prefix.with-diagnostic-scope.stderr +++ b/tests/ui/errors/remap-path-prefix.with-diagnostic-scope.stderr @@ -1,5 +1,5 @@ error[E0425]: cannot find value `ferris` in this scope - --> remapped/errors/remap-path-prefix.rs:19:5 + --> remapped/errors/remap-path-prefix.rs:15:5 | LL | ferris | ^^^^^^ not found in this scope diff --git a/tests/ui/errors/remap-path-prefix.without-diagnostic-scope.stderr b/tests/ui/errors/remap-path-prefix.without-diagnostic-scope.stderr index 0badea6e27b..b6332685dbf 100644 --- a/tests/ui/errors/remap-path-prefix.without-diagnostic-scope.stderr +++ b/tests/ui/errors/remap-path-prefix.without-diagnostic-scope.stderr @@ -1,5 +1,5 @@ error[E0425]: cannot find value `ferris` in this scope - --> $DIR/remap-path-prefix.rs:19:5 + --> $DIR/remap-path-prefix.rs:15:5 | LL | ferris | ^^^^^^ not found in this scope diff --git a/tests/ui/expr/if/if-typeck.rs b/tests/ui/expr/if/if-typeck.rs index ba828f11e79..0985598f0f7 100644 --- a/tests/ui/expr/if/if-typeck.rs +++ b/tests/ui/expr/if/if-typeck.rs @@ -1,4 +1,3 @@ -//@ error-pattern:mismatched types // issue #513 fn f() { } @@ -6,5 +5,5 @@ fn f() { } fn main() { // f is not a bool - if f { } + if f { } //~ ERROR mismatched types } diff --git a/tests/ui/expr/if/if-typeck.stderr b/tests/ui/expr/if/if-typeck.stderr index 1be43a20105..bca00f890cb 100644 --- a/tests/ui/expr/if/if-typeck.stderr +++ b/tests/ui/expr/if/if-typeck.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/if-typeck.rs:9:8 + --> $DIR/if-typeck.rs:8:8 | LL | if f { } | ^ expected `bool`, found fn item diff --git a/tests/ui/ext-nonexistent.rs b/tests/ui/ext-nonexistent.rs index a66407953a9..1293324b67e 100644 --- a/tests/ui/ext-nonexistent.rs +++ b/tests/ui/ext-nonexistent.rs @@ -1,2 +1,2 @@ -//@ error-pattern:cannot find macro fn main() { iamnotanextensionthatexists!(""); } +//~^ ERROR cannot find macro `iamnotanextensionthatexists` in this scope diff --git a/tests/ui/ext-nonexistent.stderr b/tests/ui/ext-nonexistent.stderr index 8891e823e4a..edb59bba6e5 100644 --- a/tests/ui/ext-nonexistent.stderr +++ b/tests/ui/ext-nonexistent.stderr @@ -1,5 +1,5 @@ error: cannot find macro `iamnotanextensionthatexists` in this scope - --> $DIR/ext-nonexistent.rs:2:13 + --> $DIR/ext-nonexistent.rs:1:13 | LL | fn main() { iamnotanextensionthatexists!(""); } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/extern-flag/empty-extern-arg.rs b/tests/ui/extern-flag/empty-extern-arg.rs index dea68b5b1ad..2dee721ed03 100644 --- a/tests/ui/extern-flag/empty-extern-arg.rs +++ b/tests/ui/extern-flag/empty-extern-arg.rs @@ -1,6 +1,9 @@ +//~ ERROR extern location for std does not exist //@ compile-flags: --extern std= -//@ error-pattern: extern location for std does not exist //@ needs-unwind since it affects the error output //@ ignore-emscripten missing eh_catch_typeinfo lang item fn main() {} + +//~? ERROR `#[panic_handler]` function required, but not found +//~? ERROR unwinding panics are not supported without std diff --git a/tests/ui/extern-flag/invalid-crate-name-dashed.rs b/tests/ui/extern-flag/invalid-crate-name-dashed.rs index b846214175e..b336cc84569 100644 --- a/tests/ui/extern-flag/invalid-crate-name-dashed.rs +++ b/tests/ui/extern-flag/invalid-crate-name-dashed.rs @@ -1,5 +1,4 @@ //@ compile-flags: --extern=my-awesome-library=libawesome.rlib -//@ error-pattern: crate name `my-awesome-library` passed to `--extern` is not a valid ASCII identifier //@ error-pattern: consider replacing the dashes with underscores: `my_awesome_library` // In a sense, this is a regression test for issue #113035. We no longer suggest @@ -8,3 +7,5 @@ pub use my_awesome_library::*; fn main() {} + +//~? ERROR crate name `my-awesome-library` passed to `--extern` is not a valid ASCII identifier diff --git a/tests/ui/extern-flag/invalid-crate-name-non-ascii.rs b/tests/ui/extern-flag/invalid-crate-name-non-ascii.rs index 5231503820f..71818938283 100644 --- a/tests/ui/extern-flag/invalid-crate-name-non-ascii.rs +++ b/tests/ui/extern-flag/invalid-crate-name-non-ascii.rs @@ -1,4 +1,5 @@ //@ compile-flags: --extern čɍαţē=libnon_ascii.rlib -//@ error-pattern: crate name `čɍαţē` passed to `--extern` is not a valid ASCII identifier fn main() {} + +//~? ERROR crate name `čɍαţē` passed to `--extern` is not a valid ASCII identifier diff --git a/tests/ui/extern-flag/invalid-crate-name.rs b/tests/ui/extern-flag/invalid-crate-name.rs index c7b5b637217..5d73e119673 100644 --- a/tests/ui/extern-flag/invalid-crate-name.rs +++ b/tests/ui/extern-flag/invalid-crate-name.rs @@ -1,4 +1,5 @@ //@ compile-flags: --extern=?#1%$ -//@ error-pattern: crate name `?#1%$` passed to `--extern` is not a valid ASCII identifier fn main() {} + +//~? ERROR crate name `?#1%$` passed to `--extern` is not a valid ASCII identifier diff --git a/tests/ui/extern-flag/no-force-extern.rs b/tests/ui/extern-flag/no-force-extern.rs index 11d2f91c7bb..c9317abe292 100644 --- a/tests/ui/extern-flag/no-force-extern.rs +++ b/tests/ui/extern-flag/no-force-extern.rs @@ -1,10 +1,12 @@ //@ aux-crate:panic_handler=panic_handler.rs //@ ignore-cross-compile (needs dylibs and compiletest doesn't have a more specific header) // compile_flags: -Zunstable-options --crate-type dylib -//@ error-pattern: `#[panic_handler]` function required, but not found //@ dont-check-compiler-stderr //@ edition: 2018 #![no_std] -fn foo() {} +fn foo() {} //~ ERROR `main` function not found in crate `no_force_extern` + +//~? ERROR `#[panic_handler]` function required, but not found +//~? ERROR unwinding panics are not supported without std diff --git a/tests/ui/feature-gates/feature-gate-f128.e2015.stderr b/tests/ui/feature-gates/feature-gate-f128.e2015.stderr index 771aee79dce..7e8ea5e948d 100644 --- a/tests/ui/feature-gates/feature-gate-f128.e2015.stderr +++ b/tests/ui/feature-gates/feature-gate-f128.e2015.stderr @@ -19,7 +19,7 @@ LL | let a: f128 = 100.0; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the type `f128` is unstable - --> $DIR/feature-gate-f128.rs:15:11 + --> $DIR/feature-gate-f128.rs:16:11 | LL | fn foo(a: f128) {} | ^^^^ @@ -29,7 +29,7 @@ LL | fn foo(a: f128) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the type `f128` is unstable - --> $DIR/feature-gate-f128.rs:18:8 + --> $DIR/feature-gate-f128.rs:19:8 | LL | a: f128, | ^^^^ @@ -48,6 +48,16 @@ LL | let b = 0.0f128; = help: add `#![feature(f128)]` 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 +error[E0658]: the type `f128` is unstable + --> $DIR/feature-gate-f128.rs:12:13 + | +LL | let c = 0f128; + | ^^^^^ + | + = note: see issue #116909 <https://github.com/rust-lang/rust/issues/116909> for more information + = help: add `#![feature(f128)]` 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 6 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-f128.e2018.stderr b/tests/ui/feature-gates/feature-gate-f128.e2018.stderr index 771aee79dce..7e8ea5e948d 100644 --- a/tests/ui/feature-gates/feature-gate-f128.e2018.stderr +++ b/tests/ui/feature-gates/feature-gate-f128.e2018.stderr @@ -19,7 +19,7 @@ LL | let a: f128 = 100.0; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the type `f128` is unstable - --> $DIR/feature-gate-f128.rs:15:11 + --> $DIR/feature-gate-f128.rs:16:11 | LL | fn foo(a: f128) {} | ^^^^ @@ -29,7 +29,7 @@ LL | fn foo(a: f128) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the type `f128` is unstable - --> $DIR/feature-gate-f128.rs:18:8 + --> $DIR/feature-gate-f128.rs:19:8 | LL | a: f128, | ^^^^ @@ -48,6 +48,16 @@ LL | let b = 0.0f128; = help: add `#![feature(f128)]` 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 +error[E0658]: the type `f128` is unstable + --> $DIR/feature-gate-f128.rs:12:13 + | +LL | let c = 0f128; + | ^^^^^ + | + = note: see issue #116909 <https://github.com/rust-lang/rust/issues/116909> for more information + = help: add `#![feature(f128)]` 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 6 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-f128.rs b/tests/ui/feature-gates/feature-gate-f128.rs index d25b6dde4ee..dcbe60e934a 100644 --- a/tests/ui/feature-gates/feature-gate-f128.rs +++ b/tests/ui/feature-gates/feature-gate-f128.rs @@ -9,6 +9,7 @@ const A: f128 = 10.0; //~ ERROR the type `f128` is unstable pub fn main() { let a: f128 = 100.0; //~ ERROR the type `f128` is unstable let b = 0.0f128; //~ ERROR the type `f128` is unstable + let c = 0f128; //~ ERROR the type `f128` is unstable foo(1.23); } diff --git a/tests/ui/feature-gates/feature-gate-f16.e2015.stderr b/tests/ui/feature-gates/feature-gate-f16.e2015.stderr index 2bb3b59465a..5d1ca8f6d04 100644 --- a/tests/ui/feature-gates/feature-gate-f16.e2015.stderr +++ b/tests/ui/feature-gates/feature-gate-f16.e2015.stderr @@ -19,7 +19,7 @@ LL | let a: f16 = 100.0; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the type `f16` is unstable - --> $DIR/feature-gate-f16.rs:15:11 + --> $DIR/feature-gate-f16.rs:16:11 | LL | fn foo(a: f16) {} | ^^^ @@ -29,7 +29,7 @@ LL | fn foo(a: f16) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the type `f16` is unstable - --> $DIR/feature-gate-f16.rs:18:8 + --> $DIR/feature-gate-f16.rs:19:8 | LL | a: f16, | ^^^ @@ -48,6 +48,16 @@ LL | let b = 0.0f16; = help: add `#![feature(f16)]` 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 +error[E0658]: the type `f16` is unstable + --> $DIR/feature-gate-f16.rs:12:13 + | +LL | let c = 0f16; + | ^^^^ + | + = note: see issue #116909 <https://github.com/rust-lang/rust/issues/116909> for more information + = help: add `#![feature(f16)]` 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 6 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-f16.e2018.stderr b/tests/ui/feature-gates/feature-gate-f16.e2018.stderr index 2bb3b59465a..5d1ca8f6d04 100644 --- a/tests/ui/feature-gates/feature-gate-f16.e2018.stderr +++ b/tests/ui/feature-gates/feature-gate-f16.e2018.stderr @@ -19,7 +19,7 @@ LL | let a: f16 = 100.0; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the type `f16` is unstable - --> $DIR/feature-gate-f16.rs:15:11 + --> $DIR/feature-gate-f16.rs:16:11 | LL | fn foo(a: f16) {} | ^^^ @@ -29,7 +29,7 @@ LL | fn foo(a: f16) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the type `f16` is unstable - --> $DIR/feature-gate-f16.rs:18:8 + --> $DIR/feature-gate-f16.rs:19:8 | LL | a: f16, | ^^^ @@ -48,6 +48,16 @@ LL | let b = 0.0f16; = help: add `#![feature(f16)]` 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 +error[E0658]: the type `f16` is unstable + --> $DIR/feature-gate-f16.rs:12:13 + | +LL | let c = 0f16; + | ^^^^ + | + = note: see issue #116909 <https://github.com/rust-lang/rust/issues/116909> for more information + = help: add `#![feature(f16)]` 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 6 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-f16.rs b/tests/ui/feature-gates/feature-gate-f16.rs index af906d71f5f..f748c603efe 100644 --- a/tests/ui/feature-gates/feature-gate-f16.rs +++ b/tests/ui/feature-gates/feature-gate-f16.rs @@ -9,6 +9,7 @@ const A: f16 = 10.0; //~ ERROR the type `f16` is unstable pub fn main() { let a: f16 = 100.0; //~ ERROR the type `f16` is unstable let b = 0.0f16; //~ ERROR the type `f16` is unstable + let c = 0f16; //~ ERROR the type `f16` is unstable foo(1.23); } diff --git a/tests/ui/feature-gates/feature-gate-super-let.rs b/tests/ui/feature-gates/feature-gate-super-let.rs new file mode 100644 index 00000000000..cfe92a42669 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-super-let.rs @@ -0,0 +1,4 @@ +fn main() { + super let a = 1; + //~^ ERROR `super let` is experimental +} diff --git a/tests/ui/feature-gates/feature-gate-super-let.stderr b/tests/ui/feature-gates/feature-gate-super-let.stderr new file mode 100644 index 00000000000..a64e1b374f9 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-super-let.stderr @@ -0,0 +1,13 @@ +error[E0658]: `super let` is experimental + --> $DIR/feature-gate-super-let.rs:2:5 + | +LL | super let a = 1; + | ^^^^^ + | + = note: see issue #139076 <https://github.com/rust-lang/rust/issues/139076> for more information + = help: add `#![feature(super_let)]` 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/fn/fn-bad-block-type.rs b/tests/ui/fn/fn-bad-block-type.rs index c7ad462f143..47ddc583c87 100644 --- a/tests/ui/fn/fn-bad-block-type.rs +++ b/tests/ui/fn/fn-bad-block-type.rs @@ -1,5 +1,3 @@ -//@ error-pattern:mismatched types - -fn f() -> isize { true } +fn f() -> isize { true } //~ ERROR mismatched types fn main() { } diff --git a/tests/ui/fn/fn-bad-block-type.stderr b/tests/ui/fn/fn-bad-block-type.stderr index 6917bea6591..287caee4582 100644 --- a/tests/ui/fn/fn-bad-block-type.stderr +++ b/tests/ui/fn/fn-bad-block-type.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/fn-bad-block-type.rs:3:19 + --> $DIR/fn-bad-block-type.rs:1:19 | LL | fn f() -> isize { true } | ----- ^^^^ expected `isize`, found `bool` diff --git a/tests/ui/imports/import-loop-2.rs b/tests/ui/imports/import-loop-2.rs index d9a56cb1378..1bd0f06c671 100644 --- a/tests/ui/imports/import-loop-2.rs +++ b/tests/ui/imports/import-loop-2.rs @@ -1,11 +1,9 @@ -//@ error-pattern:import - mod a { pub use b::x; } mod b { - pub use a::x; + pub use a::x; //~ ERROR unresolved import `a::x` fn main() { let y = x; } } diff --git a/tests/ui/imports/import-loop-2.stderr b/tests/ui/imports/import-loop-2.stderr index 1a95200a662..2521b6e7c04 100644 --- a/tests/ui/imports/import-loop-2.stderr +++ b/tests/ui/imports/import-loop-2.stderr @@ -1,5 +1,5 @@ error[E0432]: unresolved import `a::x` - --> $DIR/import-loop-2.rs:8:13 + --> $DIR/import-loop-2.rs:6:13 | LL | pub use a::x; | ^^^^ no `x` in `a` diff --git a/tests/ui/imports/import-loop.rs b/tests/ui/imports/import-loop.rs index 1ba9e090033..fc5bd32adee 100644 --- a/tests/ui/imports/import-loop.rs +++ b/tests/ui/imports/import-loop.rs @@ -1,9 +1,7 @@ -//@ error-pattern:import - use y::x; mod y { - pub use y::x; + pub use y::x; //~ ERROR unresolved import `y::x` } fn main() { } diff --git a/tests/ui/imports/import-loop.stderr b/tests/ui/imports/import-loop.stderr index 8ad2d6be4d2..801fc2552b6 100644 --- a/tests/ui/imports/import-loop.stderr +++ b/tests/ui/imports/import-loop.stderr @@ -1,5 +1,5 @@ error[E0432]: unresolved import `y::x` - --> $DIR/import-loop.rs:6:13 + --> $DIR/import-loop.rs:4:13 | LL | pub use y::x; | ^^^^ no `x` in `y` diff --git a/tests/ui/imports/import3.rs b/tests/ui/imports/import3.rs index 71eea0ebb26..7bd6458cba1 100644 --- a/tests/ui/imports/import3.rs +++ b/tests/ui/imports/import3.rs @@ -1,4 +1,3 @@ -//@ error-pattern: unresolved -use main::bar; +use main::bar; //~ ERROR unresolved import `main` fn main() { println!("foo"); } diff --git a/tests/ui/imports/import3.stderr b/tests/ui/imports/import3.stderr index 7f581146781..871104ce50d 100644 --- a/tests/ui/imports/import3.stderr +++ b/tests/ui/imports/import3.stderr @@ -1,5 +1,5 @@ error[E0432]: unresolved import `main` - --> $DIR/import3.rs:2:5 + --> $DIR/import3.rs:1:5 | LL | use main::bar; | ^^^^ use of unresolved module or unlinked crate `main` diff --git a/tests/ui/imports/import4.rs b/tests/ui/imports/import4.rs index 8d727ced890..01535fc6f45 100644 --- a/tests/ui/imports/import4.rs +++ b/tests/ui/imports/import4.rs @@ -1,7 +1,4 @@ -//@ error-pattern: import - - mod a { pub use b::foo; } -mod b { pub use a::foo; } +mod b { pub use a::foo; } //~ ERROR unresolved import `a::foo` fn main() { println!("loop"); } diff --git a/tests/ui/imports/import4.stderr b/tests/ui/imports/import4.stderr index c99e8385118..c979d6c9ae2 100644 --- a/tests/ui/imports/import4.stderr +++ b/tests/ui/imports/import4.stderr @@ -1,5 +1,5 @@ error[E0432]: unresolved import `a::foo` - --> $DIR/import4.rs:5:17 + --> $DIR/import4.rs:2:17 | LL | mod b { pub use a::foo; } | ^^^^^^ no `foo` in `a` diff --git a/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.rs b/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.rs index e28b8f373da..f50c4a5207a 100644 --- a/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.rs +++ b/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.rs @@ -1,8 +1,6 @@ +//~ ERROR reached the recursion limit while instantiating `<VirtualWrapper<VirtualWrapper<VirtualWrapper //@ build-fail -//@ error-pattern: reached the recursion limit while instantiating -//@ error-pattern: reached the recursion limit finding the struct tail - // Regression test for #114484: This used to ICE during monomorphization, because we treated // `<VirtualWrapper<...> as Pointee>::Metadata` as a rigid projection after reaching the recursion // limit when finding the struct tail. @@ -73,3 +71,16 @@ fn main() { let test = SomeData([0; 256]); test.virtualize(); } + +//~? ERROR reached the recursion limit finding the struct tail for `[u8; 256]` +//~? ERROR reached the recursion limit finding the struct tail for `[u8; 256]` +//~? ERROR reached the recursion limit finding the struct tail for `[u8; 256]` +//~? ERROR reached the recursion limit finding the struct tail for `[u8; 256]` +//~? ERROR reached the recursion limit finding the struct tail for `SomeData<256>` +//~? ERROR reached the recursion limit finding the struct tail for `SomeData<256>` +//~? ERROR reached the recursion limit finding the struct tail for `SomeData<256>` +//~? ERROR reached the recursion limit finding the struct tail for `SomeData<256>` +//~? ERROR reached the recursion limit finding the struct tail for `VirtualWrapper<SomeData<256>, 0>` +//~? ERROR reached the recursion limit finding the struct tail for `VirtualWrapper<SomeData<256>, 0>` +//~? ERROR reached the recursion limit finding the struct tail for `VirtualWrapper<SomeData<256>, 0>` +//~? ERROR reached the recursion limit finding the struct tail for `VirtualWrapper<SomeData<256>, 0>` diff --git a/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.stderr b/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.stderr index 475e26fd0f0..59addc5cc4a 100644 --- a/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.stderr +++ b/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.stderr @@ -18,7 +18,7 @@ error: reached the recursion limit finding the struct tail for `[u8; 256]` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` note: the above error was encountered while instantiating `fn virtualize_my_trait::<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<SomeData<256>, 0>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>>` - --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:26:18 + --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:24:18 | LL | unsafe { virtualize_my_trait(L, self) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -43,7 +43,7 @@ error: reached the recursion limit finding the struct tail for `SomeData<256>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` note: the above error was encountered while instantiating `fn virtualize_my_trait::<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<SomeData<256>, 0>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>>` - --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:26:18 + --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:24:18 | LL | unsafe { virtualize_my_trait(L, self) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -68,7 +68,7 @@ error: reached the recursion limit finding the struct tail for `VirtualWrapper<S = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` note: the above error was encountered while instantiating `fn virtualize_my_trait::<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<SomeData<256>, 0>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>, 1>>` - --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:26:18 + --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:24:18 | LL | unsafe { virtualize_my_trait(L, self) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -76,7 +76,7 @@ LL | unsafe { virtualize_my_trait(L, self) } error: reached the recursion limit while instantiating `<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<VirtualWrapper<..., 1>, 1>, 1>, 1>, 1> as MyTrait>::virtualize` | note: `<VirtualWrapper<T, L> as MyTrait>::virtualize` defined here - --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:25:5 + --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:23:5 | LL | fn virtualize(&self) -> &dyn MyTrait { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/instrument-xray/flags-always-never-1.rs b/tests/ui/instrument-xray/flags-always-never-1.rs index 91032662e6b..97f03fca102 100644 --- a/tests/ui/instrument-xray/flags-always-never-1.rs +++ b/tests/ui/instrument-xray/flags-always-never-1.rs @@ -2,6 +2,7 @@ // //@ needs-xray //@ compile-flags: -Z instrument-xray=always,never -//@ error-pattern: incorrect value `always,never` for unstable option `instrument-xray` fn main() {} + +//~? ERROR incorrect value `always,never` for unstable option `instrument-xray` diff --git a/tests/ui/instrument-xray/flags-dupe-always.rs b/tests/ui/instrument-xray/flags-dupe-always.rs index 41e4f267b47..e3a5b3b1c3e 100644 --- a/tests/ui/instrument-xray/flags-dupe-always.rs +++ b/tests/ui/instrument-xray/flags-dupe-always.rs @@ -2,6 +2,7 @@ // //@ needs-xray //@ compile-flags: -Z instrument-xray=always,always -//@ error-pattern: incorrect value `always,always` for unstable option `instrument-xray` fn main() {} + +//~? ERROR incorrect value `always,always` for unstable option `instrument-xray` diff --git a/tests/ui/instrument-xray/flags-dupe-ignore-loops.rs b/tests/ui/instrument-xray/flags-dupe-ignore-loops.rs index ba5ea28d40b..648bd144632 100644 --- a/tests/ui/instrument-xray/flags-dupe-ignore-loops.rs +++ b/tests/ui/instrument-xray/flags-dupe-ignore-loops.rs @@ -2,6 +2,7 @@ // //@ needs-xray //@ compile-flags: -Z instrument-xray=ignore-loops,ignore-loops -//@ error-pattern: incorrect value `ignore-loops,ignore-loops` for unstable option `instrument-xray` fn main() {} + +//~? ERROR incorrect value `ignore-loops,ignore-loops` for unstable option `instrument-xray` diff --git a/tests/ui/instrument-xray/target-not-supported.rs b/tests/ui/instrument-xray/target-not-supported.rs index cdae26f993d..2045913b186 100644 --- a/tests/ui/instrument-xray/target-not-supported.rs +++ b/tests/ui/instrument-xray/target-not-supported.rs @@ -2,8 +2,9 @@ // //@ needs-llvm-components: x86 //@ compile-flags: -Z instrument-xray --target x86_64-apple-darwin -//@ error-pattern: error: XRay instrumentation is not supported for this target #![feature(no_core)] #![no_core] #![no_main] + +//~? ERROR XRay instrumentation is not supported for this target diff --git a/tests/ui/internal/internal-unstable-noallow.rs b/tests/ui/internal/internal-unstable-noallow.rs index 57ddb93d880..507eeebddc0 100644 --- a/tests/ui/internal/internal-unstable-noallow.rs +++ b/tests/ui/internal/internal-unstable-noallow.rs @@ -4,20 +4,18 @@ // the // ~ form. //@ aux-build:internal_unstable.rs -//@ error-pattern:use of unstable library feature `function` -//@ error-pattern:use of unstable library feature `struct_field` -//@ error-pattern:use of unstable library feature `method` -//@ error-pattern:use of unstable library feature `struct2_field` #[macro_use] extern crate internal_unstable; fn main() { - call_unstable_noallow!(); + call_unstable_noallow!(); //~ ERROR use of unstable library feature `function` - construct_unstable_noallow!(0); + construct_unstable_noallow!(0); //~ ERROR use of unstable library feature `struct_field` |x: internal_unstable::Foo| { call_method_noallow!(x) }; + //~^ ERROR use of unstable library feature `method` |x: internal_unstable::Bar| { access_field_noallow!(x) }; + //~^ ERROR use of unstable library feature `struct2_field` } diff --git a/tests/ui/internal/internal-unstable-noallow.stderr b/tests/ui/internal/internal-unstable-noallow.stderr index 22f42abbd11..2cc55022ef3 100644 --- a/tests/ui/internal/internal-unstable-noallow.stderr +++ b/tests/ui/internal/internal-unstable-noallow.stderr @@ -1,5 +1,5 @@ error[E0658]: use of unstable library feature `function` - --> $DIR/internal-unstable-noallow.rs:16:5 + --> $DIR/internal-unstable-noallow.rs:12:5 | LL | call_unstable_noallow!(); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | call_unstable_noallow!(); = note: this error originates in the macro `call_unstable_noallow` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0658]: use of unstable library feature `struct_field` - --> $DIR/internal-unstable-noallow.rs:18:5 + --> $DIR/internal-unstable-noallow.rs:14:5 | LL | construct_unstable_noallow!(0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | construct_unstable_noallow!(0); = note: this error originates in the macro `construct_unstable_noallow` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0658]: use of unstable library feature `method` - --> $DIR/internal-unstable-noallow.rs:20:35 + --> $DIR/internal-unstable-noallow.rs:16:35 | LL | |x: internal_unstable::Foo| { call_method_noallow!(x) }; | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -29,7 +29,7 @@ LL | |x: internal_unstable::Foo| { call_method_noallow!(x) }; = note: this error originates in the macro `call_method_noallow` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0658]: use of unstable library feature `struct2_field` - --> $DIR/internal-unstable-noallow.rs:22:35 + --> $DIR/internal-unstable-noallow.rs:19:35 | LL | |x: internal_unstable::Bar| { access_field_noallow!(x) }; | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/invalid-compile-flags/crate-type-flag.rs b/tests/ui/invalid-compile-flags/crate-type-flag.rs index 01014307149..8ccce97f7bf 100644 --- a/tests/ui/invalid-compile-flags/crate-type-flag.rs +++ b/tests/ui/invalid-compile-flags/crate-type-flag.rs @@ -45,16 +45,17 @@ // `proc-macro` is accepted, but `proc_macro` is not. //@ revisions: proc_underscore_macro //@[proc_underscore_macro] compile-flags: --crate-type=proc_macro -//@[proc_underscore_macro] error-pattern: unknown crate type: `proc_macro` // Empty `--crate-type` not accepted. //@ revisions: empty_crate_type //@[empty_crate_type] compile-flags: --crate-type= -//@[empty_crate_type] error-pattern: unknown crate type: `` // Random unknown crate type. Also check that we can handle non-ASCII. //@ revisions: unknown //@[unknown] compile-flags: --crate-type=🤡 -//@[unknown] error-pattern: unknown crate type: `🤡` fn main() {} + +//[proc_underscore_macro]~? ERROR unknown crate type: `proc_macro` +//[empty_crate_type]~? ERROR unknown crate type: `` +//[unknown]~? ERROR unknown crate type: `🤡` diff --git a/tests/ui/invalid-compile-flags/function-return/requires-x86-or-x86_64.rs b/tests/ui/invalid-compile-flags/function-return/requires-x86-or-x86_64.rs index 6a4ecb9d839..c7973c686da 100644 --- a/tests/ui/invalid-compile-flags/function-return/requires-x86-or-x86_64.rs +++ b/tests/ui/invalid-compile-flags/function-return/requires-x86-or-x86_64.rs @@ -13,8 +13,9 @@ //@[aarch64] check-fail //@[aarch64] needs-llvm-components: aarch64 //@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu -//@[aarch64] error-pattern: `-Zfunction-return` (except `keep`) is only supported on x86 and x86_64 #![feature(no_core)] #![no_core] #![no_main] + +//[aarch64]~? ERROR `-Zfunction-return` (except `keep`) is only supported on x86 and x86_64 diff --git a/tests/ui/invalid-compile-flags/function-return/thunk-extern-requires-non-large-code-model.rs b/tests/ui/invalid-compile-flags/function-return/thunk-extern-requires-non-large-code-model.rs index f4be36e08f0..fa3958c1f98 100644 --- a/tests/ui/invalid-compile-flags/function-return/thunk-extern-requires-non-large-code-model.rs +++ b/tests/ui/invalid-compile-flags/function-return/thunk-extern-requires-non-large-code-model.rs @@ -14,8 +14,9 @@ //@[large] check-fail //@[large] compile-flags: -Ccode-model=large -//@[large] error-pattern: `-Zfunction-return=thunk-extern` is only supported on non-large code models #![feature(no_core)] #![no_core] #![no_main] + +//[large]~? ERROR `-Zfunction-return=thunk-extern` is only supported on non-large code models diff --git a/tests/ui/invalid-compile-flags/reg-struct-return/requires-x86.rs b/tests/ui/invalid-compile-flags/reg-struct-return/requires-x86.rs index b5e34bece32..436442ee729 100644 --- a/tests/ui/invalid-compile-flags/reg-struct-return/requires-x86.rs +++ b/tests/ui/invalid-compile-flags/reg-struct-return/requires-x86.rs @@ -9,13 +9,14 @@ //@[x86_64] check-fail //@[x86_64] needs-llvm-components: x86 //@[x86_64] compile-flags: --target x86_64-unknown-linux-gnu -//@[x86_64] error-pattern: `-Zreg-struct-return` is only supported on x86 //@[aarch64] check-fail //@[aarch64] needs-llvm-components: aarch64 //@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu -//@[aarch64] error-pattern: `-Zreg-struct-return` is only supported on x86 #![feature(no_core)] #![no_core] #![no_main] + +//[x86_64]~? ERROR `-Zreg-struct-return` is only supported on x86 +//[aarch64]~? ERROR `-Zreg-struct-return` is only supported on x86 diff --git a/tests/ui/invalid-compile-flags/regparm/regparm-valid-values.rs b/tests/ui/invalid-compile-flags/regparm/regparm-valid-values.rs index b548d678520..a66dfe85977 100644 --- a/tests/ui/invalid-compile-flags/regparm/regparm-valid-values.rs +++ b/tests/ui/invalid-compile-flags/regparm/regparm-valid-values.rs @@ -17,8 +17,9 @@ //@[regparm4] check-fail //@[regparm4] compile-flags: -Zregparm=4 -//@[regparm4] error-pattern: `-Zregparm=4` is unsupported (valid values 0-3) #![feature(no_core)] #![no_core] #![no_main] + +//[regparm4]~? ERROR `-Zregparm=4` is unsupported (valid values 0-3) diff --git a/tests/ui/invalid-compile-flags/regparm/requires-x86.rs b/tests/ui/invalid-compile-flags/regparm/requires-x86.rs index ce6e437fb47..32c4b5af357 100644 --- a/tests/ui/invalid-compile-flags/regparm/requires-x86.rs +++ b/tests/ui/invalid-compile-flags/regparm/requires-x86.rs @@ -9,13 +9,14 @@ //@[x86_64] check-fail //@[x86_64] needs-llvm-components: x86 //@[x86_64] compile-flags: --target x86_64-unknown-linux-gnu -//@[x86_64] error-pattern: `-Zregparm=N` is only supported on x86 //@[aarch64] check-fail //@[aarch64] needs-llvm-components: aarch64 //@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu -//@[aarch64] error-pattern: `-Zregparm=N` is only supported on x86 #![feature(no_core)] #![no_core] #![no_main] + +//[x86_64]~? ERROR `-Zregparm=N` is only supported on x86 +//[aarch64]~? ERROR `-Zregparm=N` is only supported on x86 diff --git a/tests/ui/invalid/issue-114435-layout-type-err.rs b/tests/ui/invalid/issue-114435-layout-type-err.rs index 2a86839e416..07f310478d3 100644 --- a/tests/ui/invalid/issue-114435-layout-type-err.rs +++ b/tests/ui/invalid/issue-114435-layout-type-err.rs @@ -1,6 +1,5 @@ //@ check-fail //@ compile-flags: --crate-type lib -Cdebuginfo=2 -//@ error-pattern: recursion limit #![recursion_limit = "10"] macro_rules! link { @@ -41,3 +40,5 @@ link!(J, K); link!(K, Bottom); fn main() {} + +//~? ERROR reached the recursion limit finding the struct tail for `Bottom` diff --git a/tests/ui/io-checks/non-ice-error-on-worker-io-fail.rs b/tests/ui/io-checks/non-ice-error-on-worker-io-fail.rs index 7cae77eb67f..5a5d0086aa9 100644 --- a/tests/ui/io-checks/non-ice-error-on-worker-io-fail.rs +++ b/tests/ui/io-checks/non-ice-error-on-worker-io-fail.rs @@ -16,8 +16,6 @@ // rely on the checking of the normalized stderr output as our actual // "verification" of the diagnostic). -//@ error-pattern: error - // On Mac OS X, we get an error like the below //@ normalize-stderr: "failed to write bytecode to ./does-not-exist/output.non_ice_error_on_worker_io_fail.*" -> "io error modifying ./does-not-exist/" @@ -29,3 +27,5 @@ //@ ignore-arm - the file-system issues do not replicate here, at least on armhf-gnu #![crate_type = "lib"] + +//~? ERROR /does-not-exist/ diff --git a/tests/ui/issues/issue-37131.rs b/tests/ui/issues/issue-37131.rs index 3ea14672e23..16681ac21d1 100644 --- a/tests/ui/issues/issue-37131.rs +++ b/tests/ui/issues/issue-37131.rs @@ -1,3 +1,4 @@ +//~ ERROR can't find crate for `std` // Tests that compiling for a target which is not installed will result in a helpful // error message. diff --git a/tests/ui/lang-items/lang-item-missing.rs b/tests/ui/lang-items/lang-item-missing.rs index 5b832a5bb8f..75e203d04f2 100644 --- a/tests/ui/lang-items/lang-item-missing.rs +++ b/tests/ui/lang-items/lang-item-missing.rs @@ -1,13 +1,11 @@ // Test that a missing lang item (in this case `sized`) does not cause an ICE, // see #17392. -//@ error-pattern: requires `sized` lang_item - #![feature(lang_items, no_core)] #![no_core] #![no_main] #[no_mangle] -extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 { +extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 { //~ ERROR requires `sized` lang_item loop {} } diff --git a/tests/ui/lang-items/lang-item-missing.stderr b/tests/ui/lang-items/lang-item-missing.stderr index 63bca95adf7..85e9eaafe72 100644 --- a/tests/ui/lang-items/lang-item-missing.stderr +++ b/tests/ui/lang-items/lang-item-missing.stderr @@ -1,5 +1,5 @@ error: requires `sized` lang_item - --> $DIR/lang-item-missing.rs:11:60 + --> $DIR/lang-item-missing.rs:9:60 | LL | extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 { | ^^^ diff --git a/tests/ui/lang-items/missing-copy-lang-item-issue-19660.rs b/tests/ui/lang-items/missing-copy-lang-item-issue-19660.rs index 9b634ee8ee3..f92a00e602c 100644 --- a/tests/ui/lang-items/missing-copy-lang-item-issue-19660.rs +++ b/tests/ui/lang-items/missing-copy-lang-item-issue-19660.rs @@ -1,5 +1,3 @@ -//@ error-pattern: requires `copy` lang_item - #![feature(lang_items, no_core)] #![no_core] #![no_main] @@ -11,5 +9,5 @@ struct S; #[no_mangle] extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { - argc + argc //~ ERROR requires `copy` lang_item } diff --git a/tests/ui/lang-items/missing-copy-lang-item-issue-19660.stderr b/tests/ui/lang-items/missing-copy-lang-item-issue-19660.stderr index 3dc7716ecd2..9b25b1db292 100644 --- a/tests/ui/lang-items/missing-copy-lang-item-issue-19660.stderr +++ b/tests/ui/lang-items/missing-copy-lang-item-issue-19660.stderr @@ -1,5 +1,5 @@ error: requires `copy` lang_item - --> $DIR/missing-copy-lang-item-issue-19660.rs:14:5 + --> $DIR/missing-copy-lang-item-issue-19660.rs:12:5 | LL | argc | ^^^^ diff --git a/tests/ui/layout/size-of-val-raw-too-big.rs b/tests/ui/layout/size-of-val-raw-too-big.rs index dfca6d6eb76..566b01255fa 100644 --- a/tests/ui/layout/size-of-val-raw-too-big.rs +++ b/tests/ui/layout/size-of-val-raw-too-big.rs @@ -1,7 +1,8 @@ +//~ ERROR values of the type `Example` are too big for the target architecture //@ build-fail //@ compile-flags: --crate-type lib //@ only-32bit Layout computation rejects this layout for different reasons on 64-bit. -//@ error-pattern: too big for the target architecture + #![feature(core_intrinsics)] #![allow(internal_features)] diff --git a/tests/ui/layout/unknown-when-no-type-parameter.rs b/tests/ui/layout/unknown-when-no-type-parameter.rs index 94c32cf262f..500b7938eeb 100644 --- a/tests/ui/layout/unknown-when-no-type-parameter.rs +++ b/tests/ui/layout/unknown-when-no-type-parameter.rs @@ -1,6 +1,5 @@ #![feature(trivial_bounds)] -//@ error-pattern: error[E0080]: evaluation of constant value failed //@ error-pattern: the type `<() as Project>::Assoc` has an unknown layout trait Project { @@ -8,7 +7,7 @@ trait Project { } fn foo() where (): Project { - [(); size_of::<<() as Project>::Assoc>()]; + [(); size_of::<<() as Project>::Assoc>()]; //~ ERROR evaluation of constant value failed } fn main() {} diff --git a/tests/ui/layout/unknown-when-no-type-parameter.stderr b/tests/ui/layout/unknown-when-no-type-parameter.stderr index 9e414d224bb..a2dbb191ee2 100644 --- a/tests/ui/layout/unknown-when-no-type-parameter.stderr +++ b/tests/ui/layout/unknown-when-no-type-parameter.stderr @@ -1,5 +1,5 @@ error[E0080]: evaluation of constant value failed - --> $DIR/unknown-when-no-type-parameter.rs:11:10 + --> $DIR/unknown-when-no-type-parameter.rs:10:10 | LL | [(); size_of::<<() as Project>::Assoc>()]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `<() as Project>::Assoc` has an unknown layout diff --git a/tests/ui/limits/issue-17913.rs b/tests/ui/limits/issue-17913.rs index 5407902daba..85deab4bc4c 100644 --- a/tests/ui/limits/issue-17913.rs +++ b/tests/ui/limits/issue-17913.rs @@ -1,6 +1,5 @@ //@ build-fail //@ normalize-stderr: "\[&usize; \d+\]" -> "[&usize; usize::MAX]" -//@ error-pattern: too big for the target architecture #[cfg(target_pointer_width = "64")] fn main() { @@ -15,3 +14,5 @@ fn main() { let a: Box<_> = Box::new([&n; 0xFFFFFFFF_usize]); println!("{}", a[0xFFFFFF_usize]); } + +//~? ERROR are too big for the target architecture diff --git a/tests/ui/limits/issue-55878.rs b/tests/ui/limits/issue-55878.rs index db4a2724452..614ff328bf5 100644 --- a/tests/ui/limits/issue-55878.rs +++ b/tests/ui/limits/issue-55878.rs @@ -1,6 +1,6 @@ //@ build-fail -//@ error-pattern: are too big for the target architecture fn main() { println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>()); + //~^ ERROR evaluation of constant value failed } diff --git a/tests/ui/limits/issue-55878.stderr b/tests/ui/limits/issue-55878.stderr index d705b3daf79..9b3922d7933 100644 --- a/tests/ui/limits/issue-55878.stderr +++ b/tests/ui/limits/issue-55878.stderr @@ -1,5 +1,5 @@ error[E0080]: evaluation of constant value failed - --> $DIR/issue-55878.rs:5:26 + --> $DIR/issue-55878.rs:4:26 | LL | println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ values of the type `[u8; usize::MAX]` are too big for the target architecture diff --git a/tests/ui/link-native-libs/empty-kind-1.rs b/tests/ui/link-native-libs/empty-kind-1.rs index d9b8d8a7f7d..04e7e3c2c7b 100644 --- a/tests/ui/link-native-libs/empty-kind-1.rs +++ b/tests/ui/link-native-libs/empty-kind-1.rs @@ -1,6 +1,7 @@ // Unspecified kind should fail with an error //@ compile-flags: -l =mylib -//@ error-pattern: unknown library kind ``, expected one of: static, dylib, framework, link-arg fn main() {} + +//~? ERROR unknown library kind `` diff --git a/tests/ui/link-native-libs/empty-kind-2.rs b/tests/ui/link-native-libs/empty-kind-2.rs index 16cb3b917e4..1436c086dfd 100644 --- a/tests/ui/link-native-libs/empty-kind-2.rs +++ b/tests/ui/link-native-libs/empty-kind-2.rs @@ -1,6 +1,7 @@ // Unspecified kind should fail with an error //@ compile-flags: -l :+bundle=mylib -//@ error-pattern: unknown library kind ``, expected one of: static, dylib, framework, link-arg fn main() {} + +//~? ERROR unknown library kind `` diff --git a/tests/ui/link-native-libs/link-arg-error.rs b/tests/ui/link-native-libs/link-arg-error.rs index 4defb108178..9d9dcc27ccb 100644 --- a/tests/ui/link-native-libs/link-arg-error.rs +++ b/tests/ui/link-native-libs/link-arg-error.rs @@ -1,4 +1,5 @@ //@ compile-flags: -l link-arg:+bundle=arg -Z unstable-options -//@ error-pattern: linking modifier `bundle` is only compatible with `static` linking kind fn main() {} + +//~? ERROR linking modifier `bundle` is only compatible with `static` linking kind diff --git a/tests/ui/link-native-libs/manual-link-bad-form.rs b/tests/ui/link-native-libs/manual-link-bad-form.rs index 0f5723adec9..71e80c60dec 100644 --- a/tests/ui/link-native-libs/manual-link-bad-form.rs +++ b/tests/ui/link-native-libs/manual-link-bad-form.rs @@ -1,5 +1,6 @@ //@ compile-flags:-l static= -//@ error-pattern: library name must not be empty fn main() { } + +//~? ERROR library name must not be empty diff --git a/tests/ui/link-native-libs/manual-link-bad-kind.rs b/tests/ui/link-native-libs/manual-link-bad-kind.rs index d070faa6574..8b5f478e80a 100644 --- a/tests/ui/link-native-libs/manual-link-bad-kind.rs +++ b/tests/ui/link-native-libs/manual-link-bad-kind.rs @@ -1,5 +1,6 @@ //@ compile-flags:-l bar=foo -//@ error-pattern: unknown library kind `bar`, expected one of: static, dylib, framework, link-arg fn main() { } + +//~? ERROR unknown library kind `bar` diff --git a/tests/ui/link-native-libs/manual-link-bad-search-path.rs b/tests/ui/link-native-libs/manual-link-bad-search-path.rs index c9ced4734fc..cc4a5ef2267 100644 --- a/tests/ui/link-native-libs/manual-link-bad-search-path.rs +++ b/tests/ui/link-native-libs/manual-link-bad-search-path.rs @@ -1,5 +1,6 @@ //@ compile-flags:-L native= -//@ error-pattern: empty search path given via `-L` fn main() { } + +//~? ERROR empty search path given via `-L` diff --git a/tests/ui/link-native-libs/manual-link-framework.rs b/tests/ui/link-native-libs/manual-link-framework.rs index 43cdda0a4e6..b3c3d6a7c3c 100644 --- a/tests/ui/link-native-libs/manual-link-framework.rs +++ b/tests/ui/link-native-libs/manual-link-framework.rs @@ -1,5 +1,6 @@ //@ ignore-apple //@ compile-flags:-l framework=foo -//@ error-pattern: library kind `framework` is only supported on Apple targets fn main() {} + +//~? ERROR library kind `framework` is only supported on Apple targets diff --git a/tests/ui/link-native-libs/manual-link-unsupported-kind.rs b/tests/ui/link-native-libs/manual-link-unsupported-kind.rs index b5b9e3e6577..3dfe9bdebc5 100644 --- a/tests/ui/link-native-libs/manual-link-unsupported-kind.rs +++ b/tests/ui/link-native-libs/manual-link-unsupported-kind.rs @@ -1,5 +1,6 @@ //@ compile-flags:-l raw-dylib=foo -//@ error-pattern: unknown library kind `raw-dylib`, expected one of: static, dylib, framework, link-arg fn main() { } + +//~? ERROR unknown library kind `raw-dylib` diff --git a/tests/ui/link-native-libs/modifiers-override-3.rs b/tests/ui/link-native-libs/modifiers-override-3.rs index d05735ad616..3d269dbd812 100644 --- a/tests/ui/link-native-libs/modifiers-override-3.rs +++ b/tests/ui/link-native-libs/modifiers-override-3.rs @@ -2,6 +2,7 @@ // overrides another command line library with modifiers. //@ compile-flags:-lstatic:+whole-archive=foo -lstatic:+whole-archive=foo -//@ error-pattern: overriding linking modifiers from command line is not supported fn main() {} + +//~? ERROR overriding linking modifiers from command line is not supported diff --git a/tests/ui/link-native-libs/suggest-libname-only-1.rs b/tests/ui/link-native-libs/suggest-libname-only-1.rs index 328181fb5cb..4ccfa086bde 100644 --- a/tests/ui/link-native-libs/suggest-libname-only-1.rs +++ b/tests/ui/link-native-libs/suggest-libname-only-1.rs @@ -1,9 +1,10 @@ //@ build-fail //@ compile-flags: --crate-type rlib -//@ error-pattern: could not find native static library `libfoo.a` //@ error-pattern: only provide the library name `foo`, not the full filename #[link(name = "libfoo.a", kind = "static")] -extern { } +extern { } //~ WARN extern declarations without an explicit ABI are deprecated pub fn main() { } + +//~? ERROR could not find native static library `libfoo.a` diff --git a/tests/ui/link-native-libs/suggest-libname-only-1.stderr b/tests/ui/link-native-libs/suggest-libname-only-1.stderr index 47f7d92c9f9..85a3599e8db 100644 --- a/tests/ui/link-native-libs/suggest-libname-only-1.stderr +++ b/tests/ui/link-native-libs/suggest-libname-only-1.stderr @@ -1,5 +1,5 @@ warning: extern declarations without an explicit ABI are deprecated - --> $DIR/suggest-libname-only-1.rs:7:1 + --> $DIR/suggest-libname-only-1.rs:6:1 | LL | extern { } | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"` diff --git a/tests/ui/link-native-libs/suggest-libname-only-2.rs b/tests/ui/link-native-libs/suggest-libname-only-2.rs index 7ed106e4ab4..c35b4a674b7 100644 --- a/tests/ui/link-native-libs/suggest-libname-only-2.rs +++ b/tests/ui/link-native-libs/suggest-libname-only-2.rs @@ -1,9 +1,10 @@ //@ build-fail //@ compile-flags: --crate-type rlib -//@ error-pattern: could not find native static library `bar.lib` //@ error-pattern: only provide the library name `bar`, not the full filename #[link(name = "bar.lib", kind = "static")] -extern { } +extern { } //~ WARN extern declarations without an explicit ABI are deprecated pub fn main() { } + +//~? ERROR could not find native static library `bar.lib` diff --git a/tests/ui/link-native-libs/suggest-libname-only-2.stderr b/tests/ui/link-native-libs/suggest-libname-only-2.stderr index a2d8f4c8191..d5c88931ad5 100644 --- a/tests/ui/link-native-libs/suggest-libname-only-2.stderr +++ b/tests/ui/link-native-libs/suggest-libname-only-2.stderr @@ -1,5 +1,5 @@ warning: extern declarations without an explicit ABI are deprecated - --> $DIR/suggest-libname-only-2.rs:7:1 + --> $DIR/suggest-libname-only-2.rs:6:1 | LL | extern { } | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"` diff --git a/tests/ui/linkage-attr/incompatible-flavor.rs b/tests/ui/linkage-attr/incompatible-flavor.rs index acf720bc97a..7f583f47e2f 100644 --- a/tests/ui/linkage-attr/incompatible-flavor.rs +++ b/tests/ui/linkage-attr/incompatible-flavor.rs @@ -1,6 +1,7 @@ //@ compile-flags: --target=x86_64-unknown-linux-gnu -C linker-flavor=msvc --crate-type=rlib -//@ error-pattern: linker flavor `msvc` is incompatible with the current target //@ needs-llvm-components: #![feature(no_core)] #![no_core] + +//~? ERROR linker flavor `msvc` is incompatible with the current target diff --git a/tests/ui/linkage-attr/issue-10755.rs b/tests/ui/linkage-attr/issue-10755.rs index 58d5b5ead57..509f484adf8 100644 --- a/tests/ui/linkage-attr/issue-10755.rs +++ b/tests/ui/linkage-attr/issue-10755.rs @@ -1,10 +1,11 @@ //@ build-fail //@ dont-check-compiler-stderr //@ compile-flags: -C linker=llllll -//@ error-pattern: `llllll` // Before, the error-pattern checked for "not found". On WSL with appendWindowsPath=true, running // in invalid command returns a PermissionDenied instead. fn main() { } + +//~? ERROR `llllll` diff --git a/tests/ui/linkage-attr/raw-dylib/elf/multiple-libraries.rs b/tests/ui/linkage-attr/raw-dylib/elf/multiple-libraries.rs index f4715ff2d3d..030b95198f5 100644 --- a/tests/ui/linkage-attr/raw-dylib/elf/multiple-libraries.rs +++ b/tests/ui/linkage-attr/raw-dylib/elf/multiple-libraries.rs @@ -35,3 +35,5 @@ fn main() { meooooooooooooooow(); woooooooooooooooooof(); } + +//[without]~? ERROR linking with ` diff --git a/tests/ui/linkage-attr/raw-dylib/elf/single-symbol.rs b/tests/ui/linkage-attr/raw-dylib/elf/single-symbol.rs index fe9c7884e54..20de4afcee0 100644 --- a/tests/ui/linkage-attr/raw-dylib/elf/single-symbol.rs +++ b/tests/ui/linkage-attr/raw-dylib/elf/single-symbol.rs @@ -26,3 +26,5 @@ unsafe extern "C" { fn main() { meooooooooooooooow(); } + +//[without]~? ERROR linking with ` diff --git a/tests/ui/linkage-attr/raw-dylib/elf/verbatim.rs b/tests/ui/linkage-attr/raw-dylib/elf/verbatim.rs index 72cba18d841..302ec0edeaa 100644 --- a/tests/ui/linkage-attr/raw-dylib/elf/verbatim.rs +++ b/tests/ui/linkage-attr/raw-dylib/elf/verbatim.rs @@ -27,3 +27,5 @@ unsafe extern "C" { fn main() { meooooooooooooooow(); } + +//[without]~? ERROR linking with ` diff --git a/tests/ui/linkage-attr/unstable-flavor.rs b/tests/ui/linkage-attr/unstable-flavor.rs index 82d9dff3874..6aa9efb58d1 100644 --- a/tests/ui/linkage-attr/unstable-flavor.rs +++ b/tests/ui/linkage-attr/unstable-flavor.rs @@ -4,11 +4,12 @@ // //@ revisions: bpf ptx //@ [bpf] compile-flags: --target=bpfel-unknown-none -C linker-flavor=bpf --crate-type=rlib -//@ [bpf] error-pattern: linker flavor `bpf` is unstable, the `-Z unstable-options` flag //@ [bpf] needs-llvm-components: //@ [ptx] compile-flags: --target=nvptx64-nvidia-cuda -C linker-flavor=ptx --crate-type=rlib -//@ [ptx] error-pattern: linker flavor `ptx` is unstable, the `-Z unstable-options` flag //@ [ptx] needs-llvm-components: #![feature(no_core)] #![no_core] + +//[bpf]~? ERROR the linker flavor `bpf` is unstable +//[ptx]~? ERROR the linker flavor `ptx` is unstable diff --git a/tests/ui/lint/bad-lint-cap.rs b/tests/ui/lint/bad-lint-cap.rs index aab3f723796..c219cb1b665 100644 --- a/tests/ui/lint/bad-lint-cap.rs +++ b/tests/ui/lint/bad-lint-cap.rs @@ -1,4 +1,5 @@ //@ compile-flags: --cap-lints test -//@ error-pattern: unknown lint level: `test` fn main() {} + +//~? ERROR unknown lint level: `test` diff --git a/tests/ui/lint/cli-unknown-force-warn.rs b/tests/ui/lint/cli-unknown-force-warn.rs index 007f8dd8732..330d5570e21 100644 --- a/tests/ui/lint/cli-unknown-force-warn.rs +++ b/tests/ui/lint/cli-unknown-force-warn.rs @@ -4,8 +4,11 @@ //@ check-pass //@ compile-flags: --force-warn foo-qux -//@ error-pattern: unknown lint: `foo_qux` //@ error-pattern: requested on the command line with `--force-warn foo_qux` //@ error-pattern: `#[warn(unknown_lints)]` on by default fn main() {} + +//~? WARN unknown lint: `foo_qux` +//~? WARN unknown lint: `foo_qux` +//~? WARN unknown lint: `foo_qux` diff --git a/tests/ui/lint/command-line-register-unknown-lint-tool.rs b/tests/ui/lint/command-line-register-unknown-lint-tool.rs index b4e9a067fe2..a517f4c7ea6 100644 --- a/tests/ui/lint/command-line-register-unknown-lint-tool.rs +++ b/tests/ui/lint/command-line-register-unknown-lint-tool.rs @@ -1,4 +1,7 @@ //@ compile-flags: -A unknown_tool::foo -//@ error-pattern: unknown lint tool: `unknown_tool` fn main() {} + +//~? ERROR unknown lint tool: `unknown_tool` +//~? ERROR unknown lint tool: `unknown_tool` +//~? ERROR unknown lint tool: `unknown_tool` diff --git a/tests/ui/lint/force-warn/warnings-lint-group.rs b/tests/ui/lint/force-warn/warnings-lint-group.rs index 944070527a1..28de42639d3 100644 --- a/tests/ui/lint/force-warn/warnings-lint-group.rs +++ b/tests/ui/lint/force-warn/warnings-lint-group.rs @@ -1,5 +1,8 @@ // --force-warn warnings is an error //@ compile-flags: --force-warn warnings -//@ error-pattern: `warnings` lint group is not supported fn main() {} + +//~? ERROR `warnings` lint group is not supported with ´--force-warn´ +//~? ERROR `warnings` lint group is not supported with ´--force-warn´ +//~? ERROR `warnings` lint group is not supported with ´--force-warn´ diff --git a/tests/ui/lint/issue-104897.rs b/tests/ui/lint/issue-104897.rs index 3cfe94bbd22..99bc1cf3a42 100644 --- a/tests/ui/lint/issue-104897.rs +++ b/tests/ui/lint/issue-104897.rs @@ -1,5 +1,2 @@ -//@ error-pattern: this file contains an unclosed delimiter -//@ error-pattern: this file contains an unclosed delimiter -//@ error-pattern: this file contains an unclosed delimiter - +//~v ERROR this file contains an unclosed delimiter fn f(){(print!(á diff --git a/tests/ui/lint/issue-104897.stderr b/tests/ui/lint/issue-104897.stderr index 584902ee4c0..ebc794bfb73 100644 --- a/tests/ui/lint/issue-104897.stderr +++ b/tests/ui/lint/issue-104897.stderr @@ -1,5 +1,5 @@ error: this file contains an unclosed delimiter - --> $DIR/issue-104897.rs:5:18 + --> $DIR/issue-104897.rs:2:18 | LL | fn f(){(print!(á | -- - ^ diff --git a/tests/ui/lint/lint-pre-expansion-extern-module.rs b/tests/ui/lint/lint-pre-expansion-extern-module.rs index b76879ccbb8..f1ab0cf3b74 100644 --- a/tests/ui/lint/lint-pre-expansion-extern-module.rs +++ b/tests/ui/lint/lint-pre-expansion-extern-module.rs @@ -1,7 +1,9 @@ //@ check-pass //@ compile-flags: -W rust-2018-compatibility -//@ error-pattern: `try` is a keyword in the 2018 edition fn main() {} mod lint_pre_expansion_extern_module_aux; + +//~? WARN `try` is a keyword in the 2018 edition +//~? WARN this is accepted in the current edition diff --git a/tests/ui/lint/lint-removed-cmdline-deny.rs b/tests/ui/lint/lint-removed-cmdline-deny.rs index e56a95d292a..6616781d5cb 100644 --- a/tests/ui/lint/lint-removed-cmdline-deny.rs +++ b/tests/ui/lint/lint-removed-cmdline-deny.rs @@ -3,11 +3,14 @@ //@ compile-flags:-D renamed-and-removed-lints -D raw_pointer_derive -//@ error-pattern:lint `raw_pointer_derive` has been removed //@ error-pattern:requested on the command line with `-D raw_pointer_derive` //@ error-pattern:requested on the command line with `-D renamed-and-removed-lints` #![warn(unused)] #[deny(warnings)] -fn main() { let unused = (); } +fn main() { let unused = (); } //~ ERROR unused variable: `unused` + +//~? ERROR lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok +//~? ERROR lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok +//~? ERROR lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok diff --git a/tests/ui/lint/lint-removed-cmdline-deny.stderr b/tests/ui/lint/lint-removed-cmdline-deny.stderr index 3321afa7fcd..27a3504a16a 100644 --- a/tests/ui/lint/lint-removed-cmdline-deny.stderr +++ b/tests/ui/lint/lint-removed-cmdline-deny.stderr @@ -14,13 +14,13 @@ error: lint `raw_pointer_derive` has been removed: using derive with raw pointer = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: unused variable: `unused` - --> $DIR/lint-removed-cmdline-deny.rs:13:17 + --> $DIR/lint-removed-cmdline-deny.rs:12:17 | LL | fn main() { let unused = (); } | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` | note: the lint level is defined here - --> $DIR/lint-removed-cmdline-deny.rs:12:8 + --> $DIR/lint-removed-cmdline-deny.rs:11:8 | LL | #[deny(warnings)] | ^^^^^^^^ diff --git a/tests/ui/lint/lint-removed-cmdline.rs b/tests/ui/lint/lint-removed-cmdline.rs index 3c9d3eb8e7b..4dde3dbc381 100644 --- a/tests/ui/lint/lint-removed-cmdline.rs +++ b/tests/ui/lint/lint-removed-cmdline.rs @@ -3,11 +3,14 @@ //@ compile-flags:-D raw_pointer_derive -//@ error-pattern:lint `raw_pointer_derive` has been removed //@ error-pattern:`#[warn(renamed_and_removed_lints)]` on by default //@ error-pattern:requested on the command line with `-D raw_pointer_derive` #![warn(unused)] #[deny(warnings)] -fn main() { let unused = (); } +fn main() { let unused = (); } //~ ERROR unused variable: `unused` + +//~? WARN lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok +//~? WARN lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok +//~? WARN lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok diff --git a/tests/ui/lint/lint-removed-cmdline.stderr b/tests/ui/lint/lint-removed-cmdline.stderr index fd63433c308..7994f9bcfd9 100644 --- a/tests/ui/lint/lint-removed-cmdline.stderr +++ b/tests/ui/lint/lint-removed-cmdline.stderr @@ -14,13 +14,13 @@ warning: lint `raw_pointer_derive` has been removed: using derive with raw point = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: unused variable: `unused` - --> $DIR/lint-removed-cmdline.rs:13:17 + --> $DIR/lint-removed-cmdline.rs:12:17 | LL | fn main() { let unused = (); } | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` | note: the lint level is defined here - --> $DIR/lint-removed-cmdline.rs:12:8 + --> $DIR/lint-removed-cmdline.rs:11:8 | LL | #[deny(warnings)] | ^^^^^^^^ diff --git a/tests/ui/lint/lint-renamed-cmdline-deny.rs b/tests/ui/lint/lint-renamed-cmdline-deny.rs index 13500d006f8..0ea4ce40817 100644 --- a/tests/ui/lint/lint-renamed-cmdline-deny.rs +++ b/tests/ui/lint/lint-renamed-cmdline-deny.rs @@ -1,10 +1,12 @@ //@ compile-flags:-D renamed-and-removed-lints -D bare_trait_object -//@ error-pattern:lint `bare_trait_object` has been renamed to `bare_trait_objects` //@ error-pattern:use the new name `bare_trait_objects` //@ error-pattern:requested on the command line with `-D bare_trait_object` //@ error-pattern:requested on the command line with `-D renamed-and-removed-lints` -//@ error-pattern:unused #[deny(unused)] -fn main() { let unused = (); } +fn main() { let unused = (); } //~ ERROR unused variable: `unused` + +//~? ERROR lint `bare_trait_object` has been renamed to `bare_trait_objects` +//~? ERROR lint `bare_trait_object` has been renamed to `bare_trait_objects` +//~? ERROR lint `bare_trait_object` has been renamed to `bare_trait_objects` diff --git a/tests/ui/lint/lint-renamed-cmdline-deny.stderr b/tests/ui/lint/lint-renamed-cmdline-deny.stderr index 0e182a4e5de..a49cdc84f9e 100644 --- a/tests/ui/lint/lint-renamed-cmdline-deny.stderr +++ b/tests/ui/lint/lint-renamed-cmdline-deny.stderr @@ -17,13 +17,13 @@ error: lint `bare_trait_object` has been renamed to `bare_trait_objects` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: unused variable: `unused` - --> $DIR/lint-renamed-cmdline-deny.rs:10:17 + --> $DIR/lint-renamed-cmdline-deny.rs:8:17 | LL | fn main() { let unused = (); } | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` | note: the lint level is defined here - --> $DIR/lint-renamed-cmdline-deny.rs:9:8 + --> $DIR/lint-renamed-cmdline-deny.rs:7:8 | LL | #[deny(unused)] | ^^^^^^ diff --git a/tests/ui/lint/lint-renamed-cmdline.rs b/tests/ui/lint/lint-renamed-cmdline.rs index 7adea98a609..45df7b6d640 100644 --- a/tests/ui/lint/lint-renamed-cmdline.rs +++ b/tests/ui/lint/lint-renamed-cmdline.rs @@ -1,9 +1,11 @@ //@ compile-flags:-D bare_trait_object -//@ error-pattern:lint `bare_trait_object` has been renamed to `bare_trait_objects` //@ error-pattern:requested on the command line with `-D bare_trait_object` //@ error-pattern:`#[warn(renamed_and_removed_lints)]` on by default -//@ error-pattern:unused #[deny(unused)] -fn main() { let unused = (); } +fn main() { let unused = (); } //~ ERROR unused variable: `unused` + +//~? WARN lint `bare_trait_object` has been renamed to `bare_trait_objects` +//~? WARN lint `bare_trait_object` has been renamed to `bare_trait_objects` +//~? WARN lint `bare_trait_object` has been renamed to `bare_trait_objects` diff --git a/tests/ui/lint/lint-renamed-cmdline.stderr b/tests/ui/lint/lint-renamed-cmdline.stderr index d6bb72f34dc..901e7a642d1 100644 --- a/tests/ui/lint/lint-renamed-cmdline.stderr +++ b/tests/ui/lint/lint-renamed-cmdline.stderr @@ -17,13 +17,13 @@ warning: lint `bare_trait_object` has been renamed to `bare_trait_objects` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: unused variable: `unused` - --> $DIR/lint-renamed-cmdline.rs:9:17 + --> $DIR/lint-renamed-cmdline.rs:7:17 | LL | fn main() { let unused = (); } | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` | note: the lint level is defined here - --> $DIR/lint-renamed-cmdline.rs:8:8 + --> $DIR/lint-renamed-cmdline.rs:6:8 | LL | #[deny(unused)] | ^^^^^^ diff --git a/tests/ui/lint/lint-stability2.rs b/tests/ui/lint/lint-stability2.rs index 254ec8f9bee..056ff5a3e0a 100644 --- a/tests/ui/lint/lint-stability2.rs +++ b/tests/ui/lint/lint-stability2.rs @@ -1,5 +1,4 @@ //@ aux-build:lint_stability.rs -//@ error-pattern: use of deprecated function #![deny(deprecated)] @@ -9,5 +8,5 @@ extern crate lint_stability; use lint_stability::*; fn main() { - macro_test!(); + macro_test!(); //~ ERROR use of deprecated function `lint_stability::deprecated`: text } diff --git a/tests/ui/lint/lint-stability2.stderr b/tests/ui/lint/lint-stability2.stderr index 3df0c428167..fa1bce716fc 100644 --- a/tests/ui/lint/lint-stability2.stderr +++ b/tests/ui/lint/lint-stability2.stderr @@ -1,11 +1,11 @@ error: use of deprecated function `lint_stability::deprecated`: text - --> $DIR/lint-stability2.rs:12:5 + --> $DIR/lint-stability2.rs:11:5 | LL | macro_test!(); | ^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/lint-stability2.rs:4:9 + --> $DIR/lint-stability2.rs:3:9 | LL | #![deny(deprecated)] | ^^^^^^^^^^ diff --git a/tests/ui/lint/lint-stability3.rs b/tests/ui/lint/lint-stability3.rs index 3c5652ae030..1ca346f746a 100644 --- a/tests/ui/lint/lint-stability3.rs +++ b/tests/ui/lint/lint-stability3.rs @@ -1,5 +1,4 @@ //@ aux-build:lint_stability.rs -//@ error-pattern: use of deprecated function #![deny(deprecated)] #![allow(warnings)] @@ -11,4 +10,5 @@ use lint_stability::*; fn main() { macro_test_arg_nested!(deprecated_text); + //~^ ERROR use of deprecated function `lint_stability::deprecated_text`: text } diff --git a/tests/ui/lint/lint-stability3.stderr b/tests/ui/lint/lint-stability3.stderr index 3a2af452ce2..85f14c6fc17 100644 --- a/tests/ui/lint/lint-stability3.stderr +++ b/tests/ui/lint/lint-stability3.stderr @@ -1,11 +1,11 @@ error: use of deprecated function `lint_stability::deprecated_text`: text - --> $DIR/lint-stability3.rs:13:28 + --> $DIR/lint-stability3.rs:12:28 | LL | macro_test_arg_nested!(deprecated_text); | ^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/lint-stability3.rs:4:9 + --> $DIR/lint-stability3.rs:3:9 | LL | #![deny(deprecated)] | ^^^^^^^^^^ diff --git a/tests/ui/lint/lint-unknown-lint-cmdline-deny.rs b/tests/ui/lint/lint-unknown-lint-cmdline-deny.rs index c92c3999ce9..e2f7c73eacf 100644 --- a/tests/ui/lint/lint-unknown-lint-cmdline-deny.rs +++ b/tests/ui/lint/lint-unknown-lint-cmdline-deny.rs @@ -1,9 +1,15 @@ //@ compile-flags:-D unknown-lints -D bogus -D dead_cod -//@ error-pattern:unknown lint: `bogus` //@ error-pattern:requested on the command line with `-D bogus` //@ error-pattern:requested on the command line with `-D dead_cod` //@ error-pattern:requested on the command line with `-D unknown-lints` //@ error-pattern:did you mean: `dead_code` fn main() { } + +//~? ERROR unknown lint: `bogus` +//~? ERROR unknown lint: `dead_cod` +//~? ERROR unknown lint: `bogus` +//~? ERROR unknown lint: `dead_cod` +//~? ERROR unknown lint: `bogus` +//~? ERROR unknown lint: `dead_cod` diff --git a/tests/ui/lint/lint-unknown-lint-cmdline.rs b/tests/ui/lint/lint-unknown-lint-cmdline.rs index 202c617235f..931e945a1a3 100644 --- a/tests/ui/lint/lint-unknown-lint-cmdline.rs +++ b/tests/ui/lint/lint-unknown-lint-cmdline.rs @@ -1,11 +1,16 @@ //@ check-pass //@ compile-flags:-D bogus -D dead_cod -//@ error-pattern:unknown lint: `bogus` //@ error-pattern:requested on the command line with `-D bogus` //@ error-pattern:`#[warn(unknown_lints)]` on by default -//@ error-pattern:unknown lint: `dead_cod` //@ error-pattern:requested on the command line with `-D dead_cod` //@ error-pattern:did you mean: `dead_code` fn main() { } + +//~? WARN unknown lint: `bogus` +//~? WARN unknown lint: `dead_cod` +//~? WARN unknown lint: `bogus` +//~? WARN unknown lint: `dead_cod` +//~? WARN unknown lint: `bogus` +//~? WARN unknown lint: `dead_cod` diff --git a/tests/ui/lint/unused_parens_multibyte_recovery.rs b/tests/ui/lint/unused_parens_multibyte_recovery.rs index 630b25d192a..8f53c7ad262 100644 --- a/tests/ui/lint/unused_parens_multibyte_recovery.rs +++ b/tests/ui/lint/unused_parens_multibyte_recovery.rs @@ -1,10 +1,7 @@ // ignore-tidy-trailing-newlines -// -//@ error-pattern: this file contains an unclosed delimiter -//@ error-pattern: this file contains an unclosed delimiter -//@ error-pattern: this file contains an unclosed delimiter -// + // Verify that unused parens lint does not try to create a span // which points in the middle of a multibyte character. +//~v ERROR this file contains an unclosed delimiter fn f(){(print!(á \ No newline at end of file diff --git a/tests/ui/lint/unused_parens_multibyte_recovery.stderr b/tests/ui/lint/unused_parens_multibyte_recovery.stderr index ef4089f31f4..770fd6f084e 100644 --- a/tests/ui/lint/unused_parens_multibyte_recovery.stderr +++ b/tests/ui/lint/unused_parens_multibyte_recovery.stderr @@ -1,5 +1,5 @@ error: this file contains an unclosed delimiter - --> $DIR/unused_parens_multibyte_recovery.rs:10:17 + --> $DIR/unused_parens_multibyte_recovery.rs:7:17 | LL | fn f(){(print!(á | -- - ^ diff --git a/tests/ui/lto/issue-11154.rs b/tests/ui/lto/issue-11154.rs index 914b0b73e47..7770aeccd6a 100644 --- a/tests/ui/lto/issue-11154.rs +++ b/tests/ui/lto/issue-11154.rs @@ -1,6 +1,6 @@ //@ build-fail //@ compile-flags: -C lto -C prefer-dynamic -//@ error-pattern: cannot prefer dynamic linking - fn main() {} + +//~? ERROR cannot prefer dynamic linking when performing LTO diff --git a/tests/ui/lto/lto-duplicate-symbols.rs b/tests/ui/lto/lto-duplicate-symbols.rs index 27bdde418f8..a62ab2e2217 100644 --- a/tests/ui/lto/lto-duplicate-symbols.rs +++ b/tests/ui/lto/lto-duplicate-symbols.rs @@ -1,7 +1,6 @@ //@ build-fail //@ aux-build:lto-duplicate-symbols1.rs //@ aux-build:lto-duplicate-symbols2.rs -//@ error-pattern:Linking globals named 'foo': symbol multiply defined! //@ compile-flags: -C lto //@ no-prefer-dynamic //@ normalize-stderr: "lto-duplicate-symbols2\.lto_duplicate_symbols2\.[0-9a-zA-Z]+-cgu" -> "lto-duplicate-symbols2.lto_duplicate_symbols2.HASH-cgu" @@ -9,3 +8,6 @@ extern crate lto_duplicate_symbols1; extern crate lto_duplicate_symbols2; fn main() {} + +//~? WARN Linking globals named 'foo': symbol multiply defined +//~? ERROR failed to load bitcode of module "lto-duplicate-symbols2.lto_duplicate_symbols2 diff --git a/tests/ui/macros/not-utf8.rs b/tests/ui/macros/not-utf8.rs index ad8ac39d230..0993c068860 100644 --- a/tests/ui/macros/not-utf8.rs +++ b/tests/ui/macros/not-utf8.rs @@ -1,7 +1,7 @@ -//@ error-pattern: did not contain valid UTF-8 //@ reference: input.encoding.utf8 //@ reference: input.encoding.invalid fn foo() { include!("not-utf8.bin"); + //~^ ERROR couldn't read `$DIR/not-utf8.bin`: stream did not contain valid UTF-8 } diff --git a/tests/ui/macros/not-utf8.stderr b/tests/ui/macros/not-utf8.stderr index d466d5087d4..c310e70935e 100644 --- a/tests/ui/macros/not-utf8.stderr +++ b/tests/ui/macros/not-utf8.stderr @@ -1,5 +1,5 @@ error: couldn't read `$DIR/not-utf8.bin`: stream did not contain valid UTF-8 - --> $DIR/not-utf8.rs:6:5 + --> $DIR/not-utf8.rs:5:5 | LL | include!("not-utf8.bin"); | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/macros/unreachable-arg.edition_2021.stderr b/tests/ui/macros/unreachable-arg.edition_2021.stderr index ddaa2b9c1ef..fa776070789 100644 --- a/tests/ui/macros/unreachable-arg.edition_2021.stderr +++ b/tests/ui/macros/unreachable-arg.edition_2021.stderr @@ -1,5 +1,5 @@ error: format argument must be a string literal - --> $DIR/unreachable-arg.rs:15:18 + --> $DIR/unreachable-arg.rs:14:18 | LL | unreachable!(a); | ^ diff --git a/tests/ui/macros/unreachable-arg.rs b/tests/ui/macros/unreachable-arg.rs index 702bd053ab0..d18272c8072 100644 --- a/tests/ui/macros/unreachable-arg.rs +++ b/tests/ui/macros/unreachable-arg.rs @@ -6,11 +6,10 @@ //@ [edition_2015]run-fail //@ [edition_2021]check-fail //@ [edition_2015]error-pattern:internal error: entered unreachable code: hello -//@ [edition_2021]error-pattern:format argument must be a string literal #![allow(non_fmt_panics)] fn main() { let a = "hello"; - unreachable!(a); + unreachable!(a); //[edition_2021]~ ERROR format argument must be a string literal } diff --git a/tests/ui/macros/unreachable-format-args.edition_2015.stderr b/tests/ui/macros/unreachable-format-args.edition_2015.stderr index 9104848a58b..e2286b72e64 100644 --- a/tests/ui/macros/unreachable-format-args.edition_2015.stderr +++ b/tests/ui/macros/unreachable-format-args.edition_2015.stderr @@ -1,5 +1,5 @@ error: there is no argument named `x` - --> $DIR/unreachable-format-args.rs:13:5 + --> $DIR/unreachable-format-args.rs:12:5 | LL | unreachable!("x is {x} and y is {y}", y = 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/macros/unreachable-format-args.rs b/tests/ui/macros/unreachable-format-args.rs index 856fc992685..79a851348ff 100644 --- a/tests/ui/macros/unreachable-format-args.rs +++ b/tests/ui/macros/unreachable-format-args.rs @@ -5,10 +5,10 @@ //@ [edition_2021]edition:2021 //@ [edition_2015]check-fail //@ [edition_2021]run-fail -//@ [edition_2015]error-pattern:there is no argument named `x` //@ [edition_2021]error-pattern:internal error: entered unreachable code: x is 5 and y is 0 fn main() { let x = 5; unreachable!("x is {x} and y is {y}", y = 0); + //[edition_2015]~^ ERROR there is no argument named `x` } diff --git a/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.rs b/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.rs index da56fe03184..94e6900bf40 100644 --- a/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.rs +++ b/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.rs @@ -1,7 +1,4 @@ // check that we don't generate a span that points beyond EOF -//@ error-pattern: unclosed delimiter -//@ error-pattern: unclosed delimiter -//@ error-pattern: unclosed delimiter - +//~v ERROR this file contains an unclosed delimiter fn a(){{{ diff --git a/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.stderr b/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.stderr index d9748843fd7..9a86c267340 100644 --- a/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.stderr +++ b/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.stderr @@ -1,5 +1,5 @@ error: this file contains an unclosed delimiter - --> $DIR/issue-107423-unused-delim-only-one-no-pair.rs:7:11 + --> $DIR/issue-107423-unused-delim-only-one-no-pair.rs:4:11 | LL | fn a(){{{ | ---^ diff --git a/tests/ui/minus-string.rs b/tests/ui/minus-string.rs index 8d9b8d8bbf4..b83347b937e 100644 --- a/tests/ui/minus-string.rs +++ b/tests/ui/minus-string.rs @@ -1,3 +1 @@ -//@ error-pattern:cannot apply unary operator `-` to type `String` - -fn main() { -"foo".to_string(); } +fn main() { -"foo".to_string(); } //~ ERROR cannot apply unary operator `-` to type `String` diff --git a/tests/ui/minus-string.stderr b/tests/ui/minus-string.stderr index cf63ec24416..153965c810e 100644 --- a/tests/ui/minus-string.stderr +++ b/tests/ui/minus-string.stderr @@ -1,5 +1,5 @@ error[E0600]: cannot apply unary operator `-` to type `String` - --> $DIR/minus-string.rs:3:13 + --> $DIR/minus-string.rs:1:13 | LL | fn main() { -"foo".to_string(); } | ^^^^^^^^^^^^^^^^^^ cannot apply unary operator `-` diff --git a/tests/ui/mir/enable_passes_validation.rs b/tests/ui/mir/enable_passes_validation.rs index 405ada77183..b97ddfba37f 100644 --- a/tests/ui/mir/enable_passes_validation.rs +++ b/tests/ui/mir/enable_passes_validation.rs @@ -1,24 +1,25 @@ //@ revisions: empty unprefixed all_unknown all_known mixed //@[empty] compile-flags: -Zmir-enable-passes= -//@[empty] error-pattern error: incorrect value `` for unstable option `mir-enable-passes` - a comma-separated list of strings, with elements beginning with + or - was expected //@[unprefixed] compile-flags: -Zmir-enable-passes=CheckAlignment -//@[unprefixed] error-pattern error: incorrect value `CheckAlignment` for unstable option `mir-enable-passes` - a comma-separated list of strings, with elements beginning with + or - was expected //@[all_unknown] check-pass //@[all_unknown] compile-flags: -Zmir-enable-passes=+ThisPass,-DoesNotExist -//@[all_unknown] error-pattern: warning: MIR pass `ThisPass` is unknown and will be ignored -//@[all_unknown] error-pattern: warning: MIR pass `DoesNotExist` is unknown and will be ignored //@[all_known] check-pass //@[all_known] compile-flags: -Zmir-enable-passes=+CheckAlignment,+LowerIntrinsics //@[mixed] check-pass //@[mixed] compile-flags: -Zmir-enable-passes=+ThisPassDoesNotExist,+CheckAlignment -//@[mixed] error-pattern: warning: MIR pass `ThisPassDoesNotExist` is unknown and will be ignored fn main() {} //[empty]~? ERROR incorrect value `` for unstable option `mir-enable-passes` //[unprefixed]~? ERROR incorrect value `CheckAlignment` for unstable option `mir-enable-passes` +//[mixed]~? WARN MIR pass `ThisPassDoesNotExist` is unknown and will be ignored +//[mixed]~? WARN MIR pass `ThisPassDoesNotExist` is unknown and will be ignored +//[all_unknown]~? MIR pass `ThisPass` is unknown and will be ignored +//[all_unknown]~? MIR pass `DoesNotExist` is unknown and will be ignored +//[all_unknown]~? MIR pass `ThisPass` is unknown and will be ignored +//[all_unknown]~? MIR pass `DoesNotExist` is unknown and will be ignored diff --git a/tests/ui/mir/lint/assignment-overlap.rs b/tests/ui/mir/lint/assignment-overlap.rs index 6396cccd4e8..950279b1555 100644 --- a/tests/ui/mir/lint/assignment-overlap.rs +++ b/tests/ui/mir/lint/assignment-overlap.rs @@ -12,7 +12,7 @@ pub fn main() { mir! { let a: [u8; 1024]; { - a = a; + a = a; //~ ERROR broken MIR Return() } } diff --git a/tests/ui/mir/lint/call-overlap.rs b/tests/ui/mir/lint/call-overlap.rs index def78ea1e3b..3c42e04e3ec 100644 --- a/tests/ui/mir/lint/call-overlap.rs +++ b/tests/ui/mir/lint/call-overlap.rs @@ -12,7 +12,7 @@ pub fn main() { mir! { let a: [u8; 1024]; { - Call(a = f(Move(a)), ReturnTo(bb1), UnwindUnreachable()) + Call(a = f(Move(a)), ReturnTo(bb1), UnwindUnreachable()) //~ ERROR broken MIR } bb1 = { Return() diff --git a/tests/ui/mir/lint/no-storage.rs b/tests/ui/mir/lint/no-storage.rs index a6af8646f6e..68c1a2d2aab 100644 --- a/tests/ui/mir/lint/no-storage.rs +++ b/tests/ui/mir/lint/no-storage.rs @@ -21,7 +21,7 @@ pub fn f(a: bool) { Goto(bb3) } bb3 = { - b = (); + b = (); //~ ERROR broken MIR RET = b; StorageDead(b); Return() diff --git a/tests/ui/mir/lint/storage-live.rs b/tests/ui/mir/lint/storage-live.rs index 3e0cc4ee061..19d046b619c 100644 --- a/tests/ui/mir/lint/storage-live.rs +++ b/tests/ui/mir/lint/storage-live.rs @@ -20,7 +20,7 @@ fn multiple_storage() { let a: usize; { StorageLive(a); - StorageLive(a); + StorageLive(a); //~ ERROR broken MIR Return() } } diff --git a/tests/ui/mir/lint/storage-return.rs b/tests/ui/mir/lint/storage-return.rs index d51aee9518f..3bbd0045d9d 100644 --- a/tests/ui/mir/lint/storage-return.rs +++ b/tests/ui/mir/lint/storage-return.rs @@ -13,7 +13,7 @@ fn main() { { StorageLive(a); RET = a; - Return() + Return() //~ ERROR broken MIR } } } diff --git a/tests/ui/mir/validate/noncleanup-cleanup.rs b/tests/ui/mir/validate/noncleanup-cleanup.rs index b46bb46952b..3010a3804ce 100644 --- a/tests/ui/mir/validate/noncleanup-cleanup.rs +++ b/tests/ui/mir/validate/noncleanup-cleanup.rs @@ -2,16 +2,16 @@ // //@ failure-status: 101 //@ dont-check-compiler-stderr -//@ error-pattern: cleanuppad mismatch + #![feature(custom_mir, core_intrinsics)] extern crate core; use core::intrinsics::mir::*; #[custom_mir(dialect = "built")] -pub fn main() { +pub fn main() { //~ WARN function cannot return without recursing mir! { { - Call(RET = main(), ReturnTo(block), UnwindCleanup(block)) + Call(RET = main(), ReturnTo(block), UnwindCleanup(block)) //~ ERROR cleanuppad mismatch } block = { Return() diff --git a/tests/ui/mir/validate/noncleanup-resume.rs b/tests/ui/mir/validate/noncleanup-resume.rs index b2a0e92e068..a80e99e2967 100644 --- a/tests/ui/mir/validate/noncleanup-resume.rs +++ b/tests/ui/mir/validate/noncleanup-resume.rs @@ -2,7 +2,7 @@ // //@ failure-status: 101 //@ dont-check-compiler-stderr -//@ error-pattern: resume on non-cleanup block + #![feature(custom_mir, core_intrinsics)] extern crate core; use core::intrinsics::mir::*; @@ -11,7 +11,7 @@ use core::intrinsics::mir::*; pub fn main() { mir! { { - UnwindResume() + UnwindResume() //~ ERROR resume on non-cleanup block } } } diff --git a/tests/ui/mir/validate/noncleanup-terminate.rs b/tests/ui/mir/validate/noncleanup-terminate.rs index 24cf75e7d8e..859c5e71c0e 100644 --- a/tests/ui/mir/validate/noncleanup-terminate.rs +++ b/tests/ui/mir/validate/noncleanup-terminate.rs @@ -2,7 +2,7 @@ // //@ failure-status: 101 //@ dont-check-compiler-stderr -//@ error-pattern: terminate on non-cleanup block + #![feature(custom_mir, core_intrinsics)] extern crate core; use core::intrinsics::mir::*; @@ -11,7 +11,7 @@ use core::intrinsics::mir::*; pub fn main() { mir! { { - UnwindTerminate(ReasonAbi) + UnwindTerminate(ReasonAbi) //~ ERROR terminate on non-cleanup block } } } diff --git a/tests/ui/missing/missing-main.rs b/tests/ui/missing/missing-main.rs index 3cafca09afb..2b8995fb8ff 100644 --- a/tests/ui/missing/missing-main.rs +++ b/tests/ui/missing/missing-main.rs @@ -1,2 +1 @@ -//@ error-pattern: `main` function not found -fn mian() { } +fn mian() { } //~ ERROR `main` function not found in crate `missing_main` diff --git a/tests/ui/missing/missing-main.stderr b/tests/ui/missing/missing-main.stderr index 2139981eac0..51a299d6a85 100644 --- a/tests/ui/missing/missing-main.stderr +++ b/tests/ui/missing/missing-main.stderr @@ -1,5 +1,5 @@ error[E0601]: `main` function not found in crate `missing_main` - --> $DIR/missing-main.rs:2:14 + --> $DIR/missing-main.rs:1:14 | LL | fn mian() { } | ^ consider adding a `main` function to `$DIR/missing-main.rs` diff --git a/tests/ui/missing/missing-return.rs b/tests/ui/missing/missing-return.rs index defd8a3bb78..5d9839a969c 100644 --- a/tests/ui/missing/missing-return.rs +++ b/tests/ui/missing/missing-return.rs @@ -1,5 +1,5 @@ //@ error-pattern: return -fn f() -> isize { } +fn f() -> isize { } //~ ERROR mismatched types fn main() { f(); } diff --git a/tests/ui/nested-ty-params.rs b/tests/ui/nested-ty-params.rs index b7cedf97c91..866e6230f9e 100644 --- a/tests/ui/nested-ty-params.rs +++ b/tests/ui/nested-ty-params.rs @@ -1,6 +1,8 @@ //@ error-pattern:can't use generic parameters from outer item fn hd<U>(v: Vec<U> ) -> U { fn hd1(w: [U]) -> U { return w[0]; } + //~^ ERROR can't use generic parameters from outer item + //~| ERROR can't use generic parameters from outer item return hd1(v); } diff --git a/tests/ui/no-capture-arc.rs b/tests/ui/no-capture-arc.rs index aafb170c7e1..9c957a4e01b 100644 --- a/tests/ui/no-capture-arc.rs +++ b/tests/ui/no-capture-arc.rs @@ -1,5 +1,3 @@ -//@ error-pattern: borrow of moved value - use std::sync::Arc; use std::thread; @@ -11,7 +9,7 @@ fn main() { assert_eq!((*arc_v)[3], 4); }); - assert_eq!((*arc_v)[2], 3); + assert_eq!((*arc_v)[2], 3); //~ ERROR borrow of moved value: `arc_v` println!("{:?}", *arc_v); } diff --git a/tests/ui/no-capture-arc.stderr b/tests/ui/no-capture-arc.stderr index 4a51ddb67a3..9c1f5c65066 100644 --- a/tests/ui/no-capture-arc.stderr +++ b/tests/ui/no-capture-arc.stderr @@ -1,5 +1,5 @@ error[E0382]: borrow of moved value: `arc_v` - --> $DIR/no-capture-arc.rs:14:18 + --> $DIR/no-capture-arc.rs:12:18 | LL | let arc_v = Arc::new(v); | ----- move occurs because `arc_v` has type `Arc<Vec<i32>>`, which does not implement the `Copy` trait diff --git a/tests/ui/no_std/no-std-no-start-binary.rs b/tests/ui/no_std/no-std-no-start-binary.rs index 5c8a0e6c0b8..df68b99346a 100644 --- a/tests/ui/no_std/no-std-no-start-binary.rs +++ b/tests/ui/no_std/no-std-no-start-binary.rs @@ -11,3 +11,5 @@ fn handler(_info: &core::panic::PanicInfo<'_>) -> ! { } fn main() {} + +//~? ERROR using `fn main` requires the standard library diff --git a/tests/ui/no_std/no-std-unwind-binary.rs b/tests/ui/no_std/no-std-unwind-binary.rs index 74c80d75c3e..cb1dc4427ae 100644 --- a/tests/ui/no_std/no-std-unwind-binary.rs +++ b/tests/ui/no_std/no-std-unwind-binary.rs @@ -1,4 +1,3 @@ -//@ error-pattern:unwinding panics are not supported without std //@ needs-unwind //@ compile-flags: -Cpanic=unwind @@ -13,3 +12,5 @@ fn handler(_info: &core::panic::PanicInfo<'_>) -> ! { } fn main() {} + +//~? ERROR unwinding panics are not supported without std diff --git a/tests/ui/packed/packed-struct-generic-transmute.rs b/tests/ui/packed/packed-struct-generic-transmute.rs index ed655a1d483..17e72bebc7d 100644 --- a/tests/ui/packed/packed-struct-generic-transmute.rs +++ b/tests/ui/packed/packed-struct-generic-transmute.rs @@ -22,6 +22,7 @@ fn main() { let foo = Foo { bar: [1u8, 2, 3, 4, 5], baz: 10i32 }; unsafe { let oof: Oof<[u8; 5], i32> = mem::transmute(foo); + //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types println!("{:?} {:?}", &oof.rab[..], oof.zab); } } diff --git a/tests/ui/packed/packed-struct-transmute.rs b/tests/ui/packed/packed-struct-transmute.rs index 98feeea8871..5ad6524ff81 100644 --- a/tests/ui/packed/packed-struct-transmute.rs +++ b/tests/ui/packed/packed-struct-transmute.rs @@ -24,6 +24,7 @@ fn main() { let foo = Foo { bar: 1, baz: 10 }; unsafe { let oof: Oof = mem::transmute(foo); + //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types println!("{:?}", oof); } } diff --git a/tests/ui/panic-handler/panic-handler-missing.rs b/tests/ui/panic-handler/panic-handler-missing.rs index 09fbd9a69cf..ab617f93a99 100644 --- a/tests/ui/panic-handler/panic-handler-missing.rs +++ b/tests/ui/panic-handler/panic-handler-missing.rs @@ -1,5 +1,4 @@ //@ dont-check-compiler-stderr -//@ error-pattern: `#[panic_handler]` function required, but not found #![feature(lang_items)] #![no_main] @@ -7,3 +6,5 @@ #[lang = "eh_personality"] fn eh() {} + +//~? ERROR `#[panic_handler]` function required, but not found diff --git a/tests/ui/panic-handler/panic-handler-std.rs b/tests/ui/panic-handler/panic-handler-std.rs index 4eb05b5365f..f6a4b60461c 100644 --- a/tests/ui/panic-handler/panic-handler-std.rs +++ b/tests/ui/panic-handler/panic-handler-std.rs @@ -1,12 +1,11 @@ //@ normalize-stderr: "loaded from .*libstd-.*.rlib" -> "loaded from SYSROOT/libstd-*.rlib" -//@ error-pattern: found duplicate lang item `panic_impl` extern crate core; use core::panic::PanicInfo; #[panic_handler] -fn panic(info: PanicInfo) -> ! { +fn panic(info: PanicInfo) -> ! { //~ ERROR found duplicate lang item `panic_impl` loop {} } diff --git a/tests/ui/panic-handler/panic-handler-std.stderr b/tests/ui/panic-handler/panic-handler-std.stderr index caae16118ef..48c216ce27e 100644 --- a/tests/ui/panic-handler/panic-handler-std.stderr +++ b/tests/ui/panic-handler/panic-handler-std.stderr @@ -1,5 +1,5 @@ error[E0152]: found duplicate lang item `panic_impl` - --> $DIR/panic-handler-std.rs:9:1 + --> $DIR/panic-handler-std.rs:8:1 | LL | / fn panic(info: PanicInfo) -> ! { LL | | loop {} diff --git a/tests/ui/panic-handler/weak-lang-item.rs b/tests/ui/panic-handler/weak-lang-item.rs index 605e1bdd94b..cc5ccb75104 100644 --- a/tests/ui/panic-handler/weak-lang-item.rs +++ b/tests/ui/panic-handler/weak-lang-item.rs @@ -1,12 +1,13 @@ //@ aux-build:weak-lang-items.rs -//@ error-pattern: `#[panic_handler]` function required, but not found -//@ error-pattern: unwinding panics are not supported without std //@ needs-unwind since it affects the error output //@ ignore-emscripten missing eh_catch_typeinfo lang item #![no_std] -extern crate core; +extern crate core; //~ ERROR the name `core` is defined multiple times extern crate weak_lang_items; fn main() {} + +//~? ERROR `#[panic_handler]` function required, but not found +//~? ERROR unwinding panics are not supported without std diff --git a/tests/ui/panic-handler/weak-lang-item.stderr b/tests/ui/panic-handler/weak-lang-item.stderr index 5dcb37df689..5acd3e31870 100644 --- a/tests/ui/panic-handler/weak-lang-item.stderr +++ b/tests/ui/panic-handler/weak-lang-item.stderr @@ -1,5 +1,5 @@ error[E0259]: the name `core` is defined multiple times - --> $DIR/weak-lang-item.rs:9:1 + --> $DIR/weak-lang-item.rs:7:1 | LL | extern crate core; | ^^^^^^^^^^^^^^^^^^ `core` reimported here diff --git a/tests/ui/panic-runtime/abort-link-to-unwind-dylib.rs b/tests/ui/panic-runtime/abort-link-to-unwind-dylib.rs index 2939835b0f4..8b782413f6a 100644 --- a/tests/ui/panic-runtime/abort-link-to-unwind-dylib.rs +++ b/tests/ui/panic-runtime/abort-link-to-unwind-dylib.rs @@ -4,7 +4,6 @@ //@ ignore-musl - no dylibs here //@ ignore-emscripten //@ ignore-sgx no dynamic lib support -//@ error-pattern:`panic_unwind` is not compiled with this crate's panic strategy // This is a test where the local crate, compiled with `panic=abort`, links to // the standard library **dynamically** which is already linked against @@ -16,3 +15,5 @@ fn main() { } + +//~? ERROR the linked panic runtime `panic_unwind` is not compiled with this crate's panic strategy `abort` diff --git a/tests/ui/panic-runtime/bad-panic-flag1.rs b/tests/ui/panic-runtime/bad-panic-flag1.rs index 82b7c2f723b..117935847cb 100644 --- a/tests/ui/panic-runtime/bad-panic-flag1.rs +++ b/tests/ui/panic-runtime/bad-panic-flag1.rs @@ -1,4 +1,5 @@ //@ compile-flags:-C panic=foo -//@ error-pattern:either `unwind` or `abort` was expected fn main() {} + +//~? ERROR incorrect value `foo` for codegen option `panic` - either `unwind` or `abort` was expected diff --git a/tests/ui/panic-runtime/bad-panic-flag2.rs b/tests/ui/panic-runtime/bad-panic-flag2.rs index 3875325deae..b5d0442a033 100644 --- a/tests/ui/panic-runtime/bad-panic-flag2.rs +++ b/tests/ui/panic-runtime/bad-panic-flag2.rs @@ -1,4 +1,5 @@ //@ compile-flags:-C panic -//@ error-pattern:requires either `unwind` or `abort` fn main() {} + +//~? ERROR codegen option `panic` requires either `unwind` or `abort` diff --git a/tests/ui/panic-runtime/need-abort-got-unwind.rs b/tests/ui/panic-runtime/need-abort-got-unwind.rs index 74b7edd968f..afd08426395 100644 --- a/tests/ui/panic-runtime/need-abort-got-unwind.rs +++ b/tests/ui/panic-runtime/need-abort-got-unwind.rs @@ -1,8 +1,9 @@ //@ build-fail //@ needs-unwind -//@ error-pattern:is incompatible with this crate's strategy of `unwind` //@ aux-build:needs-abort.rs extern crate needs_abort; fn main() {} + +//~? ERROR the crate `needs_abort` requires panic strategy `abort` which is incompatible with this crate's strategy of `unwind` diff --git a/tests/ui/panic-runtime/need-unwind-got-abort.rs b/tests/ui/panic-runtime/need-unwind-got-abort.rs index 6bc41509b6b..bc65e9ab3d9 100644 --- a/tests/ui/panic-runtime/need-unwind-got-abort.rs +++ b/tests/ui/panic-runtime/need-unwind-got-abort.rs @@ -1,5 +1,4 @@ //@ build-fail -//@ error-pattern:is incompatible with this crate's strategy of `abort` //@ aux-build:needs-unwind.rs //@ compile-flags:-C panic=abort //@ no-prefer-dynamic @@ -7,3 +6,5 @@ extern crate needs_unwind; fn main() {} + +//~? ERROR the crate `needs_unwind` requires panic strategy `unwind` which is incompatible with this crate's strategy of `abort` diff --git a/tests/ui/panic-runtime/runtime-depend-on-needs-runtime.rs b/tests/ui/panic-runtime/runtime-depend-on-needs-runtime.rs index d0a82bd8507..eb00c071702 100644 --- a/tests/ui/panic-runtime/runtime-depend-on-needs-runtime.rs +++ b/tests/ui/panic-runtime/runtime-depend-on-needs-runtime.rs @@ -1,8 +1,9 @@ //@ dont-check-compiler-stderr //@ aux-build:needs-panic-runtime.rs //@ aux-build:depends.rs -//@ error-pattern:cannot depend on a crate that needs a panic runtime extern crate depends; fn main() {} + +//~? ERROR the crate `depends` cannot depend on a crate that needs a panic runtime, but it depends on `needs_panic_runtime` diff --git a/tests/ui/panic-runtime/transitive-link-a-bunch.rs b/tests/ui/panic-runtime/transitive-link-a-bunch.rs index 15557d35bc5..2a0b9e3fa63 100644 --- a/tests/ui/panic-runtime/transitive-link-a-bunch.rs +++ b/tests/ui/panic-runtime/transitive-link-a-bunch.rs @@ -5,7 +5,6 @@ //@ aux-build:wants-panic-runtime-unwind.rs //@ aux-build:wants-panic-runtime-abort.rs //@ aux-build:panic-runtime-lang-items.rs -//@ error-pattern: is not compiled with this crate's panic strategy `unwind` #![no_std] #![no_main] @@ -13,3 +12,7 @@ extern crate wants_panic_runtime_unwind; extern crate wants_panic_runtime_abort; extern crate panic_runtime_lang_items; + +//~? ERROR cannot link together two panic runtimes: panic_runtime_unwind and panic_runtime_abort +//~? ERROR the linked panic runtime `panic_runtime_abort` is not compiled with this crate's panic strategy `unwind` +//~? ERROR the crate `wants_panic_runtime_abort` requires panic strategy `abort` which is incompatible with this crate's strategy of `unwind` diff --git a/tests/ui/panic-runtime/two-panic-runtimes.rs b/tests/ui/panic-runtime/two-panic-runtimes.rs index 3608dca2124..15c08cbe30d 100644 --- a/tests/ui/panic-runtime/two-panic-runtimes.rs +++ b/tests/ui/panic-runtime/two-panic-runtimes.rs @@ -1,6 +1,8 @@ +// ignore-tidy-linelength //@ build-fail +//@ compile-flags: --error-format=human +//@ error-pattern: cannot link together two panic runtimes: panic_runtime_unwind and panic_runtime_unwind2 //@ dont-check-compiler-stderr -//@ error-pattern:cannot link together two panic runtimes: panic_runtime_unwind and panic_runtime_unwind2 //@ aux-build:panic-runtime-unwind.rs //@ aux-build:panic-runtime-unwind2.rs //@ aux-build:panic-runtime-lang-items.rs @@ -13,3 +15,8 @@ extern crate panic_runtime_unwind2; extern crate panic_runtime_lang_items; fn main() {} + +// FIXME: The second and third errors are target-dependent. +//FIXME~? ERROR cannot link together two panic runtimes: panic_runtime_unwind and panic_runtime_unwind2 +//FIXME~? ERROR the linked panic runtime `panic_runtime_unwind2` is not compiled with this crate's panic strategy `abort` +//FIXME~? ERROR the crate `panic_runtime_unwind` requires panic strategy `unwind` which is incompatible with this crate's strategy of `abort` diff --git a/tests/ui/panic-runtime/unwind-tables-target-required.rs b/tests/ui/panic-runtime/unwind-tables-target-required.rs index 5c6ec19c16d..ff8df284f6b 100644 --- a/tests/ui/panic-runtime/unwind-tables-target-required.rs +++ b/tests/ui/panic-runtime/unwind-tables-target-required.rs @@ -5,7 +5,8 @@ //@ compile-flags: -C force-unwind-tables=no // //@ dont-check-compiler-stderr -//@ error-pattern: target requires unwind tables, they cannot be disabled with `-C force-unwind-tables=no` pub fn main() { } + +//~? ERROR target requires unwind tables, they cannot be disabled with `-C force-unwind-tables=no` diff --git a/tests/ui/panic-runtime/want-abort-got-unwind.rs b/tests/ui/panic-runtime/want-abort-got-unwind.rs index ad9fa52f3d4..ed61c2613df 100644 --- a/tests/ui/panic-runtime/want-abort-got-unwind.rs +++ b/tests/ui/panic-runtime/want-abort-got-unwind.rs @@ -1,9 +1,16 @@ +// ignore-tidy-linelength //@ build-fail +//@ compile-flags: --error-format=human +//@ error-pattern: the linked panic runtime `panic_runtime_unwind` is not compiled with this crate's panic strategy `abort` //@ dont-check-compiler-stderr -//@ error-pattern:is not compiled with this crate's panic strategy `abort` //@ aux-build:panic-runtime-unwind.rs //@ compile-flags:-C panic=abort extern crate panic_runtime_unwind; fn main() {} + +// FIXME: The first and third errors are target-dependent. +//FIXME~? ERROR cannot link together two panic runtimes: panic_unwind and panic_runtime_unwind +//FIXME~? ERROR the linked panic runtime `panic_runtime_unwind` is not compiled with this crate's panic strategy `abort` +//FIXME~? ERROR the crate `panic_unwind` requires panic strategy `unwind` which is incompatible with this crate's strategy of `abort` diff --git a/tests/ui/panic-runtime/want-abort-got-unwind2.rs b/tests/ui/panic-runtime/want-abort-got-unwind2.rs index d63161db55c..504fd779e09 100644 --- a/tests/ui/panic-runtime/want-abort-got-unwind2.rs +++ b/tests/ui/panic-runtime/want-abort-got-unwind2.rs @@ -1,6 +1,8 @@ +// ignore-tidy-linelength //@ build-fail +//@ compile-flags: --error-format=human +//@ error-pattern: the linked panic runtime `panic_runtime_unwind` is not compiled with this crate's panic strategy `abort` //@ dont-check-compiler-stderr -//@ error-pattern:is not compiled with this crate's panic strategy `abort` //@ aux-build:panic-runtime-unwind.rs //@ aux-build:wants-panic-runtime-unwind.rs //@ compile-flags:-C panic=abort @@ -8,3 +10,8 @@ extern crate wants_panic_runtime_unwind; fn main() {} + +// FIXME: The first and third errors are target-dependent. +//FIXME~? ERROR cannot link together two panic runtimes: panic_unwind and panic_runtime_unwind +//FIXME~? ERROR the linked panic runtime `panic_runtime_unwind` is not compiled with this crate's panic strategy `abort` +//FIXME~? ERROR the crate `panic_unwind` requires panic strategy `unwind` which is incompatible with this crate's strategy of `abort` diff --git a/tests/ui/panic-runtime/want-unwind-got-abort.rs b/tests/ui/panic-runtime/want-unwind-got-abort.rs index 93342a09182..497d1eafda5 100644 --- a/tests/ui/panic-runtime/want-unwind-got-abort.rs +++ b/tests/ui/panic-runtime/want-unwind-got-abort.rs @@ -1,6 +1,5 @@ //@ build-fail //@ needs-unwind -//@ error-pattern:is not compiled with this crate's panic strategy `unwind` //@ aux-build:panic-runtime-abort.rs //@ aux-build:panic-runtime-lang-items.rs @@ -9,3 +8,5 @@ extern crate panic_runtime_abort; extern crate panic_runtime_lang_items; + +//~? ERROR the linked panic runtime `panic_runtime_abort` is not compiled with this crate's panic strategy `unwind` diff --git a/tests/ui/panic-runtime/want-unwind-got-abort2.rs b/tests/ui/panic-runtime/want-unwind-got-abort2.rs index ee3f221d09c..2609545336c 100644 --- a/tests/ui/panic-runtime/want-unwind-got-abort2.rs +++ b/tests/ui/panic-runtime/want-unwind-got-abort2.rs @@ -1,6 +1,5 @@ //@ build-fail //@ needs-unwind -//@ error-pattern:is incompatible with this crate's strategy of `unwind` //@ aux-build:panic-runtime-abort.rs //@ aux-build:wants-panic-runtime-abort.rs //@ aux-build:panic-runtime-lang-items.rs @@ -10,3 +9,6 @@ extern crate wants_panic_runtime_abort; extern crate panic_runtime_lang_items; + +//~? ERROR the linked panic runtime `panic_runtime_abort` is not compiled with this crate's panic strategy `unwind` +//~? ERROR the crate `wants_panic_runtime_abort` requires panic strategy `abort` which is incompatible with this crate's strategy of `unwind` diff --git a/tests/ui/panics/default-backtrace-ice.rs b/tests/ui/panics/default-backtrace-ice.rs index 9933f548758..cf8b0cea849 100644 --- a/tests/ui/panics/default-backtrace-ice.rs +++ b/tests/ui/panics/default-backtrace-ice.rs @@ -20,4 +20,4 @@ // Ignored on msvc because the `__rust_{begin,end}_short_backtrace` symbols // aren't reliable. -fn main() { missing_ident; } +fn main() { missing_ident; } //~ ERROR cannot find value `missing_ident` in this scope diff --git a/tests/ui/parser/attribute/attr-dangling-in-fn.rs b/tests/ui/parser/attribute/attr-dangling-in-fn.rs index d59f90aed5d..b1436b8d89d 100644 --- a/tests/ui/parser/attribute/attr-dangling-in-fn.rs +++ b/tests/ui/parser/attribute/attr-dangling-in-fn.rs @@ -1,7 +1,5 @@ -//@ error-pattern:expected statement - fn f() { - #[foo = "bar"] + #[foo = "bar"] //~ ERROR expected statement after outer attribute } fn main() { diff --git a/tests/ui/parser/attribute/attr-dangling-in-fn.stderr b/tests/ui/parser/attribute/attr-dangling-in-fn.stderr index c7b948ea8f7..3e9413f5357 100644 --- a/tests/ui/parser/attribute/attr-dangling-in-fn.stderr +++ b/tests/ui/parser/attribute/attr-dangling-in-fn.stderr @@ -1,5 +1,5 @@ error: expected statement after outer attribute - --> $DIR/attr-dangling-in-fn.rs:4:3 + --> $DIR/attr-dangling-in-fn.rs:2:3 | LL | #[foo = "bar"] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/parser/attribute/attr-dangling-in-mod.rs b/tests/ui/parser/attribute/attr-dangling-in-mod.rs index 001ac1135f6..17bc7e547d9 100644 --- a/tests/ui/parser/attribute/attr-dangling-in-mod.rs +++ b/tests/ui/parser/attribute/attr-dangling-in-mod.rs @@ -1,6 +1,4 @@ -//@ error-pattern:expected item - fn main() { } -#[foo = "bar"] +#[foo = "bar"] //~ ERROR expected item after attributes diff --git a/tests/ui/parser/attribute/attr-dangling-in-mod.stderr b/tests/ui/parser/attribute/attr-dangling-in-mod.stderr index 882400c1d6f..22cc092109d 100644 --- a/tests/ui/parser/attribute/attr-dangling-in-mod.stderr +++ b/tests/ui/parser/attribute/attr-dangling-in-mod.stderr @@ -1,5 +1,5 @@ error: expected item after attributes - --> $DIR/attr-dangling-in-mod.rs:6:1 + --> $DIR/attr-dangling-in-mod.rs:4:1 | LL | #[foo = "bar"] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/parser/circular_modules_main.rs b/tests/ui/parser/circular_modules_main.rs index d5cdff34a26..c130c6792b8 100644 --- a/tests/ui/parser/circular_modules_main.rs +++ b/tests/ui/parser/circular_modules_main.rs @@ -1,5 +1,3 @@ -//@ error-pattern: circular modules - #[path = "circular_modules_hello.rs"] mod circular_modules_hello; @@ -10,3 +8,5 @@ pub fn hi_str() -> String { fn main() { circular_modules_hello::say_hello(); } + +//~? ERROR circular modules: $DIR/circular_modules_main.rs -> $DIR/circular_modules_hello.rs -> $DIR/circular_modules_main.rs diff --git a/tests/ui/parser/class-implements-bad-trait.rs b/tests/ui/parser/class-implements-bad-trait.rs index 152fe09b51c..e30c1bc3a7f 100644 --- a/tests/ui/parser/class-implements-bad-trait.rs +++ b/tests/ui/parser/class-implements-bad-trait.rs @@ -1,5 +1,4 @@ -//@ error-pattern:nonexistent -class cat : nonexistent { +class cat : nonexistent { //~ ERROR expected one of `!` or `::`, found `cat` let meows: usize; new(in_x : usize) { self.meows = in_x; } } diff --git a/tests/ui/parser/class-implements-bad-trait.stderr b/tests/ui/parser/class-implements-bad-trait.stderr index 5290e3594d5..5cdb85a8cff 100644 --- a/tests/ui/parser/class-implements-bad-trait.stderr +++ b/tests/ui/parser/class-implements-bad-trait.stderr @@ -1,5 +1,5 @@ error: expected one of `!` or `::`, found `cat` - --> $DIR/class-implements-bad-trait.rs:2:7 + --> $DIR/class-implements-bad-trait.rs:1:7 | LL | class cat : nonexistent { | ^^^ expected one of `!` or `::` diff --git a/tests/ui/parser/import-from-path.rs b/tests/ui/parser/import-from-path.rs index 54349d4971e..0d38c7224c5 100644 --- a/tests/ui/parser/import-from-path.rs +++ b/tests/ui/parser/import-from-path.rs @@ -1,2 +1 @@ -//@ error-pattern:expected -use foo::{bar}::baz +use foo::{bar}::baz //~ ERROR expected `;`, found `::` diff --git a/tests/ui/parser/import-from-path.stderr b/tests/ui/parser/import-from-path.stderr index b63e48d6679..f70c3b2e870 100644 --- a/tests/ui/parser/import-from-path.stderr +++ b/tests/ui/parser/import-from-path.stderr @@ -1,5 +1,5 @@ error: expected `;`, found `::` - --> $DIR/import-from-path.rs:2:15 + --> $DIR/import-from-path.rs:1:15 | LL | use foo::{bar}::baz | ^^ expected `;` diff --git a/tests/ui/parser/import-from-rename.rs b/tests/ui/parser/import-from-rename.rs index f6a4bb55553..4929b270e45 100644 --- a/tests/ui/parser/import-from-rename.rs +++ b/tests/ui/parser/import-from-rename.rs @@ -1,6 +1,4 @@ -//@ error-pattern:expected - -use foo::{bar} as baz; +use foo::{bar} as baz; //~ ERROR expected `;`, found keyword `as` mod foo { pub fn bar() {} diff --git a/tests/ui/parser/import-from-rename.stderr b/tests/ui/parser/import-from-rename.stderr index 2f267a8d026..3289f1bdbe7 100644 --- a/tests/ui/parser/import-from-rename.stderr +++ b/tests/ui/parser/import-from-rename.stderr @@ -1,5 +1,5 @@ error: expected `;`, found keyword `as` - --> $DIR/import-from-rename.rs:3:16 + --> $DIR/import-from-rename.rs:1:16 | LL | use foo::{bar} as baz; | ^^ expected `;` diff --git a/tests/ui/parser/import-glob-path.rs b/tests/ui/parser/import-glob-path.rs index cb854de0cff..3f1c98fcade 100644 --- a/tests/ui/parser/import-glob-path.rs +++ b/tests/ui/parser/import-glob-path.rs @@ -1,2 +1 @@ -//@ error-pattern:expected -use foo::*::bar +use foo::*::bar //~ ERROR expected `;`, found `::` diff --git a/tests/ui/parser/import-glob-path.stderr b/tests/ui/parser/import-glob-path.stderr index 3bde32d1ea4..04f8a6e96fa 100644 --- a/tests/ui/parser/import-glob-path.stderr +++ b/tests/ui/parser/import-glob-path.stderr @@ -1,5 +1,5 @@ error: expected `;`, found `::` - --> $DIR/import-glob-path.rs:2:11 + --> $DIR/import-glob-path.rs:1:11 | LL | use foo::*::bar | ^^ expected `;` diff --git a/tests/ui/parser/import-glob-rename.rs b/tests/ui/parser/import-glob-rename.rs index 899818b15b6..5027a75f881 100644 --- a/tests/ui/parser/import-glob-rename.rs +++ b/tests/ui/parser/import-glob-rename.rs @@ -1,6 +1,4 @@ -//@ error-pattern:expected - -use foo::* as baz; +use foo::* as baz; //~ ERROR expected `;`, found keyword `as` mod foo { pub fn bar() {} diff --git a/tests/ui/parser/import-glob-rename.stderr b/tests/ui/parser/import-glob-rename.stderr index 24e6c3f0006..2a5f2b66404 100644 --- a/tests/ui/parser/import-glob-rename.stderr +++ b/tests/ui/parser/import-glob-rename.stderr @@ -1,5 +1,5 @@ error: expected `;`, found keyword `as` - --> $DIR/import-glob-rename.rs:3:12 + --> $DIR/import-glob-rename.rs:1:12 | LL | use foo::* as baz; | ^^ expected `;` diff --git a/tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/circular-module-with-doc-comment-issue-97589.rs b/tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/circular-module-with-doc-comment-issue-97589.rs index ff28548b795..9c164813de2 100644 --- a/tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/circular-module-with-doc-comment-issue-97589.rs +++ b/tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/circular-module-with-doc-comment-issue-97589.rs @@ -1,6 +1,7 @@ -//@ error-pattern: circular modules // Regression test for #97589: a doc-comment on a circular module bypassed cycle detection #![crate_type = "lib"] pub mod recursive; + +//~? ERROR circular modules: $DIR/recursive.rs -> $DIR/recursive.rs diff --git a/tests/ui/parser/issues/issue-21146.rs b/tests/ui/parser/issues/issue-21146.rs index 81112808b21..95cae47939f 100644 --- a/tests/ui/parser/issues/issue-21146.rs +++ b/tests/ui/parser/issues/issue-21146.rs @@ -1,3 +1,4 @@ -//@ error-pattern: expected one of `!` or `::`, found `<eof>` include!("auxiliary/issue-21146-inc.rs"); fn main() {} + +//~? ERROR expected one of `!` or `::`, found `<eof>` diff --git a/tests/ui/parser/issues/issue-66473.rs b/tests/ui/parser/issues/issue-66473.rs index baa00f95e12..d0786add1af 100644 --- a/tests/ui/parser/issues/issue-66473.rs +++ b/tests/ui/parser/issues/issue-66473.rs Binary files differdiff --git a/tests/ui/parser/issues/issue-66473.stderr b/tests/ui/parser/issues/issue-66473.stderr index ba38c4fa1b7..65b2d5a34ee 100644 --- a/tests/ui/parser/issues/issue-66473.stderr +++ b/tests/ui/parser/issues/issue-66473.stderr @@ -1,11 +1,11 @@ error: unknown start of token: \u{348} - --> $DIR/issue-66473.rs:4:2 + --> $DIR/issue-66473.rs:1:2 | LL | #͈␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀ | ^ error: unknown start of token: \u{0} - --> $DIR/issue-66473.rs:4:3 + --> $DIR/issue-66473.rs:1:3 | LL | #͈␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀ | ^^^^^^^^^^^^^^^^^^ @@ -14,19 +14,19 @@ LL | #͈␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀ = note: character appears 17 more times error: unknown start of token: \u{1d} - --> $DIR/issue-66473.rs:5:2 + --> $DIR/issue-66473.rs:4:2 | LL | ␋␝6␝␀␀ | ^ error: unknown start of token: \u{1d} - --> $DIR/issue-66473.rs:5:4 + --> $DIR/issue-66473.rs:4:4 | LL | ␋␝6␝␀␀ | ^ error: unknown start of token: \u{0} - --> $DIR/issue-66473.rs:5:5 + --> $DIR/issue-66473.rs:4:5 | LL | ␋␝6␝␀␀ | ^^ @@ -35,10 +35,11 @@ LL | ␋␝6␝␀␀ = note: character appears once more error: expected one of `!` or `[`, found `6` - --> $DIR/issue-66473.rs:5:3 + --> $DIR/issue-66473.rs:4:3 | LL | #͈␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀ | - expected one of `!` or `[` +... LL | ␋␝6␝␀␀ | ^ unexpected token diff --git a/tests/ui/parser/issues/issue-68629.rs b/tests/ui/parser/issues/issue-68629.rs index d353d1f56ce..d1ea4ca8b03 100644 --- a/tests/ui/parser/issues/issue-68629.rs +++ b/tests/ui/parser/issues/issue-68629.rs Binary files differdiff --git a/tests/ui/parser/issues/issue-68629.stderr b/tests/ui/parser/issues/issue-68629.stderr index f003f378179..373ad142778 100644 --- a/tests/ui/parser/issues/issue-68629.stderr +++ b/tests/ui/parser/issues/issue-68629.stderr @@ -1,17 +1,17 @@ error: unknown start of token: \u{1c} - --> $DIR/issue-68629.rs:4:1 + --> $DIR/issue-68629.rs:6:1 | LL | ␜␟ts␀![{i | ^ error: unknown start of token: \u{1f} - --> $DIR/issue-68629.rs:4:2 + --> $DIR/issue-68629.rs:6:2 | LL | ␜␟ts␀![{i | ^ error: unknown start of token: \u{0} - --> $DIR/issue-68629.rs:4:5 + --> $DIR/issue-68629.rs:6:5 | LL | ␜␟ts␀![{i | ^ @@ -19,7 +19,7 @@ LL | ␜␟ts␀![{i = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/issue-68629.rs:5:1 + --> $DIR/issue-68629.rs:7:1 | LL | ␀␀ fn rݻoa>rݻm | ^^ @@ -28,7 +28,7 @@ LL | ␀␀ fn rݻoa>rݻm = note: character appears once more error: this file contains an unclosed delimiter - --> $DIR/issue-68629.rs:5:17 + --> $DIR/issue-68629.rs:7:17 | LL | ␜␟ts␀![{i | -- unclosed delimiter diff --git a/tests/ui/parser/issues/issue-68730.rs b/tests/ui/parser/issues/issue-68730.rs index f7f11cbc98b..9cf51b720eb 100644 --- a/tests/ui/parser/issues/issue-68730.rs +++ b/tests/ui/parser/issues/issue-68730.rs Binary files differdiff --git a/tests/ui/parser/issues/issue-68730.stderr b/tests/ui/parser/issues/issue-68730.stderr index 838a6569bdc..1e01e02bdb7 100644 --- a/tests/ui/parser/issues/issue-68730.stderr +++ b/tests/ui/parser/issues/issue-68730.stderr @@ -1,5 +1,5 @@ error: unknown start of token: \u{0} - --> $DIR/issue-68730.rs:5:5 + --> $DIR/issue-68730.rs:8:5 | LL | enum␀em␀˂˂ | ^ @@ -7,7 +7,7 @@ LL | enum␀em␀˂˂ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/issue-68730.rs:5:8 + --> $DIR/issue-68730.rs:8:8 | LL | enum␀em␀˂˂ | ^ @@ -15,7 +15,7 @@ LL | enum␀em␀˂˂ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{2c2} - --> $DIR/issue-68730.rs:5:9 + --> $DIR/issue-68730.rs:8:9 | LL | enum␀em␀˂˂ | ^^ @@ -28,7 +28,7 @@ LL + enum␀em␀<< | error: unknown start of token: \u{2c2} - --> $DIR/issue-68730.rs:5:10 + --> $DIR/issue-68730.rs:8:10 | LL | enum␀em␀˂˂ | ^ @@ -40,7 +40,7 @@ LL + enum␀em␀˂< | error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `<` - --> $DIR/issue-68730.rs:5:10 + --> $DIR/issue-68730.rs:8:10 | LL | enum␀em␀˂˂ | ^ expected one of `#`, `>`, `const`, identifier, or lifetime diff --git a/tests/ui/parser/shebang/shebang-split.rs b/tests/ui/parser/shebang/shebang-split.rs index 470bb669143..eb8f0f769c8 100644 --- a/tests/ui/parser/shebang/shebang-split.rs +++ b/tests/ui/parser/shebang/shebang-split.rs @@ -1,5 +1,4 @@ // empty line # !/bin/env - +//~^ ERROR expected `[`, found `/` // checks that diagnostics for shebang lookalikes is not present -//@ error-pattern: expected `[`\n\n diff --git a/tests/ui/parser/utf16-be-without-bom.rs b/tests/ui/parser/utf16-be-without-bom.rs index f5fe8dc5a8c..538728735f0 100644 --- a/tests/ui/parser/utf16-be-without-bom.rs +++ b/tests/ui/parser/utf16-be-without-bom.rs Binary files differdiff --git a/tests/ui/parser/utf16-be-without-bom.stderr b/tests/ui/parser/utf16-be-without-bom.stderr index 0493bcbc77a..467e0ed7313 100644 --- a/tests/ui/parser/utf16-be-without-bom.stderr +++ b/tests/ui/parser/utf16-be-without-bom.stderr @@ -1,5 +1,5 @@ error: unknown start of token: \u{0} - --> $DIR/utf16-be-without-bom.rs:5:1 + --> $DIR/utf16-be-without-bom.rs:6:1 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -7,7 +7,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-be-without-bom.rs:5:3 + --> $DIR/utf16-be-without-bom.rs:6:3 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -15,7 +15,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-be-without-bom.rs:5:5 + --> $DIR/utf16-be-without-bom.rs:6:5 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -23,7 +23,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-be-without-bom.rs:5:7 + --> $DIR/utf16-be-without-bom.rs:6:7 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -31,7 +31,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-be-without-bom.rs:5:9 + --> $DIR/utf16-be-without-bom.rs:6:9 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -39,7 +39,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-be-without-bom.rs:5:11 + --> $DIR/utf16-be-without-bom.rs:6:11 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -47,7 +47,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-be-without-bom.rs:5:13 + --> $DIR/utf16-be-without-bom.rs:6:13 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -55,7 +55,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-be-without-bom.rs:5:15 + --> $DIR/utf16-be-without-bom.rs:6:15 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -63,7 +63,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-be-without-bom.rs:5:17 + --> $DIR/utf16-be-without-bom.rs:6:17 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -71,7 +71,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-be-without-bom.rs:5:19 + --> $DIR/utf16-be-without-bom.rs:6:19 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -79,7 +79,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-be-without-bom.rs:5:21 + --> $DIR/utf16-be-without-bom.rs:6:21 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -87,7 +87,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-be-without-bom.rs:5:23 + --> $DIR/utf16-be-without-bom.rs:6:23 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -95,7 +95,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-be-without-bom.rs:5:25 + --> $DIR/utf16-be-without-bom.rs:6:25 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -103,7 +103,7 @@ LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: expected one of `!` or `::`, found `n` - --> $DIR/utf16-be-without-bom.rs:5:4 + --> $DIR/utf16-be-without-bom.rs:6:4 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ expected one of `!` or `::` diff --git a/tests/ui/parser/utf16-le-without-bom.rs b/tests/ui/parser/utf16-le-without-bom.rs index 8c781b27dc0..fc413663c9c 100644 --- a/tests/ui/parser/utf16-le-without-bom.rs +++ b/tests/ui/parser/utf16-le-without-bom.rs Binary files differdiff --git a/tests/ui/parser/utf16-le-without-bom.stderr b/tests/ui/parser/utf16-le-without-bom.stderr index 4b195ed0da1..701379d4067 100644 --- a/tests/ui/parser/utf16-le-without-bom.stderr +++ b/tests/ui/parser/utf16-le-without-bom.stderr @@ -1,5 +1,5 @@ error: unknown start of token: \u{0} - --> $DIR/utf16-le-without-bom.rs:5:2 + --> $DIR/utf16-le-without-bom.rs:6:2 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -7,7 +7,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-le-without-bom.rs:5:4 + --> $DIR/utf16-le-without-bom.rs:6:4 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -15,7 +15,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-le-without-bom.rs:5:6 + --> $DIR/utf16-le-without-bom.rs:6:6 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -23,7 +23,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-le-without-bom.rs:5:8 + --> $DIR/utf16-le-without-bom.rs:6:8 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -31,7 +31,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-le-without-bom.rs:5:10 + --> $DIR/utf16-le-without-bom.rs:6:10 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -39,7 +39,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-le-without-bom.rs:5:12 + --> $DIR/utf16-le-without-bom.rs:6:12 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -47,7 +47,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-le-without-bom.rs:5:14 + --> $DIR/utf16-le-without-bom.rs:6:14 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -55,7 +55,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-le-without-bom.rs:5:16 + --> $DIR/utf16-le-without-bom.rs:6:16 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -63,7 +63,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-le-without-bom.rs:5:18 + --> $DIR/utf16-le-without-bom.rs:6:18 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -71,7 +71,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-le-without-bom.rs:5:20 + --> $DIR/utf16-le-without-bom.rs:6:20 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -79,7 +79,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-le-without-bom.rs:5:22 + --> $DIR/utf16-le-without-bom.rs:6:22 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -87,7 +87,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-le-without-bom.rs:5:24 + --> $DIR/utf16-le-without-bom.rs:6:24 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ @@ -95,7 +95,7 @@ LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: unknown start of token: \u{0} - --> $DIR/utf16-le-without-bom.rs:6:1 + --> $DIR/utf16-le-without-bom.rs:7:1 | LL | ␀ | ^ @@ -103,7 +103,7 @@ LL | ␀ = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used error: expected one of `!` or `::`, found `n` - --> $DIR/utf16-le-without-bom.rs:5:3 + --> $DIR/utf16-le-without-bom.rs:6:3 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ | ^ expected one of `!` or `::` diff --git a/tests/ui/print-request/print-lints-help.rs b/tests/ui/print-request/print-lints-help.rs index 420eae27ed4..6dd88a701c3 100644 --- a/tests/ui/print-request/print-lints-help.rs +++ b/tests/ui/print-request/print-lints-help.rs @@ -2,6 +2,7 @@ //! `--print=lints` (which is not a valid print request). //@ compile-flags: --print lints -//@ error-pattern: error: unknown print request: `lints` //@ error-pattern: help: use `-Whelp` to print a list of lints //@ error-pattern: help: for more information, see the rustc book + +//~? ERROR unknown print request: `lints` diff --git a/tests/ui/print-request/stability.rs b/tests/ui/print-request/stability.rs index 0ec0886e941..54142ce78ce 100644 --- a/tests/ui/print-request/stability.rs +++ b/tests/ui/print-request/stability.rs @@ -16,23 +16,18 @@ //@ revisions: all_target_specs_json //@[all_target_specs_json] compile-flags: --print=all-target-specs-json -//@[all_target_specs_json] error-pattern: the `-Z unstable-options` flag must also be passed //@ revisions: crate_root_lint_levels //@[crate_root_lint_levels] compile-flags: --print=crate-root-lint-levels -//@[crate_root_lint_levels] error-pattern: the `-Z unstable-options` flag must also be passed //@ revisions: check_cfg //@[check_cfg] compile-flags: --print=check-cfg -//@[check_cfg] error-pattern: the `-Z unstable-options` flag must also be passed //@ revisions: supported_crate_types //@[supported_crate_types] compile-flags: --print=supported-crate-types -//@[supported_crate_types] error-pattern: the `-Z unstable-options` flag must also be passed //@ revisions: target_spec_json //@[target_spec_json] compile-flags: --print=target-spec-json -//@[target_spec_json] error-pattern: the `-Z unstable-options` flag must also be passed // ======================= // Stable print requests @@ -109,3 +104,9 @@ //@[tls_models] check-pass fn main() {} + +//[all_target_specs_json]~? ERROR the `-Z unstable-options` flag must also be passed to enable the `all-target-specs-json` print option +//[crate_root_lint_levels]~? ERROR the `-Z unstable-options` flag must also be passed to enable the `crate-root-lint-levels` print option +//[check_cfg]~? ERROR the `-Z unstable-options` flag must also be passed to enable the `check-cfg` print option +//[supported_crate_types]~? ERROR the `-Z unstable-options` flag must also be passed to enable the `supported-crate-types` print option +//[target_spec_json]~? ERROR the `-Z unstable-options` flag must also be passed to enable the `target-spec-json` print option diff --git a/tests/ui/privacy/private-inferred-type-3.rs b/tests/ui/privacy/private-inferred-type-3.rs index 7bf6bea4b0f..820b0cbb30f 100644 --- a/tests/ui/privacy/private-inferred-type-3.rs +++ b/tests/ui/privacy/private-inferred-type-3.rs @@ -1,17 +1,16 @@ //@ aux-build:private-inferred-type.rs -//@ error-pattern:type `fn() {ext::priv_fn}` is private -//@ error-pattern:static `ext::PRIV_STATIC` is private -//@ error-pattern:type `ext::PrivEnum` is private -//@ error-pattern:type `fn() {<u8 as ext::PrivTrait>::method}` is private -//@ error-pattern:type `fn(u8) -> ext::PrivTupleStruct {ext::PrivTupleStruct}` is private -//@ error-pattern:type `fn(u8) -> PubTupleStruct {PubTupleStruct}` is private -//@ error-pattern:type `for<'a> fn(&'a Pub<u8>) {Pub::<u8>::priv_method}` is private - #![feature(decl_macro)] extern crate private_inferred_type as ext; fn main() { ext::m!(); + //~^ ERROR type `fn() {ext::priv_fn}` is private + //~| ERROR static `ext::PRIV_STATIC` is private + //~| ERROR type `ext::PrivEnum` is private + //~| ERROR type `fn() {<u8 as ext::PrivTrait>::method}` is private + //~| ERROR type `fn(u8) -> ext::PrivTupleStruct {ext::PrivTupleStruct}` is private + //~| ERROR type `fn(u8) -> PubTupleStruct {PubTupleStruct}` is private + //~| ERROR type `for<'a> fn(&'a Pub<u8>) {Pub::<u8>::priv_method}` is private } diff --git a/tests/ui/privacy/private-inferred-type-3.stderr b/tests/ui/privacy/private-inferred-type-3.stderr index 42faeb4bf34..0b4899c8d3d 100644 --- a/tests/ui/privacy/private-inferred-type-3.stderr +++ b/tests/ui/privacy/private-inferred-type-3.stderr @@ -1,5 +1,5 @@ error: type `fn() {ext::priv_fn}` is private - --> $DIR/private-inferred-type-3.rs:16:5 + --> $DIR/private-inferred-type-3.rs:8:5 | LL | ext::m!(); | ^^^^^^^^^ private type @@ -7,7 +7,7 @@ LL | ext::m!(); = note: this error originates in the macro `ext::m` (in Nightly builds, run with -Z macro-backtrace for more info) error: static `ext::PRIV_STATIC` is private - --> $DIR/private-inferred-type-3.rs:16:5 + --> $DIR/private-inferred-type-3.rs:8:5 | LL | ext::m!(); | ^^^^^^^^^ private static @@ -15,7 +15,7 @@ LL | ext::m!(); = note: this error originates in the macro `ext::m` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `ext::PrivEnum` is private - --> $DIR/private-inferred-type-3.rs:16:5 + --> $DIR/private-inferred-type-3.rs:8:5 | LL | ext::m!(); | ^^^^^^^^^ private type @@ -23,7 +23,7 @@ LL | ext::m!(); = note: this error originates in the macro `ext::m` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `fn() {<u8 as ext::PrivTrait>::method}` is private - --> $DIR/private-inferred-type-3.rs:16:5 + --> $DIR/private-inferred-type-3.rs:8:5 | LL | ext::m!(); | ^^^^^^^^^ private type @@ -31,7 +31,7 @@ LL | ext::m!(); = note: this error originates in the macro `ext::m` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `fn(u8) -> ext::PrivTupleStruct {ext::PrivTupleStruct}` is private - --> $DIR/private-inferred-type-3.rs:16:5 + --> $DIR/private-inferred-type-3.rs:8:5 | LL | ext::m!(); | ^^^^^^^^^ private type @@ -39,7 +39,7 @@ LL | ext::m!(); = note: this error originates in the macro `ext::m` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `fn(u8) -> PubTupleStruct {PubTupleStruct}` is private - --> $DIR/private-inferred-type-3.rs:16:5 + --> $DIR/private-inferred-type-3.rs:8:5 | LL | ext::m!(); | ^^^^^^^^^ private type @@ -47,7 +47,7 @@ LL | ext::m!(); = note: this error originates in the macro `ext::m` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `for<'a> fn(&'a Pub<u8>) {Pub::<u8>::priv_method}` is private - --> $DIR/private-inferred-type-3.rs:16:5 + --> $DIR/private-inferred-type-3.rs:8:5 | LL | ext::m!(); | ^^^^^^^^^ private type diff --git a/tests/ui/proc-macro/export-macro.rs b/tests/ui/proc-macro/export-macro.rs index e6001d06f0f..33bf8cfb255 100644 --- a/tests/ui/proc-macro/export-macro.rs +++ b/tests/ui/proc-macro/export-macro.rs @@ -1,11 +1,9 @@ -//@ error-pattern: cannot export macro_rules! macros from a `proc-macro` crate - //@ force-host //@ no-prefer-dynamic #![crate_type = "proc-macro"] #[macro_export] -macro_rules! foo { +macro_rules! foo { //~ ERROR cannot export macro_rules! macros from a `proc-macro` crate type ($e:expr) => ($e) } diff --git a/tests/ui/proc-macro/export-macro.stderr b/tests/ui/proc-macro/export-macro.stderr index 410770eca08..be586d50459 100644 --- a/tests/ui/proc-macro/export-macro.stderr +++ b/tests/ui/proc-macro/export-macro.stderr @@ -1,5 +1,5 @@ error: cannot export macro_rules! macros from a `proc-macro` crate type currently - --> $DIR/export-macro.rs:9:1 + --> $DIR/export-macro.rs:7:1 | LL | macro_rules! foo { | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/proc-macro/issue-59191-replace-root-with-fn.rs b/tests/ui/proc-macro/issue-59191-replace-root-with-fn.rs index 6afafb7114a..df236cce6d2 100644 --- a/tests/ui/proc-macro/issue-59191-replace-root-with-fn.rs +++ b/tests/ui/proc-macro/issue-59191-replace-root-with-fn.rs @@ -4,8 +4,10 @@ //@ edition:2018 //@ proc-macro: issue-59191.rs //@ needs-unwind (affects error output) -//@ error-pattern: error: `#[panic_handler]` function required #![feature(custom_inner_attributes)] #![issue_59191::no_main] #![issue_59191::no_main] + +//~? ERROR `#[panic_handler]` function required, but not found +//~? ERROR unwinding panics are not supported without std diff --git a/tests/ui/proc-macro/panic-abort.rs b/tests/ui/proc-macro/panic-abort.rs index 40d8aec5ef6..58e1d006433 100644 --- a/tests/ui/proc-macro/panic-abort.rs +++ b/tests/ui/proc-macro/panic-abort.rs @@ -1,4 +1,5 @@ -//@ error-pattern: building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic //@ compile-flags: --crate-type proc-macro -Cpanic=abort //@ force-host //@ check-pass + +//~? WARN building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic diff --git a/tests/ui/proc-macro/two-crate-types-1.rs b/tests/ui/proc-macro/two-crate-types-1.rs index 432b0a601b2..9d21a430537 100644 --- a/tests/ui/proc-macro/two-crate-types-1.rs +++ b/tests/ui/proc-macro/two-crate-types-1.rs @@ -1,7 +1,7 @@ -//@ error-pattern: cannot mix `proc-macro` crate type with others - //@ force-host //@ no-prefer-dynamic #![crate_type = "proc-macro"] #![crate_type = "rlib"] + +//~? ERROR cannot mix `proc-macro` crate type with others diff --git a/tests/ui/proc-macro/two-crate-types-2.rs b/tests/ui/proc-macro/two-crate-types-2.rs index 491c5c71d76..c4cc0b4d80d 100644 --- a/tests/ui/proc-macro/two-crate-types-2.rs +++ b/tests/ui/proc-macro/two-crate-types-2.rs @@ -1,3 +1,4 @@ -//@ error-pattern: cannot mix `proc-macro` crate type with others //@ compile-flags: --crate-type rlib --crate-type proc-macro //@ force-host + +//~? ERROR cannot mix `proc-macro` crate type with others diff --git a/tests/ui/reachable/unreachable-code-ret.rs b/tests/ui/reachable/unreachable-code-ret.rs index ed9fbd5c5a2..746c4d53e7b 100644 --- a/tests/ui/reachable/unreachable-code-ret.rs +++ b/tests/ui/reachable/unreachable-code-ret.rs @@ -1,8 +1,6 @@ -//@ error-pattern: unreachable statement - #![deny(unreachable_code)] fn main() { return; - println!("Paul is dead"); + println!("Paul is dead"); //~ ERROR unreachable statement } diff --git a/tests/ui/reachable/unreachable-code-ret.stderr b/tests/ui/reachable/unreachable-code-ret.stderr index 824515a2271..d86def536df 100644 --- a/tests/ui/reachable/unreachable-code-ret.stderr +++ b/tests/ui/reachable/unreachable-code-ret.stderr @@ -1,5 +1,5 @@ error: unreachable statement - --> $DIR/unreachable-code-ret.rs:7:5 + --> $DIR/unreachable-code-ret.rs:5:5 | LL | return; | ------ any code following this expression is unreachable @@ -7,7 +7,7 @@ LL | println!("Paul is dead"); | ^^^^^^^^^^^^^^^^^^^^^^^^ unreachable statement | note: the lint level is defined here - --> $DIR/unreachable-code-ret.rs:3:9 + --> $DIR/unreachable-code-ret.rs:1:9 | LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/resolve/bad-env-capture.rs b/tests/ui/resolve/bad-env-capture.rs index ccd98b6ef06..a0efe88e2a9 100644 --- a/tests/ui/resolve/bad-env-capture.rs +++ b/tests/ui/resolve/bad-env-capture.rs @@ -1,6 +1,8 @@ -//@ error-pattern: can't capture dynamic environment in a fn item fn foo() { let x: isize; fn bar() { log(debug, x); } + //~^ ERROR can't capture dynamic environment in a fn item + //~| ERROR cannot find value `debug` in this scope + //~| ERROR cannot find function `log` in this scope } fn main() { foo(); } diff --git a/tests/ui/resolve/bad-env-capture.stderr b/tests/ui/resolve/bad-env-capture.stderr index 59b1fabfd7c..a3a15ca245b 100644 --- a/tests/ui/resolve/bad-env-capture.stderr +++ b/tests/ui/resolve/bad-env-capture.stderr @@ -1,5 +1,5 @@ error[E0434]: can't capture dynamic environment in a fn item - --> $DIR/bad-env-capture.rs:4:27 + --> $DIR/bad-env-capture.rs:3:27 | LL | fn bar() { log(debug, x); } | ^ @@ -7,13 +7,13 @@ LL | fn bar() { log(debug, x); } = help: use the `|| { ... }` closure form instead error[E0425]: cannot find value `debug` in this scope - --> $DIR/bad-env-capture.rs:4:20 + --> $DIR/bad-env-capture.rs:3:20 | LL | fn bar() { log(debug, x); } | ^^^^^ not found in this scope error[E0425]: cannot find function `log` in this scope - --> $DIR/bad-env-capture.rs:4:16 + --> $DIR/bad-env-capture.rs:3:16 | LL | fn bar() { log(debug, x); } | ^^^ not found in this scope diff --git a/tests/ui/resolve/bad-env-capture2.rs b/tests/ui/resolve/bad-env-capture2.rs index 84d1832be60..8298e6fcd24 100644 --- a/tests/ui/resolve/bad-env-capture2.rs +++ b/tests/ui/resolve/bad-env-capture2.rs @@ -1,5 +1,7 @@ -//@ error-pattern: can't capture dynamic environment in a fn item fn foo(x: isize) { fn bar() { log(debug, x); } + //~^ ERROR can't capture dynamic environment in a fn item + //~| ERROR cannot find value `debug` in this scope + //~| ERROR cannot find function `log` in this scope } fn main() { foo(2); } diff --git a/tests/ui/resolve/bad-env-capture2.stderr b/tests/ui/resolve/bad-env-capture2.stderr index 811c259de6b..403fe2d32b9 100644 --- a/tests/ui/resolve/bad-env-capture2.stderr +++ b/tests/ui/resolve/bad-env-capture2.stderr @@ -1,5 +1,5 @@ error[E0434]: can't capture dynamic environment in a fn item - --> $DIR/bad-env-capture2.rs:3:27 + --> $DIR/bad-env-capture2.rs:2:27 | LL | fn bar() { log(debug, x); } | ^ @@ -7,13 +7,13 @@ LL | fn bar() { log(debug, x); } = help: use the `|| { ... }` closure form instead error[E0425]: cannot find value `debug` in this scope - --> $DIR/bad-env-capture2.rs:3:20 + --> $DIR/bad-env-capture2.rs:2:20 | LL | fn bar() { log(debug, x); } | ^^^^^ not found in this scope error[E0425]: cannot find function `log` in this scope - --> $DIR/bad-env-capture2.rs:3:16 + --> $DIR/bad-env-capture2.rs:2:16 | LL | fn bar() { log(debug, x); } | ^^^ not found in this scope diff --git a/tests/ui/resolve/bad-env-capture3.rs b/tests/ui/resolve/bad-env-capture3.rs index 849b84cb1ab..8f5440d3339 100644 --- a/tests/ui/resolve/bad-env-capture3.rs +++ b/tests/ui/resolve/bad-env-capture3.rs @@ -1,7 +1,9 @@ -//@ error-pattern: can't capture dynamic environment in a fn item fn foo(x: isize) { fn mth() { fn bar() { log(debug, x); } + //~^ ERROR can't capture dynamic environment in a fn item + //~| ERROR cannot find value `debug` in this scope + //~| ERROR cannot find function `log` in this scope } } diff --git a/tests/ui/resolve/bad-env-capture3.stderr b/tests/ui/resolve/bad-env-capture3.stderr index eab37fde96e..962eb72ee68 100644 --- a/tests/ui/resolve/bad-env-capture3.stderr +++ b/tests/ui/resolve/bad-env-capture3.stderr @@ -1,5 +1,5 @@ error[E0434]: can't capture dynamic environment in a fn item - --> $DIR/bad-env-capture3.rs:4:31 + --> $DIR/bad-env-capture3.rs:3:31 | LL | fn bar() { log(debug, x); } | ^ @@ -7,13 +7,13 @@ LL | fn bar() { log(debug, x); } = help: use the `|| { ... }` closure form instead error[E0425]: cannot find value `debug` in this scope - --> $DIR/bad-env-capture3.rs:4:24 + --> $DIR/bad-env-capture3.rs:3:24 | LL | fn bar() { log(debug, x); } | ^^^^^ not found in this scope error[E0425]: cannot find function `log` in this scope - --> $DIR/bad-env-capture3.rs:4:20 + --> $DIR/bad-env-capture3.rs:3:20 | LL | fn bar() { log(debug, x); } | ^^^ not found in this scope diff --git a/tests/ui/return/ret-non-nil.rs b/tests/ui/return/ret-non-nil.rs index 1d039ffe18c..b9a53086b3c 100644 --- a/tests/ui/return/ret-non-nil.rs +++ b/tests/ui/return/ret-non-nil.rs @@ -1,7 +1,5 @@ -//@ error-pattern: `return;` in a function whose return type is not `()` - fn f() { return; } -fn g() -> isize { return; } +fn g() -> isize { return; } //~ ERROR `return;` in a function whose return type is not `()` fn main() { f(); g(); } diff --git a/tests/ui/return/ret-non-nil.stderr b/tests/ui/return/ret-non-nil.stderr index 802900e61a3..44edecf501f 100644 --- a/tests/ui/return/ret-non-nil.stderr +++ b/tests/ui/return/ret-non-nil.stderr @@ -1,5 +1,5 @@ error[E0069]: `return;` in a function whose return type is not `()` - --> $DIR/ret-non-nil.rs:5:19 + --> $DIR/ret-non-nil.rs:3:19 | LL | fn g() -> isize { return; } | ----- ^^^^^^ return type is not `()` diff --git a/tests/ui/rfcs/rfc-1717-dllimport/missing-link-attr.rs b/tests/ui/rfcs/rfc-1717-dllimport/missing-link-attr.rs index d54b428bf22..9dc856959c0 100644 --- a/tests/ui/rfcs/rfc-1717-dllimport/missing-link-attr.rs +++ b/tests/ui/rfcs/rfc-1717-dllimport/missing-link-attr.rs @@ -1,4 +1,5 @@ //@ compile-flags: -l foo:bar -//@ error-pattern: renaming of the library `foo` was specified #![crate_type = "lib"] + +//~? ERROR renaming of the library `foo` was specified diff --git a/tests/ui/rfcs/rfc-1717-dllimport/multiple-renames.rs b/tests/ui/rfcs/rfc-1717-dllimport/multiple-renames.rs index ec1a246245e..69132895510 100644 --- a/tests/ui/rfcs/rfc-1717-dllimport/multiple-renames.rs +++ b/tests/ui/rfcs/rfc-1717-dllimport/multiple-renames.rs @@ -1,7 +1,8 @@ //@ compile-flags: -l foo:bar -l foo:baz -//@ error-pattern: multiple renamings were specified for library #![crate_type = "lib"] #[link(name = "foo")] extern "C" {} + +//~? ERROR multiple renamings were specified for library `foo` diff --git a/tests/ui/rfcs/rfc-1717-dllimport/rename-modifiers.rs b/tests/ui/rfcs/rfc-1717-dllimport/rename-modifiers.rs index 2a13d22e22a..e1fec305932 100644 --- a/tests/ui/rfcs/rfc-1717-dllimport/rename-modifiers.rs +++ b/tests/ui/rfcs/rfc-1717-dllimport/rename-modifiers.rs @@ -1,5 +1,4 @@ //@ compile-flags: -l dylib=foo:bar -//@ error-pattern: overriding linking modifiers from command line is not supported #![feature(native_link_modifiers_as_needed)] @@ -7,3 +6,4 @@ #[link(name = "foo", kind = "dylib", modifiers = "-as-needed")] extern "C" {} +//~^ ERROR overriding linking modifiers from command line is not supported diff --git a/tests/ui/rfcs/rfc-1717-dllimport/rename-modifiers.stderr b/tests/ui/rfcs/rfc-1717-dllimport/rename-modifiers.stderr index ce145689f90..84b197a9b98 100644 --- a/tests/ui/rfcs/rfc-1717-dllimport/rename-modifiers.stderr +++ b/tests/ui/rfcs/rfc-1717-dllimport/rename-modifiers.stderr @@ -1,5 +1,5 @@ error: overriding linking modifiers from command line is not supported - --> $DIR/rename-modifiers.rs:9:1 + --> $DIR/rename-modifiers.rs:8:1 | LL | extern "C" {} | ^^^^^^^^^^^^^ diff --git a/tests/ui/rfcs/rfc-1717-dllimport/rename-to-empty.rs b/tests/ui/rfcs/rfc-1717-dllimport/rename-to-empty.rs index 39205a11dd7..6fee80f0294 100644 --- a/tests/ui/rfcs/rfc-1717-dllimport/rename-to-empty.rs +++ b/tests/ui/rfcs/rfc-1717-dllimport/rename-to-empty.rs @@ -1,7 +1,8 @@ //@ compile-flags: -l foo: -//@ error-pattern: an empty renaming target was specified for library #![crate_type = "lib"] #[link(name = "foo")] extern "C" {} + +//~? ERROR an empty renaming target was specified for library `foo` diff --git a/tests/ui/rmeta/rmeta_bin.rs b/tests/ui/rmeta/rmeta_bin.rs index c7d2050cd59..9eb65241faf 100644 --- a/tests/ui/rmeta/rmeta_bin.rs +++ b/tests/ui/rmeta/rmeta_bin.rs @@ -2,7 +2,6 @@ //@ compile-flags: --crate-type=bin //@ aux-build:rmeta-meta.rs //@ no-prefer-dynamic -//@ error-pattern: crate `rmeta_meta` required to be available in rlib format, but was not found // Check that building a bin crate fails if a dependent crate is metadata-only. @@ -12,3 +11,5 @@ use rmeta_meta::Foo; fn main() { let _ = Foo { field: 42 }; } + +//~? ERROR crate `rmeta_meta` required to be available in rlib format, but was not found in this form diff --git a/tests/ui/rmeta/rmeta_lib.rs b/tests/ui/rmeta/rmeta_lib.rs index 1be4ee8de79..d1a2b653ed8 100644 --- a/tests/ui/rmeta/rmeta_lib.rs +++ b/tests/ui/rmeta/rmeta_lib.rs @@ -1,7 +1,6 @@ //@ build-fail //@ aux-build:rmeta-meta.rs //@ no-prefer-dynamic -//@ error-pattern: crate `rmeta_meta` required to be available in rlib format, but was not found // Check that building a non-metadata crate fails if a dependent crate is // metadata-only. @@ -12,3 +11,5 @@ use rmeta_meta::Foo; fn main() { let _ = Foo { field: 42 }; } + +//~? ERROR crate `rmeta_meta` required to be available in rlib format, but was not found in this form diff --git a/tests/ui/sanitizer/incompatible.rs b/tests/ui/sanitizer/incompatible.rs index d000abb26ac..c706a5a2e4e 100644 --- a/tests/ui/sanitizer/incompatible.rs +++ b/tests/ui/sanitizer/incompatible.rs @@ -1,7 +1,8 @@ //@ compile-flags: -Z sanitizer=address -Z sanitizer=memory --target x86_64-unknown-linux-gnu //@ needs-llvm-components: x86 -//@ error-pattern: error: `-Zsanitizer=address` is incompatible with `-Zsanitizer=memory` #![feature(no_core)] #![no_core] #![no_main] + +//~? ERROR `-Zsanitizer=address` is incompatible with `-Zsanitizer=memory` diff --git a/tests/ui/sanitizer/unsupported-target.rs b/tests/ui/sanitizer/unsupported-target.rs index 7c7dc24b5d9..14925548e92 100644 --- a/tests/ui/sanitizer/unsupported-target.rs +++ b/tests/ui/sanitizer/unsupported-target.rs @@ -1,6 +1,8 @@ //@ compile-flags: -Z sanitizer=leak --target i686-unknown-linux-gnu //@ needs-llvm-components: x86 -//@ error-pattern: error: leak sanitizer is not supported for this target + #![feature(no_core)] #![no_core] #![no_main] + +//~? ERROR leak sanitizer is not supported for this target diff --git a/tests/ui/simd/monomorphize-too-long.rs b/tests/ui/simd/monomorphize-too-long.rs index 4bcde782292..4fac987b0b5 100644 --- a/tests/ui/simd/monomorphize-too-long.rs +++ b/tests/ui/simd/monomorphize-too-long.rs @@ -1,5 +1,4 @@ //@ build-fail -//@ error-pattern: monomorphising SIMD type `Simd<u16, 54321>` of length greater than 32768 #![feature(repr_simd)] @@ -9,3 +8,5 @@ struct Simd<T, const N: usize>([T; N]); fn main() { let _too_big = Simd([1_u16; 54321]); } + +//~? ERROR monomorphising SIMD type `Simd<u16, 54321>` of length greater than 32768 diff --git a/tests/ui/simd/monomorphize-zero-length.rs b/tests/ui/simd/monomorphize-zero-length.rs index 44b4cfc0bcf..d38870c572d 100644 --- a/tests/ui/simd/monomorphize-zero-length.rs +++ b/tests/ui/simd/monomorphize-zero-length.rs @@ -1,5 +1,4 @@ //@ build-fail -//@ error-pattern: monomorphising SIMD type `Simd<f64, 0>` of zero length #![feature(repr_simd)] @@ -9,3 +8,5 @@ struct Simd<T, const N: usize>([T; N]); fn main() { let _empty = Simd([1.0; 0]); } + +//~? ERROR monomorphising SIMD type `Simd<f64, 0>` of zero length diff --git a/tests/ui/simd/type-generic-monomorphisation-empty.rs b/tests/ui/simd/type-generic-monomorphisation-empty.rs index 4700f642065..c08dc9fe3df 100644 --- a/tests/ui/simd/type-generic-monomorphisation-empty.rs +++ b/tests/ui/simd/type-generic-monomorphisation-empty.rs @@ -2,11 +2,11 @@ #![feature(repr_simd, intrinsics)] -//@ error-pattern:monomorphising SIMD type `Simd<0>` of zero length - #[repr(simd)] struct Simd<const N: usize>([f32; N]); fn main() { let _ = Simd::<0>([]); } + +//~? ERROR monomorphising SIMD type `Simd<0>` of zero length diff --git a/tests/ui/simd/type-generic-monomorphisation-non-primitive.rs b/tests/ui/simd/type-generic-monomorphisation-non-primitive.rs index a2f6998c6d9..7924aeb8684 100644 --- a/tests/ui/simd/type-generic-monomorphisation-non-primitive.rs +++ b/tests/ui/simd/type-generic-monomorphisation-non-primitive.rs @@ -4,11 +4,11 @@ struct E; -//@ error-pattern:monomorphising SIMD type `S<E>` with a non-primitive-scalar (integer/float/pointer) element type `E` - #[repr(simd)] struct S<T>([T; 4]); fn main() { let _v: Option<S<E>> = None; } + +//~? ERROR monomorphising SIMD type `S<E>` with a non-primitive-scalar (integer/float/pointer) element type `E` diff --git a/tests/ui/simd/type-generic-monomorphisation-oversized.rs b/tests/ui/simd/type-generic-monomorphisation-oversized.rs index 9949f913c44..efe3480317c 100644 --- a/tests/ui/simd/type-generic-monomorphisation-oversized.rs +++ b/tests/ui/simd/type-generic-monomorphisation-oversized.rs @@ -2,11 +2,11 @@ #![feature(repr_simd, intrinsics)] -//@ error-pattern:monomorphising SIMD type `Simd<65536>` of length greater than 32768 - #[repr(simd)] struct Simd<const N: usize>([f32; N]); fn main() { let _ = Simd::<65536>([0.; 65536]); } + +//~? ERROR monomorphising SIMD type `Simd<65536>` of length greater than 32768 diff --git a/tests/ui/simd/type-generic-monomorphisation-wide-ptr.rs b/tests/ui/simd/type-generic-monomorphisation-wide-ptr.rs index 18fc0753430..97640514dee 100644 --- a/tests/ui/simd/type-generic-monomorphisation-wide-ptr.rs +++ b/tests/ui/simd/type-generic-monomorphisation-wide-ptr.rs @@ -2,11 +2,11 @@ #![feature(repr_simd)] -//@ error-pattern:monomorphising SIMD type `S<*mut [u8]>` with a non-primitive-scalar (integer/float/pointer) element type `*mut [u8]` - #[repr(simd)] struct S<T>([T; 4]); fn main() { let _v: Option<S<*mut [u8]>> = None; } + +//~? ERROR monomorphising SIMD type `S<*mut [u8]>` with a non-primitive-scalar (integer/float/pointer) element type `*mut [u8]` diff --git a/tests/ui/simd/type-generic-monomorphisation.rs b/tests/ui/simd/type-generic-monomorphisation.rs index 8b8d645a264..2563b917e34 100644 --- a/tests/ui/simd/type-generic-monomorphisation.rs +++ b/tests/ui/simd/type-generic-monomorphisation.rs @@ -2,9 +2,6 @@ #![feature(repr_simd, intrinsics)] - -//@ error-pattern:monomorphising SIMD type `Simd2<X>` with a non-primitive-scalar (integer/float/pointer) element type `X` - struct X(Vec<i32>); #[repr(simd)] struct Simd2<T>([T; 2]); @@ -12,3 +9,5 @@ struct Simd2<T>([T; 2]); fn main() { let _ = Simd2([X(vec![]), X(vec![])]); } + +//~? ERROR monomorphising SIMD type `Simd2<X>` with a non-primitive-scalar (integer/float/pointer) element type `X` diff --git a/tests/ui/simd/type-wide-ptr.rs b/tests/ui/simd/type-wide-ptr.rs index 41d9fac26ad..5740a4e8318 100644 --- a/tests/ui/simd/type-wide-ptr.rs +++ b/tests/ui/simd/type-wide-ptr.rs @@ -2,11 +2,11 @@ #![feature(repr_simd)] -//@ error-pattern:monomorphising SIMD type `S` with a non-primitive-scalar (integer/float/pointer) element type `*mut [u8]` - #[repr(simd)] struct S([*mut [u8]; 4]); fn main() { let _v: Option<S> = None; } + +//~? ERROR monomorphising SIMD type `S` with a non-primitive-scalar (integer/float/pointer) element type `*mut [u8]` diff --git a/tests/ui/tail-typeck.rs b/tests/ui/tail-typeck.rs index feef58a3388..1deb43c9496 100644 --- a/tests/ui/tail-typeck.rs +++ b/tests/ui/tail-typeck.rs @@ -1,6 +1,4 @@ -//@ error-pattern: mismatched types - -fn f() -> isize { return g(); } +fn f() -> isize { return g(); } //~ ERROR mismatched types fn g() -> usize { return 0; } diff --git a/tests/ui/tail-typeck.stderr b/tests/ui/tail-typeck.stderr index 0e470a7b405..3cfbfa0fb56 100644 --- a/tests/ui/tail-typeck.stderr +++ b/tests/ui/tail-typeck.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/tail-typeck.rs:3:26 + --> $DIR/tail-typeck.rs:1:26 | LL | fn f() -> isize { return g(); } | ----- ^^^ expected `isize`, found `usize` diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-implied.rs b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-implied.rs index 81f138b175f..12e7e3bc45b 100644 --- a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-implied.rs +++ b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-implied.rs @@ -5,9 +5,11 @@ //@ compile-flags: -Ctarget-feature=-sse // For now this is just a warning. //@ build-pass -//@error-pattern: must be enabled to ensure that the ABI + #![feature(no_core, lang_items)] #![no_core] #[lang = "sized"] pub trait Sized {} + +//~? WARN target feature `sse2` must be enabled to ensure that the ABI of the current target can be implemented correctly diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-neon.rs b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-neon.rs index 7242bcc85bf..33e4f12694f 100644 --- a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-neon.rs +++ b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-neon.rs @@ -3,9 +3,11 @@ //@ compile-flags: -Ctarget-feature=-neon // For now this is just a warning. //@ build-pass -//@error-pattern: must be enabled to ensure that the ABI + #![feature(no_core, lang_items)] #![no_core] #[lang = "sized"] pub trait Sized {} + +//~? WARN target feature `neon` must be enabled to ensure that the ABI of the current target can be implemented correctly diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable.rs b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable.rs index 7eebcf05dc0..e1bd25ffad1 100644 --- a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable.rs +++ b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable.rs @@ -4,9 +4,12 @@ //@ compile-flags: -Ctarget-feature=-x87 // For now this is just a warning. //@ build-pass -//@error-pattern: must be enabled to ensure that the ABI + #![feature(no_core, lang_items)] #![no_core] #[lang = "sized"] pub trait Sized {} + +//~? WARN target feature `x87` must be enabled to ensure that the ABI of the current target can be implemented correctly +//~? WARN unstable feature specified for `-Ctarget-feature`: `x87` diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag.rs b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag.rs index f277a309cd6..4ccc6e0e941 100644 --- a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag.rs +++ b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag.rs @@ -4,9 +4,12 @@ //@ compile-flags: -Ctarget-feature=+soft-float // For now this is just a warning. //@ build-pass -//@error-pattern: must be disabled to ensure that the ABI + #![feature(no_core, lang_items, riscv_target_feature)] #![no_core] #[lang = "sized"] pub trait Sized {} + +//~? WARN target feature `soft-float` must be disabled to ensure that the ABI of the current target can be implemented correctl +//~? WARN unstable feature specified for `-Ctarget-feature`: `soft-float` diff --git a/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs b/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs index cf85c521228..fda0b1c08cb 100644 --- a/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs +++ b/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs @@ -10,3 +10,5 @@ #[lang = "sized"] pub trait Sized {} + +//~? WARN target feature `forced-atomics` cannot be disabled with `-Ctarget-feature`: unsound because it changes the ABI of atomic operations diff --git a/tests/ui/target-feature/forbidden-target-feature-flag.rs b/tests/ui/target-feature/forbidden-target-feature-flag.rs index 245841eb039..a04d7e34753 100644 --- a/tests/ui/target-feature/forbidden-target-feature-flag.rs +++ b/tests/ui/target-feature/forbidden-target-feature-flag.rs @@ -4,9 +4,11 @@ //@ compile-flags: -Ctarget-feature=+forced-atomics // For now this is just a warning. //@ build-pass -//@error-pattern: unsound because it changes the ABI + #![feature(no_core, lang_items)] #![no_core] #[lang = "sized"] pub trait Sized {} + +//~? WARN target feature `forced-atomics` cannot be enabled with `-Ctarget-feature`: unsound because it changes the ABI of atomic operations diff --git a/tests/ui/target-feature/target-cpu-lacks-required-target-feature.rs b/tests/ui/target-feature/target-cpu-lacks-required-target-feature.rs index 28d026c1a9a..be6cd2b6faf 100644 --- a/tests/ui/target-feature/target-cpu-lacks-required-target-feature.rs +++ b/tests/ui/target-feature/target-cpu-lacks-required-target-feature.rs @@ -3,10 +3,11 @@ //@ compile-flags: -Ctarget-cpu=pentium // For now this is just a warning. //@ build-pass -//@error-pattern: must be enabled #![feature(no_core, lang_items)] #![no_core] #[lang = "sized"] pub trait Sized {} + +//~? WARN target feature `sse2` must be enabled to ensure that the ABI of the current target can be implemented correctly diff --git a/tests/ui/target-feature/tied-features-no-implication.pacg.stderr b/tests/ui/target-feature/tied-features-no-implication.pacg.stderr index 0e31dea24ea..4ff42d31e94 100644 --- a/tests/ui/target-feature/tied-features-no-implication.pacg.stderr +++ b/tests/ui/target-feature/tied-features-no-implication.pacg.stderr @@ -1,10 +1,10 @@ error[E0428]: the name `foo` is defined multiple times - --> $DIR/tied-features-no-implication.rs:28:1 + --> $DIR/tied-features-no-implication.rs:27:1 | LL | fn foo() {} | -------- previous definition of the value `foo` here ... -LL | pub unsafe fn foo() { +LL | pub unsafe fn foo() {} | ^^^^^^^^^^^^^^^^^^^ `foo` redefined here | = note: `foo` must be defined only once in the value namespace of this module diff --git a/tests/ui/target-feature/tied-features-no-implication.rs b/tests/ui/target-feature/tied-features-no-implication.rs index 157b50bb0d3..1625f71431a 100644 --- a/tests/ui/target-feature/tied-features-no-implication.rs +++ b/tests/ui/target-feature/tied-features-no-implication.rs @@ -2,9 +2,8 @@ //@ compile-flags: --crate-type=rlib --target=aarch64-unknown-linux-gnu //@ needs-llvm-components: aarch64 //@[paca] compile-flags: -Ctarget-feature=+paca -//@[paca] error-pattern: the target features paca, pacg must all be either enabled or disabled together //@[pacg] compile-flags: -Ctarget-feature=+pacg -//@[pacg] error-pattern: the name `foo` is defined multiple times + #![feature(no_core, lang_items)] #![no_core] @@ -25,5 +24,6 @@ fn foo() {} // be). #[cfg(target_feature = "pacg")] -pub unsafe fn foo() { -} +pub unsafe fn foo() {} //[pacg]~ ERROR the name `foo` is defined multiple times + +//[paca]~? ERROR the target features paca, pacg must all be either enabled or disabled together diff --git a/tests/ui/test-attrs/test-panic-abort-disabled.rs b/tests/ui/test-attrs/test-panic-abort-disabled.rs index e83be65f925..cb1b2af9e26 100644 --- a/tests/ui/test-attrs/test-panic-abort-disabled.rs +++ b/tests/ui/test-attrs/test-panic-abort-disabled.rs @@ -1,4 +1,3 @@ -//@ error-pattern:building tests with panic=abort is not supported //@ no-prefer-dynamic //@ compile-flags: --test -Cpanic=abort -Zpanic-abort-tests=no //@ run-flags: --test-threads=1 @@ -18,3 +17,5 @@ fn it_works() { fn it_panics() { assert_eq!(1 + 1, 4); } + +//~? ERROR building tests with panic=abort is not supported without `-Zpanic_abort_tests` diff --git a/tests/ui/track-diagnostics/track.rs b/tests/ui/track-diagnostics/track.rs index 9e81cb53fc1..78ff85489be 100644 --- a/tests/ui/track-diagnostics/track.rs +++ b/tests/ui/track-diagnostics/track.rs @@ -15,4 +15,7 @@ fn main() { break rust + //~^ ERROR cannot find value `rust` in this scope + //~| ERROR `break` outside of a loop or labeled block + //~| ERROR It looks like you're trying to break rust; would you like some ICE? } diff --git a/tests/ui/track-diagnostics/track2.rs b/tests/ui/track-diagnostics/track2.rs index 5805fd21220..f51a42cf86f 100644 --- a/tests/ui/track-diagnostics/track2.rs +++ b/tests/ui/track-diagnostics/track2.rs @@ -6,5 +6,5 @@ //@ normalize-stderr: ".rs:\d+:\d+" -> ".rs:LL:CC" fn main() { - let _moved @ _from = String::from("foo"); + let _moved @ _from = String::from("foo"); //~ ERROR use of moved value } diff --git a/tests/ui/track-diagnostics/track3.rs b/tests/ui/track-diagnostics/track3.rs index bac1fc7e184..428067572af 100644 --- a/tests/ui/track-diagnostics/track3.rs +++ b/tests/ui/track-diagnostics/track3.rs @@ -7,4 +7,6 @@ fn main() { let _unimported = Blah { field: u8 }; + //~^ ERROR cannot find struct, variant or union type `Blah` in this scope + //~| ERROR expected value, found builtin type `u8` } diff --git a/tests/ui/track-diagnostics/track4.rs b/tests/ui/track-diagnostics/track4.rs index ec9e3efa481..b6edfdba259 100644 --- a/tests/ui/track-diagnostics/track4.rs +++ b/tests/ui/track-diagnostics/track4.rs @@ -5,7 +5,7 @@ // updating everytime someone adds or removes a line. //@ normalize-stderr: ".rs:\d+:\d+" -> ".rs:LL:CC" -pub onion { +pub onion { //~ ERROR missing `enum` for enum definition Owo(u8), Uwu(i8), } diff --git a/tests/ui/track-diagnostics/track5.rs b/tests/ui/track-diagnostics/track5.rs index e72e3482ad3..800bb21b2b1 100644 --- a/tests/ui/track-diagnostics/track5.rs +++ b/tests/ui/track-diagnostics/track5.rs @@ -5,4 +5,4 @@ // updating everytime someone adds or removes a line. //@ normalize-stderr: ".rs:\d+:\d+" -> ".rs:LL:CC" -} +} //~ ERROR unexpected closing delimiter: `}` diff --git a/tests/ui/track-diagnostics/track6.rs b/tests/ui/track-diagnostics/track6.rs index e4d124a22e4..55db2ecf939 100644 --- a/tests/ui/track-diagnostics/track6.rs +++ b/tests/ui/track-diagnostics/track6.rs @@ -11,7 +11,7 @@ pub trait Foo { } impl <T> Foo for T { - default fn bar() {} + default fn bar() {} //~ ERROR specialization is unstable } fn main() {} diff --git a/tests/ui/traits/default_auto_traits/backward-compatible-lazy-bounds-pass.rs b/tests/ui/traits/default_auto_traits/backward-compatible-lazy-bounds-pass.rs new file mode 100644 index 00000000000..3818456d3a6 --- /dev/null +++ b/tests/ui/traits/default_auto_traits/backward-compatible-lazy-bounds-pass.rs @@ -0,0 +1,25 @@ +//@ check-pass +//@ compile-flags: -Zexperimental-default-bounds + +#![feature(auto_traits, lang_items, no_core, rustc_attrs, trait_alias)] +#![no_std] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +#[lang = "default_trait1"] +auto trait DefaultTrait1 {} + +#[lang = "default_trait2"] +auto trait DefaultTrait2 {} + +trait Trait<Rhs: ?Sized = Self> {} +trait Trait1 : Trait {} + +trait Trait2 { + type Type; +} +trait Trait3<T> = Trait2<Type = T>; + +fn main() {} diff --git a/tests/ui/traits/default_auto_traits/default-bounds.rs b/tests/ui/traits/default_auto_traits/default-bounds.rs new file mode 100644 index 00000000000..64733a40034 --- /dev/null +++ b/tests/ui/traits/default_auto_traits/default-bounds.rs @@ -0,0 +1,41 @@ +//@ compile-flags: -Zexperimental-default-bounds + +#![feature( + auto_traits, + lang_items, + negative_impls, + no_core, + rustc_attrs +)] +#![allow(incomplete_features)] +#![no_std] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +#[lang = "copy"] +pub trait Copy {} + +#[lang = "default_trait1"] +auto trait Leak {} + +#[lang = "default_trait2"] +auto trait SyncDrop {} + +struct Forbidden; + +impl !Leak for Forbidden {} +impl !SyncDrop for Forbidden {} + +struct Accepted; + +fn bar<T: Leak>(_: T) {} + +fn main() { + // checking that bounds can be added explicitly + bar(Forbidden); + //~^ ERROR the trait bound `Forbidden: Leak` is not satisfied + //~| ERROR the trait bound `Forbidden: SyncDrop` is not satisfied + bar(Accepted); +} diff --git a/tests/ui/traits/default_auto_traits/default-bounds.stderr b/tests/ui/traits/default_auto_traits/default-bounds.stderr new file mode 100644 index 00000000000..10fdcc43417 --- /dev/null +++ b/tests/ui/traits/default_auto_traits/default-bounds.stderr @@ -0,0 +1,31 @@ +error[E0277]: the trait bound `Forbidden: SyncDrop` is not satisfied + --> $DIR/default-bounds.rs:37:9 + | +LL | bar(Forbidden); + | --- ^^^^^^^^^ the trait `SyncDrop` is not implemented for `Forbidden` + | | + | required by a bound introduced by this call + | +note: required by a bound in `bar` + --> $DIR/default-bounds.rs:33:8 + | +LL | fn bar<T: Leak>(_: T) {} + | ^ required by this bound in `bar` + +error[E0277]: the trait bound `Forbidden: Leak` is not satisfied + --> $DIR/default-bounds.rs:37:9 + | +LL | bar(Forbidden); + | --- ^^^^^^^^^ the trait `Leak` is not implemented for `Forbidden` + | | + | required by a bound introduced by this call + | +note: required by a bound in `bar` + --> $DIR/default-bounds.rs:33:11 + | +LL | fn bar<T: Leak>(_: T) {} + | ^^^^ required by this bound in `bar` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/default_auto_traits/extern-types.current.stderr b/tests/ui/traits/default_auto_traits/extern-types.current.stderr new file mode 100644 index 00000000000..e1bd99b900f --- /dev/null +++ b/tests/ui/traits/default_auto_traits/extern-types.current.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `extern_non_leak::Opaque: Leak` is not satisfied + --> $DIR/extern-types.rs:44:13 + | +LL | foo(x); + | --- ^ the trait `Leak` is not implemented for `extern_non_leak::Opaque` + | | + | required by a bound introduced by this call + | +note: required by a bound in `foo` + --> $DIR/extern-types.rs:20:8 + | +LL | fn foo<T: ?Sized>(_: &T) {} + | ^ required by this bound in `foo` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/default_auto_traits/extern-types.next.stderr b/tests/ui/traits/default_auto_traits/extern-types.next.stderr new file mode 100644 index 00000000000..e1bd99b900f --- /dev/null +++ b/tests/ui/traits/default_auto_traits/extern-types.next.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `extern_non_leak::Opaque: Leak` is not satisfied + --> $DIR/extern-types.rs:44:13 + | +LL | foo(x); + | --- ^ the trait `Leak` is not implemented for `extern_non_leak::Opaque` + | | + | required by a bound introduced by this call + | +note: required by a bound in `foo` + --> $DIR/extern-types.rs:20:8 + | +LL | fn foo<T: ?Sized>(_: &T) {} + | ^ required by this bound in `foo` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/default_auto_traits/extern-types.rs b/tests/ui/traits/default_auto_traits/extern-types.rs new file mode 100644 index 00000000000..822d4c0637f --- /dev/null +++ b/tests/ui/traits/default_auto_traits/extern-types.rs @@ -0,0 +1,49 @@ +//@ compile-flags: -Zexperimental-default-bounds +//@ revisions: current next +//@ [next] compile-flags: -Znext-solver + +#![feature(auto_traits, extern_types, lang_items, negative_impls, no_core, rustc_attrs)] +#![allow(incomplete_features)] +#![no_std] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +#[lang = "copy"] +pub trait Copy {} + +#[lang = "default_trait1"] +auto trait Leak {} + +// implicit T: Leak here +fn foo<T: ?Sized>(_: &T) {} + +mod extern_leak { + use crate::*; + + extern "C" { + type Opaque; + } + + fn forward_extern_ty(x: &Opaque) { + // ok, extern type leak by default + crate::foo(x); + } +} + +mod extern_non_leak { + use crate::*; + + extern "C" { + type Opaque; + } + + impl !Leak for Opaque {} + fn forward_extern_ty(x: &Opaque) { + foo(x); + //~^ ERROR: the trait bound `extern_non_leak::Opaque: Leak` is not satisfied + } +} + +fn main() {} diff --git a/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.rs b/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.rs new file mode 100644 index 00000000000..49f2faba146 --- /dev/null +++ b/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.rs @@ -0,0 +1,61 @@ +//@ compile-flags: -Zexperimental-default-bounds + +#![feature( + auto_traits, + lang_items, + more_maybe_bounds, + negative_impls, + no_core, + rustc_attrs +)] +#![allow(internal_features)] +#![no_std] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +#[lang = "copy"] +pub trait Copy {} +impl<'a, T: ?Sized> Copy for &'a T {} + +#[lang = "legacy_receiver"] +trait Receiver {} +impl<T: ?Sized + ?Leak> Receiver for &T {} + +#[lang = "unsize"] +trait Unsize<T: ?Sized + ?Leak> {} + +#[lang = "coerce_unsized"] +trait CoerceUnsized<T: ?Leak + ?Sized> {} +impl<'a, 'b: 'a, T: ?Sized + ?Leak + Unsize<U>, U: ?Sized + ?Leak> CoerceUnsized<&'a U> for &'b T {} + +#[lang = "dispatch_from_dyn"] +trait DispatchFromDyn<T: ?Leak> {} +impl<'a, T: ?Sized + ?Leak + Unsize<U>, U: ?Sized + ?Leak> DispatchFromDyn<&'a U> for &'a T {} + +#[lang = "default_trait1"] +auto trait Leak {} + +struct NonLeakS; +impl !Leak for NonLeakS {} +struct LeakS; + +trait Trait { + fn leak_foo(&self) {} + fn maybe_leak_foo(&self) where Self: ?Leak {} +} + +impl Trait for NonLeakS {} +impl Trait for LeakS {} + +fn main() { + let _: &dyn Trait = &NonLeakS; + //~^ ERROR the trait bound `NonLeakS: Leak` is not satisfied + let _: &dyn Trait = &LeakS; + let _: &(dyn Trait + ?Leak) = &LeakS; + let x: &(dyn Trait + ?Leak) = &NonLeakS; + x.leak_foo(); + //~^ ERROR the trait bound `dyn Trait: Leak` is not satisfied + x.maybe_leak_foo(); +} diff --git a/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.stderr b/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.stderr new file mode 100644 index 00000000000..b7ffb66e60b --- /dev/null +++ b/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.stderr @@ -0,0 +1,23 @@ +error[E0277]: the trait bound `NonLeakS: Leak` is not satisfied + --> $DIR/maybe-bounds-in-dyn-traits.rs:53:25 + | +LL | let _: &dyn Trait = &NonLeakS; + | ^^^^^^^^^ the trait `Leak` is not implemented for `NonLeakS` + | + = note: required for the cast from `&NonLeakS` to `&dyn Trait + Leak` + +error[E0277]: the trait bound `dyn Trait: Leak` is not satisfied + --> $DIR/maybe-bounds-in-dyn-traits.rs:58:7 + | +LL | x.leak_foo(); + | ^^^^^^^^ the trait `Leak` is not implemented for `dyn Trait` + | +note: required by a bound in `Trait::leak_foo` + --> $DIR/maybe-bounds-in-dyn-traits.rs:45:5 + | +LL | fn leak_foo(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Trait::leak_foo` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/default_auto_traits/maybe-bounds-in-traits.rs b/tests/ui/traits/default_auto_traits/maybe-bounds-in-traits.rs new file mode 100644 index 00000000000..761f22d1be5 --- /dev/null +++ b/tests/ui/traits/default_auto_traits/maybe-bounds-in-traits.rs @@ -0,0 +1,115 @@ +//@ compile-flags: -Zexperimental-default-bounds + +#![feature( + auto_traits, + associated_type_defaults, + generic_const_items, + lang_items, + more_maybe_bounds, + negative_impls, + no_core, + rustc_attrs +)] +#![allow(incomplete_features)] +#![no_std] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +#[lang = "legacy_receiver"] +trait LegacyReceiver {} +impl<T: ?Sized + ?Leak> LegacyReceiver for &T {} +impl<T: ?Sized> LegacyReceiver for &mut T {} + +#[lang = "default_trait1"] +auto trait Leak {} + +struct NonLeakS; +impl !Leak for NonLeakS {} +struct LeakS; + +mod supertraits { + use crate::*; + + trait MaybeLeakT1: ?Leak {} + trait MaybeLeakT2 where Self: ?Leak {} + + impl MaybeLeakT1 for NonLeakS {} + impl MaybeLeakT2 for NonLeakS {} +} + +mod maybe_self_assoc_type { + use crate::*; + + trait TestBase1<T: ?Sized> {} + trait TestBase2<T: ?Leak + ?Sized> {} + + trait Test1<T> { + type MaybeLeakSelf: TestBase1<Self> where Self: ?Leak; + //~^ ERROR the trait bound `Self: Leak` is not satisfied + type LeakSelf: TestBase1<Self>; + } + + trait Test2<T> { + type MaybeLeakSelf: TestBase2<Self> where Self: ?Leak; + type LeakSelf: TestBase2<Self>; + } + + trait Test3 { + type Leak1 = LeakS; + type Leak2 = NonLeakS; + //~^ ERROR the trait bound `NonLeakS: Leak` is not satisfied + } + + trait Test4 { + type MaybeLeak1: ?Leak = LeakS; + type MaybeLeak2: ?Leak = NonLeakS; + } + + trait Test5: ?Leak { + // ok, because assoc types have implicit where Self: Leak + type MaybeLeakSelf1: TestBase1<Self>; + type MaybeLeakSelf2: TestBase2<Self>; + } +} + +mod maybe_self_assoc_const { + use crate::*; + + const fn size_of<T: ?Sized>() -> usize { + 0 + } + + trait Trait { + const CLeak: usize = size_of::<Self>(); + const CNonLeak: usize = size_of::<Self>() where Self: ?Leak; + //~^ ERROR the trait bound `Self: Leak` is not satisfied + } +} + +mod methods { + use crate::*; + + trait Trait { + fn leak_foo(&self) {} + fn maybe_leak_foo(&self) where Self: ?Leak {} + fn mut_leak_foo(&mut self) {} + // there is no relax bound on corresponding Receiver impl + fn mut_maybe_leak_foo(&mut self) where Self: ?Leak {} + //~^ `&mut Self` cannot be used as the type of `self` without the `arbitrary_self_types` + } + + impl Trait for NonLeakS {} + impl Trait for LeakS {} + + fn foo() { + LeakS.leak_foo(); + LeakS.maybe_leak_foo(); + NonLeakS.leak_foo(); + //~^ ERROR the trait bound `NonLeakS: Leak` is not satisfied + NonLeakS.maybe_leak_foo(); + } +} + +fn main() {} diff --git a/tests/ui/traits/default_auto_traits/maybe-bounds-in-traits.stderr b/tests/ui/traits/default_auto_traits/maybe-bounds-in-traits.stderr new file mode 100644 index 00000000000..3dd8418b100 --- /dev/null +++ b/tests/ui/traits/default_auto_traits/maybe-bounds-in-traits.stderr @@ -0,0 +1,71 @@ +error[E0277]: the trait bound `NonLeakS: Leak` is not satisfied + --> $DIR/maybe-bounds-in-traits.rs:61:22 + | +LL | type Leak2 = NonLeakS; + | ^^^^^^^^ the trait `Leak` is not implemented for `NonLeakS` + | +note: required by a bound in `Test3::Leak2` + --> $DIR/maybe-bounds-in-traits.rs:61:9 + | +LL | type Leak2 = NonLeakS; + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Test3::Leak2` + +error[E0277]: the trait bound `Self: Leak` is not satisfied + --> $DIR/maybe-bounds-in-traits.rs:49:29 + | +LL | type MaybeLeakSelf: TestBase1<Self> where Self: ?Leak; + | ^^^^^^^^^^^^^^^ the trait `Leak` is not implemented for `Self` + | +note: required by a bound in `TestBase1` + --> $DIR/maybe-bounds-in-traits.rs:45:21 + | +LL | trait TestBase1<T: ?Sized> {} + | ^ required by this bound in `TestBase1` +help: consider further restricting `Self` + | +LL | trait Test1<T>: Leak { + | ++++++ + +error[E0658]: `&mut Self` cannot be used as the type of `self` without the `arbitrary_self_types` feature + --> $DIR/maybe-bounds-in-traits.rs:99:31 + | +LL | fn mut_maybe_leak_foo(&mut self) where Self: ?Leak {} + | ^^^^^^^^^ + | + = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information + = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>` + +error[E0277]: the trait bound `Self: Leak` is not satisfied + --> $DIR/maybe-bounds-in-traits.rs:86:43 + | +LL | const CNonLeak: usize = size_of::<Self>() where Self: ?Leak; + | ^^^^ the trait `Leak` is not implemented for `Self` + | +note: required by a bound in `size_of` + --> $DIR/maybe-bounds-in-traits.rs:80:22 + | +LL | const fn size_of<T: ?Sized>() -> usize { + | ^ required by this bound in `size_of` +help: consider further restricting `Self` + | +LL | trait Trait: Leak { + | ++++++ + +error[E0277]: the trait bound `NonLeakS: Leak` is not satisfied + --> $DIR/maybe-bounds-in-traits.rs:109:18 + | +LL | NonLeakS.leak_foo(); + | ^^^^^^^^ the trait `Leak` is not implemented for `NonLeakS` + | +note: required by a bound in `methods::Trait::leak_foo` + --> $DIR/maybe-bounds-in-traits.rs:95:9 + | +LL | fn leak_foo(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Trait::leak_foo` + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0277, E0658. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/solver-cycles/129541-recursive-struct.rs b/tests/ui/traits/solver-cycles/129541-recursive-struct.rs index 1f5d0a772a2..723179302e3 100644 --- a/tests/ui/traits/solver-cycles/129541-recursive-struct.rs +++ b/tests/ui/traits/solver-cycles/129541-recursive-struct.rs @@ -4,7 +4,6 @@ //@ ignore-compare-mode-next-solver (explicit revisions) //@[unique_next] compile-flags: -Znext-solver //@[multiple_next] compile-flags: -Znext-solver -//@ error-pattern: reached the recursion limit finding the struct tail for `<[Hello] as Normalize>::Assoc` trait Bound {} trait Normalize { @@ -25,3 +24,5 @@ struct Hello { } fn main() {} + +//~? ERROR reached the recursion limit finding the struct tail for `<[Hello] as Normalize>::Assoc` diff --git a/tests/ui/treat-err-as-bug/panic-causes-oom-112708.rs b/tests/ui/treat-err-as-bug/panic-causes-oom-112708.rs index 0b75bb23faf..cfb2d7c5218 100644 --- a/tests/ui/treat-err-as-bug/panic-causes-oom-112708.rs +++ b/tests/ui/treat-err-as-bug/panic-causes-oom-112708.rs @@ -6,5 +6,5 @@ fn main() { #[deny(while_true)] - while true {} + while true {} //~ ERROR denote infinite loops with `loop { ... }` } diff --git a/tests/ui/treat-err-as-bug/span_delayed_bug.rs b/tests/ui/treat-err-as-bug/span_delayed_bug.rs index 88a9d07c94c..a242d11129f 100644 --- a/tests/ui/treat-err-as-bug/span_delayed_bug.rs +++ b/tests/ui/treat-err-as-bug/span_delayed_bug.rs @@ -9,4 +9,4 @@ #![feature(rustc_attrs)] #[rustc_delayed_bug_from_inside_query] -fn main() {} +fn main() {} //~ ERROR delayed bug triggered by #[rustc_delayed_bug_from_inside_query] diff --git a/tests/ui/type/issue-91268.rs b/tests/ui/type/issue-91268.rs index 16d5b241145..6297880702e 100644 --- a/tests/ui/type/issue-91268.rs +++ b/tests/ui/type/issue-91268.rs @@ -1,5 +1,6 @@ -//@ error-pattern: this file contains an unclosed delimiter // ignore-tidy-trailing-newlines // `ţ` must be the last character in this file, it cannot be followed by a newline + +//~vv ERROR this file contains an unclosed delimiter fn main() { 0: u8(ţ \ No newline at end of file diff --git a/tests/ui/type/issue-91268.stderr b/tests/ui/type/issue-91268.stderr index 395559442d1..db7b5a188cf 100644 --- a/tests/ui/type/issue-91268.stderr +++ b/tests/ui/type/issue-91268.stderr @@ -1,5 +1,5 @@ error: this file contains an unclosed delimiter - --> $DIR/issue-91268.rs:5:12 + --> $DIR/issue-91268.rs:6:12 | LL | fn main() { | - unclosed delimiter diff --git a/tests/ui/type/type-arg-out-of-scope.rs b/tests/ui/type/type-arg-out-of-scope.rs index 3f8a6ff1016..05ed54ec832 100644 --- a/tests/ui/type/type-arg-out-of-scope.rs +++ b/tests/ui/type/type-arg-out-of-scope.rs @@ -1,5 +1,6 @@ -//@ error-pattern:can't use generic parameters from outer item fn foo<T>(x: T) { fn bar(f: Box<dyn FnMut(T) -> T>) { } + //~^ ERROR can't use generic parameters from outer item + //~| ERROR can't use generic parameters from outer item } fn main() { foo(1); } diff --git a/tests/ui/type/type-arg-out-of-scope.stderr b/tests/ui/type/type-arg-out-of-scope.stderr index 8665001e243..fcaaca1770f 100644 --- a/tests/ui/type/type-arg-out-of-scope.stderr +++ b/tests/ui/type/type-arg-out-of-scope.stderr @@ -1,5 +1,5 @@ error[E0401]: can't use generic parameters from outer item - --> $DIR/type-arg-out-of-scope.rs:3:29 + --> $DIR/type-arg-out-of-scope.rs:2:29 | LL | fn foo<T>(x: T) { | - type parameter from outer item @@ -9,7 +9,7 @@ LL | fn bar(f: Box<dyn FnMut(T) -> T>) { } | help: try introducing a local generic parameter here: `<T>` error[E0401]: can't use generic parameters from outer item - --> $DIR/type-arg-out-of-scope.rs:3:35 + --> $DIR/type-arg-out-of-scope.rs:2:35 | LL | fn foo<T>(x: T) { | - type parameter from outer item diff --git a/tests/ui/typeck/issue-91334.rs b/tests/ui/typeck/issue-91334.rs index ec0d4ad70f1..c820014ff93 100644 --- a/tests/ui/typeck/issue-91334.rs +++ b/tests/ui/typeck/issue-91334.rs @@ -1,7 +1,7 @@ // Regression test for the ICE described in issue #91334. -//@ error-pattern: this file contains an unclosed delimiter - #![feature(coroutines)] +//~vv ERROR mismatched closing delimiter: `)` +//~v ERROR this file contains an unclosed delimiter fn f(){||yield(((){), diff --git a/tests/ui/typeck/output-type-mismatch.rs b/tests/ui/typeck/output-type-mismatch.rs index d5691c9c353..0d7c7d1dfe1 100644 --- a/tests/ui/typeck/output-type-mismatch.rs +++ b/tests/ui/typeck/output-type-mismatch.rs @@ -1,5 +1,3 @@ -//@ error-pattern: mismatched types - fn f() { } -fn main() { let i: isize; i = f(); } +fn main() { let i: isize; i = f(); } //~ ERROR mismatched types diff --git a/tests/ui/typeck/output-type-mismatch.stderr b/tests/ui/typeck/output-type-mismatch.stderr index c6df6650654..ba50cd4e6d7 100644 --- a/tests/ui/typeck/output-type-mismatch.stderr +++ b/tests/ui/typeck/output-type-mismatch.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/output-type-mismatch.rs:5:31 + --> $DIR/output-type-mismatch.rs:3:31 | LL | fn main() { let i: isize; i = f(); } | ----- ^^^ expected `isize`, found `()` diff --git a/tests/ui/typeck/while-type-error.rs b/tests/ui/typeck/while-type-error.rs index ca3b8921f54..abc607516e6 100644 --- a/tests/ui/typeck/while-type-error.rs +++ b/tests/ui/typeck/while-type-error.rs @@ -1,3 +1 @@ -//@ error-pattern: mismatched types - -fn main() { while main { } } +fn main() { while main { } } //~ ERROR mismatched types diff --git a/tests/ui/typeck/while-type-error.stderr b/tests/ui/typeck/while-type-error.stderr index b67ec561531..4bd86aafc17 100644 --- a/tests/ui/typeck/while-type-error.stderr +++ b/tests/ui/typeck/while-type-error.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/while-type-error.rs:3:19 + --> $DIR/while-type-error.rs:1:19 | LL | fn main() { while main { } } | ^^^^ expected `bool`, found fn item diff --git a/tests/ui/typeck/wrong-ret-type.rs b/tests/ui/typeck/wrong-ret-type.rs index b83aefad1e9..2d6751a823c 100644 --- a/tests/ui/typeck/wrong-ret-type.rs +++ b/tests/ui/typeck/wrong-ret-type.rs @@ -1,3 +1,2 @@ -//@ error-pattern: mismatched types -fn mk_int() -> usize { let i: isize = 3; return i; } +fn mk_int() -> usize { let i: isize = 3; return i; } //~ ERROR mismatched types fn main() { } diff --git a/tests/ui/typeck/wrong-ret-type.stderr b/tests/ui/typeck/wrong-ret-type.stderr index 33a094ce95d..918eb2d5c88 100644 --- a/tests/ui/typeck/wrong-ret-type.stderr +++ b/tests/ui/typeck/wrong-ret-type.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/wrong-ret-type.rs:2:49 + --> $DIR/wrong-ret-type.rs:1:49 | LL | fn mk_int() -> usize { let i: isize = 3; return i; } | ----- ^ expected `usize`, found `isize` diff --git a/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.rs b/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.rs index 7bd4df47220..9304e20b429 100644 --- a/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.rs +++ b/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.rs @@ -1,6 +1,6 @@ +//~ ERROR unknown lint: `test_unstable_lint` //@ check-fail //@ compile-flags: -Dunknown_lints -Atest_unstable_lint -//@ error-pattern: unknown lint: `test_unstable_lint` //@ error-pattern: the `test_unstable_lint` lint is unstable fn main() {} diff --git a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.rs b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.rs index 995f65ef83d..76983419c68 100644 --- a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.rs +++ b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.rs @@ -1,6 +1,6 @@ +//~ WARN unknown lint: `test_unstable_lint` //@ check-pass //@ compile-flags: -Wunknown_lints -Atest_unstable_lint -//@ error-pattern: unknown lint: `test_unstable_lint` //@ error-pattern: the `test_unstable_lint` lint is unstable fn main() {} diff --git a/tests/ui/use/use-meta-mismatch.rs b/tests/ui/use/use-meta-mismatch.rs index 2c5ae9cd9a1..8d15e46375c 100644 --- a/tests/ui/use/use-meta-mismatch.rs +++ b/tests/ui/use/use-meta-mismatch.rs @@ -1,5 +1,3 @@ -//@ error-pattern:can't find crate for `fake_crate` - -extern crate fake_crate as extra; +extern crate fake_crate as extra; //~ ERROR can't find crate for `fake_crate` fn main() { } diff --git a/tests/ui/use/use-meta-mismatch.stderr b/tests/ui/use/use-meta-mismatch.stderr index b793229e5fd..ffc471fa722 100644 --- a/tests/ui/use/use-meta-mismatch.stderr +++ b/tests/ui/use/use-meta-mismatch.stderr @@ -1,5 +1,5 @@ error[E0463]: can't find crate for `fake_crate` - --> $DIR/use-meta-mismatch.rs:3:1 + --> $DIR/use-meta-mismatch.rs:1:1 | LL | extern crate fake_crate as extra; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't find crate diff --git a/tests/ui/windows-subsystem/windows-subsystem-invalid.rs b/tests/ui/windows-subsystem/windows-subsystem-invalid.rs index c6a6dd00a92..4dadfc6fd5d 100644 --- a/tests/ui/windows-subsystem/windows-subsystem-invalid.rs +++ b/tests/ui/windows-subsystem/windows-subsystem-invalid.rs @@ -1,5 +1,5 @@ -//@ error-pattern: invalid windows subsystem `wrong`, only `windows` and `console` are allowed - #![windows_subsystem = "wrong"] fn main() {} + +//~? ERROR invalid windows subsystem `wrong` diff --git a/triagebot.toml b/triagebot.toml index e2b9e321a48..4abd164080b 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1125,6 +1125,7 @@ contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" users_on_vacation = [ "jyn514", "saethlin", + "Noratrieb", ] [[assign.warn_non_default_branch.exceptions]] |
