diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 53df848459e32..833a933ed467a 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -4239,11 +4239,20 @@ pub struct TestBinderBody { pub span: Span, pub foralls: ThinVec, pub exists: ThinVec, + pub region_equalities: Vec, pub constraints: Vec, /// These are not where clauses, but rather predicates within the body to be proven pub predicates: Vec, } +#[derive(Clone, Encodable, Decodable, Debug, Walkable)] +pub struct TestBinderRegionEquality { + #[visitable(extra = LifetimeCtxt::Bound)] + pub lhs: Lifetime, + #[visitable(extra = LifetimeCtxt::Bound)] + pub rhs: Lifetime, +} + #[derive(Clone, Encodable, Decodable, Debug, Walkable)] pub struct TestBinderForall { pub span: Span, diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index e6305995016fe..f0e5e54c114c4 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -560,6 +560,7 @@ macro_rules! common_visitor_and_walkers { StructExpr, StructRest, Term, + TestBinderRegionEquality, Trait, TraitBoundModifiers, TraitObjectSyntax, diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index b2cb1718b86a3..dbed9093fc29b 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -1,5 +1,5 @@ use rustc_ast::{Block, BlockCheckMode, Local, LocalKind, Stmt, StmtKind}; -use rustc_attr_ir::target::Target; +use rustc_attr_ir::target::{AstTarget, Target}; use rustc_hir as hir; use rustc_span::sym; use smallvec::SmallVec; @@ -37,7 +37,7 @@ impl<'hir> LoweringContext<'_, 'hir> { match &s.kind { StmtKind::Let(local) => { let hir_id = self.lower_node_id(s.id); - let local = self.lower_local(local); + let local = self.lower_local(local, &s); self.alias_attrs(hir_id, local.hir_id); let kind = hir::StmtKind::Let(local); let span = self.lower_span(s.span); @@ -88,7 +88,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - fn lower_local(&mut self, l: &Local) -> &'hir hir::LetStmt<'hir> { + fn lower_local(&mut self, l: &Local, s: &Stmt) -> &'hir hir::LetStmt<'hir> { // Let statements are allowed to have impl trait in bindings. let super_ = l.super_.map(|span| self.lower_span(span)); let ty = l.ty.as_ref().map(|t| { @@ -104,7 +104,7 @@ impl<'hir> LoweringContext<'_, 'hir> { }; let span = self.lower_span(l.span); let source = hir::LocalSource::Normal; - self.lower_attrs(hir_id, &l.attrs, l.span, Target::Statement); + self.lower_attrs(hir_id, &l.attrs, l.span, Target::Statement, AstTarget::Statement(s)); self.arena.alloc(hir::LetStmt { hir_id, super_, ty, pat, init, els, span, source }) } diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index c10ad4b2a398c..d4328d75faad3 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -6,7 +6,7 @@ use rustc_ast::node_id::NodeMap; use rustc_ast::visit::{Visitor, walk_expr}; use rustc_ast::*; use rustc_attr_ir::lang_items::LangItem; -use rustc_attr_ir::target::Target; +use rustc_attr_ir::target::{AstTarget, Target}; use rustc_errors::msg; use rustc_hir as hir; use rustc_hir::HirId; @@ -231,7 +231,13 @@ impl<'hir> LoweringContext<'_, 'hir> { let old_attrs = self.curr_owner.attrs.get(&ex.hir_id.local_id).copied().unwrap_or(&[]); let new_attrs = self - .lower_attrs_vec(&e.attrs, e.span, ex.hir_id, Target::from_expr(e), None) + .lower_attrs_vec( + &e.attrs, + e.span, + ex.hir_id, + Target::from_expr(e), + AstTarget::Expression(e), + ) .into_iter() .chain(old_attrs.iter().cloned()); let new_attrs = &*self.arena.alloc_from_iter(new_attrs); @@ -255,7 +261,13 @@ impl<'hir> LoweringContext<'_, 'hir> { } let expr_hir_id = self.lower_node_id(e.id); - self.lower_attrs(expr_hir_id, &e.attrs, e.span, Target::from_expr(e)); + self.lower_attrs( + expr_hir_id, + &e.attrs, + e.span, + Target::from_expr(e), + AstTarget::Expression(e), + ); let kind = match &e.kind { ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)), @@ -480,8 +492,8 @@ impl<'hir> LoweringContext<'_, 'hir> { ExprKind::Continue(opt_label) => { hir::ExprKind::Continue(self.lower_jump_destination(e.id, *opt_label)) } - ExprKind::Ret(e) => { - let expr = e.as_ref().map(|x| self.lower_expr(x)); + ExprKind::Ret(box_e) => { + let expr = box_e.as_ref().map(|x| self.lower_expr(x)); self.checked_return(expr) } ExprKind::Yeet(sub_expr) => self.lower_expr_yeet(e.span, sub_expr.as_deref()), @@ -795,7 +807,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let guard = arm.guard.as_ref().map(|guard| self.lower_expr(&guard.cond)); let hir_id = self.next_id(); let span = self.lower_span(arm.span); - self.lower_attrs(hir_id, &arm.attrs, arm.span, Target::Arm); + self.lower_attrs(hir_id, &arm.attrs, arm.span, Target::Arm, AstTarget::Arm(arm)); let is_never_pattern = pat.is_never_pattern(); // We need to lower the body even if it's unneeded for never pattern in match, // ensure that we can get HirId for DefId if need (issue #137708). @@ -1659,7 +1671,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_expr_field(&mut self, f: &ExprField) -> hir::ExprField<'hir> { let hir_id = self.lower_node_id(f.id); - self.lower_attrs(hir_id, &f.attrs, f.span, Target::ExprField); + self.lower_attrs(hir_id, &f.attrs, f.span, Target::ExprField, AstTarget::ExprField(f)); hir::ExprField { hir_id, ident: self.lower_ident(f.ident), @@ -1926,7 +1938,13 @@ impl<'hir> LoweringContext<'_, 'hir> { // // Also, add the attributes to the outer returned expr node. let expr = self.expr_drop_temps_mut(for_span, match_expr); - self.lower_attrs(expr.hir_id, &e.attrs, e.span, Target::from_expr(e)); + self.lower_attrs( + expr.hir_id, + &e.attrs, + e.span, + Target::from_expr(e), + AstTarget::Expression(e), + ); expr } diff --git a/compiler/rustc_ast_lowering/src/expr/closure.rs b/compiler/rustc_ast_lowering/src/expr/closure.rs index 5924d53dd11e4..808248db3204e 100644 --- a/compiler/rustc_ast_lowering/src/expr/closure.rs +++ b/compiler/rustc_ast_lowering/src/expr/closure.rs @@ -1,6 +1,6 @@ use rustc_ast::*; use rustc_attr_ir::find_attr; -use rustc_attr_ir::target::Target; +use rustc_attr_ir::target::{AstTarget, Target}; use rustc_hir as hir; use rustc_hir::HirId; use rustc_span::{Span, span_bug}; @@ -20,7 +20,13 @@ impl<'hir> LoweringContext<'_, 'hir> { closure: &Closure, ) -> hir::Expr<'hir> { let expr_hir_id = self.lower_node_id(e.id); - let attrs = self.lower_attrs(expr_hir_id, &e.attrs, e.span, Target::from_expr(e)); + let attrs = self.lower_attrs( + expr_hir_id, + &e.attrs, + e.span, + Target::from_expr(e), + AstTarget::Closure(closure), + ); match closure.coroutine_marker { Some(coroutine_marker) => self.lower_expr_coroutine_closure_with_move_exprs( diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 296b0887f6002..51f1aa2f4c81e 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1,7 +1,7 @@ use rustc_abi::ExternAbi; use rustc_ast::visit::AssocCtxt; use rustc_ast::*; -use rustc_attr_ir::target::Target; +use rustc_attr_ir::target::{AstTarget, Target}; use rustc_attr_ir::{AttributeKind, EiiImplResolution, find_attr}; use rustc_errors::{E0570, ErrorGuaranteed, struct_span_code_err}; use rustc_hir::def::{DefKind, Res}; @@ -165,7 +165,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &i.attrs, i.span, Target::from_ast_item(i), - Some(i), + AstTarget::from_ast_item(&i.kind), &extra_hir_attributes, ); @@ -614,8 +614,13 @@ impl<'hir> LoweringContext<'_, 'hir> { pub(super) fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> { let owner_id = self.curr_owner.owner_id(); let hir_id: HirId = owner_id.into(); - let attrs = - self.lower_attrs(hir_id, &i.attrs, i.span, Target::from_foreign_item_kind(&i.kind)); + let attrs = self.lower_attrs( + hir_id, + &i.attrs, + i.span, + Target::from_foreign_item_kind(&i.kind), + AstTarget::from_foreign_item_kind(&i.kind), + ); let (ident, kind) = match &i.kind { ForeignItemKind::Fn(Fn { sig, ident, generics, define_opaque, .. }) => { let fdec = &sig.decl; @@ -693,7 +698,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.dcx().span_fatal(v.span, "unnamed enum variants are not yet implemented"); } let hir_id = self.lower_node_id(v.id); - self.lower_attrs(hir_id, &v.attrs, v.span, Target::Variant); + self.lower_attrs(hir_id, &v.attrs, v.span, Target::Variant, AstTarget::Variant(v)); hir::Variant { hir_id, def_id: self.local_def_id(v.id), @@ -780,7 +785,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let ty = self.lower_ty_alloc(&f.ty, ImplTraitContext::Disallowed(ImplTraitPosition::FieldTy)); let hir_id = self.lower_node_id(f.id); - self.lower_attrs(hir_id, &f.attrs, f.span, Target::Field); + self.lower_attrs(hir_id, &f.attrs, f.span, Target::Field, AstTarget::Field(f)); hir::FieldDef { span: self.lower_span(f.span), hir_id, @@ -808,6 +813,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &i.attrs, i.span, Target::from_assoc_item_kind(&i.kind, AssocCtxt::Trait), + AstTarget::from_assoc_item_kind(&i.kind), ); let (ident, generics, kind, has_value) = match &i.kind { @@ -1070,6 +1076,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &i.attrs, i.span, Target::from_assoc_item_kind(&i.kind, AssocCtxt::Impl { of_trait: is_in_trait_impl }), + AstTarget::from_assoc_item_kind(&i.kind), ); let (ident, (generics, kind)) = match &i.kind { @@ -1238,7 +1245,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_param(&mut self, param: &Param) -> hir::Param<'hir> { let hir_id = self.lower_node_id(param.id); - self.lower_attrs(hir_id, ¶m.attrs, param.span, Target::Param); + self.lower_attrs(hir_id, ¶m.attrs, param.span, Target::Param, AstTarget::Param(param)); hir::Param { hir_id, pat: self.lower_pat(¶m.pat), @@ -1948,7 +1955,13 @@ impl<'hir> LoweringContext<'_, 'hir> { ) -> hir::WherePredicate<'hir> { let hir_id = self.lower_node_id(pred.id); let span = self.lower_span(pred.span); - self.lower_attrs(hir_id, &pred.attrs, span, Target::WherePredicate); + self.lower_attrs( + hir_id, + &pred.attrs, + span, + Target::WherePredicate, + AstTarget::WherePredicate(pred), + ); let kind = self.arena.alloc(match &pred.kind { WherePredicateKind::BoundPredicate(WhereBoundPredicate { bound_generic_params, @@ -2008,6 +2021,13 @@ impl<'hir> LoweringContext<'_, 'hir> { let exists = self.arena.alloc_from_iter( body.exists.iter().map(|exists| self.lower_test_binder_exists(exists)), ); + let region_equalities = self.arena.alloc_from_iter(body.region_equalities.iter().map( + |TestBinderRegionEquality { lhs, rhs }| { + let lhs = self.lower_lifetime(lhs, LifetimeSource::Other, lhs.ident.into()); + let rhs = self.lower_lifetime(rhs, LifetimeSource::Other, rhs.ident.into()); + (lhs, rhs) + }, + )); let constraints = self.lower_test_binder_constraints_as_and(&body.constraints); let mut dedup_map = Default::default(); let predicates = self.arena.alloc_from_iter( @@ -2016,7 +2036,7 @@ impl<'hir> LoweringContext<'_, 'hir> { .map(|predicate| self.lower_where_predicate(predicate, &[], &mut dedup_map)), ); let span = self.lower_span(body.span); - hir::TestBinderBody { foralls, exists, constraints, predicates, span } + hir::TestBinderBody { span, foralls, exists, region_equalities, constraints, predicates } } fn lower_test_binder_forall( diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index c68fcb18427c5..76da5a3306b58 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -47,7 +47,7 @@ use rustc_ast::visit::{self, Visitor}; use rustc_ast::{self as ast, *}; use rustc_attr_ir::find_attr; use rustc_attr_ir::lang_items::LangItem; -use rustc_attr_ir::target::Target; +use rustc_attr_ir::target::{AstTarget, Target}; use rustc_attr_parsing::{AttributeParser, Recovery, ShouldEmit}; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sorted_map::SortedMap; @@ -762,7 +762,13 @@ fn lower_to_hir(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::MaybeOwner<'_> { AstOwner::Crate(c) => with_lctx(tcx, &*resolver, CRATE_NODE_ID, |lctx| { debug_assert_eq!(lctx.curr_owner.owner_id(), CRATE_OWNER_ID); let module = lctx.lower_mod(&c.items, &c.spans); - lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs, c.spans.inner_span, Target::Crate); + lctx.lower_attrs( + hir::CRATE_HIR_ID, + &c.attrs, + c.spans.inner_span, + Target::Crate, + AstTarget::Crate(c), + ); hir::OwnerNode::Crate(module) }), AstOwner::Item(item) => { @@ -1149,8 +1155,9 @@ impl<'hir> LoweringContext<'_, 'hir> { attrs: &[Attribute], target_span: Span, target: Target, + ast_target: AstTarget<'_>, ) -> &'hir [rustc_attr_ir::Attribute] { - self.lower_attrs_with_extra(id, attrs, target_span, target, None, &[]) + self.lower_attrs_with_extra(id, attrs, target_span, target, ast_target, &[]) } fn lower_attrs_with_extra( @@ -1159,14 +1166,14 @@ impl<'hir> LoweringContext<'_, 'hir> { attrs: &[Attribute], target_span: Span, target: Target, - target_item: Option<&ast::Item>, + ast_target: AstTarget<'_>, extra_hir_attributes: &[rustc_attr_ir::Attribute], ) -> &'hir [rustc_attr_ir::Attribute] { if attrs.is_empty() && extra_hir_attributes.is_empty() { &[] } else { let mut lowered_attrs = - self.lower_attrs_vec(attrs, self.lower_span(target_span), id, target, target_item); + self.lower_attrs_vec(attrs, self.lower_span(target_span), id, target, ast_target); lowered_attrs.extend(extra_hir_attributes.iter().cloned()); assert_eq!(id.owner, self.curr_owner.owner_id()); @@ -1193,14 +1200,14 @@ impl<'hir> LoweringContext<'_, 'hir> { target_span: Span, target_hir_id: HirId, target: Target, - target_item: Option<&ast::Item>, + ast_target: AstTarget<'_>, ) -> Vec { let l = self.span_lowerer(); self.attribute_parser.parse_attribute_list( attrs, target_span, target, - target_item, + ast_target, |s| l.lower(s), |lint_id, span, kind| { self.curr_owner.delayed_lints.push(DelayedLint { @@ -1993,7 +2000,26 @@ impl<'hir> LoweringContext<'_, 'hir> { colon_span: None, source: hir::GenericParamSource::Generics, }; - self.lower_attrs(hir_id, ¶m.attrs, param.span, Target::from(&generic_param)); + let ast_generic_param = ast::GenericParam { + id: param.id, + ident, + attrs: param.attrs.clone(), + bounds: Default::default(), + is_placeholder: false, + kind: ast::GenericParamKind::Const { + ty: param.ty.clone(), + span: param.span, + default: None, + }, + colon_span: None, + }; + self.lower_attrs( + hir_id, + ¶m.attrs, + param.span, + Target::from(&generic_param), + AstTarget::GenericParam(&ast_generic_param), + ); self.curr_owner.const_defs.push(generic_param); return None; } @@ -2001,7 +2027,13 @@ impl<'hir> LoweringContext<'_, 'hir> { // FIXME This uses `fn_hir_id`, which is not correct, it should use the parameter hir id instead // The parameter is currently not lowered for functions without bodies, so there is no place to store the lowered hir id // This should be fixed by storing function parameters in the `hir::FnSig` instead of `hir::Body` - self.lower_attrs(fn_hir_id, ¶m.attrs, param.span, Target::Param); + self.lower_attrs( + fn_hir_id, + ¶m.attrs, + param.span, + Target::Param, + AstTarget::Param(param), + ); } let itctx = match kind { FnDeclKind::Fn | FnDeclKind::Inherent | FnDeclKind::Impl | FnDeclKind::Trait => { @@ -2318,7 +2350,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let hir_id = self.lower_node_id(param.id); let param_attrs = ¶m.attrs; let param_span = param.span(); - let param = hir::GenericParam { + let param_hir = hir::GenericParam { hir_id, def_id: self.local_def_id(param.id), name, @@ -2328,8 +2360,14 @@ impl<'hir> LoweringContext<'_, 'hir> { colon_span: param.colon_span.map(|s| self.lower_span(s)), source, }; - self.lower_attrs(hir_id, param_attrs, param_span, Target::from(¶m)); - param + self.lower_attrs( + hir_id, + param_attrs, + param_span, + Target::from(¶m_hir), + AstTarget::GenericParam(param), + ); + param_hir } fn lower_generic_param_kind( @@ -2932,7 +2970,13 @@ impl<'hir> LoweringContext<'_, 'hir> { // FIXME(mgca): This might result in lowering attributes that // then go unused as the `Target::ExprField` is not actually // corresponding to `Node::ExprField`. - self.lower_attrs(hir_id, &f.attrs, f.span, Target::ExprField); + self.lower_attrs( + hir_id, + &f.attrs, + f.span, + Target::ExprField, + AstTarget::ExprField(f), + ); let expr = self.lower_expr_to_const_arg_direct(&f.expr, None); hir::ConstArgExprField { diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index df3d7b1a3c0a6..cce1b7039e7b2 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -2,7 +2,7 @@ use std::sync::Arc; use rustc_ast::*; use rustc_attr_ir::lang_items::LangItem; -use rustc_attr_ir::target::Target; +use rustc_attr_ir::target::{AstTarget, Target}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_span::{DesugaringKind, Ident, Span, Spanned, respan, span_bug}; @@ -92,7 +92,13 @@ impl<'hir> LoweringContext<'_, 'hir> { let fs = self.arena.alloc_from_iter(fields.iter().map(|f| { let hir_id = self.lower_node_id(f.id); - self.lower_attrs(hir_id, &f.attrs, f.span, Target::PatField); + self.lower_attrs( + hir_id, + &f.attrs, + f.span, + Target::PatField, + AstTarget::Pat(pattern), + ); hir::PatField { hir_id, diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index f410a9d280347..0dfd0f10f920e 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use rustc_ast::{self as ast, *}; -use rustc_attr_ir::target::Target; +use rustc_attr_ir::target::{AstTarget, Target}; use rustc_errors::StashKey; use rustc_hir::def::{DefKind, PerNS, Res}; use rustc_hir::def_id::DefId; @@ -523,7 +523,13 @@ impl<'hir> LoweringContext<'_, 'hir> { // FIXME uses the segments HIR id which is not correct, it should // be the parameters HIR id instead. This is currently not lowered. for input in inputs { - self.lower_attrs(segment_hir_id, &input.attrs, input.span, Target::Param); + self.lower_attrs( + segment_hir_id, + &input.attrs, + input.span, + Target::Param, + AstTarget::Param(input), + ); } let inputs = self.arena.alloc_from_iter(inputs.iter().map(|param| { diff --git a/compiler/rustc_attr_ir/src/target.rs b/compiler/rustc_attr_ir/src/target.rs index c41e78c4a96e0..180f03f60fc85 100644 --- a/compiler/rustc_attr_ir/src/target.rs +++ b/compiler/rustc_attr_ir/src/target.rs @@ -2,9 +2,76 @@ use std::fmt::{self, Display}; +use rustc_abi::ExternAbi; pub use rustc_ast::visit::AssocCtxt; -use rustc_ast::{AssocItemKind, ForeignItemKind, ast}; +use rustc_ast::{ + Arm, AssocItemKind, Closure, ConstBlockItem, ConstItem, Crate, EnumDef, Expr, ExprField, + FieldDef, Fn, ForeignItemKind, ForeignMod, GenericParam, Generics, Impl, InlineAsm, MacroDef, + ModKind, Param, Pat, Safety, StaticItem, Stmt, Trait, TraitAlias, TyAlias, UseTree, Variant, + VariantData, WherePredicate, ast, +}; use rustc_macros::StableHash; +use rustc_span::{Ident, Symbol}; + +/// This enum lists all possible types of AST items. +#[derive(Clone, Copy, Debug)] +pub enum AstTarget<'a> { + // Target types that may correspond to different kinds of items. + Delegation, + MacroCall, + + // Target types that correspond exclusively to `AssocItem` kind. Mapping is obtained from `Target::from_assoc_item_kind`. + AssocConst(&'a ConstItem), + Method(&'a Fn), + AssocTy(&'a TyAlias), + + // Target types that correspond exclusively to `ForeignItem` kind. Mapping is obtained from `Target::from_foreign_item_kind`. + ForeignStatic(&'a StaticItem), + ForeignFn(&'a Fn), + ForeignTy(&'a TyAlias), + + // Target types that correspond exclusively to `Item` kind. Mapping is obtained from `Target::from_ast_item`. + ExternCrate(&'a Option, &'a Ident), + Use(&'a UseTree), + Static(&'a StaticItem), + Const(ConstTypeAstTarget<'a>), + Fn(&'a Fn), + Mod(&'a Safety, &'a Ident, &'a ModKind), + ForeignMod(&'a ForeignMod), + GlobalAsm(&'a InlineAsm), + TyAlias(&'a TyAlias), + Enum(&'a Ident, &'a Generics, &'a EnumDef), + Struct(&'a Ident, &'a Generics, &'a VariantData), + Union(&'a Ident, &'a Generics, &'a VariantData), + Trait(&'a Trait), + TraitAlias(&'a TraitAlias), + Impl(&'a Impl), + MacroDef(&'a Ident, &'a MacroDef), + + // Target types that correspond exclusively to `Expr` kind. Mapping is obtained from `Target::from_expr`. + Closure(&'a Closure), + Expression(&'a Expr), + + Arm(&'a Arm), + Crate(&'a Crate), + ExprField(&'a ExprField), + Field(&'a FieldDef), + GenericParam(&'a GenericParam), + Param(&'a Param), + Pat(&'a Pat), + Statement(&'a Stmt), + Variant(&'a Variant), + WherePredicate(&'a WherePredicate), + + // Only reserved for cases when it is not possible to obtain detailed Ast Target + None, +} + +#[derive(Clone, Copy, Debug)] +pub enum ConstTypeAstTarget<'a> { + ConstItem(&'a ConstItem), + ConstBlockItem(&'a ConstBlockItem), +} #[derive(Copy, Clone, PartialEq, Debug, Eq, StableHash)] pub enum MethodKind { @@ -19,6 +86,8 @@ pub enum MethodKind { Inherent, } +// FIXME(rtjkro): `AstTarget` has nearly one-to-one mapping with `Target`, barring the extra fields from `AssocConst`, `Method`, and `AssocTy`. +// In the future, remove `Target` and use `AstTarget` instead. #[derive(Copy, Clone, PartialEq, Debug, Eq, StableHash)] pub enum Target { ExternCrate, @@ -65,6 +134,82 @@ pub enum Target { Break, } +impl<'a> AstTarget<'a> { + pub fn get_abi(&self) -> Option { + let ext = match self { + AstTarget::Method(fn_item) => fn_item.sig.header.ext, + AstTarget::Fn(fn_item) => fn_item.sig.header.ext, + AstTarget::ForeignFn(fn_item) => fn_item.sig.header.ext, + _ => return None, + }; + + match ext { + ast::Extern::None => Some(ExternAbi::Rust), + ast::Extern::Implicit(_) => Some(ExternAbi::FALLBACK), + ast::Extern::Explicit(abi, _) => Some(abi.symbol_unescaped.as_str().parse().ok()?), + } + } + + pub fn get_fn_sig(&self) -> Option<&rustc_ast::ast::FnSig> { + match self { + AstTarget::Method(fn_item) => Some(&fn_item.sig), + AstTarget::Fn(fn_item) => Some(&fn_item.sig), + AstTarget::ForeignFn(fn_item) => Some(&fn_item.sig), + _ => None, + } + } + + pub fn from_foreign_item_kind(kind: &'a ast::ForeignItemKind) -> Self { + match kind { + ForeignItemKind::Static(static_item) => AstTarget::ForeignStatic(static_item), + ForeignItemKind::Fn(f) => AstTarget::ForeignFn(f), + ForeignItemKind::TyAlias(ty_alias) => AstTarget::ForeignTy(ty_alias), + ForeignItemKind::MacCall(_) => AstTarget::MacroCall, + } + } + + pub fn from_assoc_item_kind(kind: &'a ast::AssocItemKind) -> Self { + match kind { + AssocItemKind::Const(const_item) => AstTarget::AssocConst(const_item), + AssocItemKind::Fn(f) => AstTarget::Method(f), + AssocItemKind::Type(type_alias) => AstTarget::AssocTy(type_alias), + AssocItemKind::Delegation(_) => AstTarget::Delegation, + AssocItemKind::DelegationMac(_) => AstTarget::Delegation, + AssocItemKind::MacCall(_) => AstTarget::MacroCall, + } + } + + pub fn from_ast_item(kind: &'a ast::ItemKind) -> Self { + match kind { + ast::ItemKind::ExternCrate(symbol, ident) => AstTarget::ExternCrate(symbol, ident), + ast::ItemKind::Use(use_tree) => AstTarget::Use(use_tree), + ast::ItemKind::Static(static_item) => AstTarget::Static(static_item), + ast::ItemKind::Const(const_item) => { + AstTarget::Const(ConstTypeAstTarget::ConstItem(const_item)) + } + ast::ItemKind::ConstBlock(const_block_item) => { + AstTarget::Const(ConstTypeAstTarget::ConstBlockItem(const_block_item)) + } + ast::ItemKind::Fn(f) => AstTarget::Fn(f), + ast::ItemKind::Mod(s, i, mk) => AstTarget::Mod(s, i, mk), + ast::ItemKind::ForeignMod(foreign_mod) => AstTarget::ForeignMod(foreign_mod), + ast::ItemKind::GlobalAsm(inline_asm) => AstTarget::GlobalAsm(inline_asm), + ast::ItemKind::TyAlias(ty_alias) => AstTarget::TyAlias(ty_alias), + ast::ItemKind::Enum(i, g, ed) => AstTarget::Enum(i, g, ed), + ast::ItemKind::Struct(i, g, vd) => AstTarget::Struct(i, g, vd), + ast::ItemKind::Union(i, g, vd) => AstTarget::Union(i, g, vd), + ast::ItemKind::Trait(trait_kind) => AstTarget::Trait(trait_kind), + ast::ItemKind::TraitAlias(trait_alias) => AstTarget::TraitAlias(trait_alias), + ast::ItemKind::Impl(i) => AstTarget::Impl(i), + ast::ItemKind::MacCall(..) => AstTarget::MacroCall, + ast::ItemKind::MacroDef(ident, macro_def) => AstTarget::MacroDef(ident, macro_def), + ast::ItemKind::Delegation(..) => AstTarget::Delegation, + ast::ItemKind::DelegationMac(..) => AstTarget::Delegation, + ast::ItemKind::TestBinderConstraints(..) => AstTarget::MacroCall, + } + } +} + impl Display for Target { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", Self::name(*self)) diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index bd30983cd69d4..0adc5751373b6 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -8,6 +8,7 @@ use rustc_structures::SanitizerSet; use super::prelude::*; use crate::attributes::AttributeSafety; +use crate::context::FinalizeCheckFn; use crate::diagnostics::{ EmptyExportName, EmptySection, NakedFunctionIncompatibleAttribute, NullOnExport, NullOnObjcClass, NullOnObjcSelector, NullOnSection, ObjcClassExpectedStringLiteral, @@ -327,6 +328,40 @@ impl AttributeParser for NakedParser { Some(AttributeKind::Naked(span)) } + + fn deferred_finalize_check(&self) -> Option<(FinalizeCheckFn, Span)> { + // FIXME(rtjkro): Currently, we're enum matching on `cx.target` instead of `cx.ast_target` + // because `AstTarget::Method` doesn't contain `MethodKind` yet. In the future, when this field is available to `AstTarget::Method`, + // update this check to use `cx.ast_target` instead of `cx.target`. + Some(( + |cx, _| match cx.target { + Target::Fn + | Target::Method( + MethodKind::Trait { body: true } | MethodKind::TraitImpl | MethodKind::Inherent, + ) => { + let fn_sig = + cx.ast_target.get_fn_sig().expect("missing fn signature for AST target"); + let Some(abi) = cx.ast_target.get_abi() else { + return; + }; + + if abi.is_rustic_abi() && !cx.features().naked_functions_rustic_abi() { + feature_err( + cx.sess(), + sym::naked_functions_rustic_abi, + fn_sig.span, + format!( + "`#[naked]` is currently unstable on `extern {abi}` functions", + ), + ) + .emit(); + } + } + _ => {} + }, + self.span?, + )) + } } pub(crate) struct TrackCallerParser; diff --git a/compiler/rustc_attr_parsing/src/attributes/doc.rs b/compiler/rustc_attr_parsing/src/attributes/doc.rs index 7dc5c6ce9f2b8..c7335c1aab171 100644 --- a/compiler/rustc_attr_parsing/src/attributes/doc.rs +++ b/compiler/rustc_attr_parsing/src/attributes/doc.rs @@ -14,8 +14,8 @@ use super::prelude::{ALL_TARGETS, AllowedTargets}; use super::{AcceptMapping, AttributeParser, template}; use crate::context::{AcceptContext, FinalizeContext}; use crate::diagnostics::{ - AttrCrateLevelOnly, DocAliasBadChar, DocAliasDuplicated, DocAliasEmpty, DocAliasMalformed, - DocAliasStartEnd, DocAttrNotCrateLevel, DocAttributeNotAttribute, DocAutoCfgExpectsHideOrShow, + DocAliasBadChar, DocAliasDuplicated, DocAliasEmpty, DocAliasMalformed, DocAliasStartEnd, + DocAttrNotCrateLevel, DocAttributeNotAttribute, DocAutoCfgExpectsHideOrShow, DocAutoCfgHideShowExpectsList, DocAutoCfgHideShowNoIdentBeforeValues, DocAutoCfgHideShowUnexpectedItem, DocAutoCfgHideShowUnexpectedItemAfterValues, DocAutoCfgHideShowValuesMix, DocAutoCfgWrongLiteral, DocInlineConflict, DocInlineOnlyUse, @@ -26,6 +26,7 @@ use crate::diagnostics::{ use crate::parser::{ ArgParser, MetaItemListParser, MetaItemOrLitParser, MetaItemParser, OwnedPathParser, }; +use crate::target_checking::Policy::Allow; fn check_keyword(cx: &mut AcceptContext<'_, '_>, keyword: Symbol, span: Span) -> bool { // FIXME: Once rustdoc can handle URL conflicts on case insensitive file systems, we @@ -63,15 +64,6 @@ fn check_attr_not_crate_level( true } -/// Checks that an attribute is used at the crate level. Returns `true` if valid. -fn check_attr_crate_level(cx: &mut AcceptContext<'_, '_>, span: Span) -> bool { - if cx.shared.target != Target::Crate { - cx.emit_lint(INVALID_DOC_ATTRIBUTES, AttrCrateLevelOnly, span); - return false; - } - true -} - // FIXME: To be removed once merged and replace with `cx.expected_name_value(span, _name)`. fn expected_name_value(cx: &mut AcceptContext<'_, '_>, span: Span, _name: Option) { cx.emit_lint(INVALID_DOC_ATTRIBUTES, ExpectedNameValue, span); @@ -163,9 +155,10 @@ impl DocParser { return; } - if !check_attr_crate_level(cx, path.span()) { - return; - } + cx.check_target( + sym::no_crate_inject.as_str(), + &AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]), + ); self.attribute.no_crate_inject = Some(path.span()) } @@ -552,9 +545,10 @@ impl DocParser { return; } let span = path.span(); - if !check_attr_crate_level(cx, span) { - return; - } + cx.check_target( + concat!("(", stringify!($ident), ")"), + &AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]), + ); self.attribute.$ident = Some(span); }}; } @@ -570,9 +564,10 @@ impl DocParser { return; }; - if !check_attr_crate_level(cx, path.span()) { - return; - } + cx.check_target( + s.as_str(), + &AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]), + ); // FIXME: It's errorring when the attribute is passed multiple times on the command // line. diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index ed911a63eb7fe..d5b2f7accb621 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -1,6 +1,6 @@ use rustc_abi::ExternAbi; -use rustc_ast::ItemKind; use rustc_attr_ir::AttributeKind::{LinkName, LinkOrdinal, LinkSection}; +use rustc_attr_ir::target::AstTarget; use rustc_attr_ir::*; use rustc_errors::msg; use rustc_feature::{AttributeStability, Features}; @@ -262,14 +262,10 @@ impl CombineAttributeParser for LinkParser { } fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) { - if cx.target != Target::ForeignMod { + let AstTarget::ForeignMod(fm) = cx.ast_target else { return; - } - - let item = cx.target_item.expect("missing AST target item for Target::ForeignMod"); - let ItemKind::ForeignMod(fm) = &item.kind else { - panic!("expected foreign module AST target item for Target::ForeignMod"); }; + let abi = fm.abi.map_or(ExternAbi::FALLBACK, |abi| { abi.symbol_unescaped.as_str().parse().unwrap_or_else(|_| { cx.dcx().span_delayed_bug( diff --git a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs index 8bb5e6b7fc270..8a0c31400b100 100644 --- a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs @@ -1,4 +1,4 @@ -use rustc_ast::ItemKind; +use rustc_attr_ir::target::AstTarget; use rustc_attr_ir::{MacroUseArgs, find_attr}; use rustc_feature::AttributeStability; use rustc_lint_defs::builtin::{INVALID_MACRO_EXPORT_ARGUMENTS, UNUSED_ATTRIBUTES}; @@ -181,14 +181,11 @@ impl SingleAttributeParser for MacroExportParser { } fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) { - if cx.target != Target::MacroDef { + let AstTarget::MacroDef(_, macro_def) = cx.ast_target else { return; - } + }; - let item = cx.target_item.unwrap(); - if let ItemKind::MacroDef(_, macro_def) = &item.kind - && !macro_def.macro_rules - { + if !macro_def.macro_rules { cx.emit_lint(UNUSED_ATTRIBUTES, MacroExport::OnDeclMacro, attr_span); } } diff --git a/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs b/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs index 2acba84956e67..c2f8875e440e7 100644 --- a/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs +++ b/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs @@ -1,4 +1,5 @@ -use rustc_ast::{ItemKind, VariantData}; +use rustc_ast::VariantData; +use rustc_attr_ir::target::AstTarget; use rustc_feature::AttributeStability; use super::prelude::*; @@ -22,13 +23,8 @@ impl NoArgsAttributeParser for NonExhaustiveParser { const CREATE: fn(Span) -> AttributeKind = AttributeKind::NonExhaustive; fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) { - if cx.target != Target::Struct { + let AstTarget::Struct(_, _, data) = cx.ast_target else { return; - } - - let item = cx.target_item.expect("missing AST target item for Target::Struct"); - let ItemKind::Struct(_, _, data) = &item.kind else { - panic!("expected struct AST target item for Target::Struct"); }; if let VariantData::Struct { fields, .. } = data && fields.iter().any(|f| f.default_value().is_some()) diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 52422a85041a4..e8bdce0df5b95 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -1,7 +1,8 @@ use std::path::PathBuf; -use rustc_ast::{GenericParamKind, ItemKind, LitIntType, LitKind, MetaItemLit}; +use rustc_ast::{GenericParamKind, LitIntType, LitKind, MetaItemLit}; use rustc_attr_ir::lang_items::LangItem; +use rustc_attr_ir::target::AstTarget; use rustc_attr_ir::{ BorrowckGraphvizFormatKind, CguFields, CguKind, RustcAssertVarianceKind, RustcCleanAttribute, RustcCleanQueries, RustcMirKind, @@ -171,13 +172,8 @@ impl SingleAttributeParser for RustcLegacyConstGenericsParser { } fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) { - if cx.target != Target::Fn { - // Invalid targets are already diagnosed by target checking. + let AstTarget::Fn(function) = cx.ast_target else { return; - } - let item = cx.target_item.expect("missing AST target item for Target::Fn"); - let ItemKind::Fn(function) = &item.kind else { - panic!("expected fn AST target item for Target::Fn"); }; let index_list = rustc_attr_ir::find_attr!(cx.parsed_attrs, RustcLegacyConstGenerics { fn_indexes, .. } => fn_indexes) .expect("missing parsed RustcLegacyConstGenerics attribute in finalize_check"); diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index f5e1868364355..172973633af4e 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -864,9 +864,8 @@ pub(crate) struct FinalizeCheckContext<'p, 'sess> { /// Unlike [`all_attrs`](Self::all_attrs), this contains the fully parsed attributes. pub(crate) parsed_attrs: &'p [Attribute], - /// The AST item these attributes were applied to, when the target is an item. - /// Used by `finalize_check` to inspect item structure that is not encoded in [`Target`]. - pub(crate) target_item: Option<&'p rustc_ast::ast::Item>, + /// The AST item these attributes were applied to. + pub(crate) ast_target: rustc_attr_ir::target::AstTarget<'p>, } impl<'p, 'sess: 'p> Deref for FinalizeCheckContext<'p, 'sess> { diff --git a/compiler/rustc_attr_parsing/src/diagnostics.rs b/compiler/rustc_attr_parsing/src/diagnostics.rs index b5bfbc9e3dc3b..2b41db75ed5bb 100644 --- a/compiler/rustc_attr_parsing/src/diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/diagnostics.rs @@ -320,13 +320,6 @@ pub(crate) struct DocTestUnknown { #[diag("`#![doc(test(...)]` does not take a literal")] pub(crate) struct DocTestLiteral; -#[derive(Diagnostic)] -#[diag("this attribute can only be applied at the crate level")] -#[note( - "read for more information" -)] -pub(crate) struct AttrCrateLevelOnly; - #[derive(Diagnostic)] #[diag("conflicting doc inlining attributes")] #[help("remove one of the conflicting attributes")] @@ -347,6 +340,13 @@ pub(crate) struct DocInlineOnlyUse { pub item_span: Span, } +#[derive(Diagnostic)] +#[diag("this attribute can only be applied at the crate level")] +#[note( + "read for more information" +)] +pub(crate) struct AttrCrateLevelOnly; + #[derive(Diagnostic)] #[diag("`#[diagnostic::do_not_recommend]` does not expect any arguments")] pub(crate) struct DoNotRecommendDoesNotExpectArgs; diff --git a/compiler/rustc_attr_parsing/src/interface.rs b/compiler/rustc_attr_parsing/src/interface.rs index 6895dda06cb6a..e2f56541e70db 100644 --- a/compiler/rustc_attr_parsing/src/interface.rs +++ b/compiler/rustc_attr_parsing/src/interface.rs @@ -6,7 +6,7 @@ use std::sync::atomic::{AtomicBool, Ordering}; use rustc_ast as ast; use rustc_ast::token::DocFragmentKind; use rustc_ast::{AttrStyle, CRATE_NODE_ID, NodeId, Safety}; -use rustc_attr_ir::target::Target; +use rustc_attr_ir::target::{AstTarget, Target}; use rustc_attr_ir::{AttrArgs, AttrItem, AttrPath, Attribute, AttributeKind, HashIgnoredAttrId}; use rustc_data_structures::sync::{DynSend, DynSync}; use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, Level, MultiSpan}; @@ -162,7 +162,7 @@ impl<'sess> AttributeParser<'sess> { attrs, target_span, target, - None, + AstTarget::None, std::convert::identity, |lint_id, span, kind| { sess.psess.dyn_buffer_lint_sess(lint_id.lint, span, target_node_id, kind.0) @@ -319,7 +319,7 @@ impl<'sess> AttributeParser<'sess> { attrs: &[ast::Attribute], target_span: Span, target: Target, - target_item: Option<&ast::Item>, + ast_target: AstTarget<'_>, lower_span: impl Copy + Fn(Span) -> Span, mut emit_lint: impl FnMut(LintId, MultiSpan, EmitAttribute), ) -> Vec { @@ -519,7 +519,7 @@ impl<'sess> AttributeParser<'sess> { }, all_attrs: &attr_paths, parsed_attrs: &attributes, - target_item, + ast_target, }, attr_span, ); diff --git a/compiler/rustc_attr_parsing/src/target_checking.rs b/compiler/rustc_attr_parsing/src/target_checking.rs index 7eb3e8e1f319a..723f4a31823ab 100644 --- a/compiler/rustc_attr_parsing/src/target_checking.rs +++ b/compiler/rustc_attr_parsing/src/target_checking.rs @@ -6,7 +6,7 @@ use rustc_attr_ir::{AttrItem, Attribute, AttributeKind}; use rustc_errors::{DiagArgValue, MultiSpan, StashKey}; use rustc_feature::Features; use rustc_lint_defs::builtin::{ - MISPLACED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES, USELESS_DEPRECATED, + INVALID_DOC_ATTRIBUTES, MISPLACED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES, USELESS_DEPRECATED, }; use rustc_span::{BytePos, FileName, RemapPathScopeComponents, Span, Symbol, sym}; @@ -244,6 +244,16 @@ impl<'sess> AttributeParser<'sess> { }) .unwrap_or_default(); + if name == "doc" { + let diag = crate::diagnostics::AttrCrateLevelOnly; + if warn { + cx.emit_lint(INVALID_DOC_ATTRIBUTES, diag, attr_span); + } else { + cx.emit_err(diag); + } + return; + } + let diag = crate::diagnostics::InvalidAttrStyle { name, is_used_as_inner, diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 1130b89a67805..9bb60d47ac849 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -17,12 +17,13 @@ use rustc_middle::mir::{AnnotationSource, ConstraintCategory, ReturnConstraint}; use rustc_middle::ty::{ self, GenericArgs, Region, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitor, fold_regions, }; -use rustc_span::{Ident, Span, bug, kw}; +use rustc_span::{Ident, Span, Symbol, bug, kw}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::error_reporting::infer::nice_region_error::{ self, HirTraitObjectVisitor, NiceRegionError, TraitObjectVisitor, find_anon_type, find_param_with_region, suggest_adding_lifetime_params, }; +use rustc_trait_selection::error_reporting::traits::suggestions::ReturnsVisitor; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::{Obligation, ObligationCtxt}; use tracing::{debug, instrument, trace}; @@ -947,7 +948,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { /// | is returning data with lifetime `'b` /// ``` fn report_general_error(&self, errci: &ErrorConstraintInfo<'tcx>) -> Diag<'diag> { - let ErrorConstraintInfo { fr, outlived_fr, span, category, .. } = errci; + let ErrorConstraintInfo { fr, outlived_fr, span, category } = errci; let mir_def_name = self.infcx.tcx.def_descr(self.mir_def_id().to_def_id()); @@ -990,10 +991,170 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { self.suggest_adding_lifetime_params(&mut diag, *fr, *outlived_fr); self.suggest_move_on_borrowing_closure(&mut diag); self.suggest_deref_closure_return(&mut diag); + self.point_at_dyn_trait_in_field_def(&mut diag, *span, *outlived_fr); diag } + /// When a returned value has a field with a lifetime that isn't `'static`, and the requirement + /// comes from a `dyn Trait` with an implicit `'static` in the given field, point at the trait + /// object in the definition and suggest constraining it with a lifetime. + fn point_at_dyn_trait_in_field_def( + &self, + diag: &mut Diag<'_>, + span: Span, + outlived_fr: RegionVid, + ) { + let Some(outlived_f) = self.regioncx.to_error_region(outlived_fr) else { return }; + if outlived_f.kind() != ty::ReStatic { + return; + } + let Some(body_id) = self.infcx.tcx.hir_node_by_def_id(self.mir_def_id()).body_id() else { + return; + }; + let mut visitor = ReturnsVisitor::default(); + visitor.visit_body(&self.infcx.tcx.hir_body(body_id)); + if visitor.returns.is_empty() { + return; + } + + enum NameOrPos { + Name(Symbol), + Pos(usize), + } + + for ret in visitor.returns { + let (def_id, lit_field) = match ret.kind { + hir::ExprKind::Struct(hir::QPath::Resolved(_, path), fields, _tail) => { + let Def(_, def_id) = path.res else { continue }; + let Some(def_id) = def_id.as_local() else { continue }; + let Some(field) = fields.iter().find(|f| f.expr.span.contains(span)) else { + continue; + }; + (def_id, NameOrPos::Name(field.ident.name)) + } + hir::ExprKind::Call(callee, args) + if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = callee.kind => + { + let Def(_, def_id) = path.res else { continue }; + let Some(def_id) = def_id.as_local() else { continue }; + let Some((pos, _)) = + args.iter().enumerate().find(|(_, a)| a.span.contains(span)) + else { + continue; + }; + (def_id, NameOrPos::Pos(pos)) + } + _ => continue, + }; + let (def_spans, fields, generics) = match self.infcx.tcx.hir_node_by_def_id(def_id) { + hir::Node::Item(item) => match item.kind { + hir::ItemKind::Struct(name, generics, data) => { + let (hir::VariantData::Struct { fields, .. } + | hir::VariantData::Tuple(fields, ..)) = data + else { + continue; + }; + (vec![name.span], fields, generics) + } + _ => continue, + }, + hir::Node::Variant(variant) => { + let hir::VariantData::Struct { fields, .. } = variant.data else { continue }; + let parent = self.infcx.tcx.parent(def_id.into()); + let mut def_spans = vec![self.infcx.tcx.def_span(parent).shrink_to_lo()]; + let generics = if let DefKind::Variant = self.infcx.tcx.def_kind(parent) { + let parent = self.infcx.tcx.parent(parent); + def_spans.push(self.infcx.tcx.def_span(parent).shrink_to_lo()); + self.infcx + .tcx + .hir_get_generics(parent.expect_local()) + .expect("item with no generics?") + } else { + self.infcx + .tcx + .hir_get_generics(parent.expect_local()) + .expect("item with no generics?") + }; + (def_spans, fields, generics) + } + hir::Node::Ctor(data) => { + let hir::VariantData::Tuple(fields, ..) = data else { continue }; + let parent = self.infcx.tcx.parent(def_id.into()); + let mut def_spans = vec![self.infcx.tcx.def_span(parent).shrink_to_lo()]; + let generics = if let DefKind::Variant = self.infcx.tcx.def_kind(parent) { + let parent = self.infcx.tcx.parent(parent); + def_spans.push(self.infcx.tcx.def_span(parent).shrink_to_lo()); + self.infcx + .tcx + .hir_get_generics(parent.expect_local()) + .expect("item with no generics?") + } else { + self.infcx + .tcx + .hir_get_generics(parent.expect_local()) + .expect("item with no generics?") + }; + (def_spans, *fields, generics) + } + _ => continue, + }; + + let Some((_, f)) = fields.iter().enumerate().find(|(i, f)| match lit_field { + NameOrPos::Name(name) => f.ident.name == name, + NameOrPos::Pos(pos) => *i == pos, + }) else { + continue; + }; + + let mut v = ty::TraitObjectVisitor(vec![]); + v.visit_ty_unambig(f.ty); + let mut span: MultiSpan = v.0.iter().map(|x| x.span).collect::>().into(); + // Display the item and variant lines. + for def_span in def_spans { + span.push_span_context(def_span); + } + // Display the field's line (even if different to its type's). + span.push_span_context(f.ident.span); + // Display the type's start line (even if different to its type's). + span.push_span_context(f.ty.span.shrink_to_lo()); + let (these, s, introduce) = if v.0.len() == 1 { + ("this", "", "introduces") + } else { + ("these", "s", "introduce") + }; + diag.span_note( + span, + format!("{these} `dyn Trait`{s} {introduce} an implicit `'static` obligation"), + ); + let suggestion_param_name = generics + .params + .iter() + .filter(|p| matches!(p.kind, hir::GenericParamKind::Lifetime { .. })) + .map(|p| p.name.ident().name) + .find(|i| *i != kw::UnderscoreLifetime); + if let Some(name) = suggestion_param_name { + let msg = "consider using an explicit lifetime"; + let mut sugg = vec![]; + for ty in v.0 { + sugg.push((ty.span.shrink_to_hi(), format!(" + {name}"))); + } + diag.multipart_suggestion(msg, sugg, Applicability::MachineApplicable); + } else { + let msg = "consider introducing an explicit lifetime"; + let mut sugg = vec![match generics.span_for_lifetime_suggestion() { + Some(span) => (span, "'a, ".to_string()), + None => (generics.span, "<'a>".to_string()), + }]; + for ty in v.0 { + sugg.push((ty.span.shrink_to_hi(), " + 'a".to_string())); + } + diag.multipart_suggestion(msg, sugg, Applicability::MachineApplicable); + } + return; + } + } + /// Adds a suggestion to errors where an `impl Trait` is returned. /// /// ```text diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 1d1c9c0baef51..99203fe0ebf18 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -61,11 +61,11 @@ pub(crate) enum RegionNameHighlight { MatchedAdtAndSegment(Span), /// The anonymous region corresponds to a region where the type annotation is completely missing /// from the code, e.g. in a closure arguments `|x| { ... }`, where `x` is a reference. - CannotMatchHirTy(Span, Symbol), + CannotMatchHirTy(Span, Symbol, Option), /// The anonymous region corresponds to a region where the type annotation is completely missing /// from the code, and *even if* we print out the full name of the type, the region name won't /// be included. This currently occurs for opaque types like `impl Future`. - Occluded(Span, Symbol), + Occluded(Span, Symbol, Option), } impl RegionName { @@ -98,8 +98,8 @@ impl RegionName { | RegionNameSource::AnonRegionFromOutput(ref highlight, _) => match *highlight { RegionNameHighlight::MatchedHirTy(span) | RegionNameHighlight::MatchedAdtAndSegment(span) - | RegionNameHighlight::CannotMatchHirTy(span, _) - | RegionNameHighlight::Occluded(span, _) => Some(span), + | RegionNameHighlight::CannotMatchHirTy(span, _, _) + | RegionNameHighlight::Occluded(span, _, _) => Some(span), }, } } @@ -120,8 +120,12 @@ impl RegionName { RegionNameSource::AnonRegionFromArgument(RegionNameHighlight::CannotMatchHirTy( span, type_name, + lt_span, )) => { diag.span_label(*span, format!("has type `{type_name}`")); + if let Some(span) = lt_span { + diag.span_label(*span, format!("lifetime `{self}` introduced here")); + } } RegionNameSource::AnonRegionFromArgument(RegionNameHighlight::MatchedHirTy(span)) | RegionNameSource::AnonRegionFromOutput(RegionNameHighlight::MatchedHirTy(span), _) @@ -143,14 +147,18 @@ impl RegionName { RegionNameSource::AnonRegionFromArgument(RegionNameHighlight::Occluded( span, type_name, + lt_span, )) => { diag.span_label( *span, format!("lifetime `{self}` appears in the type `{type_name}`"), ); + if let Some(span) = lt_span { + diag.span_label(*span, format!("lifetime `{self}` introduced here")); + } } RegionNameSource::AnonRegionFromOutput( - RegionNameHighlight::Occluded(span, type_name), + RegionNameHighlight::Occluded(span, type_name, lt_span), mir_description, ) => { diag.span_label( @@ -159,6 +167,9 @@ impl RegionName { "return type{mir_description} `{type_name}` contains a lifetime `{self}`" ), ); + if let Some(span) = lt_span { + diag.span_label(*span, format!("lifetime `{self}` introduced here")); + } } RegionNameSource::AnonRegionFromUpvar(span, upvar_name) => { diag.span_label( @@ -167,10 +178,13 @@ impl RegionName { ); } RegionNameSource::AnonRegionFromOutput( - RegionNameHighlight::CannotMatchHirTy(span, type_name), + RegionNameHighlight::CannotMatchHirTy(span, type_name, lt_span), mir_description, ) => { diag.span_label(*span, format!("return type{mir_description} is `{type_name}`")); + if let Some(span) = lt_span { + diag.span_label(*span, format!("lifetime `{self}` introduced here")); + } } RegionNameSource::AnonRegionFromYieldTy(span, type_name) => { diag.span_label(*span, format!("yield type is {type_name}")); @@ -576,11 +590,18 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { "highlight_if_we_cannot_match_hir_ty: type_name={:?} needle_fr={:?}", type_name, needle_fr ); + let lt_span = if let Some(needle) = self.regioncx.to_error_region(needle_fr) + && let Some(def_id) = needle.opt_param_def_id(self.infcx.tcx, self.mir_def_id().into()) + { + Some(self.infcx.tcx.def_span(def_id)) + } else { + None + }; if type_name.contains(&format!("'{counter}")) { // Only add a label if we can confirm that a region was labelled. - RegionNameHighlight::CannotMatchHirTy(span, Symbol::intern(&type_name)) + RegionNameHighlight::CannotMatchHirTy(span, Symbol::intern(&type_name), lt_span) } else { - RegionNameHighlight::Occluded(span, Symbol::intern(&type_name)) + RegionNameHighlight::Occluded(span, Symbol::intern(&type_name), lt_span) } } @@ -1111,7 +1132,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { Some(RegionName { name: region_name, source: RegionNameSource::AnonRegionFromArgument( - RegionNameHighlight::CannotMatchHirTy(arg_span, arg_name?), + RegionNameHighlight::CannotMatchHirTy(arg_span, arg_name?, None), ), }) } else { diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 2e212f3f1ef86..01230e5bc4c9e 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -4533,6 +4533,7 @@ pub struct TestBinderBody<'hir> { pub span: Span, pub foralls: &'hir [TestBinderForall<'hir>], pub exists: &'hir [TestBinderExists<'hir>], + pub region_equalities: &'hir [(&'hir Lifetime, &'hir Lifetime)], /// Constraints to be inserted directly into constraint storage to be proven pub constraints: TestBinderConstraint<'hir>, /// Constraints declared using `where` syntax, used via `register_obligation` diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index ebfe6b469b00d..5acd959bc2160 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -1600,9 +1600,14 @@ pub fn walk_test_binder_body<'v, V: Visitor<'v>>( visitor: &mut V, body: &'v TestBinderBody<'v>, ) -> V::Result { - let TestBinderBody { span: _, foralls, exists, constraints, predicates } = body; + let TestBinderBody { span: _, foralls, exists, region_equalities, constraints, predicates } = + body; walk_list!(visitor, visit_test_binder_forall, *foralls); walk_list!(visitor, visit_test_binder_exists, *exists); + for (lhs, rhs) in *region_equalities { + try_visit!(visitor.visit_lifetime(lhs)); + try_visit!(visitor.visit_lifetime(rhs)); + } try_visit!(visitor.visit_test_binder_constraint(&constraints)); walk_list!(visitor, visit_where_predicate, *predicates); V::Result::output() diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 930d2c45605d2..110245385c1a7 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -2380,7 +2380,16 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { #[instrument(level = "debug", skip(self))] pub(super) fn check_test_binder_body(&self, body: TestBinderBody<'tcx>) { - let TestBinderBody { span, foralls, exists, constraints, predicates } = body; + let TestBinderBody { span, foralls, exists, region_equalities, constraints, predicates } = + body; + for (equality, span) in region_equalities { + let cause = traits::ObligationCause::misc(span, self.body_def_id); + self.infcx.register_region_eq_constraint( + equality, + ty::VisibleForLeakCheck::Yes, + &cause, + ); + } if !predicates.is_empty() { for (predicate, span) in predicates { let cause = traits::ObligationCause::misc(span, self.body_def_id); @@ -2800,6 +2809,7 @@ pub(crate) struct TestBinderBody<'tcx> { pub span: Span, pub foralls: Vec>, pub exists: Vec>, + pub region_equalities: Vec<(ty::RegionEqPredicate<'tcx>, Span)>, /// Constraints to be inserted directly into constraint storage to be proven pub constraints: SolverRegionConstraint<'tcx>, /// Constraints declared using `where` syntax, used via `register_obligation` diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index ecfa8f6c67be6..0a42a2e94a551 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -328,16 +328,32 @@ impl<'tcx> ItemCtxt<'tcx> { &self, item: &hir::TestBinderBody<'tcx>, ) -> TestBinderBody<'tcx> { - let hir::TestBinderBody { span, foralls, exists, constraints, predicates } = item; + let hir::TestBinderBody { + span, + foralls, + exists, + region_equalities, + constraints, + predicates, + } = item; let foralls = foralls.iter().map(|forall| self.lower_test_binder_forall(forall)).collect(); let exists = exists.iter().map(|exists| self.lower_test_binder_exists(exists)).collect(); + let region_equalities = region_equalities + .iter() + .map(|(lhs, rhs)| { + let span = lhs.ident.span.to(rhs.ident.span); + let lhs = self.lowerer().lower_lifetime(lhs, RegionInferReason::RegionPredicate); + let rhs = self.lowerer().lower_lifetime(rhs, RegionInferReason::RegionPredicate); + (ty::RegionEqPredicate(lhs, rhs), span) + }) + .collect(); let constraints = self.lower_test_binder_constraint(&constraints); let mut clauses = Default::default(); for predicate in *predicates { clauses_of::where_predicate_clauses(self, predicate, &mut clauses); } let predicates = clauses.into_iter().map(|(c, span)| (c.kind(), span)).collect(); - TestBinderBody { span: *span, foralls, exists, constraints, predicates } + TestBinderBody { span: *span, foralls, exists, region_equalities, constraints, predicates } } #[instrument(level = "debug", skip(self), ret)] diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 7dc4b8d7674ca..6059ede2ecdc6 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1515,9 +1515,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .type_of(param.def_id) .instantiate(self.tcx, method.args) .skip_norm_wip(); + // Insert function argument const param types back into the inputs. // We use pos - 1 since method_inputs skips self, but arg_pos counts it. - method_inputs.to_mut().insert(pos as usize - 1, ty); + method_inputs.to_mut().insert( + pos.checked_sub(1).expect("pos should always be greater than 0") as usize, + ty, + ); } let method_tuple_args_flag = diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index a9809d552a2be..69ffd02466589 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1,3 +1,4 @@ +// ignore-tidy-file-filelength use std::ops::Deref; use std::{fmt, iter}; @@ -41,9 +42,8 @@ use crate::diagnostics::{ExprParenthesesNeeded, SuggestPtrNullMut, SuggestRawMut use crate::fn_ctxt::arg_matrix::{ArgMatrix, Compatibility, Error, ExpectedIdx, ProvidedIdx}; use crate::gather_locals::Declaration; use crate::inline_asm::InlineAsmCtxt; -use crate::method::probe::IsSuggestion; -use crate::method::probe::Mode::MethodCall; use crate::method::probe::ProbeScope::TraitsInScope; +use crate::method::probe::{IsSuggestion, Mode}; use crate::{ BreakableCtxt, Diverges, Expectation, FnCtxt, GatherLocalsVisitor, LoweredTy, Needs, TupleArgumentsFlag, diagnostics, struct_span_code_err, @@ -1914,9 +1914,47 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let def_kind = self.tcx.def_kind(def_id); if let DefKind::AssocFn = def_kind { - spans.push_span_context(self.tcx.def_span(self.tcx.parent(def_id)).shrink_to_lo()); + let parent_def_id = self.tcx.parent(def_id); + spans.push_span_context(self.tcx.def_span(parent_def_id).shrink_to_lo()); } err.span_note(spans, format!("{} defined here", self.tcx.def_descr(def_id))); + if let DefKind::AssocFn = def_kind + && !is_method + && let parent_def_id = self.tcx.parent(def_id) + && let Some(callee_ty) = callee_ty + && let ty::FnDef(_def_id, args) = callee_ty.kind() + && let DefKind::Trait = self.tcx.def_kind(parent_def_id) + && let Ok(Some(traits::ImplSource::UserDefined(pick))) = self.probe(|_| { + let trait_ref = ty::TraitRef::new( + self.tcx, + parent_def_id, + args.skip_binder() + .truncate_to(self.tcx, self.tcx.generics_of(parent_def_id)), + ); + let obligation = traits::Obligation::new( + self.tcx, + traits::ObligationCause::dummy(), + self.param_env, + trait_ref, + ); + SelectionContext::new(self).select(&obligation) + }) + { + err.span_note( + self.tcx.def_span(pick.impl_def_id), + format!( + "{} provided through this {}`impl`", + self.tcx.def_descr(def_id), + if let ty::Param(_) = + self.tcx.type_of(pick.impl_def_id).skip_binder().kind() + { + "blanket " + } else { + "" + }, + ), + ); + } if let DefKind::Fn | DefKind::AssocFn = def_kind && let ty::Param(_) = self.tcx.fn_sig(def_id).instantiate_identity().skip_binder().output().kind() @@ -3430,7 +3468,7 @@ impl<'a, 'tcx> ArgsCtxt<'a, 'tcx> { if let Some(callee_ty) = self.call_ctxt.callee_ty && let Ok(Some(assoc)) = self.call_ctxt.fn_ctxt.probe_op( call_name.span, - MethodCall, + Mode::MethodCall, Some(call_name), None, IsSuggestion(true), diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index df1daac366c53..b3159384b951d 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -578,7 +578,7 @@ pub fn suggest_constraining_type_params<'a>( } /// Collect al types that have an implicit `'static` obligation that we could suggest `'_` for. -pub(crate) struct TraitObjectVisitor<'tcx>(pub(crate) Vec<&'tcx hir::Ty<'tcx>>); +pub struct TraitObjectVisitor<'tcx>(pub Vec<&'tcx hir::Ty<'tcx>>); impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> { fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) { diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index d734a70399b11..b6d31acb0b1e8 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -127,18 +127,15 @@ pub enum AttemptLocalParseRecovery { } impl AttemptLocalParseRecovery { - pub(super) fn yes(&self) -> bool { + pub(super) fn yes(&self, p: &Parser<'_>) -> bool { match self { - AttemptLocalParseRecovery::Yes => true, + AttemptLocalParseRecovery::Yes => p.may_recover(), AttemptLocalParseRecovery::No => false, } } - pub(super) fn no(&self) -> bool { - match self { - AttemptLocalParseRecovery::Yes => false, - AttemptLocalParseRecovery::No => true, - } + pub(super) fn no(&self, p: &Parser<'_>) -> bool { + !self.yes(p) } } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 45bae73deda8d..fb8d9ce303865 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2729,6 +2729,7 @@ impl<'a> Parser<'a> { pub fn parse_test_binder_body(&mut self) -> PResult<'a, TestBinderBody> { let mut foralls = ThinVec::new(); let mut exists = ThinVec::new(); + let mut region_equalities = Vec::new(); let mut constraints = Vec::new(); let mut predicates = Vec::new(); let mut span = self.token.span; @@ -2746,12 +2747,21 @@ impl<'a> Parser<'a> { exists.push(this.parse_test_binder_exists()?) } + _ if this.token.is_lifetime() && this.look_ahead(1, |t| t.kind == token::Eq) => { + let lhs = this.expect_lifetime(); + this.expect(exp!(Eq))?; + if !this.check_lifetime() { + this.unexpected()?; + } + let rhs = this.expect_lifetime(); + region_equalities.push(TestBinderRegionEquality { lhs, rhs }); + } _ => constraints.push(this.parse_test_binder_constraint()?), } Ok(()) })?; span = span.to(self.prev_token.span); - Ok(TestBinderBody { foralls, exists, constraints, predicates, span }) + Ok(TestBinderBody { foralls, exists, region_equalities, constraints, predicates, span }) } pub fn parse_test_binder_forall(&mut self) -> PResult<'a, TestBinderForall> { diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 4382420a59b7c..49bcdbbe8fa57 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -765,7 +765,7 @@ impl<'a> Parser<'a> { snapshot = Some(self.create_snapshot_for_diagnostic()); } let stmt = match self.parse_full_stmt(recover) { - Err(mut err) if recover.yes() => { + Err(mut err) if recover.yes(self) => { if let Some(ref mut snapshot) = snapshot { snapshot.recover_vcs_conflict_marker(); } @@ -1072,7 +1072,7 @@ impl<'a> Parser<'a> { let res = self.check_mistyped_turbofish_with_multiple_type_params(e, expr); - Some(if recover.no() { + Some(if recover.no(self) { res? } else { res.unwrap_or_else(|mut e| { diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index ab951a2cc1ce9..c59425feb3173 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -38,7 +38,6 @@ use rustc_middle::query::Providers; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{self, TyCtxt, TypingMode, Unnormalized, Variance}; -use rustc_session::diagnostics::feature_err; use rustc_span::edition::Edition; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, bug, kw, span_bug, sym}; use rustc_structures::CrateType; @@ -195,7 +194,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { AttributeKind::RustcAllowConstFnUnstable(_, first_span) => { self.check_rustc_allow_const_fn_unstable(hir_id, *first_span, span, target) } - AttributeKind::Naked(..) => self.check_naked(hir_id, target), AttributeKind::MayDangle(attr_span) => self.check_may_dangle(hir_id, *attr_span), AttributeKind::Doc(attr) => self.check_doc_attrs(attr, hir_id, target), AttributeKind::EiiImpl(eii_impl) => self.check_eii_impl(eii_impl), @@ -270,6 +268,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { AttributeKind::MoveSizeLimit { .. } => (), AttributeKind::MustNotSupend { .. } => (), AttributeKind::MustUse { .. } => (), + AttributeKind::Naked(..) => (), AttributeKind::NeedsAllocator => (), AttributeKind::NeedsPanicRuntime => (), AttributeKind::NoBuiltins => (), @@ -731,32 +730,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - /// Checks if `#[naked]` is applied to a function definition. - fn check_naked(&self, hir_id: HirId, target: Target) { - match target { - Target::Fn - | Target::Method( - MethodKind::Trait { body: true } | MethodKind::TraitImpl | MethodKind::Inherent, - ) => { - let fn_sig = self.tcx.hir_node(hir_id).fn_sig().unwrap(); - let abi = fn_sig.header.abi; - if abi.is_rustic_abi() && !self.tcx.features().naked_functions_rustic_abi() { - feature_err( - &self.tcx.sess, - sym::naked_functions_rustic_abi, - fn_sig.span, - format!( - "`#[naked]` is currently unstable on `extern \"{}\"` functions", - abi.as_str() - ), - ) - .emit(); - } - } - _ => {} - } - } - fn check_doc_alias_value(&self, span: Span, hir_id: HirId, target: Target, alias: Symbol) { if let Some(location) = match target { Target::AssocTy(_) => { diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 1b0045d4e02f3..474615c9a7672 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -2,7 +2,7 @@ use std::mem; use rustc_ast::visit::FnKind; use rustc_ast::*; -use rustc_attr_ir::target::Target; +use rustc_attr_ir::target::{AstTarget, Target}; use rustc_attr_parsing::{AttributeParser, ShouldEmit}; use rustc_expand::expand::AstFragment; use rustc_hir as hir; @@ -183,7 +183,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { &i.attrs, i.span, Target::MacroDef, - None, + AstTarget::from_ast_item(&i.kind), std::convert::identity, |_lint_id, _span, _kind| { // FIXME(jdonszelmann): emit lints here properly diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index bff2f1e6804af..6b30019127f27 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -2,7 +2,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_hir::definitions::{DefPathData, PerParentDisambiguatorState}; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{self as hir, ImplItemImplKind, ItemKind}; +use rustc_hir::{self as hir, Generics, ImplItemImplKind, ItemKind}; use rustc_middle::query::Providers; use rustc_middle::ty::{self, ImplTraitInTraitData, TyCtxt}; use rustc_span::symbol::kw; @@ -76,8 +76,14 @@ fn associated_item(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AssocItem { assoc_item } -fn fn_has_self_parameter(tcx: TyCtxt<'_>, owner_id: hir::OwnerId) -> bool { +fn fn_has_self_parameter(tcx: TyCtxt<'_>, owner_id: hir::OwnerId, generics: &Generics<'_>) -> bool { + // With `function_arg_const_generics`, const parameters are moved into the + // generics. We check the original `arg_pos` to avoid treating a later `self` + // as a valid receiver after the const parameters are removed. matches!(tcx.fn_arg_idents(owner_id.def_id), [Some(Ident { name: kw::SelfLower, .. }), ..]) + && !generics.params.iter().any(|param| { + matches!(param.kind, hir::GenericParamKind::Const { arg_pos: Some(0), .. }) + }) } fn associated_item_from_trait_item( @@ -88,9 +94,10 @@ fn associated_item_from_trait_item( let name = trait_item.ident.name; let kind = match trait_item.kind { hir::TraitItemKind::Const(_, _) => ty::AssocKind::Const { name }, - hir::TraitItemKind::Fn { .. } => { - ty::AssocKind::Fn { name, has_self: fn_has_self_parameter(tcx, owner_id) } - } + hir::TraitItemKind::Fn { .. } => ty::AssocKind::Fn { + name, + has_self: fn_has_self_parameter(tcx, owner_id, trait_item.generics), + }, hir::TraitItemKind::Type { .. } => { ty::AssocKind::Type { data: ty::AssocTypeData::Normal(name) } } @@ -104,9 +111,10 @@ fn associated_item_from_impl_item(tcx: TyCtxt<'_>, impl_item: &hir::ImplItem<'_> let name = impl_item.ident.name; let kind = match impl_item.kind { hir::ImplItemKind::Const(..) => ty::AssocKind::Const { name }, - hir::ImplItemKind::Fn(..) => { - ty::AssocKind::Fn { name, has_self: fn_has_self_parameter(tcx, owner_id) } - } + hir::ImplItemKind::Fn(..) => ty::AssocKind::Fn { + name, + has_self: fn_has_self_parameter(tcx, owner_id, impl_item.generics), + }, hir::ImplItemKind::Type(..) => { ty::AssocKind::Type { data: ty::AssocTypeData::Normal(name) } } diff --git a/compiler/rustc_type_ir/src/region_constraint.rs b/compiler/rustc_type_ir/src/region_constraint.rs index 890a1ddaead78..a866f849f25e2 100644 --- a/compiler/rustc_type_ir/src/region_constraint.rs +++ b/compiler/rustc_type_ir/src/region_constraint.rs @@ -627,6 +627,7 @@ pub fn eagerly_handle_placeholders_in_universe RegionConstraint { assert!(u > UniverseIndex::ROOT, "eagerly handle placeholders called for root universe"); + let constraint = infcx.deeply_resolve_via_unification_table(constraint); let assumptions = infcx.get_placeholder_assumptions(u); // 1. rewrite type outlives constraints involving things from `u` into either region constraints diff --git a/library/core/src/num/imp/mod.rs b/library/core/src/num/imp/mod.rs index 6fccfd1c238ed..e04f3cd93ba5f 100644 --- a/library/core/src/num/imp/mod.rs +++ b/library/core/src/num/imp/mod.rs @@ -11,6 +11,9 @@ pub mod diy_float; pub mod flt2dec; pub mod fmt; +// Public for core_arch. +pub mod ppcf128; + pub(crate) mod int_bits; pub(crate) mod int_log10; pub(crate) mod int_sqrt; diff --git a/library/core/src/num/imp/ppcf128.rs b/library/core/src/num/imp/ppcf128.rs new file mode 100644 index 0000000000000..04499e48cbd5d --- /dev/null +++ b/library/core/src/num/imp/ppcf128.rs @@ -0,0 +1,13 @@ +/// The IBM extended-precision (double-double) floating-point lang item. +/// +/// Here we define just the lang item, the public-facing type is defined +/// in core_arch. It transparently wraps this definition. +/// +/// The ppcf128 type should only be used on PowerPC targets, but is always defined +/// for the purpose of doc builds, specifically doc builds in the stdarch repo. +#[doc(hidden)] +#[cfg_attr(any(target_arch = "powerpc", target_arch = "powerpc64"), lang = "ppcf128")] +#[unstable(feature = "num_internals", issue = "none")] +#[allow(non_camel_case_types, dead_code)] +#[derive(Debug, Clone, Copy)] +pub struct ppcf128(u128); diff --git a/library/stdarch/crates/core_arch/src/lib.rs b/library/stdarch/crates/core_arch/src/lib.rs index 0c5daffaf05d9..c7e2d93b886a7 100644 --- a/library/stdarch/crates/core_arch/src/lib.rs +++ b/library/stdarch/crates/core_arch/src/lib.rs @@ -40,7 +40,11 @@ movrs_target_feature, clflushopt_target_feature, min_adt_const_params, - lang_items, + num_internals +)] +#![cfg_attr( + any(target_arch = "powerpc", target_arch = "powerpc64"), + feature(powerpc_ppcf128) )] #![cfg_attr( test, @@ -104,4 +108,4 @@ pub mod arch { } #[allow(unused_imports)] -use core::{array, cmp, convert, ffi, fmt, hint, intrinsics, marker, mem, ops, ptr, sync}; +use core::{array, cmp, convert, ffi, fmt, hint, intrinsics, marker, mem, num, ops, ptr, sync}; diff --git a/library/stdarch/crates/core_arch/src/powerpc/mod.rs b/library/stdarch/crates/core_arch/src/powerpc/mod.rs index e98a738e65ff4..57fcd17852157 100644 --- a/library/stdarch/crates/core_arch/src/powerpc/mod.rs +++ b/library/stdarch/crates/core_arch/src/powerpc/mod.rs @@ -4,7 +4,6 @@ pub(crate) mod macros; /// The IBM extended-precision (double-double) floating-point type. // FIXME(ppcf128) improve the docs. -#[lang = "ppcf128"] #[doc(alias = "__ibm128")] #[doc(alias = "doubledouble")] #[doc(alias = "f64f64")] @@ -12,7 +11,8 @@ pub(crate) mod macros; #[allow(non_camel_case_types)] #[doc(cfg(any(target_arch = "powerpc", target_arch = "powerpc64")))] #[derive(Clone, Copy)] -pub struct ppcf128(u128); +#[repr(transparent)] +pub struct ppcf128(crate::num::imp::ppcf128::ppcf128); #[unstable(feature = "powerpc_ppcf128", issue = "163323")] impl crate::fmt::Debug for ppcf128 { diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index c5f9a4288c632..4d72f562a0bc6 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -48,9 +48,9 @@ dependencies = [ "clap", "clap_complete", "cmake", + "expect-test", "home", "ignore", - "insta", "junction", "libc", "object", @@ -175,17 +175,6 @@ dependencies = [ "cc", ] -[[package]] -name = "console" -version = "0.16.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d64e8af5551369d19cf50138de61f1c42074ab970f74e99be916646777f8fc87" -dependencies = [ - "encode_unicode", - "libc", - "windows-sys", -] - [[package]] name = "cpufeatures" version = "0.2.15" @@ -241,10 +230,10 @@ dependencies = [ ] [[package]] -name = "encode_unicode" -version = "1.0.0" +name = "dissimilar" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" +checksum = "aeda16ab4059c5fd2a83f2b9c9e9c981327b18aa8e3b313f7e6563799d4f093e" [[package]] name = "errno" @@ -256,6 +245,16 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "expect-test" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63af43ff4431e848fb47472a920f14fa71c24de13255a5692e93d4e90302acb0" +dependencies = [ + "dissimilar", + "once_cell", +] + [[package]] name = "fastrand" version = "2.3.0" @@ -345,18 +344,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "insta" -version = "1.47.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b4a6248eb93a4401ed2f37dfe8ea592d3cf05b7cf4f8efa867b6895af7e094e" -dependencies = [ - "console", - "once_cell", - "similar", - "tempfile", -] - [[package]] name = "itoa" version = "1.0.11" @@ -682,12 +669,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" -[[package]] -name = "similar" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" - [[package]] name = "smallvec" version = "1.13.2" diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 4dcf87e3290a2..fa744c895477f 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -89,7 +89,7 @@ features = [ ] [dev-dependencies] -insta = "1.43" +expect-test = "1" # We care a lot about bootstrap's compile times, so don't include debuginfo for # dependencies, only bootstrap itself. diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md index 03d178630f8bb..dda7cecf64486 100644 --- a/src/bootstrap/README.md +++ b/src/bootstrap/README.md @@ -222,9 +222,7 @@ please file issues on the [Rust issue tracker][rust-issue-tracker]. ## Testing To run bootstrap tests, execute `x test bootstrap`. -If you want to bless snapshot tests, -then install `cargo-insta` (`cargo install --locked cargo-insta`), -and then run `cargo insta review --manifest-path src/bootstrap/Cargo.toml`. +If you want to bless snapshot tests, use `x test bootstrap --bless`. ## Changelog diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 70a97c8b87826..081f469069de9 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -4177,10 +4177,9 @@ impl CommandLineStep for Bootstrap { .env("RUSTC_BOOTSTRAP", "1"); if builder.config.cmd.bless() { - // Tell `insta` to automatically bless any failing `.snap` files. - // Unlike compiletest blessing, the tests might still report failure. - // Does not bless inline snapshots. - cargo.env("INSTA_UPDATE", "always"); + // Tell `expect-test` to automatically bless any failing `.snap` files + // and inline snapshots. + cargo.env("UPDATE_EXPECT", "1"); } run_cargo_test(cargo, &[], &[], None, host, builder, record_failed_tests); diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_fmt.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_fmt.snap index d7a99d45bfa70..48169a9210079 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_fmt.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_fmt.snap @@ -2,4 +2,3 @@ source: src/bootstrap/src/core/builder/cli_paths/tests.rs expression: fmt --- - diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_run.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_run.snap index fb4968b51c147..a20f552e1d26a 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_run.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_run.snap @@ -2,4 +2,3 @@ source: src/bootstrap/src/core/builder/cli_paths/tests.rs expression: run --- - diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_rustdoc_skip_rustdoc.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_rustdoc_skip_rustdoc.snap index f7e480936ebb7..321dda12654e9 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_rustdoc_skip_rustdoc.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_rustdoc_skip_rustdoc.snap @@ -2,4 +2,3 @@ source: src/bootstrap/src/core/builder/cli_paths/tests.rs expression: test rustdoc --skip=rustdoc --- - diff --git a/src/bootstrap/src/core/builder/cli_paths/tests.rs b/src/bootstrap/src/core/builder/cli_paths/tests.rs index a6754e063caf4..6432836a09565 100644 --- a/src/bootstrap/src/core/builder/cli_paths/tests.rs +++ b/src/bootstrap/src/core/builder/cli_paths/tests.rs @@ -1,5 +1,5 @@ use std::collections::{BTreeSet, HashSet}; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::sync::{Arc, Mutex}; use crate::core::builder::{Builder, CommandLineStepDescription}; @@ -59,12 +59,18 @@ fn render_steps_for_cli_args(args_str: &str) -> String { } fn snapshot_test_inner(name: &str, args_str: &str) { - let mut settings = insta::Settings::clone_current(); - // Use the test name as the snapshot filename, not its whole fully-qualified name. - settings.set_prepend_module_to_snapshot(false); - settings.bind(|| { - insta::assert_snapshot!(name, render_steps_for_cli_args(args_str), args_str); - }); + let name = Path::new("snapshots").join(format!("{name}.snap")); + let steps = render_steps_for_cli_args(args_str); + // Normalize Windows path separators + let file = file!().replace("\\", "/"); + let content = format!( + r"--- +source: {file} +expression: {args_str} +--- +{steps}", + ); + expect_test::expect_file![name].assert_eq(&content); } /// Keep the snapshots directory tidy by forbidding `.snap` files that don't @@ -119,10 +125,7 @@ macro_rules! declare_tests { // Snapshot tests for bootstrap's command-line path-to-step handling. // -// To bless these tests as necessary, choose one: -// - Run `INSTA_UPDATE=always ./x test bootstrap` -// - Run `./x test bootstrap --bless` -// - Follow the instructions for `cargo-insta` in bootstrap's README.md +// To bless these tests as necessary, run `./x test bootstrap --bless`. // // These snapshot tests capture _current_ behavior, to prevent unintended // changes or regressions. If the current behavior is wrong or undersirable, diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index ecdb057fd43b7..544c47602136a 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -358,8 +358,8 @@ fn any_debug() { assert_eq!(x.downcast_ref::(), Some(&MyStruct { x: 7 })); } -/// These tests use insta for snapshot testing. -/// See bootstrap's README on how to bless the snapshots. +/// These tests use expect-test for snapshot testing. +/// Run `x test bootstrap --bless` to update them. mod snapshot { use crate::core::build_steps::test; use crate::core::builder::tests::{RenderConfig, TEST_TRIPLE_1, TEST_TRIPLE_2, host_target}; @@ -374,80 +374,67 @@ mod snapshot { #[test] fn build_default() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("build") - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustdoc 1 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustdoc 1 "#]] + .assert_eq(&ctx.config("build").render_steps()); } #[test] fn build_cross_compile() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("build") + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 1 -> rustc 2 + [build] rustc 2 -> std 2 + [build] rustc 1 -> std 1 + [build] rustc 2 -> std 2 + [build] rustdoc 2 + [build] llvm + [build] rustc 1 -> rustc 2 + [build] rustdoc 2 "#]] + .assert_eq( + &ctx.config("build") // Cross-compilation fails on stage 1, as we don't have a stage0 std available // for non-host targets. .stage(2) .hosts(&[&host_target(), TEST_TRIPLE_1]) .targets(&[&host_target(), TEST_TRIPLE_1]) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 1 -> rustc 2 - [build] rustc 2 -> std 2 - [build] rustc 1 -> std 1 - [build] rustc 2 -> std 2 - [build] rustdoc 2 - [build] llvm - [build] rustc 1 -> rustc 2 - [build] rustdoc 2 - "); + .render_steps(), + ); } #[test] fn build_with_empty_host() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx - .config("build") - .hosts(&[]) - .targets(&[TEST_TRIPLE_1]) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - " - ); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 "#]] + .assert_eq(&ctx.config("build").hosts(&[]).targets(&[TEST_TRIPLE_1]).render_steps()); } #[test] fn build_compiler_no_explicit_stage() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("build") - .path("compiler") - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 "#]] + .assert_eq(&ctx.config("build").path("compiler").render_steps()); } #[test] fn build_rustc_no_explicit_stage() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("build") - .path("rustc") - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 "#]] + .assert_eq(&ctx.config("build").path("rustc").render_steps()); } #[test] @@ -460,174 +447,158 @@ mod snapshot { #[test] fn build_compiler_stage_1() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("build") - .path("compiler") - .stage(1) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 "#]] + .assert_eq(&ctx.config("build").path("compiler").stage(1).render_steps()); } #[test] fn build_compiler_stage_2() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("build") - .path("compiler") - .stage(2) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 1 -> rustc 2 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 1 -> rustc 2 "#]] + .assert_eq(&ctx.config("build").path("compiler").stage(2).render_steps()); } #[test] fn build_compiler_stage_3() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("build") - .path("compiler") - .stage(3) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 1 -> rustc 2 - [build] rustc 2 -> std 2 - [build] rustc 2 -> rustc 3 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 1 -> rustc 2 + [build] rustc 2 -> std 2 + [build] rustc 2 -> rustc 3 "#]] + .assert_eq(&ctx.config("build").path("compiler").stage(3).render_steps()); } #[test] fn build_compiler_stage_3_cross() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("build") - .path("compiler") - .hosts(&[TEST_TRIPLE_1]) - .stage(3) - .render_steps(), @r" - [build] llvm - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 1 -> rustc 2 - [build] rustc 1 -> std 1 - [build] rustc 2 -> std 2 - [build] rustc 2 -> std 2 - [build] rustc 2 -> rustc 3 - "); + expect_test::expect![[r#" + [build] llvm + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 1 -> rustc 2 + [build] rustc 1 -> std 1 + [build] rustc 2 -> std 2 + [build] rustc 2 -> std 2 + [build] rustc 2 -> rustc 3 "#]] + .assert_eq( + &ctx.config("build").path("compiler").hosts(&[TEST_TRIPLE_1]).stage(3).render_steps(), + ); } #[test] fn build_compiler_stage_3_full_bootstrap() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("build") + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 1 -> rustc 2 + [build] rustc 2 -> std 2 + [build] rustc 2 -> rustc 3 "#]] + .assert_eq( + &ctx.config("build") .path("compiler") .stage(3) .args(&["--set", "build.full-bootstrap=true"]) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 1 -> rustc 2 - [build] rustc 2 -> std 2 - [build] rustc 2 -> rustc 3 - "); + .render_steps(), + ); } #[test] fn build_compiler_stage_3_cross_full_bootstrap() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("build") + expect_test::expect![[r#" + [build] llvm + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 1 -> rustc 2 + [build] rustc 2 -> std 2 + [build] rustc 2 -> std 2 + [build] rustc 2 -> rustc 3 "#]] + .assert_eq( + &ctx.config("build") .path("compiler") .stage(3) .hosts(&[TEST_TRIPLE_1]) .args(&["--set", "build.full-bootstrap=true"]) - .render_steps(), @r" - [build] llvm - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 1 -> rustc 2 - [build] rustc 2 -> std 2 - [build] rustc 2 -> std 2 - [build] rustc 2 -> rustc 3 - "); + .render_steps(), + ); } #[test] fn build_compiler_codegen_backend() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx - .config("build") + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 0 -> rustc_codegen_cranelift 1 + [build] rustc 1 -> std 1 + [build] rustdoc 1 "#]] + .assert_eq( + &ctx.config("build") .args(&["--set", "rust.codegen-backends=['llvm', 'cranelift']"]) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 0 -> rustc_codegen_cranelift 1 - [build] rustc 1 -> std 1 - [build] rustdoc 1 - " + .render_steps(), ); } #[test] fn build_compiler_tools() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx - .config("build") + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 0 -> LldWrapper 1 + [build] rustc 0 -> LlvmBitcodeLinker 1 + [build] rustc 1 -> std 1 + [build] rustc 1 -> rustc 2 + [build] rustc 1 -> LldWrapper 2 + [build] rustc 1 -> LlvmBitcodeLinker 2 + [build] rustc 2 -> std 2 + [build] rustdoc 2 "#]] + .assert_eq( + &ctx.config("build") .stage(2) .args(&["--set", "rust.lld=true", "--set", "rust.llvm-bitcode-linker=true"]) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 0 -> LldWrapper 1 - [build] rustc 0 -> LlvmBitcodeLinker 1 - [build] rustc 1 -> std 1 - [build] rustc 1 -> rustc 2 - [build] rustc 1 -> LldWrapper 2 - [build] rustc 1 -> LlvmBitcodeLinker 2 - [build] rustc 2 -> std 2 - [build] rustdoc 2 - " + .render_steps(), ); } #[test] fn build_compiler_tools_cross() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx - .config("build") + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 0 -> LldWrapper 1 + [build] rustc 0 -> LlvmBitcodeLinker 1 + [build] rustc 1 -> std 1 + [build] rustc 1 -> rustc 2 + [build] rustc 1 -> LldWrapper 2 + [build] rustc 1 -> LlvmBitcodeLinker 2 + [build] rustc 1 -> std 1 + [build] rustc 2 -> std 2 + [build] llvm + [build] rustc 1 -> rustc 2 + [build] rustc 1 -> LldWrapper 2 + [build] rustc 1 -> LlvmBitcodeLinker 2 + [build] rustdoc 2 "#]] + .assert_eq( + &ctx.config("build") .stage(2) .args(&["--set", "rust.lld=true", "--set", "rust.llvm-bitcode-linker=true"]) .hosts(&[TEST_TRIPLE_1]) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 0 -> LldWrapper 1 - [build] rustc 0 -> LlvmBitcodeLinker 1 - [build] rustc 1 -> std 1 - [build] rustc 1 -> rustc 2 - [build] rustc 1 -> LldWrapper 2 - [build] rustc 1 -> LlvmBitcodeLinker 2 - [build] rustc 1 -> std 1 - [build] rustc 2 -> std 2 - [build] llvm - [build] rustc 1 -> rustc 2 - [build] rustc 1 -> LldWrapper 2 - [build] rustc 1 -> LlvmBitcodeLinker 2 - [build] rustdoc 2 - " + .render_steps(), ); } @@ -637,14 +608,11 @@ mod snapshot { [(host_target(), DefaultLinuxLinkerOverride::SelfContainedLldCc)].into(), || { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("build") - .path("compiler") - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 0 -> LldWrapper 1 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 0 -> LldWrapper 1 "#]] + .assert_eq(&ctx.config("build").path("compiler").render_steps()); }, ); } @@ -655,14 +623,15 @@ mod snapshot { [(host_target(), DefaultLinuxLinkerOverride::SelfContainedLldCc)].into(), || { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("build") - .path("compiler") - .args(&["--set", "rust.lld=false"]) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 "#]] + .assert_eq( + &ctx.config("build") + .path("compiler") + .args(&["--set", "rust.lld=false"]) + .render_steps(), + ); }, ); } @@ -670,14 +639,11 @@ mod snapshot { #[test] fn build_library_no_explicit_stage() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("build") - .path("library") - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 "#]] + .assert_eq(&ctx.config("build").path("library").render_steps()); } #[test] @@ -690,56 +656,46 @@ mod snapshot { #[test] fn build_library_stage_0_local_rebuild() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("build") + expect_test::expect![["[build] rustc 0 -> std 0 "]].assert_eq( + &ctx.config("build") .path("library") .stage(0) .targets(&[TEST_TRIPLE_1]) .args(&["--set", "build.local-rebuild=true"]) - .render_steps(), @"[build] rustc 0 -> std 0 "); + .render_steps(), + ); } #[test] fn build_library_stage_1() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("build") - .path("library") - .stage(1) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 "#]] + .assert_eq(&ctx.config("build").path("library").stage(1).render_steps()); } #[test] fn build_library_stage_2() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("build") - .path("library") - .stage(2) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 1 -> rustc 2 - [build] rustc 2 -> std 2 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 1 -> rustc 2 + [build] rustc 2 -> std 2 "#]] + .assert_eq(&ctx.config("build").path("library").stage(2).render_steps()); } #[test] fn build_miri_no_explicit_stage() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("build") - .path("miri") - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 0 -> miri 1 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 0 -> miri 1 "#]] + .assert_eq(&ctx.config("build").path("miri").render_steps()); } #[test] @@ -752,53 +708,40 @@ mod snapshot { #[test] fn build_miri_stage_1() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("build") - .path("miri") - .stage(1) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 0 -> miri 1 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 0 -> miri 1 "#]] + .assert_eq(&ctx.config("build").path("miri").stage(1).render_steps()); } #[test] fn build_miri_stage_2() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("build") - .path("miri") - .stage(2) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 1 -> rustc 2 - [build] rustc 1 -> miri 2 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 1 -> rustc 2 + [build] rustc 1 -> miri 2 "#]] + .assert_eq(&ctx.config("build").path("miri").stage(2).render_steps()); } #[test] fn build_error_index() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("build") - .path("error_index_generator") - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 0 -> error-index 1 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 0 -> error-index 1 "#]] + .assert_eq(&ctx.config("build").path("error_index_generator").render_steps()); } #[test] fn build_bootstrap_tool_no_explicit_stage() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("build") - .path("opt-dist") - .render_steps(), @"[build] rustc 0 -> OptimizedDist 1 "); + expect_test::expect![["[build] rustc 0 -> OptimizedDist 1 "]] + .assert_eq(&ctx.config("build").path("opt-dist").render_steps()); } #[test] @@ -811,21 +754,15 @@ mod snapshot { #[test] fn build_bootstrap_tool_stage_1() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("build") - .path("opt-dist") - .stage(1) - .render_steps(), @"[build] rustc 0 -> OptimizedDist 1 "); + expect_test::expect![["[build] rustc 0 -> OptimizedDist 1 "]] + .assert_eq(&ctx.config("build").path("opt-dist").stage(1).render_steps()); } #[test] fn build_bootstrap_tool_stage_2() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("build") - .path("opt-dist") - .stage(2) - .render_steps(), @"[build] rustc 0 -> OptimizedDist 1 "); + expect_test::expect![["[build] rustc 0 -> OptimizedDist 1 "]] + .assert_eq(&ctx.config("build").path("opt-dist").stage(2).render_steps()); } #[test] @@ -839,95 +776,81 @@ mod snapshot { #[test] fn alias_and_path_for_library() { let ctx = TestCtx::new(); - insta::assert_snapshot!(ctx.config("build") - .paths(&["library", "core"]) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - "); - - insta::assert_snapshot!(ctx.config("build") - .paths(&["std"]) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - "); - - insta::assert_snapshot!(ctx.config("build") - .paths(&["core"]) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - "); - - insta::assert_snapshot!(ctx.config("build") - .paths(&["alloc"]) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - "); - - insta::assert_snapshot!(ctx.config("doc") + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 "#]] + .assert_eq(&ctx.config("build").paths(&["library", "core"]).render_steps()); + + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 "#]] + .assert_eq(&ctx.config("build").paths(&["std"]).render_steps()); + + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 "#]] + .assert_eq(&ctx.config("build").paths(&["core"]).render_steps()); + + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 "#]] + .assert_eq(&ctx.config("build").paths(&["alloc"]).render_steps()); + + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustdoc 1 + [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]"#]].assert_eq(&ctx.config("doc") .paths(&["library", "core"]) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustdoc 1 - [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] - "); + .render_steps()); } #[test] fn build_all() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("build") + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 1 -> rustc 2 + [build] llvm + [build] rustc 1 -> std 1 + [build] rustc 1 -> rustc 2 + [build] rustc 2 -> std 2 + [build] rustc 2 -> std 2 + [build] rustc 1 -> std 1 + [build] rustc 2 -> std 2 "#]] + .assert_eq( + &ctx.config("build") .stage(2) .paths(&["compiler/rustc", "library"]) .hosts(&[&host_target(), TEST_TRIPLE_1]) .targets(&[&host_target(), TEST_TRIPLE_1, TEST_TRIPLE_2]) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 1 -> rustc 2 - [build] llvm - [build] rustc 1 -> std 1 - [build] rustc 1 -> rustc 2 - [build] rustc 2 -> std 2 - [build] rustc 2 -> std 2 - [build] rustc 1 -> std 1 - [build] rustc 2 -> std 2 - "); + .render_steps(), + ); } #[test] fn build_cargo() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("build") - .paths(&["cargo"]) - .render_steps(), @"[build] rustc 0 -> cargo 1 "); + expect_test::expect![["[build] rustc 0 -> cargo 1 "]] + .assert_eq(&ctx.config("build").paths(&["cargo"]).render_steps()); } #[test] fn build_cargo_cross() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("build") - .paths(&["cargo"]) - .hosts(&[TEST_TRIPLE_1]) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 1 -> std 1 - [build] rustc 1 -> cargo 2 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 1 -> std 1 + [build] rustc 1 -> cargo 2 "#]] + .assert_eq(&ctx.config("build").paths(&["cargo"]).hosts(&[TEST_TRIPLE_1]).render_steps()); } #[test] @@ -941,475 +864,457 @@ mod snapshot { let ctx = TestCtx::new(); // Note that stdlib is uplifted, that is why `[dist] rustc 1 -> std ` is in // the output. - insta::assert_snapshot!( - ctx - .config("dist") - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 0 -> UnstableBookGen 1 - [build] rustc 0 -> Rustbook 1 - [doc] unstable-book (book) - [doc] book (book) - [doc] book/first-edition (book) - [doc] book/second-edition (book) - [doc] book/2018-edition (book) - [build] rustdoc 1 - [doc] rustc 1 -> standalone 2 - [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] - [build] rustc 1 -> rustc 2 - [build] rustc 1 -> error-index 2 - [doc] rustc 1 -> error-index 2 - [doc] nomicon (book) - [doc] rustc 1 -> reference (book) 2 - [doc] rustdoc (book) - [doc] rust-by-example (book) - [build] rustc 0 -> LintDocs 1 - [doc] rustc (book) - [doc] cargo (book) - [doc] clippy (book) - [doc] embedded-book (book) - [doc] edition-guide (book) - [doc] style-guide (book) - [doc] rustc 1 -> releases 2 - [build] rustc 0 -> RustInstaller 1 - [dist] docs - [doc] rustc 1 -> std 1 crates=[] - [dist] rustc 1 -> json-docs 2 - [dist] mingw - [build] rustdoc 2 - [build] rustc 0 -> GenerateCopyright 1 - [dist] rustc - [dist] rustc 1 -> std 1 - [dist] rustc 1 -> rustc-dev 2 - [dist] src <> - [dist] reproducible-artifacts - " - ); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 0 -> UnstableBookGen 1 + [build] rustc 0 -> Rustbook 1 + [doc] unstable-book (book) + [doc] book (book) + [doc] book/first-edition (book) + [doc] book/second-edition (book) + [doc] book/2018-edition (book) + [build] rustdoc 1 + [doc] rustc 1 -> standalone 2 + [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [build] rustc 1 -> rustc 2 + [build] rustc 1 -> error-index 2 + [doc] rustc 1 -> error-index 2 + [doc] nomicon (book) + [doc] rustc 1 -> reference (book) 2 + [doc] rustdoc (book) + [doc] rust-by-example (book) + [build] rustc 0 -> LintDocs 1 + [doc] rustc (book) + [doc] cargo (book) + [doc] clippy (book) + [doc] embedded-book (book) + [doc] edition-guide (book) + [doc] style-guide (book) + [doc] rustc 1 -> releases 2 + [build] rustc 0 -> RustInstaller 1 + [dist] docs + [doc] rustc 1 -> std 1 crates=[] + [dist] rustc 1 -> json-docs 2 + [dist] mingw + [build] rustdoc 2 + [build] rustc 0 -> GenerateCopyright 1 + [dist] rustc + [dist] rustc 1 -> std 1 + [dist] rustc 1 -> rustc-dev 2 + [dist] src <> + [dist] reproducible-artifacts "#]].assert_eq(&ctx + .config("dist") + .render_steps()); } #[test] fn dist_extended() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("dist") - .args(&[ - "--set", - "build.extended=true", - "--set", - "rust.llvm-bitcode-linker=true", - "--set", - "rust.lld=true", - ]) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 0 -> LldWrapper 1 - [build] rustc 0 -> WasmComponentLd 1 - [build] rustc 0 -> LlvmBitcodeLinker 1 - [build] rustc 1 -> std 1 - [build] rustc 0 -> UnstableBookGen 1 - [build] rustc 0 -> Rustbook 1 - [doc] unstable-book (book) - [doc] book (book) - [doc] book/first-edition (book) - [doc] book/second-edition (book) - [doc] book/2018-edition (book) - [build] rustdoc 1 - [doc] rustc 1 -> standalone 2 - [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] - [build] rustc 1 -> rustc 2 - [build] rustc 1 -> LldWrapper 2 - [build] rustc 1 -> WasmComponentLd 2 - [build] rustc 1 -> LlvmBitcodeLinker 2 - [build] rustc 1 -> error-index 2 - [doc] rustc 1 -> error-index 2 - [doc] nomicon (book) - [doc] rustc 1 -> reference (book) 2 - [doc] rustdoc (book) - [doc] rust-by-example (book) - [build] rustc 0 -> LintDocs 1 - [doc] rustc (book) - [doc] cargo (book) - [doc] clippy (book) - [doc] embedded-book (book) - [doc] edition-guide (book) - [doc] style-guide (book) - [doc] rustc 1 -> releases 2 - [build] rustc 0 -> RustInstaller 1 - [dist] docs - [doc] rustc 1 -> std 1 crates=[] - [dist] rustc 1 -> json-docs 2 - [dist] mingw - [build] rustdoc 2 - [build] rustc 1 -> rust-analyzer-proc-macro-srv 2 - [build] rustc 0 -> GenerateCopyright 1 - [dist] rustc - [dist] rustc 1 -> std 1 - [dist] rustc 1 -> rustc-dev 2 - [dist] rustc 1 -> analysis 2 - [dist] src <> - [build] rustc 1 -> cargo 2 - [dist] rustc 1 -> cargo 2 - [build] rustc 1 -> rust-analyzer 2 - [dist] rustc 1 -> rust-analyzer 2 - [build] rustc 1 -> rustfmt 2 - [build] rustc 1 -> cargo-fmt 2 - [dist] rustc 1 -> rustfmt 2 - [build] rustc 1 -> clippy-driver 2 - [build] rustc 1 -> cargo-clippy 2 - [dist] rustc 1 -> clippy 2 - [build] rustc 1 -> miri 2 - [build] rustc 1 -> cargo-miri 2 - [dist] rustc 1 -> miri 2 - [doc] rustc 2 -> std 2 crates=[] - [dist] rustc 2 -> json-docs 3 - [dist] rustc 1 -> extended 2 - [dist] reproducible-artifacts - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 0 -> LldWrapper 1 + [build] rustc 0 -> WasmComponentLd 1 + [build] rustc 0 -> LlvmBitcodeLinker 1 + [build] rustc 1 -> std 1 + [build] rustc 0 -> UnstableBookGen 1 + [build] rustc 0 -> Rustbook 1 + [doc] unstable-book (book) + [doc] book (book) + [doc] book/first-edition (book) + [doc] book/second-edition (book) + [doc] book/2018-edition (book) + [build] rustdoc 1 + [doc] rustc 1 -> standalone 2 + [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [build] rustc 1 -> rustc 2 + [build] rustc 1 -> LldWrapper 2 + [build] rustc 1 -> WasmComponentLd 2 + [build] rustc 1 -> LlvmBitcodeLinker 2 + [build] rustc 1 -> error-index 2 + [doc] rustc 1 -> error-index 2 + [doc] nomicon (book) + [doc] rustc 1 -> reference (book) 2 + [doc] rustdoc (book) + [doc] rust-by-example (book) + [build] rustc 0 -> LintDocs 1 + [doc] rustc (book) + [doc] cargo (book) + [doc] clippy (book) + [doc] embedded-book (book) + [doc] edition-guide (book) + [doc] style-guide (book) + [doc] rustc 1 -> releases 2 + [build] rustc 0 -> RustInstaller 1 + [dist] docs + [doc] rustc 1 -> std 1 crates=[] + [dist] rustc 1 -> json-docs 2 + [dist] mingw + [build] rustdoc 2 + [build] rustc 1 -> rust-analyzer-proc-macro-srv 2 + [build] rustc 0 -> GenerateCopyright 1 + [dist] rustc + [dist] rustc 1 -> std 1 + [dist] rustc 1 -> rustc-dev 2 + [dist] rustc 1 -> analysis 2 + [dist] src <> + [build] rustc 1 -> cargo 2 + [dist] rustc 1 -> cargo 2 + [build] rustc 1 -> rust-analyzer 2 + [dist] rustc 1 -> rust-analyzer 2 + [build] rustc 1 -> rustfmt 2 + [build] rustc 1 -> cargo-fmt 2 + [dist] rustc 1 -> rustfmt 2 + [build] rustc 1 -> clippy-driver 2 + [build] rustc 1 -> cargo-clippy 2 + [dist] rustc 1 -> clippy 2 + [build] rustc 1 -> miri 2 + [build] rustc 1 -> cargo-miri 2 + [dist] rustc 1 -> miri 2 + [doc] rustc 2 -> std 2 crates=[] + [dist] rustc 2 -> json-docs 3 + [dist] rustc 1 -> extended 2 + [dist] reproducible-artifacts "#]].assert_eq(&ctx.config("dist") + .args(&[ + "--set", + "build.extended=true", + "--set", + "rust.llvm-bitcode-linker=true", + "--set", + "rust.lld=true", + ]) + .render_steps()); } #[test] fn dist_with_targets() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx - .config("dist") - .hosts(&[&host_target()]) - .targets(&[&host_target(), TEST_TRIPLE_1]) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 0 -> UnstableBookGen 1 - [build] rustc 0 -> Rustbook 1 - [doc] unstable-book (book) - [build] rustc 1 -> std 1 - [doc] unstable-book (book) - [doc] book (book) - [doc] book/first-edition (book) - [doc] book/second-edition (book) - [doc] book/2018-edition (book) - [doc] book (book) - [doc] book/first-edition (book) - [doc] book/second-edition (book) - [doc] book/2018-edition (book) - [build] rustdoc 1 - [doc] rustc 1 -> standalone 2 - [doc] rustc 1 -> standalone 2 - [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] - [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] - [build] rustc 1 -> rustc 2 - [build] rustc 1 -> error-index 2 - [doc] rustc 1 -> error-index 2 - [doc] nomicon (book) - [doc] nomicon (book) - [doc] rustc 1 -> reference (book) 2 - [doc] rustc 1 -> reference (book) 2 - [doc] rustdoc (book) - [doc] rustdoc (book) - [doc] rust-by-example (book) - [doc] rust-by-example (book) - [build] rustc 0 -> LintDocs 1 - [doc] rustc (book) - [doc] cargo (book) - [doc] cargo (book) - [doc] clippy (book) - [doc] clippy (book) - [doc] embedded-book (book) - [doc] embedded-book (book) - [doc] edition-guide (book) - [doc] edition-guide (book) - [doc] style-guide (book) - [doc] style-guide (book) - [doc] rustc 1 -> releases 2 - [doc] rustc 1 -> releases 2 - [build] rustc 0 -> RustInstaller 1 - [dist] docs - [dist] docs - [doc] rustc 1 -> std 1 crates=[] - [dist] rustc 1 -> json-docs 2 - [doc] rustc 1 -> std 1 crates=[] - [dist] rustc 1 -> json-docs 2 - [dist] mingw - [dist] mingw - [build] rustdoc 2 - [build] rustc 0 -> GenerateCopyright 1 - [dist] rustc - [dist] rustc 1 -> std 1 - [dist] rustc 1 -> std 1 - [dist] rustc 1 -> rustc-dev 2 - [dist] src <> - [dist] reproducible-artifacts - " - ); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 0 -> UnstableBookGen 1 + [build] rustc 0 -> Rustbook 1 + [doc] unstable-book (book) + [build] rustc 1 -> std 1 + [doc] unstable-book (book) + [doc] book (book) + [doc] book/first-edition (book) + [doc] book/second-edition (book) + [doc] book/2018-edition (book) + [doc] book (book) + [doc] book/first-edition (book) + [doc] book/second-edition (book) + [doc] book/2018-edition (book) + [build] rustdoc 1 + [doc] rustc 1 -> standalone 2 + [doc] rustc 1 -> standalone 2 + [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [build] rustc 1 -> rustc 2 + [build] rustc 1 -> error-index 2 + [doc] rustc 1 -> error-index 2 + [doc] nomicon (book) + [doc] nomicon (book) + [doc] rustc 1 -> reference (book) 2 + [doc] rustc 1 -> reference (book) 2 + [doc] rustdoc (book) + [doc] rustdoc (book) + [doc] rust-by-example (book) + [doc] rust-by-example (book) + [build] rustc 0 -> LintDocs 1 + [doc] rustc (book) + [doc] cargo (book) + [doc] cargo (book) + [doc] clippy (book) + [doc] clippy (book) + [doc] embedded-book (book) + [doc] embedded-book (book) + [doc] edition-guide (book) + [doc] edition-guide (book) + [doc] style-guide (book) + [doc] style-guide (book) + [doc] rustc 1 -> releases 2 + [doc] rustc 1 -> releases 2 + [build] rustc 0 -> RustInstaller 1 + [dist] docs + [dist] docs + [doc] rustc 1 -> std 1 crates=[] + [dist] rustc 1 -> json-docs 2 + [doc] rustc 1 -> std 1 crates=[] + [dist] rustc 1 -> json-docs 2 + [dist] mingw + [dist] mingw + [build] rustdoc 2 + [build] rustc 0 -> GenerateCopyright 1 + [dist] rustc + [dist] rustc 1 -> std 1 + [dist] rustc 1 -> std 1 + [dist] rustc 1 -> rustc-dev 2 + [dist] src <> + [dist] reproducible-artifacts "#]].assert_eq(&ctx + .config("dist") + .hosts(&[&host_target()]) + .targets(&[&host_target(), TEST_TRIPLE_1]) + .render_steps()); } #[test] fn dist_with_hosts() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx - .config("dist") - .hosts(&[&host_target(), TEST_TRIPLE_1]) - .targets(&[&host_target()]) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 0 -> UnstableBookGen 1 - [build] rustc 0 -> Rustbook 1 - [doc] unstable-book (book) - [build] rustc 1 -> std 1 - [doc] book (book) - [doc] book/first-edition (book) - [doc] book/second-edition (book) - [doc] book/2018-edition (book) - [build] rustdoc 1 - [doc] rustc 1 -> standalone 2 - [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] - [build] rustc 1 -> rustc 2 - [build] rustc 1 -> error-index 2 - [doc] rustc 1 -> error-index 2 - [build] llvm - [build] rustc 1 -> rustc 2 - [build] rustc 1 -> error-index 2 - [doc] rustc 1 -> error-index 2 - [doc] nomicon (book) - [doc] rustc 1 -> reference (book) 2 - [doc] rustdoc (book) - [doc] rust-by-example (book) - [build] rustc 0 -> LintDocs 1 - [doc] rustc (book) - [doc] rustc (book) - [doc] cargo (book) - [doc] clippy (book) - [doc] embedded-book (book) - [doc] edition-guide (book) - [doc] style-guide (book) - [doc] rustc 1 -> releases 2 - [build] rustc 0 -> RustInstaller 1 - [dist] docs - [doc] rustc 1 -> std 1 crates=[] - [dist] rustc 1 -> json-docs 2 - [dist] mingw - [build] rustdoc 2 - [build] rustc 0 -> GenerateCopyright 1 - [dist] rustc - [build] rustdoc 2 - [dist] rustc - [dist] rustc 1 -> std 1 - [dist] rustc 1 -> rustc-dev 2 - [dist] rustc 1 -> rustc-dev 2 - [dist] src <> - [dist] reproducible-artifacts - [dist] reproducible-artifacts - " - ); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 0 -> UnstableBookGen 1 + [build] rustc 0 -> Rustbook 1 + [doc] unstable-book (book) + [build] rustc 1 -> std 1 + [doc] book (book) + [doc] book/first-edition (book) + [doc] book/second-edition (book) + [doc] book/2018-edition (book) + [build] rustdoc 1 + [doc] rustc 1 -> standalone 2 + [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [build] rustc 1 -> rustc 2 + [build] rustc 1 -> error-index 2 + [doc] rustc 1 -> error-index 2 + [build] llvm + [build] rustc 1 -> rustc 2 + [build] rustc 1 -> error-index 2 + [doc] rustc 1 -> error-index 2 + [doc] nomicon (book) + [doc] rustc 1 -> reference (book) 2 + [doc] rustdoc (book) + [doc] rust-by-example (book) + [build] rustc 0 -> LintDocs 1 + [doc] rustc (book) + [doc] rustc (book) + [doc] cargo (book) + [doc] clippy (book) + [doc] embedded-book (book) + [doc] edition-guide (book) + [doc] style-guide (book) + [doc] rustc 1 -> releases 2 + [build] rustc 0 -> RustInstaller 1 + [dist] docs + [doc] rustc 1 -> std 1 crates=[] + [dist] rustc 1 -> json-docs 2 + [dist] mingw + [build] rustdoc 2 + [build] rustc 0 -> GenerateCopyright 1 + [dist] rustc + [build] rustdoc 2 + [dist] rustc + [dist] rustc 1 -> std 1 + [dist] rustc 1 -> rustc-dev 2 + [dist] rustc 1 -> rustc-dev 2 + [dist] src <> + [dist] reproducible-artifacts + [dist] reproducible-artifacts "#]].assert_eq(&ctx + .config("dist") + .hosts(&[&host_target(), TEST_TRIPLE_1]) + .targets(&[&host_target()]) + .render_steps()); } #[test] fn dist_with_targets_and_hosts() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx - .config("dist") - .hosts(&[&host_target(), TEST_TRIPLE_1]) - .targets(&[&host_target(), TEST_TRIPLE_1]) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 0 -> UnstableBookGen 1 - [build] rustc 0 -> Rustbook 1 - [doc] unstable-book (book) - [build] rustc 1 -> std 1 - [doc] unstable-book (book) - [doc] book (book) - [doc] book/first-edition (book) - [doc] book/second-edition (book) - [doc] book/2018-edition (book) - [doc] book (book) - [doc] book/first-edition (book) - [doc] book/second-edition (book) - [doc] book/2018-edition (book) - [build] rustdoc 1 - [doc] rustc 1 -> standalone 2 - [doc] rustc 1 -> standalone 2 - [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] - [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] - [build] rustc 1 -> rustc 2 - [build] rustc 1 -> error-index 2 - [doc] rustc 1 -> error-index 2 - [build] llvm - [build] rustc 1 -> rustc 2 - [build] rustc 1 -> error-index 2 - [doc] rustc 1 -> error-index 2 - [doc] nomicon (book) - [doc] nomicon (book) - [doc] rustc 1 -> reference (book) 2 - [doc] rustc 1 -> reference (book) 2 - [doc] rustdoc (book) - [doc] rustdoc (book) - [doc] rust-by-example (book) - [doc] rust-by-example (book) - [build] rustc 0 -> LintDocs 1 - [doc] rustc (book) - [doc] rustc (book) - [doc] cargo (book) - [doc] cargo (book) - [doc] clippy (book) - [doc] clippy (book) - [doc] embedded-book (book) - [doc] embedded-book (book) - [doc] edition-guide (book) - [doc] edition-guide (book) - [doc] style-guide (book) - [doc] style-guide (book) - [doc] rustc 1 -> releases 2 - [doc] rustc 1 -> releases 2 - [build] rustc 0 -> RustInstaller 1 - [dist] docs - [dist] docs - [doc] rustc 1 -> std 1 crates=[] - [dist] rustc 1 -> json-docs 2 - [doc] rustc 1 -> std 1 crates=[] - [dist] rustc 1 -> json-docs 2 - [dist] mingw - [dist] mingw - [build] rustdoc 2 - [build] rustc 0 -> GenerateCopyright 1 - [dist] rustc - [build] rustdoc 2 - [dist] rustc - [dist] rustc 1 -> std 1 - [dist] rustc 1 -> std 1 - [dist] rustc 1 -> rustc-dev 2 - [dist] rustc 1 -> rustc-dev 2 - [dist] src <> - [dist] reproducible-artifacts - [dist] reproducible-artifacts - " - ); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 0 -> UnstableBookGen 1 + [build] rustc 0 -> Rustbook 1 + [doc] unstable-book (book) + [build] rustc 1 -> std 1 + [doc] unstable-book (book) + [doc] book (book) + [doc] book/first-edition (book) + [doc] book/second-edition (book) + [doc] book/2018-edition (book) + [doc] book (book) + [doc] book/first-edition (book) + [doc] book/second-edition (book) + [doc] book/2018-edition (book) + [build] rustdoc 1 + [doc] rustc 1 -> standalone 2 + [doc] rustc 1 -> standalone 2 + [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [build] rustc 1 -> rustc 2 + [build] rustc 1 -> error-index 2 + [doc] rustc 1 -> error-index 2 + [build] llvm + [build] rustc 1 -> rustc 2 + [build] rustc 1 -> error-index 2 + [doc] rustc 1 -> error-index 2 + [doc] nomicon (book) + [doc] nomicon (book) + [doc] rustc 1 -> reference (book) 2 + [doc] rustc 1 -> reference (book) 2 + [doc] rustdoc (book) + [doc] rustdoc (book) + [doc] rust-by-example (book) + [doc] rust-by-example (book) + [build] rustc 0 -> LintDocs 1 + [doc] rustc (book) + [doc] rustc (book) + [doc] cargo (book) + [doc] cargo (book) + [doc] clippy (book) + [doc] clippy (book) + [doc] embedded-book (book) + [doc] embedded-book (book) + [doc] edition-guide (book) + [doc] edition-guide (book) + [doc] style-guide (book) + [doc] style-guide (book) + [doc] rustc 1 -> releases 2 + [doc] rustc 1 -> releases 2 + [build] rustc 0 -> RustInstaller 1 + [dist] docs + [dist] docs + [doc] rustc 1 -> std 1 crates=[] + [dist] rustc 1 -> json-docs 2 + [doc] rustc 1 -> std 1 crates=[] + [dist] rustc 1 -> json-docs 2 + [dist] mingw + [dist] mingw + [build] rustdoc 2 + [build] rustc 0 -> GenerateCopyright 1 + [dist] rustc + [build] rustdoc 2 + [dist] rustc + [dist] rustc 1 -> std 1 + [dist] rustc 1 -> std 1 + [dist] rustc 1 -> rustc-dev 2 + [dist] rustc 1 -> rustc-dev 2 + [dist] src <> + [dist] reproducible-artifacts + [dist] reproducible-artifacts "#]].assert_eq(&ctx + .config("dist") + .hosts(&[&host_target(), TEST_TRIPLE_1]) + .targets(&[&host_target(), TEST_TRIPLE_1]) + .render_steps()); } #[test] fn dist_with_empty_host() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx - .config("dist") - .hosts(&[]) - .targets(&[TEST_TRIPLE_1]) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 0 -> UnstableBookGen 1 - [build] rustc 0 -> Rustbook 1 - [doc] unstable-book (book) - [doc] book (book) - [doc] book/first-edition (book) - [doc] book/second-edition (book) - [doc] book/2018-edition (book) - [build] rustc 1 -> std 1 - [build] rustdoc 1 - [doc] rustc 1 -> standalone 2 - [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] - [doc] nomicon (book) - [doc] rustc 1 -> reference (book) 2 - [doc] rustdoc (book) - [doc] rust-by-example (book) - [doc] cargo (book) - [doc] clippy (book) - [doc] embedded-book (book) - [doc] edition-guide (book) - [doc] style-guide (book) - [doc] rustc 1 -> releases 2 - [build] rustc 0 -> RustInstaller 1 - [dist] docs - [doc] rustc 1 -> std 1 crates=[] - [dist] rustc 1 -> json-docs 2 - [dist] mingw - [dist] rustc 1 -> std 1 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 0 -> UnstableBookGen 1 + [build] rustc 0 -> Rustbook 1 + [doc] unstable-book (book) + [doc] book (book) + [doc] book/first-edition (book) + [doc] book/second-edition (book) + [doc] book/2018-edition (book) + [build] rustc 1 -> std 1 + [build] rustdoc 1 + [doc] rustc 1 -> standalone 2 + [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [doc] nomicon (book) + [doc] rustc 1 -> reference (book) 2 + [doc] rustdoc (book) + [doc] rust-by-example (book) + [doc] cargo (book) + [doc] clippy (book) + [doc] embedded-book (book) + [doc] edition-guide (book) + [doc] style-guide (book) + [doc] rustc 1 -> releases 2 + [build] rustc 0 -> RustInstaller 1 + [dist] docs + [doc] rustc 1 -> std 1 crates=[] + [dist] rustc 1 -> json-docs 2 + [dist] mingw + [dist] rustc 1 -> std 1 "#]].assert_eq(&ctx + .config("dist") + .hosts(&[]) + .targets(&[TEST_TRIPLE_1]) + .render_steps()); } #[test] fn dist_all_cross_extended() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx - .config("dist") - .hosts(&[TEST_TRIPLE_1]) - .targets(&[TEST_TRIPLE_1]) - .args(&["--set", "rust.channel=nightly", "--set", "build.extended=true"]) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 0 -> WasmComponentLd 1 - [build] rustc 1 -> std 1 - [build] rustc 0 -> UnstableBookGen 1 - [build] rustc 0 -> Rustbook 1 - [doc] unstable-book (book) - [doc] book (book) - [doc] book/first-edition (book) - [doc] book/second-edition (book) - [doc] book/2018-edition (book) - [build] rustc 1 -> std 1 - [build] rustdoc 1 - [doc] rustc 1 -> standalone 2 - [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] - [build] llvm - [build] rustc 1 -> rustc 2 - [build] rustc 1 -> WasmComponentLd 2 - [build] rustc 1 -> error-index 2 - [doc] rustc 1 -> error-index 2 - [doc] nomicon (book) - [doc] rustc 1 -> reference (book) 2 - [doc] rustdoc (book) - [doc] rust-by-example (book) - [build] rustc 0 -> LintDocs 1 - [doc] rustc (book) - [doc] cargo (book) - [doc] clippy (book) - [doc] embedded-book (book) - [doc] edition-guide (book) - [doc] style-guide (book) - [doc] rustc 1 -> releases 2 - [build] rustc 0 -> RustInstaller 1 - [dist] docs - [doc] rustc 1 -> std 1 crates=[] - [dist] rustc 1 -> json-docs 2 - [dist] mingw - [build] rustdoc 2 - [build] rustc 1 -> rust-analyzer-proc-macro-srv 2 - [build] rustc 0 -> GenerateCopyright 1 - [dist] rustc - [dist] rustc 1 -> std 1 - [dist] rustc 1 -> rustc-dev 2 - [dist] rustc 1 -> analysis 2 - [dist] src <> - [build] rustc 1 -> cargo 2 - [dist] rustc 1 -> cargo 2 - [build] rustc 1 -> rust-analyzer 2 - [dist] rustc 1 -> rust-analyzer 2 - [build] rustc 1 -> rustfmt 2 - [build] rustc 1 -> cargo-fmt 2 - [dist] rustc 1 -> rustfmt 2 - [build] rustc 1 -> clippy-driver 2 - [build] rustc 1 -> cargo-clippy 2 - [dist] rustc 1 -> clippy 2 - [build] rustc 1 -> miri 2 - [build] rustc 1 -> cargo-miri 2 - [dist] rustc 1 -> miri 2 - [build] rustc 1 -> LlvmBitcodeLinker 2 - [doc] rustc 2 -> std 2 crates=[] - [dist] rustc 2 -> json-docs 3 - [dist] rustc 1 -> extended 2 - [dist] reproducible-artifacts - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 0 -> WasmComponentLd 1 + [build] rustc 1 -> std 1 + [build] rustc 0 -> UnstableBookGen 1 + [build] rustc 0 -> Rustbook 1 + [doc] unstable-book (book) + [doc] book (book) + [doc] book/first-edition (book) + [doc] book/second-edition (book) + [doc] book/2018-edition (book) + [build] rustc 1 -> std 1 + [build] rustdoc 1 + [doc] rustc 1 -> standalone 2 + [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [build] llvm + [build] rustc 1 -> rustc 2 + [build] rustc 1 -> WasmComponentLd 2 + [build] rustc 1 -> error-index 2 + [doc] rustc 1 -> error-index 2 + [doc] nomicon (book) + [doc] rustc 1 -> reference (book) 2 + [doc] rustdoc (book) + [doc] rust-by-example (book) + [build] rustc 0 -> LintDocs 1 + [doc] rustc (book) + [doc] cargo (book) + [doc] clippy (book) + [doc] embedded-book (book) + [doc] edition-guide (book) + [doc] style-guide (book) + [doc] rustc 1 -> releases 2 + [build] rustc 0 -> RustInstaller 1 + [dist] docs + [doc] rustc 1 -> std 1 crates=[] + [dist] rustc 1 -> json-docs 2 + [dist] mingw + [build] rustdoc 2 + [build] rustc 1 -> rust-analyzer-proc-macro-srv 2 + [build] rustc 0 -> GenerateCopyright 1 + [dist] rustc + [dist] rustc 1 -> std 1 + [dist] rustc 1 -> rustc-dev 2 + [dist] rustc 1 -> analysis 2 + [dist] src <> + [build] rustc 1 -> cargo 2 + [dist] rustc 1 -> cargo 2 + [build] rustc 1 -> rust-analyzer 2 + [dist] rustc 1 -> rust-analyzer 2 + [build] rustc 1 -> rustfmt 2 + [build] rustc 1 -> cargo-fmt 2 + [dist] rustc 1 -> rustfmt 2 + [build] rustc 1 -> clippy-driver 2 + [build] rustc 1 -> cargo-clippy 2 + [dist] rustc 1 -> clippy 2 + [build] rustc 1 -> miri 2 + [build] rustc 1 -> cargo-miri 2 + [dist] rustc 1 -> miri 2 + [build] rustc 1 -> LlvmBitcodeLinker 2 + [doc] rustc 2 -> std 2 crates=[] + [dist] rustc 2 -> json-docs 3 + [dist] rustc 1 -> extended 2 + [dist] reproducible-artifacts "#]].assert_eq(&ctx + .config("dist") + .hosts(&[TEST_TRIPLE_1]) + .targets(&[TEST_TRIPLE_1]) + .args(&["--set", "rust.channel=nightly", "--set", "build.extended=true"]) + .render_steps()); } /// Simulates e.g. the powerpc64 builder, which is fully cross-compiled from x64, but it does @@ -1441,43 +1346,42 @@ mod snapshot { && *m.target.triple == host_target() }); - insta::assert_snapshot!( - steps.render(), @r" - [dist] mingw - [build] llvm - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 0 -> WasmComponentLd 1 - [build] rustc 1 -> std 1 - [build] rustc 1 -> std 1 - [build] rustc 1 -> rustc 2 - [build] rustc 1 -> WasmComponentLd 2 - [build] rustdoc 2 - [build] rustc 1 -> rust-analyzer-proc-macro-srv 2 - [build] rustc 0 -> GenerateCopyright 1 - [build] rustc 0 -> RustInstaller 1 - [dist] rustc - [dist] rustc 1 -> std 1 - [dist] rustc 1 -> rustc-dev 2 - [dist] rustc 1 -> analysis 2 - [dist] src <> - [build] rustc 1 -> cargo 2 - [dist] rustc 1 -> cargo 2 - [build] rustc 1 -> rust-analyzer 2 - [dist] rustc 1 -> rust-analyzer 2 - [build] rustc 1 -> rustfmt 2 - [build] rustc 1 -> cargo-fmt 2 - [dist] rustc 1 -> rustfmt 2 - [build] rustc 1 -> clippy-driver 2 - [build] rustc 1 -> cargo-clippy 2 - [dist] rustc 1 -> clippy 2 - [build] rustc 1 -> miri 2 - [build] rustc 1 -> cargo-miri 2 - [dist] rustc 1 -> miri 2 - [build] rustc 1 -> LlvmBitcodeLinker 2 - [dist] rustc 1 -> extended 2 - [dist] reproducible-artifacts - "); + expect_test::expect![[r#" + [dist] mingw + [build] llvm + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 0 -> WasmComponentLd 1 + [build] rustc 1 -> std 1 + [build] rustc 1 -> std 1 + [build] rustc 1 -> rustc 2 + [build] rustc 1 -> WasmComponentLd 2 + [build] rustdoc 2 + [build] rustc 1 -> rust-analyzer-proc-macro-srv 2 + [build] rustc 0 -> GenerateCopyright 1 + [build] rustc 0 -> RustInstaller 1 + [dist] rustc + [dist] rustc 1 -> std 1 + [dist] rustc 1 -> rustc-dev 2 + [dist] rustc 1 -> analysis 2 + [dist] src <> + [build] rustc 1 -> cargo 2 + [dist] rustc 1 -> cargo 2 + [build] rustc 1 -> rust-analyzer 2 + [dist] rustc 1 -> rust-analyzer 2 + [build] rustc 1 -> rustfmt 2 + [build] rustc 1 -> cargo-fmt 2 + [dist] rustc 1 -> rustfmt 2 + [build] rustc 1 -> clippy-driver 2 + [build] rustc 1 -> cargo-clippy 2 + [dist] rustc 1 -> clippy 2 + [build] rustc 1 -> miri 2 + [build] rustc 1 -> cargo-miri 2 + [dist] rustc 1 -> miri 2 + [build] rustc 1 -> LlvmBitcodeLinker 2 + [dist] rustc 1 -> extended 2 + [dist] reproducible-artifacts "#]] + .assert_eq(&steps.render()); } /// Enable dist cranelift tarball by default with `x dist` if cranelift is enabled in @@ -1485,131 +1389,118 @@ mod snapshot { #[test] fn dist_cranelift_by_default() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx - .config("dist") - .args(&["--set", "rust.codegen-backends=['llvm', 'cranelift']"]) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 0 -> rustc_codegen_cranelift 1 - [build] rustc 1 -> std 1 - [build] rustc 0 -> UnstableBookGen 1 - [build] rustc 0 -> Rustbook 1 - [doc] unstable-book (book) - [doc] book (book) - [doc] book/first-edition (book) - [doc] book/second-edition (book) - [doc] book/2018-edition (book) - [build] rustdoc 1 - [doc] rustc 1 -> standalone 2 - [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] - [build] rustc 1 -> rustc 2 - [build] rustc 1 -> rustc_codegen_cranelift 2 - [build] rustc 1 -> error-index 2 - [doc] rustc 1 -> error-index 2 - [doc] nomicon (book) - [doc] rustc 1 -> reference (book) 2 - [doc] rustdoc (book) - [doc] rust-by-example (book) - [build] rustc 0 -> LintDocs 1 - [doc] rustc (book) - [doc] cargo (book) - [doc] clippy (book) - [doc] embedded-book (book) - [doc] edition-guide (book) - [doc] style-guide (book) - [doc] rustc 1 -> releases 2 - [build] rustc 0 -> RustInstaller 1 - [dist] docs - [doc] rustc 1 -> std 1 crates=[] - [dist] rustc 1 -> json-docs 2 - [dist] mingw - [build] rustdoc 2 - [build] rustc 0 -> GenerateCopyright 1 - [dist] rustc - [dist] rustc 1 -> rustc_codegen_cranelift 2 - [dist] rustc 1 -> std 1 - [dist] rustc 1 -> rustc-dev 2 - [dist] src <> - [dist] reproducible-artifacts - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 0 -> rustc_codegen_cranelift 1 + [build] rustc 1 -> std 1 + [build] rustc 0 -> UnstableBookGen 1 + [build] rustc 0 -> Rustbook 1 + [doc] unstable-book (book) + [doc] book (book) + [doc] book/first-edition (book) + [doc] book/second-edition (book) + [doc] book/2018-edition (book) + [build] rustdoc 1 + [doc] rustc 1 -> standalone 2 + [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [build] rustc 1 -> rustc 2 + [build] rustc 1 -> rustc_codegen_cranelift 2 + [build] rustc 1 -> error-index 2 + [doc] rustc 1 -> error-index 2 + [doc] nomicon (book) + [doc] rustc 1 -> reference (book) 2 + [doc] rustdoc (book) + [doc] rust-by-example (book) + [build] rustc 0 -> LintDocs 1 + [doc] rustc (book) + [doc] cargo (book) + [doc] clippy (book) + [doc] embedded-book (book) + [doc] edition-guide (book) + [doc] style-guide (book) + [doc] rustc 1 -> releases 2 + [build] rustc 0 -> RustInstaller 1 + [dist] docs + [doc] rustc 1 -> std 1 crates=[] + [dist] rustc 1 -> json-docs 2 + [dist] mingw + [build] rustdoc 2 + [build] rustc 0 -> GenerateCopyright 1 + [dist] rustc + [dist] rustc 1 -> rustc_codegen_cranelift 2 + [dist] rustc 1 -> std 1 + [dist] rustc 1 -> rustc-dev 2 + [dist] src <> + [dist] reproducible-artifacts "#]].assert_eq(&ctx + .config("dist") + .args(&["--set", "rust.codegen-backends=['llvm', 'cranelift']"]) + .render_steps()); } #[test] fn dist_bootstrap() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx - .config("dist") - .path("bootstrap") - .render_steps(), @r" - [build] rustc 0 -> RustInstaller 1 - [dist] bootstrap - "); + expect_test::expect![[r#" + [build] rustc 0 -> RustInstaller 1 + [dist] bootstrap "#]] + .assert_eq(&ctx.config("dist").path("bootstrap").render_steps()); } #[test] fn dist_library_stage_0_local_rebuild() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("dist") + expect_test::expect![[r#" + [build] rustc 0 -> std 0 + [build] rustc 0 -> RustInstaller 1 + [dist] rustc 0 -> std 0 "#]] + .assert_eq( + &ctx.config("dist") .path("rust-std") .stage(0) .targets(&[TEST_TRIPLE_1]) .args(&["--set", "build.local-rebuild=true"]) - .render_steps(), @r" - [build] rustc 0 -> std 0 - [build] rustc 0 -> RustInstaller 1 - [dist] rustc 0 -> std 0 - "); + .render_steps(), + ); } #[test] fn dist_rustc_docs() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx - .config("dist") - .path("rustc-docs") - .render_steps(), @" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustdoc 1 - [doc] rustc 1 -> rustc 2 - [build] rustc 1 -> rustc 2 - [doc] rustc 1 -> Rustdoc 2 - [doc] rustc 1 -> Rustfmt 2 - [doc] rustc 1 -> Clippy 2 - [doc] rustc 1 -> Miri 2 - [doc] rustc 1 -> Cargo 2 - [doc] rustc 1 -> Tidy 2 - [doc] rustc 1 -> Bootstrap 2 - [doc] rustc 1 -> BuildHelper 2 - [doc] rustc 1 -> Compiletest 2 - [doc] rustc 1 -> RunMakeSupport 2 - [doc] rustc 1 -> CompilerWithTools 2 - [build] rustc 0 -> RustInstaller 1 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustdoc 1 + [doc] rustc 1 -> rustc 2 + [build] rustc 1 -> rustc 2 + [doc] rustc 1 -> Rustdoc 2 + [doc] rustc 1 -> Rustfmt 2 + [doc] rustc 1 -> Clippy 2 + [doc] rustc 1 -> Miri 2 + [doc] rustc 1 -> Cargo 2 + [doc] rustc 1 -> Tidy 2 + [doc] rustc 1 -> Bootstrap 2 + [doc] rustc 1 -> BuildHelper 2 + [doc] rustc 1 -> Compiletest 2 + [doc] rustc 1 -> RunMakeSupport 2 + [doc] rustc 1 -> CompilerWithTools 2 + [build] rustc 0 -> RustInstaller 1 "#]] + .assert_eq(&ctx.config("dist").path("rustc-docs").render_steps()); } #[test] fn check_compiler_no_explicit_stage() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("check") - .path("compiler") - .render_steps(), @"[check] rustc 0 -> rustc 1 (78 crates)"); + expect_test::expect![["[check] rustc 0 -> rustc 1 (78 crates)"]] + .assert_eq(&ctx.config("check").path("compiler").render_steps()); } #[test] fn check_rustc_no_explicit_stage() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("check") - .path("rustc") - .render_steps(), @"[check] rustc 0 -> rustc 1 (1 crates)"); + expect_test::expect![["[check] rustc 0 -> rustc 1 (1 crates)"]] + .assert_eq(&ctx.config("check").path("rustc").render_steps()); } #[test] @@ -1622,66 +1513,54 @@ mod snapshot { #[test] fn check_compiler_stage_1() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("check") - .path("compiler") - .stage(1) - .render_steps(), @"[check] rustc 0 -> rustc 1 (78 crates)"); + expect_test::expect![["[check] rustc 0 -> rustc 1 (78 crates)"]] + .assert_eq(&ctx.config("check").path("compiler").stage(1).render_steps()); } #[test] fn check_compiler_stage_2() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("check") - .path("compiler") - .stage(2) - .render_steps(), @" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [check] rustc 1 -> rustc 2 (78 crates) - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [check] rustc 1 -> rustc 2 (78 crates)"#]] + .assert_eq(&ctx.config("check").path("compiler").stage(2).render_steps()); } #[test] fn check_cross_compile() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("check") - .targets(&[TEST_TRIPLE_1]) - .hosts(&[TEST_TRIPLE_1]) - .render_steps(), @" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [check] rustc 1 -> std 1 - [check] rustc 1 -> rustc 2 (78 crates) - [check] rustc 1 -> rustc 2 - [check] rustc 1 -> Rustdoc 2 - [check] rustc 1 -> rustc_codegen_cranelift 2 - [check] rustc 1 -> rustc_codegen_gcc 2 - [check] rustc 1 -> Clippy 2 - [check] rustc 1 -> Miri 2 - [check] rustc 1 -> CargoMiri 2 - [check] rustc 1 -> Rustfmt 2 - [check] rustc 1 -> RustAnalyzer 2 - [check] rustc 1 -> TestFloatParse 2 - [check] rustc 1 -> std 1 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [check] rustc 1 -> std 1 + [check] rustc 1 -> rustc 2 (78 crates) + [check] rustc 1 -> rustc 2 + [check] rustc 1 -> Rustdoc 2 + [check] rustc 1 -> rustc_codegen_cranelift 2 + [check] rustc 1 -> rustc_codegen_gcc 2 + [check] rustc 1 -> Clippy 2 + [check] rustc 1 -> Miri 2 + [check] rustc 1 -> CargoMiri 2 + [check] rustc 1 -> Rustfmt 2 + [check] rustc 1 -> RustAnalyzer 2 + [check] rustc 1 -> TestFloatParse 2 + [check] rustc 1 -> std 1 "#]] + .assert_eq( + &ctx.config("check").targets(&[TEST_TRIPLE_1]).hosts(&[TEST_TRIPLE_1]).render_steps(), + ); } #[test] fn check_library_no_explicit_stage() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("check") - .path("library") - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [check] rustc 1 -> std 1 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [check] rustc 1 -> std 1 "#]] + .assert_eq(&ctx.config("check").path("library").render_steps()); } #[test] @@ -1694,46 +1573,39 @@ mod snapshot { #[test] fn check_library_stage_1() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("check") - .path("library") - .stage(1) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [check] rustc 1 -> std 1 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [check] rustc 1 -> std 1 "#]] + .assert_eq(&ctx.config("check").path("library").stage(1).render_steps()); } #[test] fn check_library_stage_2() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("check") - .path("library") - .stage(2) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 1 -> rustc 2 - [check] rustc 2 -> std 2 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 1 -> rustc 2 + [check] rustc 2 -> std 2 "#]] + .assert_eq(&ctx.config("check").path("library").stage(2).render_steps()); } #[test] fn check_library_cross_compile() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("check") + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [check] rustc 1 -> std 1 + [check] rustc 1 -> std 1 "#]] + .assert_eq( + &ctx.config("check") .paths(&["core", "alloc", "std"]) .targets(&[TEST_TRIPLE_1, TEST_TRIPLE_2]) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [check] rustc 1 -> std 1 - [check] rustc 1 -> std 1 - "); + .render_steps(), + ); } /// Make sure that we don't check library when download-rustc is disabled @@ -1742,29 +1614,21 @@ mod snapshot { fn check_library_skip_without_download_rustc() { let ctx = TestCtx::new(); let args = ["--set", "rust.download-rustc=false", "--skip-std-check-if-no-download-rustc"]; - insta::assert_snapshot!( - ctx.config("check") - .paths(&["library"]) - .args(&args) - .render_steps(), @""); + expect_test::expect![[""]] + .assert_eq(&ctx.config("check").paths(&["library"]).args(&args).render_steps()); - insta::assert_snapshot!( - ctx.config("check") - .paths(&["library", "compiler"]) - .args(&args) - .render_steps(), @"[check] rustc 0 -> rustc 1 (78 crates)"); + expect_test::expect![["[check] rustc 0 -> rustc 1 (78 crates)"]].assert_eq( + &ctx.config("check").paths(&["library", "compiler"]).args(&args).render_steps(), + ); } #[test] fn check_miri_no_explicit_stage() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("check") - .path("miri") - .render_steps(), @r" - [check] rustc 0 -> rustc 1 - [check] rustc 0 -> Miri 1 - "); + expect_test::expect![[r#" + [check] rustc 0 -> rustc 1 + [check] rustc 0 -> Miri 1 "#]] + .assert_eq(&ctx.config("check").path("miri").render_steps()); } #[test] @@ -1777,72 +1641,54 @@ mod snapshot { #[test] fn check_miri_stage_1() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("check") - .path("miri") - .stage(1) - .render_steps(), @r" - [check] rustc 0 -> rustc 1 - [check] rustc 0 -> Miri 1 - "); + expect_test::expect![[r#" + [check] rustc 0 -> rustc 1 + [check] rustc 0 -> Miri 1 "#]] + .assert_eq(&ctx.config("check").path("miri").stage(1).render_steps()); } #[test] fn check_miri_stage_2() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("check") - .path("miri") - .stage(2) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [check] rustc 1 -> rustc 2 - [check] rustc 1 -> Miri 2 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [check] rustc 1 -> rustc 2 + [check] rustc 1 -> Miri 2 "#]] + .assert_eq(&ctx.config("check").path("miri").stage(2).render_steps()); } #[test] fn check_compiletest() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("check") - .path("compiletest") - .render_steps(), @"[check] rustc 0 -> Compiletest 1 "); + expect_test::expect![["[check] rustc 0 -> Compiletest 1 "]] + .assert_eq(&ctx.config("check").path("compiletest").render_steps()); } #[test] fn check_codegen() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("check") - .path("rustc_codegen_cranelift") - .render_steps(), @r" - [check] rustc 0 -> rustc 1 - [check] rustc 0 -> rustc_codegen_cranelift 1 - "); + expect_test::expect![[r#" + [check] rustc 0 -> rustc 1 + [check] rustc 0 -> rustc_codegen_cranelift 1 "#]] + .assert_eq(&ctx.config("check").path("rustc_codegen_cranelift").render_steps()); } #[test] fn check_rust_analyzer() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("check") - .path("rust-analyzer") - .render_steps(), @r" - [check] rustc 0 -> rustc 1 - [check] rustc 0 -> RustAnalyzer 1 - "); + expect_test::expect![[r#" + [check] rustc 0 -> rustc 1 + [check] rustc 0 -> RustAnalyzer 1 "#]] + .assert_eq(&ctx.config("check").path("rust-analyzer").render_steps()); } #[test] fn check_bootstrap_tool() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("check") - .path("run-make-support") - .render_steps(), @"[check] rustc 0 -> RunMakeSupport 1 "); + expect_test::expect![["[check] rustc 0 -> RunMakeSupport 1 "]] + .assert_eq(&ctx.config("check").path("run-make-support").render_steps()); } fn prepare_test_config(ctx: &TestCtx) -> ConfigBuilder { @@ -1860,305 +1706,310 @@ mod snapshot { #[test] fn test_all_stage_1() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - prepare_test_config(&ctx) - .render_steps(), @" - [build] rustc 0 -> Tidy 1 - [test] tidy <> - [build] rustdoc 0 - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 0 -> Compiletest 1 - [test] compiletest-ui 1 - [test] compiletest-crashes 1 - [build] rustc 0 -> CoverageDump 1 - [test] compiletest-coverage 1 - [test] compiletest-coverage 1 - [build] rustc 1 -> std 1 - [test] compiletest-mir-opt 1 - [test] compiletest-codegen-llvm 1 - [test] compiletest-codegen-units 1 - [test] compiletest-assembly-gcc 1 - [test] compiletest-assembly-llvm 1 - [test] compiletest-incremental 1 - [test] compiletest-debuginfo 1 - [test] compiletest-ui-fulldeps 1 - [build] rustdoc 1 - [test] compiletest-rustdoc-html 1 - [test] compiletest-coverage-run-rustdoc 1 - [test] compiletest-pretty 1 - [build] rustc 1 -> std 1 - [build] rustc 0 -> std 0 - [test] rustc 0 -> CrateLibrustc 1 - [build] rustc 1 -> rustc 2 - [test] crate-bootstrap src/tools/coverage-dump - [test] crate-bootstrap src/tools/jsondoclint - [test] crate-bootstrap src/tools/replace-version-placeholder - [test] crate-bootstrap tidyselftest - [build] rustc 0 -> UnstableBookGen 1 - [build] rustc 0 -> Rustbook 1 - [doc] unstable-book (book) - [doc] book (book) - [doc] book/first-edition (book) - [doc] book/second-edition (book) - [doc] book/2018-edition (book) - [doc] rustc 0 -> standalone 1 - [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] - [build] rustc 0 -> error-index 1 - [doc] rustc 0 -> error-index 1 - [doc] nomicon (book) - [doc] rustc 1 -> reference (book) 2 - [doc] rustdoc (book) - [doc] rust-by-example (book) - [build] rustc 0 -> LintDocs 1 - [doc] rustc (book) - [doc] cargo (book) - [doc] clippy (book) - [doc] embedded-book (book) - [doc] edition-guide (book) - [doc] style-guide (book) - [doc] rustc 0 -> releases 1 - [build] rustc 0 -> Linkchecker 1 - [test] link-check - [test] tier-check - [test] rustc 0 -> rust-analyzer 1 - [build] rustc 0 -> RustdocTheme 1 - [test] rustdoc-theme 1 - [test] compiletest-rustdoc-ui 1 - [build] rustc 0 -> JsonDocCk 1 - [build] rustc 0 -> JsonDocLint 1 - [test] compiletest-rustdoc-json 1 - [doc] rustc 0 -> rustc 1 - [build] rustc 0 -> HtmlChecker 1 - [test] html-check - [test] test-float-parse - [build] rustc 0 -> RunMakeSupport 1 - [test] compiletest-run-make 1 - [build] rustc 0 -> cargo 1 - [test] compiletest-run-make-cargo 1 - [test] intrinsic-test - "); + expect_test::expect![[r#" + [build] rustc 0 -> Tidy 1 + [test] tidy <> + [build] rustdoc 0 + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 0 -> Compiletest 1 + [test] compiletest-ui 1 + [test] compiletest-crashes 1 + [build] rustc 0 -> CoverageDump 1 + [test] compiletest-coverage 1 + [test] compiletest-coverage 1 + [build] rustc 1 -> std 1 + [test] compiletest-mir-opt 1 + [test] compiletest-codegen-llvm 1 + [test] compiletest-codegen-units 1 + [test] compiletest-assembly-gcc 1 + [test] compiletest-assembly-llvm 1 + [test] compiletest-incremental 1 + [test] compiletest-debuginfo 1 + [test] compiletest-ui-fulldeps 1 + [build] rustdoc 1 + [test] compiletest-rustdoc-html 1 + [test] compiletest-coverage-run-rustdoc 1 + [test] compiletest-pretty 1 + [build] rustc 1 -> std 1 + [build] rustc 0 -> std 0 + [test] rustc 0 -> CrateLibrustc 1 + [build] rustc 1 -> rustc 2 + [test] crate-bootstrap src/tools/coverage-dump + [test] crate-bootstrap src/tools/jsondoclint + [test] crate-bootstrap src/tools/replace-version-placeholder + [test] crate-bootstrap tidyselftest + [build] rustc 0 -> UnstableBookGen 1 + [build] rustc 0 -> Rustbook 1 + [doc] unstable-book (book) + [doc] book (book) + [doc] book/first-edition (book) + [doc] book/second-edition (book) + [doc] book/2018-edition (book) + [doc] rustc 0 -> standalone 1 + [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [build] rustc 0 -> error-index 1 + [doc] rustc 0 -> error-index 1 + [doc] nomicon (book) + [doc] rustc 1 -> reference (book) 2 + [doc] rustdoc (book) + [doc] rust-by-example (book) + [build] rustc 0 -> LintDocs 1 + [doc] rustc (book) + [doc] cargo (book) + [doc] clippy (book) + [doc] embedded-book (book) + [doc] edition-guide (book) + [doc] style-guide (book) + [doc] rustc 0 -> releases 1 + [build] rustc 0 -> Linkchecker 1 + [test] link-check + [test] tier-check + [test] rustc 0 -> rust-analyzer 1 + [build] rustc 0 -> RustdocTheme 1 + [test] rustdoc-theme 1 + [test] compiletest-rustdoc-ui 1 + [build] rustc 0 -> JsonDocCk 1 + [build] rustc 0 -> JsonDocLint 1 + [test] compiletest-rustdoc-json 1 + [doc] rustc 0 -> rustc 1 + [build] rustc 0 -> HtmlChecker 1 + [test] html-check + [test] test-float-parse + [build] rustc 0 -> RunMakeSupport 1 + [test] compiletest-run-make 1 + [build] rustc 0 -> cargo 1 + [test] compiletest-run-make-cargo 1 + [test] intrinsic-test "#]].assert_eq(&prepare_test_config(&ctx) + .render_steps()); } #[test] fn test_compiletest_self_test() { let ctx = TestCtx::new(); let steps = ctx.config("test").arg("compiletest").render_steps(); - insta::assert_snapshot!(steps, @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustdoc 0 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustdoc 0 "#]] + .assert_eq(&steps); } #[test] fn test_compiletest_suites_stage1() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("test") - .args(&["ui", "ui-fulldeps", "run-make", "rustdoc-html", "rustdoc-gui", "incremental"]) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 0 -> Compiletest 1 - [test] compiletest-ui 1 - [test] compiletest-ui-fulldeps 1 - [build] rustc 0 -> RunMakeSupport 1 - [build] rustdoc 1 - [test] compiletest-run-make 1 - [test] compiletest-rustdoc-html 1 - [build] rustc 0 -> RustdocGUITest 1 - [test] rustdoc-gui 1 - [test] compiletest-incremental 1 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 0 -> Compiletest 1 + [test] compiletest-ui 1 + [test] compiletest-ui-fulldeps 1 + [build] rustc 0 -> RunMakeSupport 1 + [build] rustdoc 1 + [test] compiletest-run-make 1 + [test] compiletest-rustdoc-html 1 + [build] rustc 0 -> RustdocGUITest 1 + [test] rustdoc-gui 1 + [test] compiletest-incremental 1 "#]] + .assert_eq( + &ctx.config("test") + .args(&[ + "ui", + "ui-fulldeps", + "run-make", + "rustdoc-html", + "rustdoc-gui", + "incremental", + ]) + .render_steps(), + ); } #[test] fn test_compiletest_suites_stage2() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("test") - .args(&["ui", "ui-fulldeps", "run-make", "rustdoc-html", "rustdoc-gui", "incremental"]) + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 1 -> rustc 2 + [build] rustc 2 -> std 2 + [build] rustc 0 -> Compiletest 1 + [test] compiletest-ui 2 + [build] rustc 2 -> rustc 3 + [test] compiletest-ui-fulldeps 2 + [build] rustc 0 -> RunMakeSupport 1 + [build] rustdoc 2 + [test] compiletest-run-make 2 + [test] compiletest-rustdoc-html 2 + [build] rustc 0 -> RustdocGUITest 1 + [test] rustdoc-gui 2 + [test] compiletest-incremental 2 "#]] + .assert_eq( + &ctx.config("test") + .args(&[ + "ui", + "ui-fulldeps", + "run-make", + "rustdoc-html", + "rustdoc-gui", + "incremental", + ]) .stage(2) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 1 -> rustc 2 - [build] rustc 2 -> std 2 - [build] rustc 0 -> Compiletest 1 - [test] compiletest-ui 2 - [build] rustc 2 -> rustc 3 - [test] compiletest-ui-fulldeps 2 - [build] rustc 0 -> RunMakeSupport 1 - [build] rustdoc 2 - [test] compiletest-run-make 2 - [test] compiletest-rustdoc-html 2 - [build] rustc 0 -> RustdocGUITest 1 - [test] rustdoc-gui 2 - [test] compiletest-incremental 2 - "); + .render_steps(), + ); } #[test] fn test_compiletest_suites_stage2_cross() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("test") + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 1 -> rustc 2 + [build] rustc 2 -> std 2 + [build] rustc 0 -> Compiletest 1 + [build] rustc 1 -> std 1 + [build] rustc 2 -> std 2 + [test] compiletest-ui 2 + [build] llvm + [build] rustc 2 -> rustc 3 + [test] compiletest-ui-fulldeps 2 + [build] rustc 0 -> RunMakeSupport 1 + [build] rustdoc 2 + [test] compiletest-run-make 2 + [build] rustc 1 -> rustc 2 + [build] rustdoc 1 + [build] rustc 2 -> std 2 + [build] rustdoc 2 + [build] rustc 0 -> RustdocGUITest 1 + [test] rustdoc-gui 2 + [test] compiletest-incremental 2 "#]] + .assert_eq( + &ctx.config("test") .hosts(&[TEST_TRIPLE_1]) .targets(&[TEST_TRIPLE_1]) .args(&["ui", "ui-fulldeps", "run-make", "rustdoc", "rustdoc-gui", "incremental"]) .stage(2) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 1 -> rustc 2 - [build] rustc 2 -> std 2 - [build] rustc 0 -> Compiletest 1 - [build] rustc 1 -> std 1 - [build] rustc 2 -> std 2 - [test] compiletest-ui 2 - [build] llvm - [build] rustc 2 -> rustc 3 - [test] compiletest-ui-fulldeps 2 - [build] rustc 0 -> RunMakeSupport 1 - [build] rustdoc 2 - [test] compiletest-run-make 2 - [build] rustc 1 -> rustc 2 - [build] rustdoc 1 - [build] rustc 2 -> std 2 - [build] rustdoc 2 - [build] rustc 0 -> RustdocGUITest 1 - [test] rustdoc-gui 2 - [test] compiletest-incremental 2 - "); + .render_steps(), + ); } #[test] fn test_all_stage_2() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - prepare_test_config(&ctx) - .stage(2) - .render_steps(), @" - [build] rustc 0 -> Tidy 1 - [test] tidy <> - [build] rustdoc 0 - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 1 -> rustc 2 - [build] rustc 2 -> std 2 - [build] rustc 0 -> Compiletest 1 - [test] compiletest-ui 2 - [test] compiletest-crashes 2 - [build] rustc 0 -> CoverageDump 1 - [test] compiletest-coverage 2 - [test] compiletest-coverage 2 - [build] rustc 2 -> std 2 - [test] compiletest-mir-opt 2 - [test] compiletest-codegen-llvm 2 - [test] compiletest-codegen-units 2 - [test] compiletest-assembly-gcc 2 - [test] compiletest-assembly-llvm 2 - [test] compiletest-incremental 2 - [test] compiletest-debuginfo 2 - [build] rustc 2 -> rustc 3 - [test] compiletest-ui-fulldeps 2 - [build] rustdoc 2 - [test] compiletest-rustdoc-html 2 - [test] compiletest-coverage-run-rustdoc 2 - [test] compiletest-pretty 2 - [build] rustc 2 -> std 2 - [build] rustc 1 -> std 1 - [build] rustdoc 1 - [test] rustc 1 -> CrateLibrustc 2 - [test] crate-bootstrap src/tools/coverage-dump - [test] crate-bootstrap src/tools/jsondoclint - [test] crate-bootstrap src/tools/replace-version-placeholder - [test] crate-bootstrap tidyselftest - [build] rustc 0 -> UnstableBookGen 1 - [build] rustc 0 -> Rustbook 1 - [doc] unstable-book (book) - [doc] book (book) - [doc] book/first-edition (book) - [doc] book/second-edition (book) - [doc] book/2018-edition (book) - [doc] rustc 1 -> standalone 2 - [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] - [build] rustc 1 -> error-index 2 - [doc] rustc 1 -> error-index 2 - [doc] nomicon (book) - [doc] rustc 1 -> reference (book) 2 - [doc] rustdoc (book) - [doc] rust-by-example (book) - [build] rustc 0 -> LintDocs 1 - [doc] rustc (book) - [doc] cargo (book) - [doc] clippy (book) - [doc] embedded-book (book) - [doc] edition-guide (book) - [doc] style-guide (book) - [doc] rustc 1 -> releases 2 - [build] rustc 0 -> Linkchecker 1 - [test] link-check - [test] tier-check - [test] rustc 1 -> rust-analyzer 2 - [doc] rustc (book) - [test] rustc 1 -> lint-docs 2 - [build] rustc 0 -> RustdocTheme 1 - [test] rustdoc-theme 2 - [test] compiletest-rustdoc-ui 2 - [build] rustc 0 -> JsonDocCk 1 - [build] rustc 0 -> JsonDocLint 1 - [test] compiletest-rustdoc-json 2 - [doc] rustc 1 -> rustc 2 - [build] rustc 0 -> HtmlChecker 1 - [test] html-check - [test] test-float-parse - [build] rustc 0 -> RunMakeSupport 1 - [test] compiletest-run-make 2 - [build] rustc 1 -> cargo 2 - [test] compiletest-run-make-cargo 2 - [test] intrinsic-test - "); + expect_test::expect![[r#" + [build] rustc 0 -> Tidy 1 + [test] tidy <> + [build] rustdoc 0 + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 1 -> rustc 2 + [build] rustc 2 -> std 2 + [build] rustc 0 -> Compiletest 1 + [test] compiletest-ui 2 + [test] compiletest-crashes 2 + [build] rustc 0 -> CoverageDump 1 + [test] compiletest-coverage 2 + [test] compiletest-coverage 2 + [build] rustc 2 -> std 2 + [test] compiletest-mir-opt 2 + [test] compiletest-codegen-llvm 2 + [test] compiletest-codegen-units 2 + [test] compiletest-assembly-gcc 2 + [test] compiletest-assembly-llvm 2 + [test] compiletest-incremental 2 + [test] compiletest-debuginfo 2 + [build] rustc 2 -> rustc 3 + [test] compiletest-ui-fulldeps 2 + [build] rustdoc 2 + [test] compiletest-rustdoc-html 2 + [test] compiletest-coverage-run-rustdoc 2 + [test] compiletest-pretty 2 + [build] rustc 2 -> std 2 + [build] rustc 1 -> std 1 + [build] rustdoc 1 + [test] rustc 1 -> CrateLibrustc 2 + [test] crate-bootstrap src/tools/coverage-dump + [test] crate-bootstrap src/tools/jsondoclint + [test] crate-bootstrap src/tools/replace-version-placeholder + [test] crate-bootstrap tidyselftest + [build] rustc 0 -> UnstableBookGen 1 + [build] rustc 0 -> Rustbook 1 + [doc] unstable-book (book) + [doc] book (book) + [doc] book/first-edition (book) + [doc] book/second-edition (book) + [doc] book/2018-edition (book) + [doc] rustc 1 -> standalone 2 + [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [build] rustc 1 -> error-index 2 + [doc] rustc 1 -> error-index 2 + [doc] nomicon (book) + [doc] rustc 1 -> reference (book) 2 + [doc] rustdoc (book) + [doc] rust-by-example (book) + [build] rustc 0 -> LintDocs 1 + [doc] rustc (book) + [doc] cargo (book) + [doc] clippy (book) + [doc] embedded-book (book) + [doc] edition-guide (book) + [doc] style-guide (book) + [doc] rustc 1 -> releases 2 + [build] rustc 0 -> Linkchecker 1 + [test] link-check + [test] tier-check + [test] rustc 1 -> rust-analyzer 2 + [doc] rustc (book) + [test] rustc 1 -> lint-docs 2 + [build] rustc 0 -> RustdocTheme 1 + [test] rustdoc-theme 2 + [test] compiletest-rustdoc-ui 2 + [build] rustc 0 -> JsonDocCk 1 + [build] rustc 0 -> JsonDocLint 1 + [test] compiletest-rustdoc-json 2 + [doc] rustc 1 -> rustc 2 + [build] rustc 0 -> HtmlChecker 1 + [test] html-check + [test] test-float-parse + [build] rustc 0 -> RunMakeSupport 1 + [test] compiletest-run-make 2 + [build] rustc 1 -> cargo 2 + [test] compiletest-run-make-cargo 2 + [test] intrinsic-test "#]].assert_eq(&prepare_test_config(&ctx) + .stage(2) + .render_steps()); } #[test] fn test_compiler_stage_1() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("test") - .path("compiler") - .stage(1) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 0 -> std 0 - [build] rustdoc 0 - [test] rustc 0 -> CrateLibrustc 1 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 0 -> std 0 + [build] rustdoc 0 + [test] rustc 0 -> CrateLibrustc 1 "#]] + .assert_eq(&ctx.config("test").path("compiler").stage(1).render_steps()); } #[test] fn test_compiler_stage_2() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("test") - .path("compiler") - .stage(2) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 1 -> rustc 2 - [build] rustc 1 -> std 1 - [build] rustdoc 1 - [test] rustc 1 -> CrateLibrustc 2 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 1 -> rustc 2 + [build] rustc 1 -> std 1 + [build] rustdoc 1 + [test] rustc 1 -> CrateLibrustc 2 "#]] + .assert_eq(&ctx.config("test").path("compiler").stage(2).render_steps()); } #[test] @@ -2216,80 +2067,65 @@ mod snapshot { #[test] fn test_library_tests_only_does_not_build_rustdoc() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("test").args(&["--tests", "library/core"]).render_steps(), - @r" + expect_test::expect![[r#" [build] llvm [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - "); + [build] rustc 1 -> std 1 "#]] + .assert_eq(&ctx.config("test").args(&["--tests", "library/core"]).render_steps()); } #[test] fn test_cargo_stage_1() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("test") - .path("cargo") - .render_steps(), @r" - [build] rustc 0 -> cargo 1 - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustdoc 1 - [build] rustdoc 0 - [test] rustc 0 -> cargo 1 - "); + expect_test::expect![[r#" + [build] rustc 0 -> cargo 1 + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustdoc 1 + [build] rustdoc 0 + [test] rustc 0 -> cargo 1 "#]] + .assert_eq(&ctx.config("test").path("cargo").render_steps()); } #[test] fn test_cargo_stage_2() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("test") - .path("cargo") - .stage(2) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 1 -> cargo 2 - [build] rustc 1 -> rustc 2 - [build] rustc 2 -> std 2 - [build] rustdoc 2 - [build] rustdoc 1 - [test] rustc 1 -> cargo 2 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 1 -> cargo 2 + [build] rustc 1 -> rustc 2 + [build] rustc 2 -> std 2 + [build] rustdoc 2 + [build] rustdoc 1 + [test] rustc 1 -> cargo 2 "#]] + .assert_eq(&ctx.config("test").path("cargo").stage(2).render_steps()); } #[test] fn test_cargotest() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("test") - .path("cargotest") - .render_steps(), @r" - [build] rustc 0 -> cargo 1 - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 0 -> CargoTest 1 - [build] rustdoc 1 - [test] cargotest 1 - "); + expect_test::expect![[r#" + [build] rustc 0 -> cargo 1 + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 0 -> CargoTest 1 + [build] rustdoc 1 + [test] cargotest 1 "#]] + .assert_eq(&ctx.config("test").path("cargotest").render_steps()); } #[test] fn test_tier_check() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("test") - .path("tier-check") - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [test] tier-check - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [test] tier-check "#]] + .assert_eq(&ctx.config("test").path("tier-check").render_steps()); } // Differential snapshots for `./x test run-make` run `./x test run-make-cargo`: only @@ -2297,199 +2133,176 @@ mod snapshot { #[test] fn test_run_make_no_cargo() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("test") - .path("run-make") - .render_steps(), @" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 0 -> Compiletest 1 - [build] rustc 0 -> RunMakeSupport 1 - [build] rustdoc 1 - [test] compiletest-run-make 1 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 0 -> Compiletest 1 + [build] rustc 0 -> RunMakeSupport 1 + [build] rustdoc 1 + [test] compiletest-run-make 1 "#]] + .assert_eq(&ctx.config("test").path("run-make").render_steps()); } #[test] fn test_run_make_cargo_builds_cargo() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("test") - .path("run-make-cargo") - .render_steps(), @" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 0 -> Compiletest 1 - [build] rustc 0 -> RunMakeSupport 1 - [build] rustc 0 -> cargo 1 - [build] rustdoc 1 - [test] compiletest-run-make-cargo 1 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 0 -> Compiletest 1 + [build] rustc 0 -> RunMakeSupport 1 + [build] rustc 0 -> cargo 1 + [build] rustdoc 1 + [test] compiletest-run-make-cargo 1 "#]] + .assert_eq(&ctx.config("test").path("run-make-cargo").render_steps()); } #[test] fn doc_all() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("doc") - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 0 -> UnstableBookGen 1 - [build] rustc 0 -> Rustbook 1 - [doc] unstable-book (book) - [doc] book (book) - [doc] book/first-edition (book) - [doc] book/second-edition (book) - [doc] book/2018-edition (book) - [build] rustdoc 0 - [doc] rustc 0 -> standalone 1 - [build] rustdoc 1 - [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] - [build] rustc 0 -> error-index 1 - [doc] rustc 0 -> error-index 1 - [doc] nomicon (book) - [doc] rustc 1 -> reference (book) 2 - [doc] rustdoc (book) - [doc] rust-by-example (book) - [build] rustc 0 -> LintDocs 1 - [doc] rustc (book) - [doc] cargo (book) - [doc] clippy (book) - [doc] embedded-book (book) - [doc] edition-guide (book) - [doc] style-guide (book) - [doc] rustc 0 -> releases 1 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 0 -> UnstableBookGen 1 + [build] rustc 0 -> Rustbook 1 + [doc] unstable-book (book) + [doc] book (book) + [doc] book/first-edition (book) + [doc] book/second-edition (book) + [doc] book/2018-edition (book) + [build] rustdoc 0 + [doc] rustc 0 -> standalone 1 + [build] rustdoc 1 + [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [build] rustc 0 -> error-index 1 + [doc] rustc 0 -> error-index 1 + [doc] nomicon (book) + [doc] rustc 1 -> reference (book) 2 + [doc] rustdoc (book) + [doc] rust-by-example (book) + [build] rustc 0 -> LintDocs 1 + [doc] rustc (book) + [doc] cargo (book) + [doc] clippy (book) + [doc] embedded-book (book) + [doc] edition-guide (book) + [doc] style-guide (book) + [doc] rustc 0 -> releases 1 "#]].assert_eq(&ctx.config("doc") + .render_steps()); } #[test] fn doc_library() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("doc") - .path("library") - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustdoc 1 - [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustdoc 1 + [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]"#]].assert_eq(&ctx.config("doc") + .path("library") + .render_steps()); } #[test] fn doc_compiler_with_tools() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("doc") - .arg("compiler-with-tools") - .render_steps(), @" - [build] rustdoc 0 - [doc] rustc 0 -> rustc 1 - [build] llvm - [build] rustc 0 -> rustc 1 - [doc] rustc 0 -> Rustdoc 1 - [doc] rustc 0 -> Rustfmt 1 - [doc] rustc 0 -> Clippy 1 - [doc] rustc 0 -> Miri 1 - [doc] rustc 0 -> Cargo 1 - [doc] rustc 0 -> Tidy 1 - [doc] rustc 0 -> Bootstrap 1 - [doc] rustc 0 -> BuildHelper 1 - [doc] rustc 0 -> Compiletest 1 - [doc] rustc 0 -> RunMakeSupport 1 - [doc] rustc 0 -> CompilerWithTools 1 - "); + expect_test::expect![[r#" + [build] rustdoc 0 + [doc] rustc 0 -> rustc 1 + [build] llvm + [build] rustc 0 -> rustc 1 + [doc] rustc 0 -> Rustdoc 1 + [doc] rustc 0 -> Rustfmt 1 + [doc] rustc 0 -> Clippy 1 + [doc] rustc 0 -> Miri 1 + [doc] rustc 0 -> Cargo 1 + [doc] rustc 0 -> Tidy 1 + [doc] rustc 0 -> Bootstrap 1 + [doc] rustc 0 -> BuildHelper 1 + [doc] rustc 0 -> Compiletest 1 + [doc] rustc 0 -> RunMakeSupport 1 + [doc] rustc 0 -> CompilerWithTools 1 "#]] + .assert_eq(&ctx.config("doc").arg("compiler-with-tools").render_steps()); } #[test] fn doc_cargo_stage_1() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("doc") - .path("cargo") - .render_steps(), @r" - [build] rustdoc 0 - [doc] rustc 0 -> Cargo 1 - "); + expect_test::expect![[r#" + [build] rustdoc 0 + [doc] rustc 0 -> Cargo 1 "#]] + .assert_eq(&ctx.config("doc").path("cargo").render_steps()); } #[test] fn doc_cargo_stage_2() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("doc") - .path("cargo") - .stage(2) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustdoc 1 - [doc] rustc 1 -> Cargo 2 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustdoc 1 + [doc] rustc 1 -> Cargo 2 "#]] + .assert_eq(&ctx.config("doc").path("cargo").stage(2).render_steps()); } #[test] fn doc_core() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("doc") - .path("core") - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustdoc 1 - [doc] rustc 1 -> std 1 crates=[core] - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustdoc 1 + [doc] rustc 1 -> std 1 crates=[core]"#]] + .assert_eq(&ctx.config("doc").path("core").render_steps()); } #[test] fn doc_core_no_std_target() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("doc") - .path("core") - .override_target_no_std(&host_target()) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustdoc 1 - [doc] rustc 1 -> std 1 crates=[core] - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustdoc 1 + [doc] rustc 1 -> std 1 crates=[core]"#]] + .assert_eq( + &ctx.config("doc").path("core").override_target_no_std(&host_target()).render_steps(), + ); } #[test] fn doc_library_no_std_target() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("doc") + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustdoc 1 + [doc] rustc 1 -> std 1 crates=[alloc,core]"#]] + .assert_eq( + &ctx.config("doc") .path("library") .override_target_no_std(&host_target()) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustdoc 1 - [doc] rustc 1 -> std 1 crates=[alloc,core] - "); + .render_steps(), + ); } #[test] fn doc_library_no_std_target_cross_compile() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("doc") + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustdoc 1 + [doc] rustc 1 -> std 1 crates=[alloc,core]"#]] + .assert_eq( + &ctx.config("doc") .path("library") .targets(&[TEST_TRIPLE_1]) .override_target_no_std(TEST_TRIPLE_1) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustdoc 1 - [doc] rustc 1 -> std 1 crates=[alloc,core] - "); + .render_steps(), + ); } #[test] @@ -2502,30 +2315,22 @@ mod snapshot { #[test] fn doc_compiler_stage_1() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("doc") - .path("compiler") - .stage(1) - .render_steps(), @" - [build] rustdoc 0 - [doc] rustc 0 -> rustc 1 - "); + expect_test::expect![[r#" + [build] rustdoc 0 + [doc] rustc 0 -> rustc 1 "#]] + .assert_eq(&ctx.config("doc").path("compiler").stage(1).render_steps()); } #[test] fn doc_compiler_stage_2() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("doc") - .path("compiler") - .stage(2) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustdoc 1 - [doc] rustc 1 -> rustc 2 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustdoc 1 + [doc] rustc 1 -> rustc 2 "#]] + .assert_eq(&ctx.config("doc").path("compiler").stage(2).render_steps()); } #[test] @@ -2538,454 +2343,415 @@ mod snapshot { #[test] fn doc_compiletest_stage_1() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("doc") - .path("src/tools/compiletest") - .stage(1) - .render_steps(), @r" - [build] rustdoc 0 - [doc] rustc 0 -> Compiletest 1 - "); + expect_test::expect![[r#" + [build] rustdoc 0 + [doc] rustc 0 -> Compiletest 1 "#]] + .assert_eq(&ctx.config("doc").path("src/tools/compiletest").stage(1).render_steps()); } #[test] fn doc_compiletest_stage_2() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("doc") - .path("src/tools/compiletest") - .stage(2) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustdoc 1 - [doc] rustc 1 -> Compiletest 2 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustdoc 1 + [doc] rustc 1 -> Compiletest 2 "#]] + .assert_eq(&ctx.config("doc").path("src/tools/compiletest").stage(2).render_steps()); } // Reference should be auto-bumped to stage 2. #[test] fn doc_reference() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("doc") - .path("reference") - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 0 -> Rustbook 1 - [doc] rustc 1 -> reference (book) 2 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 0 -> Rustbook 1 + [doc] rustc 1 -> reference (book) 2 "#]] + .assert_eq(&ctx.config("doc").path("reference").render_steps()); } #[test] fn clippy_ci() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("clippy") - .path("ci") - .stage(2) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 0 -> clippy-driver 1 - [build] rustc 0 -> cargo-clippy 1 - [clippy] rustc 1 -> bootstrap 2 - [clippy] rustc 1 -> std 1 - [clippy] rustc 1 -> rustc 2 - [check] rustc 1 -> rustc 2 - [clippy] rustc 1 -> rustc_codegen_gcc 2 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 0 -> clippy-driver 1 + [build] rustc 0 -> cargo-clippy 1 + [clippy] rustc 1 -> bootstrap 2 + [clippy] rustc 1 -> std 1 + [clippy] rustc 1 -> rustc 2 + [check] rustc 1 -> rustc 2 + [clippy] rustc 1 -> rustc_codegen_gcc 2 "#]] + .assert_eq(&ctx.config("clippy").path("ci").stage(2).render_steps()); } #[test] fn clippy_compiler_stage1() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("clippy") - .path("compiler") - .render_steps(), @"[clippy] rustc 0 -> rustc 1 "); + expect_test::expect![["[clippy] rustc 0 -> rustc 1 "]] + .assert_eq(&ctx.config("clippy").path("compiler").render_steps()); } #[test] fn clippy_compiler_stage2() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("clippy") - .path("compiler") - .stage(2) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 0 -> clippy-driver 1 - [build] rustc 0 -> cargo-clippy 1 - [clippy] rustc 1 -> rustc 2 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 0 -> clippy-driver 1 + [build] rustc 0 -> cargo-clippy 1 + [clippy] rustc 1 -> rustc 2 "#]] + .assert_eq(&ctx.config("clippy").path("compiler").stage(2).render_steps()); } #[test] fn clippy_std_stage1() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("clippy") - .path("std") - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 0 -> clippy-driver 1 - [build] rustc 0 -> cargo-clippy 1 - [clippy] rustc 1 -> std 1 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 0 -> clippy-driver 1 + [build] rustc 0 -> cargo-clippy 1 + [clippy] rustc 1 -> std 1 "#]] + .assert_eq(&ctx.config("clippy").path("std").render_steps()); } #[test] fn clippy_std_stage2() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("clippy") - .path("std") - .stage(2) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 1 -> rustc 2 - [build] rustc 1 -> clippy-driver 2 - [build] rustc 1 -> cargo-clippy 2 - [clippy] rustc 2 -> std 2 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 1 -> rustc 2 + [build] rustc 1 -> clippy-driver 2 + [build] rustc 1 -> cargo-clippy 2 + [clippy] rustc 2 -> std 2 "#]] + .assert_eq(&ctx.config("clippy").path("std").stage(2).render_steps()); } #[test] fn clippy_miri_stage1() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("clippy") - .path("miri") - .stage(1) - .render_steps(), @" - [check] rustc 0 -> rustc 1 - [clippy] rustc 0 -> miri 1 - "); + expect_test::expect![[r#" + [check] rustc 0 -> rustc 1 + [clippy] rustc 0 -> miri 1 "#]] + .assert_eq(&ctx.config("clippy").path("miri").stage(1).render_steps()); } #[test] fn clippy_miri_stage2() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("clippy") - .path("miri") - .stage(2) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [check] rustc 1 -> rustc 2 - [build] rustc 0 -> clippy-driver 1 - [build] rustc 0 -> cargo-clippy 1 - [clippy] rustc 1 -> miri 2 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [check] rustc 1 -> rustc 2 + [build] rustc 0 -> clippy-driver 1 + [build] rustc 0 -> cargo-clippy 1 + [clippy] rustc 1 -> miri 2 "#]] + .assert_eq(&ctx.config("clippy").path("miri").stage(2).render_steps()); } #[test] fn clippy_bootstrap() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("clippy") - .path("bootstrap") - .render_steps(), @"[clippy] rustc 0 -> bootstrap 1 "); + expect_test::expect![["[clippy] rustc 0 -> bootstrap 1 "]] + .assert_eq(&ctx.config("clippy").path("bootstrap").render_steps()); } #[test] fn install_plain() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("install") - .args(&[ - // Using backslashes fails with `--set` - "--set", &format!("install.prefix={}", ctx.normalized_dir()), - "--set", &format!("install.bindir={}", ctx.normalized_dir()), - "--set", &format!("install.libdir={}", ctx.normalized_dir()), - "--set", &format!("install.datadir={}", ctx.normalized_dir()), - "--set", &format!("install.mandir={}", ctx.normalized_dir()), - "--set", &format!("install.sysconfdir={}", ctx.normalized_dir()), - "--build", "x86_64-unknown-linux-gnu", - "--host", "x86_64-unknown-linux-gnu", - "--target", "x86_64-unknown-linux-gnu", - ]) - .get_steps() - .render_with(RenderConfig { - normalize_host: false - }), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 0 -> UnstableBookGen 1 - [build] rustc 0 -> Rustbook 1 - [doc] unstable-book (book) - [doc] book (book) - [doc] book/first-edition (book) - [doc] book/second-edition (book) - [doc] book/2018-edition (book) - [build] rustdoc 1 - [doc] rustc 1 -> standalone 2 - [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] - [build] rustc 1 -> rustc 2 - [build] rustc 1 -> error-index 2 - [doc] rustc 1 -> error-index 2 - [doc] nomicon (book) - [doc] rustc 1 -> reference (book) 2 - [doc] rustdoc (book) - [doc] rust-by-example (book) - [build] rustc 0 -> LintDocs 1 - [doc] rustc (book) - [doc] cargo (book) - [doc] clippy (book) - [doc] embedded-book (book) - [doc] edition-guide (book) - [doc] style-guide (book) - [doc] rustc 1 -> releases 2 - [build] rustc 0 -> RustInstaller 1 - [dist] docs - [dist] rustc 1 -> std 1 - [build] rustdoc 2 - [build] rustc 0 -> GenerateCopyright 1 - [dist] rustc - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 0 -> UnstableBookGen 1 + [build] rustc 0 -> Rustbook 1 + [doc] unstable-book (book) + [doc] book (book) + [doc] book/first-edition (book) + [doc] book/second-edition (book) + [doc] book/2018-edition (book) + [build] rustdoc 1 + [doc] rustc 1 -> standalone 2 + [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [build] rustc 1 -> rustc 2 + [build] rustc 1 -> error-index 2 + [doc] rustc 1 -> error-index 2 + [doc] nomicon (book) + [doc] rustc 1 -> reference (book) 2 + [doc] rustdoc (book) + [doc] rust-by-example (book) + [build] rustc 0 -> LintDocs 1 + [doc] rustc (book) + [doc] cargo (book) + [doc] clippy (book) + [doc] embedded-book (book) + [doc] edition-guide (book) + [doc] style-guide (book) + [doc] rustc 1 -> releases 2 + [build] rustc 0 -> RustInstaller 1 + [dist] docs + [dist] rustc 1 -> std 1 + [build] rustdoc 2 + [build] rustc 0 -> GenerateCopyright 1 + [dist] rustc "#]].assert_eq(&ctx.config("install") + .args(&[ + // Using backslashes fails with `--set` + "--set", &format!("install.prefix={}", ctx.normalized_dir()), + "--set", &format!("install.bindir={}", ctx.normalized_dir()), + "--set", &format!("install.libdir={}", ctx.normalized_dir()), + "--set", &format!("install.datadir={}", ctx.normalized_dir()), + "--set", &format!("install.mandir={}", ctx.normalized_dir()), + "--set", &format!("install.sysconfdir={}", ctx.normalized_dir()), + "--build", "x86_64-unknown-linux-gnu", + "--host", "x86_64-unknown-linux-gnu", + "--target", "x86_64-unknown-linux-gnu", + ]) + .get_steps() + .render_with(RenderConfig { + normalize_host: false + })); } #[test] fn install_src() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("install") + expect_test::expect![[r#" + [build] rustc 0 -> RustInstaller 1 + [dist] src <>"#]] + .assert_eq( + &ctx.config("install") .path("rust-src") .args(&[ // Using backslashes fails with `--set` - "--set", &format!("install.prefix={}", ctx.normalized_dir()), - "--set", &format!("install.bindir={}", ctx.normalized_dir()), - "--set", &format!("install.libdir={}", ctx.normalized_dir()), - "--set", &format!("install.datadir={}", ctx.normalized_dir()), - "--set", &format!("install.mandir={}", ctx.normalized_dir()), - "--set", &format!("install.sysconfdir={}", ctx.normalized_dir()), - "--build", "x86_64-unknown-linux-gnu", - "--host", "x86_64-unknown-linux-gnu", - "--target", "x86_64-unknown-linux-gnu", + "--set", + &format!("install.prefix={}", ctx.normalized_dir()), + "--set", + &format!("install.bindir={}", ctx.normalized_dir()), + "--set", + &format!("install.libdir={}", ctx.normalized_dir()), + "--set", + &format!("install.datadir={}", ctx.normalized_dir()), + "--set", + &format!("install.mandir={}", ctx.normalized_dir()), + "--set", + &format!("install.sysconfdir={}", ctx.normalized_dir()), + "--build", + "x86_64-unknown-linux-gnu", + "--host", + "x86_64-unknown-linux-gnu", + "--target", + "x86_64-unknown-linux-gnu", ]) .get_steps() - .render_with(RenderConfig { - normalize_host: false - }), @r" - [build] rustc 0 -> RustInstaller 1 - [dist] src <> - "); + .render_with(RenderConfig { normalize_host: false }), + ); } #[test] fn install_src_no_docs() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("install") + expect_test::expect![[r#" + [build] rustc 0 -> RustInstaller 1 + [dist] src <>"#]] + .assert_eq( + &ctx.config("install") .path("rust-src") .args(&[ // Using backslashes fails with `--set` - "--set", &format!("install.prefix={}", ctx.normalized_dir()), - "--set", &format!("install.bindir={}", ctx.normalized_dir()), - "--set", &format!("install.libdir={}", ctx.normalized_dir()), - "--set", &format!("install.datadir={}", ctx.normalized_dir()), - "--set", &format!("install.mandir={}", ctx.normalized_dir()), - "--set", &format!("install.sysconfdir={}", ctx.normalized_dir()), - "--set", "build.docs=false", - "--build", "x86_64-unknown-linux-gnu", - "--host", "x86_64-unknown-linux-gnu", - "--target", "x86_64-unknown-linux-gnu", + "--set", + &format!("install.prefix={}", ctx.normalized_dir()), + "--set", + &format!("install.bindir={}", ctx.normalized_dir()), + "--set", + &format!("install.libdir={}", ctx.normalized_dir()), + "--set", + &format!("install.datadir={}", ctx.normalized_dir()), + "--set", + &format!("install.mandir={}", ctx.normalized_dir()), + "--set", + &format!("install.sysconfdir={}", ctx.normalized_dir()), + "--set", + "build.docs=false", + "--build", + "x86_64-unknown-linux-gnu", + "--host", + "x86_64-unknown-linux-gnu", + "--target", + "x86_64-unknown-linux-gnu", ]) .get_steps() - .render_with(RenderConfig { - normalize_host: false - }), @r" - [build] rustc 0 -> RustInstaller 1 - [dist] src <> - "); + .render_with(RenderConfig { normalize_host: false }), + ); } #[test] fn install_extended() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("install") - .args(&[ - // Using backslashes fails with `--set` - "--set", &format!("install.prefix={}", ctx.normalized_dir()), - "--set", &format!("install.bindir={}", ctx.normalized_dir()), - "--set", &format!("install.libdir={}", ctx.normalized_dir()), - "--set", &format!("install.datadir={}", ctx.normalized_dir()), - "--set", &format!("install.mandir={}", ctx.normalized_dir()), - "--set", &format!("install.sysconfdir={}", ctx.normalized_dir()), - "--set", "build.extended=true", - // For Cranelift to be disted - "--build", "x86_64-unknown-linux-gnu", - "--host", "x86_64-unknown-linux-gnu", - ]) - .get_steps() - .render_with(RenderConfig { - normalize_host: false - }), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 0 -> WasmComponentLd 1 - [build] rustc 1 -> std 1 - [build] rustc 0 -> UnstableBookGen 1 - [build] rustc 0 -> Rustbook 1 - [doc] unstable-book (book) - [doc] book (book) - [doc] book/first-edition (book) - [doc] book/second-edition (book) - [doc] book/2018-edition (book) - [build] rustdoc 1 - [doc] rustc 1 -> standalone 2 - [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] - [build] rustc 1 -> rustc 2 - [build] rustc 1 -> WasmComponentLd 2 - [build] rustc 1 -> error-index 2 - [doc] rustc 1 -> error-index 2 - [doc] nomicon (book) - [doc] rustc 1 -> reference (book) 2 - [doc] rustdoc (book) - [doc] rust-by-example (book) - [build] rustc 0 -> LintDocs 1 - [doc] rustc (book) - [doc] cargo (book) - [doc] clippy (book) - [doc] embedded-book (book) - [doc] edition-guide (book) - [doc] style-guide (book) - [doc] rustc 1 -> releases 2 - [build] rustc 0 -> RustInstaller 1 - [dist] docs - [dist] rustc 1 -> std 1 - [build] rustdoc 2 - [build] rustc 1 -> rust-analyzer-proc-macro-srv 2 - [build] rustc 0 -> GenerateCopyright 1 - [dist] rustc - [dist] rustc 1 -> rustc-dev 2 - [build] rustc 1 -> cargo 2 - [dist] rustc 1 -> cargo 2 - [build] rustc 1 -> rust-analyzer 2 - [dist] rustc 1 -> rust-analyzer 2 - [build] rustc 1 -> rustfmt 2 - [build] rustc 1 -> cargo-fmt 2 - [dist] rustc 1 -> rustfmt 2 - [build] rustc 1 -> clippy-driver 2 - [build] rustc 1 -> cargo-clippy 2 - [dist] rustc 1 -> clippy 2 - [build] rustc 1 -> miri 2 - [build] rustc 1 -> cargo-miri 2 - [dist] rustc 1 -> miri 2 - [dist] src <> - [build] rustc 1 -> rustc_codegen_cranelift 2 - [dist] rustc 1 -> rustc_codegen_cranelift 2 - [build] rustc 1 -> LlvmBitcodeLinker 2 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 0 -> WasmComponentLd 1 + [build] rustc 1 -> std 1 + [build] rustc 0 -> UnstableBookGen 1 + [build] rustc 0 -> Rustbook 1 + [doc] unstable-book (book) + [doc] book (book) + [doc] book/first-edition (book) + [doc] book/second-edition (book) + [doc] book/2018-edition (book) + [build] rustdoc 1 + [doc] rustc 1 -> standalone 2 + [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [build] rustc 1 -> rustc 2 + [build] rustc 1 -> WasmComponentLd 2 + [build] rustc 1 -> error-index 2 + [doc] rustc 1 -> error-index 2 + [doc] nomicon (book) + [doc] rustc 1 -> reference (book) 2 + [doc] rustdoc (book) + [doc] rust-by-example (book) + [build] rustc 0 -> LintDocs 1 + [doc] rustc (book) + [doc] cargo (book) + [doc] clippy (book) + [doc] embedded-book (book) + [doc] edition-guide (book) + [doc] style-guide (book) + [doc] rustc 1 -> releases 2 + [build] rustc 0 -> RustInstaller 1 + [dist] docs + [dist] rustc 1 -> std 1 + [build] rustdoc 2 + [build] rustc 1 -> rust-analyzer-proc-macro-srv 2 + [build] rustc 0 -> GenerateCopyright 1 + [dist] rustc + [dist] rustc 1 -> rustc-dev 2 + [build] rustc 1 -> cargo 2 + [dist] rustc 1 -> cargo 2 + [build] rustc 1 -> rust-analyzer 2 + [dist] rustc 1 -> rust-analyzer 2 + [build] rustc 1 -> rustfmt 2 + [build] rustc 1 -> cargo-fmt 2 + [dist] rustc 1 -> rustfmt 2 + [build] rustc 1 -> clippy-driver 2 + [build] rustc 1 -> cargo-clippy 2 + [dist] rustc 1 -> clippy 2 + [build] rustc 1 -> miri 2 + [build] rustc 1 -> cargo-miri 2 + [dist] rustc 1 -> miri 2 + [dist] src <> + [build] rustc 1 -> rustc_codegen_cranelift 2 + [dist] rustc 1 -> rustc_codegen_cranelift 2 + [build] rustc 1 -> LlvmBitcodeLinker 2 "#]].assert_eq(&ctx.config("install") + .args(&[ + // Using backslashes fails with `--set` + "--set", &format!("install.prefix={}", ctx.normalized_dir()), + "--set", &format!("install.bindir={}", ctx.normalized_dir()), + "--set", &format!("install.libdir={}", ctx.normalized_dir()), + "--set", &format!("install.datadir={}", ctx.normalized_dir()), + "--set", &format!("install.mandir={}", ctx.normalized_dir()), + "--set", &format!("install.sysconfdir={}", ctx.normalized_dir()), + "--set", "build.extended=true", + // For Cranelift to be disted + "--build", "x86_64-unknown-linux-gnu", + "--host", "x86_64-unknown-linux-gnu", + ]) + .get_steps() + .render_with(RenderConfig { + normalize_host: false + })); } #[test] fn cargo_miri_stage_1() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("test") - .args(&["cargo-miri"]) - .stage(1) - .get_steps() - .render(), @" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 0 -> miri 1 - [build] rustc 0 -> cargo-miri 1 - [build] rustdoc 1 - [build] rustc 1 -> std 1 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 0 -> miri 1 + [build] rustc 0 -> cargo-miri 1 + [build] rustdoc 1 + [build] rustc 1 -> std 1 "#]] + .assert_eq(&ctx.config("test").args(&["cargo-miri"]).stage(1).get_steps().render()); } #[test] fn cargo_miri_stage_2() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("test") - .args(&["cargo-miri"]) - .stage(2) - .get_steps() - .render(), @" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 1 -> rustc 2 - [build] rustc 1 -> miri 2 - [build] rustc 1 -> cargo-miri 2 - [build] rustdoc 2 - [build] rustc 2 -> std 2 - [build] rustc 0 -> cargo 1 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 1 -> rustc 2 + [build] rustc 1 -> miri 2 + [build] rustc 1 -> cargo-miri 2 + [build] rustdoc 2 + [build] rustc 2 -> std 2 + [build] rustc 0 -> cargo 1 "#]] + .assert_eq(&ctx.config("test").args(&["cargo-miri"]).stage(2).get_steps().render()); } #[test] fn test_float_parse() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("test") - .path("src/tools/test-float-parse") - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustdoc 1 - [test] test-float-parse - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustdoc 1 + [test] test-float-parse "#]] + .assert_eq(&ctx.config("test").path("src/tools/test-float-parse").render_steps()); } #[test] fn test_float_parse_cross() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("test") + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustc 1 -> std 1 + [build] rustdoc 1 + [test] test-float-parse "#]] + .assert_eq( + &ctx.config("test") .path("src/tools/test-float-parse") .targets(&[TEST_TRIPLE_1]) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 1 -> std 1 - [build] rustdoc 1 - [test] test-float-parse - "); + .render_steps(), + ); } // Check that `x run miri --target FOO` actually builds miri for the host. #[test] fn run_miri() { let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("run") - .path("miri") - .stage(1) - .targets(&[TEST_TRIPLE_1]) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 0 -> miri 1 - [build] rustc 0 -> cargo-miri 1 - [run] rustc 0 -> miri 1 - "); + expect_test::expect![[r#" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 0 -> miri 1 + [build] rustc 0 -> cargo-miri 1 + [run] rustc 0 -> miri 1 "#]] + .assert_eq( + &ctx.config("run").path("miri").stage(1).targets(&[TEST_TRIPLE_1]).render_steps(), + ); } #[test] fn fix_compiler() { let ctx = TestCtx::new(); - insta::assert_snapshot!(ctx.config("fix").path("compiler").render_steps(), @"[fix] rustc 0 -> rustc 1 (78 crates)"); + expect_test::expect![["[fix] rustc 0 -> rustc 1 (78 crates)"]] + .assert_eq(&ctx.config("fix").path("compiler").render_steps()); } } diff --git a/tests/assembly-llvm/c-variadic/s390x.rs b/tests/assembly-llvm/c-variadic/s390x.rs index 7dfcda83fda3b..4880f5430f542 100644 --- a/tests/assembly-llvm/c-variadic/s390x.rs +++ b/tests/assembly-llvm/c-variadic/s390x.rs @@ -1,7 +1,7 @@ //@ add-minicore //@ assembly-output: emit-asm // -//@ compile-flags: -Copt-level=3 --target s390x-unknown-linux-gnu +//@ compile-flags: -Copt-level=3 --target s390x-unknown-linux-gnu -Ctarget-cpu=z10 //@ needs-llvm-components: systemz #![feature(no_core, lang_items, intrinsics, rustc_attrs)] #![no_core] diff --git a/tests/assembly-llvm/slp-vectorize-closure.rs b/tests/assembly-llvm/slp-vectorize-closure.rs index fcdb469a24139..7b0893d905f82 100644 --- a/tests/assembly-llvm/slp-vectorize-closure.rs +++ b/tests/assembly-llvm/slp-vectorize-closure.rs @@ -2,7 +2,7 @@ //! Regression test for . //! also see //@ assembly-output: emit-asm -//@ compile-flags: -Copt-level=3 +//@ compile-flags: -Copt-level=3 -Ctarget-cpu=x86-64-v2 //@ only-x86_64 // to test SSE instructions diff --git a/tests/assembly-llvm/x86_64-typed-swap.rs b/tests/assembly-llvm/x86_64-typed-swap.rs index a6753011d3620..ea34c2dcac7d7 100644 --- a/tests/assembly-llvm/x86_64-typed-swap.rs +++ b/tests/assembly-llvm/x86_64-typed-swap.rs @@ -3,7 +3,7 @@ //@ [LIN] only-linux //@ only-x86_64 //@ assembly-output: emit-asm -//@ compile-flags: --crate-type=lib -Copt-level=3 +//@ compile-flags: --crate-type=lib -Copt-level=3 -Ctarget-cpu=x86-64-v2 use std::arch::x86_64::__m128; use std::mem::swap; diff --git a/tests/codegen-llvm/issues/power-of-two-implies-nonzero-with-debuginfo-137359.rs b/tests/codegen-llvm/issues/power-of-two-implies-nonzero-with-debuginfo-137359.rs new file mode 100644 index 0000000000000..4cd15000e7bbf --- /dev/null +++ b/tests/codegen-llvm/issues/power-of-two-implies-nonzero-with-debuginfo-137359.rs @@ -0,0 +1,32 @@ +//! Regression test for . +//! +//! With debuginfo enabled, LLVM did not use the fact that a power of two +//! is never zero. + +//@ compile-flags: -Copt-level=3 -Cdebuginfo=2 +//@ min-llvm-version: 23 + +#![crate_type = "lib"] + +use std::hint::assert_unchecked; + +// CHECK-LABEL: @power_of_two_is_nonzero +#[no_mangle] +pub unsafe fn power_of_two_is_nonzero(x: u32) -> bool { + // CHECK-NOT: icmp + // CHECK: ret i1 false + assert_unchecked(x.is_power_of_two()); + x == 0 +} + +// CHECK-LABEL: @rem_by_power_of_two +#[no_mangle] +pub unsafe fn rem_by_power_of_two(x: u32, y: u32) -> u32 { + // CHECK-NOT: urem + // CHECK-NOT: panic + // CHECK: %[[MASK:.+]] = add i32 %y, -1 + // CHECK: %[[REM:.+]] = and i32 %[[MASK]], %x + // CHECK: ret i32 %[[REM]] + assert_unchecked(y.is_power_of_two()); + x % y +} diff --git a/tests/rustdoc-ui/lints/invalid-crate-level-lint.rs b/tests/rustdoc-ui/lints/invalid-crate-level-lint.rs index afb0a5987deb3..e38a63cd12550 100644 --- a/tests/rustdoc-ui/lints/invalid-crate-level-lint.rs +++ b/tests/rustdoc-ui/lints/invalid-crate-level-lint.rs @@ -6,7 +6,8 @@ pub mod bar { #![doc(test(no_crate_inject))] - //~^ ERROR can only be applied at the crate level + //~^ ERROR unused attribute + //~| WARN this was previously accepted by the compiler but is being phased out #[doc(test(no_crate_inject))] //~^ ERROR can only be applied at the crate level diff --git a/tests/rustdoc-ui/lints/invalid-crate-level-lint.stderr b/tests/rustdoc-ui/lints/invalid-crate-level-lint.stderr index 7569cf575e510..b98b6fda035f4 100644 --- a/tests/rustdoc-ui/lints/invalid-crate-level-lint.stderr +++ b/tests/rustdoc-ui/lints/invalid-crate-level-lint.stderr @@ -1,8 +1,8 @@ error: this attribute can only be applied at the crate level - --> $DIR/invalid-crate-level-lint.rs:4:12 + --> $DIR/invalid-crate-level-lint.rs:4:1 | LL | #[doc(test(no_crate_inject))] - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: read for more information note: the lint level is defined here @@ -11,19 +11,24 @@ note: the lint level is defined here LL | #![deny(invalid_doc_attributes)] | ^^^^^^^^^^^^^^^^^^^^^^ -error: this attribute can only be applied at the crate level +error: unused attribute --> $DIR/invalid-crate-level-lint.rs:8:17 | LL | #![doc(test(no_crate_inject))] - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ help: remove this attribute | - = note: read for more information +note: attribute also specified here + --> $DIR/invalid-crate-level-lint.rs:4:12 + | +LL | #[doc(test(no_crate_inject))] + | ^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! error: this attribute can only be applied at the crate level - --> $DIR/invalid-crate-level-lint.rs:11:16 + --> $DIR/invalid-crate-level-lint.rs:12:5 | LL | #[doc(test(no_crate_inject))] - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: read for more information diff --git a/tests/ui/associated-inherent-types/regionck-2.stderr b/tests/ui/associated-inherent-types/regionck-2.stderr index 82f5c6a72c008..491bebce26d02 100644 --- a/tests/ui/associated-inherent-types/regionck-2.stderr +++ b/tests/ui/associated-inherent-types/regionck-2.stderr @@ -17,8 +17,9 @@ error: lifetime may not live long enough --> $DIR/regionck-2.rs:12:1 | LL | fn test(_: Lexer::Cursor) {} - | ^^^^^^^^-^^^^^^^^^^^^^^^^ - | | | + | ^^^^^^^^-^^-----^^^^^^^^^ + | | | | + | | | lifetime `'1` introduced here | | has type `Lexer<'1>::Cursor` | requires that `'1` must outlive `'static` diff --git a/tests/ui/assumptions_on_binders/mixed-ambiguous-alias-outlives.rs b/tests/ui/assumptions_on_binders/mixed-ambiguous-alias-outlives.rs new file mode 100644 index 0000000000000..f09cd03273541 --- /dev/null +++ b/tests/ui/assumptions_on_binders/mixed-ambiguous-alias-outlives.rs @@ -0,0 +1,75 @@ +//@ compile-flags: -Zassumptions-on-binders -Znext-solver=globally + +#![feature(test_binder_constraints)] + +trait Project { + type Assoc; +} + +impl Project for T { + type Assoc = T; +} + +core::test_binder_constraints! { + impl> { + forall<'a> { + or { + ambiguity, + for<> T::Assoc: 'a, + } + } + } +} + +// If the concrete candidate is rejected at the root, the ambiguous alternative must +// still cause an error rather than disappearing with the rejected candidate. +core::test_binder_constraints! { + impl { + forall<'a> { + //~^ ERROR unable to satisfy constraints involving placeholders + or { + ambiguity, + for<> T::Assoc: 'a, + } + } + } +} + +// The order of the alternatives must not change whether the bound can be proved. +core::test_binder_constraints! { + impl> { + forall<'a> { + or { + for<> T::Assoc: 'a, + ambiguity, + } + } + } +} + +// A required ambiguous constraint still makes the whole AND ambiguous, even when +// its sibling is known to hold. +core::test_binder_constraints! { + impl> { + forall<'a> { + //~^ ERROR unable to satisfy constraints involving placeholders + ambiguity, + for<> T::Assoc: 'a, + } + } +} + +// Ambiguity shared by every OR alternative is still required after canonicalization. +core::test_binder_constraints! { + impl { + forall<'a> { + //~^ ERROR unable to satisfy constraints involving placeholders + or { + ambiguity, + ambiguity, + } + } + } +} + +fn main() {} diff --git a/tests/ui/assumptions_on_binders/mixed-ambiguous-alias-outlives.stderr b/tests/ui/assumptions_on_binders/mixed-ambiguous-alias-outlives.stderr new file mode 100644 index 0000000000000..c4df98380aa1b --- /dev/null +++ b/tests/ui/assumptions_on_binders/mixed-ambiguous-alias-outlives.stderr @@ -0,0 +1,20 @@ +error: unable to satisfy constraints involving placeholders due to unknown implied bounds + --> $DIR/mixed-ambiguous-alias-outlives.rs:28:9 + | +LL | forall<'a> { + | ^^^^^^ + +error: unable to satisfy constraints involving placeholders due to unknown implied bounds + --> $DIR/mixed-ambiguous-alias-outlives.rs:54:9 + | +LL | forall<'a> { + | ^^^^^^ + +error: unable to satisfy constraints involving placeholders due to unknown implied bounds + --> $DIR/mixed-ambiguous-alias-outlives.rs:65:9 + | +LL | forall<'a> { + | ^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/assumptions_on_binders/resolve-region-vars.rs b/tests/ui/assumptions_on_binders/resolve-region-vars.rs new file mode 100644 index 0000000000000..3543a2f810e63 --- /dev/null +++ b/tests/ui/assumptions_on_binders/resolve-region-vars.rs @@ -0,0 +1,82 @@ +//@ check-pass +//@ compile-flags: -Zassumptions-on-binders -Znext-solver=globally + +#![feature(test_binder_constraints)] + +trait Trait<'a, 'b> { + type Assoc; +} + +core::test_binder_constraints! { + impl<'c, T> + where + for<'a, 'b> T: Trait<'a, 'b>, + { + forall<'a> + where + for<'b> >::Assoc: 'c, + { + forall<'b> { + predicates >::Assoc: 'c + } expect { + for<'b> >::Assoc: 'c + } + } expect { } + } +} + +core::test_binder_constraints! { + impl<'c, T> + where + for<'a, 'b> T: Trait<'a, 'b>, + { + forall<'a> + where + for<'b> >::Assoc: 'c, + { + forall<'b> { + exists<'a2, 'b2, 'c2> { + 'a2 = 'a, + 'b2 = 'b, + 'c2 = 'c, + or { + for<> >::Assoc: 'c2, + and { T: 'c2, 'a2: 'c2, 'b2: 'c2 } + } + } + } expect { + for<'b> >::Assoc: 'c + } + } expect { } + } +} + +core::test_binder_constraints! { + impl<'c, T> + where + for<'a, 'b> T: Trait<'a, 'b>, + { + forall<'a> + where + for<'b> >::Assoc: 'c, + { + forall<'b> { + exists<'a2, 'b2, 'c2> { + exists<'a3, 'b3, 'c3> { + 'a2 = 'a3, + 'b2 = 'b3, + 'c2 = 'c3, + 'a3 = 'a, + 'b3 = 'b, + 'c3 = 'c, + for<> >::Assoc: 'c3 + } + } + } expect { + for<'b> >::Assoc: 'c + } + } expect { } + } +} + +fn main() {} diff --git a/tests/ui/attributes/doc-crate-level.rs b/tests/ui/attributes/doc-crate-level.rs new file mode 100644 index 0000000000000..c58866022e2c2 --- /dev/null +++ b/tests/ui/attributes/doc-crate-level.rs @@ -0,0 +1,22 @@ +//@check-pass +#![feature(rustdoc_internals)] + +#[doc(rust_logo)] +//~^ WARN this attribute can only be applied at the crate level +#[doc(html_favicon_url = "example.org")] +//~^ WARN this attribute can only be applied at the crate level +#[doc(html_logo_url = "example.org")] +//~^ WARN this attribute can only be applied at the crate level +#[doc(html_playground_url = "example.org")] +//~^ WARN this attribute can only be applied at the crate level +#[doc(issue_tracker_base_url = "example.org")] +//~^ WARN this attribute can only be applied at the crate level +#[doc(html_root_url = "example.org")] +//~^ WARN this attribute can only be applied at the crate level +#[doc(html_no_source)] +//~^ WARN this attribute can only be applied at the crate level +#[doc(test(no_crate_inject))] +//~^ WARN this attribute can only be applied at the crate level +fn function() {} + +fn main() {} diff --git a/tests/ui/attributes/doc-crate-level.stderr b/tests/ui/attributes/doc-crate-level.stderr new file mode 100644 index 0000000000000..71c385e576101 --- /dev/null +++ b/tests/ui/attributes/doc-crate-level.stderr @@ -0,0 +1,67 @@ +warning: this attribute can only be applied at the crate level + --> $DIR/doc-crate-level.rs:4:1 + | +LL | #[doc(rust_logo)] + | ^^^^^^^^^^^^^^^^^ + | + = note: read for more information + = note: `#[warn(invalid_doc_attributes)]` on by default + +warning: this attribute can only be applied at the crate level + --> $DIR/doc-crate-level.rs:6:1 + | +LL | #[doc(html_favicon_url = "example.org")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: read for more information + +warning: this attribute can only be applied at the crate level + --> $DIR/doc-crate-level.rs:8:1 + | +LL | #[doc(html_logo_url = "example.org")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: read for more information + +warning: this attribute can only be applied at the crate level + --> $DIR/doc-crate-level.rs:10:1 + | +LL | #[doc(html_playground_url = "example.org")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: read for more information + +warning: this attribute can only be applied at the crate level + --> $DIR/doc-crate-level.rs:12:1 + | +LL | #[doc(issue_tracker_base_url = "example.org")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: read for more information + +warning: this attribute can only be applied at the crate level + --> $DIR/doc-crate-level.rs:14:1 + | +LL | #[doc(html_root_url = "example.org")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: read for more information + +warning: this attribute can only be applied at the crate level + --> $DIR/doc-crate-level.rs:16:1 + | +LL | #[doc(html_no_source)] + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: read for more information + +warning: this attribute can only be applied at the crate level + --> $DIR/doc-crate-level.rs:18:1 + | +LL | #[doc(test(no_crate_inject))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: read for more information + +warning: 8 warnings emitted + diff --git a/tests/ui/borrowck/unmatched-arg-and-hir-arg-issue-126385.stderr b/tests/ui/borrowck/unmatched-arg-and-hir-arg-issue-126385.stderr index dc19178732ba2..e1468963069d8 100644 --- a/tests/ui/borrowck/unmatched-arg-and-hir-arg-issue-126385.stderr +++ b/tests/ui/borrowck/unmatched-arg-and-hir-arg-issue-126385.stderr @@ -23,6 +23,8 @@ LL + pub fn f(field: &[u32]) -> MyStruct { error: lifetime may not live long enough --> $DIR/unmatched-arg-and-hir-arg-issue-126385.rs:10:9 | +LL | impl MyStruct<'_> { + | -- lifetime `'2` introduced here LL | pub fn f(field: &[u32]) -> Self { | - --------- return type is `MyStruct<'2>` | | diff --git a/tests/ui/c-variadic/variadic-ffi-4.stderr b/tests/ui/c-variadic/variadic-ffi-4.stderr index a92a5fd4bf61d..64dff4320b93f 100644 --- a/tests/ui/c-variadic/variadic-ffi-4.stderr +++ b/tests/ui/c-variadic/variadic-ffi-4.stderr @@ -20,8 +20,9 @@ error: lifetime may not live long enough --> $DIR/variadic-ffi-4.rs:16:5 | LL | pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaList, mut ap1: ...) { - | ------- ------- has type `VaList<'1>` - | | + | ------- ------ ------- has type `VaList<'1>` + | | | + | | lifetime `'2` introduced here | has type `&mut VaList<'2>` LL | *ap0 = ap1; | ^^^^ assignment requires that `'1` must outlive `'2` @@ -30,8 +31,9 @@ error: lifetime may not live long enough --> $DIR/variadic-ffi-4.rs:21:5 | LL | pub unsafe extern "C" fn no_escape4(_: usize, mut ap0: &mut VaList, mut ap1: ...) { - | ------- ------- has type `VaList<'2>` - | | + | ------- ------ ------- has type `VaList<'2>` + | | | + | | lifetime `'1` introduced here | has type `&mut VaList<'1>` LL | ap0 = &mut ap1; | ^^^^^^^^^^^^^^ assignment requires that `'1` must outlive `'2` @@ -44,8 +46,9 @@ error: lifetime may not live long enough --> $DIR/variadic-ffi-4.rs:21:5 | LL | pub unsafe extern "C" fn no_escape4(_: usize, mut ap0: &mut VaList, mut ap1: ...) { - | ------- ------- has type `VaList<'2>` - | | + | ------- ------ ------- has type `VaList<'2>` + | | | + | | lifetime `'1` introduced here | has type `&mut VaList<'1>` LL | ap0 = &mut ap1; | ^^^^^^^^^^^^^^ assignment requires that `'2` must outlive `'1` @@ -74,8 +77,9 @@ error: lifetime may not live long enough --> $DIR/variadic-ffi-4.rs:28:5 | LL | pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaList, mut ap1: ...) { - | ------- ------- has type `VaList<'1>` - | | + | ------- ------ ------- has type `VaList<'1>` + | | | + | | lifetime `'2` introduced here | has type `&mut VaList<'2>` LL | *ap0 = ap1.clone(); | ^^^^ assignment requires that `'1` must outlive `'2` diff --git a/tests/ui/const-generics/function_arg_const_generics/self-param-after-const-param.rs b/tests/ui/const-generics/function_arg_const_generics/self-param-after-const-param.rs new file mode 100644 index 0000000000000..f9de0a02112bd --- /dev/null +++ b/tests/ui/const-generics/function_arg_const_generics/self-param-after-const-param.rs @@ -0,0 +1,16 @@ +#![feature(function_arg_const_generics, gca_min_const_items)] + +trait Foo { + fn a(const N: usize, self: [isize; N]) -> isize; //~ ERROR + fn b(&self) -> isize { + self.a() + 2 //~ ERROR E0599 + } +} + +impl Foo for isize { + fn a(&self) -> isize { //~ ERROR E0185 + 3 + } +} + +fn main() {} diff --git a/tests/ui/const-generics/function_arg_const_generics/self-param-after-const-param.stderr b/tests/ui/const-generics/function_arg_const_generics/self-param-after-const-param.stderr new file mode 100644 index 0000000000000..0253d69602aff --- /dev/null +++ b/tests/ui/const-generics/function_arg_const_generics/self-param-after-const-param.stderr @@ -0,0 +1,42 @@ +error: unexpected `self` parameter in function + --> $DIR/self-param-after-const-param.rs:4:26 + | +LL | fn a(const N: usize, self: [isize; N]) -> isize; + | ^^^^ must be the first parameter of an associated function + +error[E0185]: method `a` has a `&self` declaration in the impl, but not in the trait + --> $DIR/self-param-after-const-param.rs:11:5 + | +LL | fn a(const N: usize, self: [isize; N]) -> isize; + | ------------------------------------------------ trait method declared without `&self` +... +LL | fn a(&self) -> isize { + | ^^^^^^^^^^^^^^^^^^^^ `&self` used in impl + +error[E0599]: no method named `a` found for reference `&Self` in the current scope + --> $DIR/self-param-after-const-param.rs:6:14 + | +LL | self.a() + 2 + | ^ this is an associated function, not a method + | + = note: found the following associated functions; to be used as methods, functions must have a `self` parameter +note: the candidate is defined in the trait `Foo` + --> $DIR/self-param-after-const-param.rs:4:5 + | +LL | fn a(const N: usize, self: [isize; N]) -> isize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: use associated function syntax instead + | +LL - self.a() + 2 +LL + Self::a() + 2 + | +help: there is a method `b` with a similar name + | +LL - self.a() + 2 +LL + self.b() + 2 + | + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0185, E0599. +For more information about an error, try `rustc --explain E0185`. diff --git a/tests/ui/delegation/delegation-first-arg.stderr b/tests/ui/delegation/delegation-first-arg.stderr index 7fd37e3f8f92e..f59f7ea97aca2 100644 --- a/tests/ui/delegation/delegation-first-arg.stderr +++ b/tests/ui/delegation/delegation-first-arg.stderr @@ -74,6 +74,11 @@ LL | trait Trait: Sized { ... LL | fn static_empty() {} | ^^^^^^^^^^^^ +note: associated function provided through this `impl` + --> $DIR/delegation-first-arg.rs:13:1 + | +LL | impl Trait for S {} + | ^^^^^^^^^^^^^^^^ help: remove the extra argument | LL - reuse ::static_empty { self.0 } diff --git a/tests/ui/delegation/explicit-paths.stderr b/tests/ui/delegation/explicit-paths.stderr index 1995b7a639f1f..2d2d42b79ed43 100644 --- a/tests/ui/delegation/explicit-paths.stderr +++ b/tests/ui/delegation/explicit-paths.stderr @@ -52,6 +52,11 @@ note: method defined here LL | trait Trait { LL | fn foo1(&self, x: i32) -> i32 { x } | ^^^^ ----- +note: method provided through this `impl` + --> $DIR/explicit-paths.rs:10:1 + | +LL | impl Trait for F {} + | ^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `S2: Trait` is not satisfied --> $DIR/explicit-paths.rs:73:16 diff --git a/tests/ui/delegation/inherent-impls-recursive-cycle.stderr b/tests/ui/delegation/inherent-impls-recursive-cycle.stderr index 943f70f55fc6e..bae8ba7f616cb 100644 --- a/tests/ui/delegation/inherent-impls-recursive-cycle.stderr +++ b/tests/ui/delegation/inherent-impls-recursive-cycle.stderr @@ -124,6 +124,11 @@ note: associated function defined here LL | trait Trait1 { LL | reuse trait_foo_reused as foo; | ^^^ +note: associated function provided through this `impl` + --> $DIR/inherent-impls-recursive-cycle.rs:33:1 + | +LL | impl Trait1 for S3 { + | ^^^^^^^^^^^^^^^^^^ help: remove the extra argument | LL - reuse ::foo { S3 } diff --git a/tests/ui/delegation/self-coercion-static-free.stderr b/tests/ui/delegation/self-coercion-static-free.stderr index 35d69da3a3f6d..66543acd080c6 100644 --- a/tests/ui/delegation/self-coercion-static-free.stderr +++ b/tests/ui/delegation/self-coercion-static-free.stderr @@ -26,6 +26,11 @@ LL | pub trait Trait: Sized { ... LL | fn static_value(_: Self) -> i32 { 1 } | ^^^^^^^^^^^^ ------- +note: associated function provided through this `impl` + --> $DIR/self-coercion-static-free.rs:17:1 + | +LL | impl Trait for F {} + | ^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/self-coercion-static-free.rs:22:40 @@ -45,6 +50,11 @@ LL | pub trait Trait: Sized { ... LL | fn static_mut_ref(_: &mut Self) -> i32 { 2 } | ^^^^^^^^^^^^^^ ------------ +note: associated function provided through this `impl` + --> $DIR/self-coercion-static-free.rs:17:1 + | +LL | impl Trait for F {} + | ^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/self-coercion-static-free.rs:22:56 @@ -64,6 +74,11 @@ LL | pub trait Trait: Sized { ... LL | fn static_ref(_: &Self) -> i32 { 3 } | ^^^^^^^^^^ -------- +note: associated function provided through this `impl` + --> $DIR/self-coercion-static-free.rs:17:1 + | +LL | impl Trait for F {} + | ^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/self-coercion-static-free.rs:35:26 @@ -81,6 +96,11 @@ LL | pub trait Trait: Sized { ... LL | fn static_value(_: Self) -> i32 { 1 } | ^^^^^^^^^^^^ ------- +note: associated function provided through this `impl` + --> $DIR/self-coercion-static-free.rs:17:1 + | +LL | impl Trait for F {} + | ^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/self-coercion-static-free.rs:35:40 @@ -100,6 +120,11 @@ LL | pub trait Trait: Sized { ... LL | fn static_mut_ref(_: &mut Self) -> i32 { 2 } | ^^^^^^^^^^^^^^ ------------ +note: associated function provided through this `impl` + --> $DIR/self-coercion-static-free.rs:17:1 + | +LL | impl Trait for F {} + | ^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/self-coercion-static-free.rs:35:56 @@ -119,6 +144,11 @@ LL | pub trait Trait: Sized { ... LL | fn static_ref(_: &Self) -> i32 { 3 } | ^^^^^^^^^^ -------- +note: associated function provided through this `impl` + --> $DIR/self-coercion-static-free.rs:17:1 + | +LL | impl Trait for F {} + | ^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/self-coercion-static-free.rs:52:43 diff --git a/tests/ui/delegation/self-mapping-arguments-errors.stderr b/tests/ui/delegation/self-mapping-arguments-errors.stderr index d63dae2478464..032561ddd8816 100644 --- a/tests/ui/delegation/self-mapping-arguments-errors.stderr +++ b/tests/ui/delegation/self-mapping-arguments-errors.stderr @@ -113,6 +113,11 @@ note: method defined here LL | trait MyAdd { LL | fn add(self, other: Box) -> Self; | ^^^ ----- +note: method provided through this `impl` + --> $DIR/self-mapping-arguments-errors.rs:37:5 + | +LL | impl MyAdd for usize { + | ^^^^^^^^^^^^^^^^^^^^ help: store this in the heap by calling `Box::new` | LL | reuse impl MyAdd for W { Box::new(self.0) } diff --git a/tests/ui/delegation/self-mapping-output.stderr b/tests/ui/delegation/self-mapping-output.stderr index 4b184f1a57446..16d72442dc4af 100644 --- a/tests/ui/delegation/self-mapping-output.stderr +++ b/tests/ui/delegation/self-mapping-output.stderr @@ -241,6 +241,11 @@ note: method defined here LL | trait Trait { LL | fn method(&self) -> Self; | ^^^^^^ ---- +note: method provided through this `impl` + --> $DIR/self-mapping-output.rs:238:5 + | +LL | impl Trait for F { + | ^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/self-mapping-output.rs:251:29 @@ -271,6 +276,11 @@ LL | trait Trait { ... LL | fn raw_S(&self) -> S { S } | ^^^^^ ----- +note: method provided through this `impl` + --> $DIR/self-mapping-output.rs:238:5 + | +LL | impl Trait for F { + | ^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/self-mapping-output.rs:263:38 @@ -289,6 +299,11 @@ note: method defined here LL | trait Trait { LL | fn method(&self) -> Self; | ^^^^^^ ---- +note: method provided through this `impl` + --> $DIR/self-mapping-output.rs:238:5 + | +LL | impl Trait for F { + | ^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/self-mapping-output.rs:263:29 @@ -319,6 +334,11 @@ LL | trait Trait { ... LL | fn raw_S(&self) -> S { S } | ^^^^^ ----- +note: method provided through this `impl` + --> $DIR/self-mapping-output.rs:238:5 + | +LL | impl Trait for F { + | ^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/self-mapping-output.rs:296:31 diff --git a/tests/ui/delegation/unused-target-expr-in-glob-or-list.stderr b/tests/ui/delegation/unused-target-expr-in-glob-or-list.stderr index 330e536f81840..21d9586d2f58e 100644 --- a/tests/ui/delegation/unused-target-expr-in-glob-or-list.stderr +++ b/tests/ui/delegation/unused-target-expr-in-glob-or-list.stderr @@ -225,6 +225,11 @@ note: associated function defined here LL | pub trait Trait: Sized { LL | fn static_self() -> F { F } | ^^^^^^^^^^^ +note: associated function provided through this `impl` + --> $DIR/unused-target-expr-in-glob-or-list.rs:14:1 + | +LL | impl Trait for F {} + | ^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/unused-target-expr-in-glob-or-list.rs:107:37 @@ -290,6 +295,11 @@ note: associated function defined here LL | pub trait Trait: Sized { LL | fn static_self() -> F { F } | ^^^^^^^^^^^ +note: associated function provided through this `impl` + --> $DIR/unused-target-expr-in-glob-or-list.rs:14:1 + | +LL | impl Trait for F {} + | ^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/unused-target-expr-in-glob-or-list.rs:127:33 diff --git a/tests/ui/feature-gates/doc-rust-logo.stderr b/tests/ui/feature-gates/doc-rust-logo.stderr index 802187e6a598c..47f7e7480bf1a 100644 --- a/tests/ui/feature-gates/doc-rust-logo.stderr +++ b/tests/ui/feature-gates/doc-rust-logo.stderr @@ -9,10 +9,10 @@ LL | #![doc(rust_logo)] = note: the `#[doc(rust_logo)]` attribute is used for Rust branding warning: this attribute can only be applied at the crate level - --> $DIR/doc-rust-logo.rs:5:7 + --> $DIR/doc-rust-logo.rs:5:1 | LL | #[doc(rust_logo)] - | ^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ | = note: read for more information = note: `#[warn(invalid_doc_attributes)]` on by default diff --git a/tests/ui/fn_traits/point-at-impl-in-call-argument-type-error.rs b/tests/ui/fn_traits/point-at-impl-in-call-argument-type-error.rs new file mode 100644 index 0000000000000..160c0c36c1f05 --- /dev/null +++ b/tests/ui/fn_traits/point-at-impl-in-call-argument-type-error.rs @@ -0,0 +1,12 @@ +// Point at blanket `impl`, which might help the user figure out that `B::from` can only convert to +// `B`. Issue #104712. + +struct A; +struct B; + +fn foo() { + let a = A; + let b = B::from(a); //~ ERROR: mismatched types +} + +fn main() {} diff --git a/tests/ui/fn_traits/point-at-impl-in-call-argument-type-error.stderr b/tests/ui/fn_traits/point-at-impl-in-call-argument-type-error.stderr new file mode 100644 index 0000000000000..8af4873ca71ed --- /dev/null +++ b/tests/ui/fn_traits/point-at-impl-in-call-argument-type-error.stderr @@ -0,0 +1,16 @@ +error[E0308]: mismatched types + --> $DIR/point-at-impl-in-call-argument-type-error.rs:9:21 + | +LL | let b = B::from(a); + | ------- ^ expected `B`, found `A` + | | + | arguments to this function are incorrect + | +note: associated function defined here + --> $SRC_DIR/core/src/convert/mod.rs:LL:COL +note: associated function provided through this blanket `impl` + --> $SRC_DIR/core/src/convert/mod.rs:LL:COL + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lifetimes/implicit-lifetime-in-assoc-type-projection.stderr b/tests/ui/lifetimes/implicit-lifetime-in-assoc-type-projection.stderr index 7c06ffd7c1e48..3c912864dfd20 100644 --- a/tests/ui/lifetimes/implicit-lifetime-in-assoc-type-projection.stderr +++ b/tests/ui/lifetimes/implicit-lifetime-in-assoc-type-projection.stderr @@ -29,8 +29,9 @@ LL | impl<'a> Publisher<'a> for MyStruct<'a> { | -- lifetime `'a` defined here LL | type Output = u64; LL | fn subscribe(&mut self, t : Box::Output> + 'a>) { - | ^^^^^^^^^^^^^^^^^^^^^^^^-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | | + | ^^^^^^^^^^^^^^^^^^^^^^^^-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------^^^^^^^^^^^^^^^^^ + | | | | + | | | lifetime `'1` introduced here | | has type `Box as Publisher<'1>>::Output>>` | requires that `'a` must outlive `'1` @@ -41,8 +42,9 @@ LL | impl<'a> Publisher<'a> for MyStruct<'a> { | -- lifetime `'a` defined here LL | type Output = u64; LL | fn subscribe(&mut self, t : Box::Output> + 'a>) { - | ^^^^^^^^^^^^^^^^^^^^^^^^-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | | + | ^^^^^^^^^^^^^^^^^^^^^^^^-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------^^^^^^^^^^^^^^^^^ + | | | | + | | | lifetime `'1` introduced here | | has type `Box as Publisher<'1>>::Output>>` | requires that `'1` must outlive `'a` diff --git a/tests/ui/lifetimes/lifetime-errors/ex2b-push-no-existing-names.stderr b/tests/ui/lifetimes/lifetime-errors/ex2b-push-no-existing-names.stderr index a187cb755dd56..a28f884b6389d 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex2b-push-no-existing-names.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex2b-push-no-existing-names.stderr @@ -2,8 +2,10 @@ error: lifetime may not live long enough --> $DIR/ex2b-push-no-existing-names.rs:6:5 | LL | fn foo(x: &mut Vec>, y: Ref) { - | - - has type `Ref<'1, i32>` - | | + | - - - - lifetime `'1` introduced here + | | | | + | | | has type `Ref<'1, i32>` + | | lifetime `'2` introduced here | has type `&mut Vec>` LL | x.push(y); | ^^^^^^^^^ argument requires that `'1` must outlive `'2` diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.stderr index f8ad923cce8a5..d25414bb5d797 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.stderr @@ -2,8 +2,10 @@ error: lifetime may not live long enough --> $DIR/ex3-both-anon-regions-both-are-structs-2.rs:7:5 | LL | fn foo(mut x: Ref, y: Ref) { - | ----- - has type `Ref<'_, '1>` - | | + | ----- --- - --- lifetime `'1` introduced here + | | | | + | | | has type `Ref<'_, '1>` + | | lifetime `'2` introduced here | has type `Ref<'_, '2>` LL | x.b = y.b; | ^^^^^^^^^ assignment requires that `'1` must outlive `'2` diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr index a1149779d2c6d..d6da2c15f88cb 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr @@ -2,8 +2,10 @@ error: lifetime may not live long enough --> $DIR/ex3-both-anon-regions-both-are-structs-3.rs:7:5 | LL | fn foo(mut x: Ref) { - | ----- - | | + | ----- --- + | | | + | | lifetime `'1` introduced here + | | lifetime `'2` introduced here | has type `Ref<'_, '1>` | has type `Ref<'2, '_>` LL | x.a = x.b; diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr index 264673ff3e82c..de47669b144b8 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr @@ -2,8 +2,10 @@ error: lifetime may not live long enough --> $DIR/ex3-both-anon-regions-both-are-structs.rs:6:5 | LL | fn foo(mut x: Vec, y: Ref) { - | ----- - has type `Ref<'1>` - | | + | ----- --- - --- lifetime `'1` introduced here + | | | | + | | | has type `Ref<'1>` + | | lifetime `'2` introduced here | has type `Vec>` LL | x.push(y); | ^^^^^^^^^ argument requires that `'1` must outlive `'2` diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.stderr index 29bf7e62985a3..d33ed7e7c0b0e 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.stderr @@ -2,8 +2,9 @@ error: lifetime may not live long enough --> $DIR/ex3-both-anon-regions-one-is-struct-2.rs:4:5 | LL | fn foo(mut x: Ref, y: &u32) { - | ----- - let's call the lifetime of this reference `'2` - | | + | ----- --- - let's call the lifetime of this reference `'2` + | | | + | | lifetime `'1` introduced here | has type `Ref<'_, '1>` LL | y = x.b; | ^^^^^^^ assignment requires that `'1` must outlive `'2` diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.stderr index d9c7530b64c57..ef9e5eedd27bd 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.stderr @@ -2,8 +2,9 @@ error: lifetime may not live long enough --> $DIR/ex3-both-anon-regions-one-is-struct-3.rs:4:5 | LL | fn foo(mut y: Ref, x: &u32) { - | ----- - let's call the lifetime of this reference `'1` - | | + | ----- --- - let's call the lifetime of this reference `'1` + | | | + | | lifetime `'2` introduced here | has type `Ref<'_, '2>` LL | y.b = x; | ^^^^^^^ assignment requires that `'1` must outlive `'2` diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.stderr index 02c0658ff1730..279450766c636 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.stderr @@ -2,8 +2,9 @@ error: lifetime may not live long enough --> $DIR/ex3-both-anon-regions-one-is-struct-4.rs:10:5 | LL | fn bar(foo: &mut Foo) { - | --- - let's call the lifetime of this reference `'1` - | | + | --- - --- lifetime `'2` introduced here + | | | + | | let's call the lifetime of this reference `'1` | has type `&mut Foo<'2>` LL | foo.modify(); | ^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct.stderr index ef28ddeacc5e2..65605846d79f8 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct.stderr @@ -2,8 +2,9 @@ error: lifetime may not live long enough --> $DIR/ex3-both-anon-regions-one-is-struct.rs:7:5 | LL | fn foo(mut x: Ref, y: &u32) { - | ----- - let's call the lifetime of this reference `'1` - | | + | ----- --- - let's call the lifetime of this reference `'1` + | | | + | | lifetime `'2` introduced here | has type `Ref<'_, '2>` LL | x.b = y; | ^^^^^^^ assignment requires that `'1` must outlive `'2` diff --git a/tests/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.stderr b/tests/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.stderr index 7f9cbc3c30a92..3f1bb892393e1 100644 --- a/tests/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.stderr +++ b/tests/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.stderr @@ -2,7 +2,9 @@ error[E0713]: borrow may still be in use when destructor runs --> $DIR/issue-52059-report-when-borrow-and-drop-conflict.rs:11:5 | LL | fn finish_1(s: S) -> &mut String { - | - has type `S<'1>` + | - - lifetime `'1` introduced here + | | + | has type `S<'1>` LL | s.url | ^^^^^ returning this value requires that `*s.url` is borrowed for `'1` LL | } @@ -12,7 +14,9 @@ error[E0713]: borrow may still be in use when destructor runs --> $DIR/issue-52059-report-when-borrow-and-drop-conflict.rs:16:13 | LL | fn finish_2(s: S) -> &mut String { - | - has type `S<'1>` + | - - lifetime `'1` introduced here + | | + | has type `S<'1>` LL | let p = &mut *s.url; p | ^^^^^^^^^^^ - returning this value requires that `*s.url` is borrowed for `'1` LL | } @@ -22,7 +26,9 @@ error[E0713]: borrow may still be in use when destructor runs --> $DIR/issue-52059-report-when-borrow-and-drop-conflict.rs:21:21 | LL | fn finish_3(s: S) -> &mut String { - | - has type `S<'1>` + | - - lifetime `'1` introduced here + | | + | has type `S<'1>` LL | let p: &mut _ = s.url; p | ^^^^^ - returning this value requires that `*s.url` is borrowed for `'1` LL | } diff --git a/tests/ui/nll/issue-52742.stderr b/tests/ui/nll/issue-52742.stderr index 8c09e542c05cc..3ddfddc2ffc98 100644 --- a/tests/ui/nll/issue-52742.stderr +++ b/tests/ui/nll/issue-52742.stderr @@ -1,9 +1,12 @@ error: lifetime may not live long enough --> $DIR/issue-52742.rs:12:9 | +LL | impl Foo<'_, '_> { + | -- lifetime `'2` introduced here LL | fn take_bar(&mut self, b: Bar<'_>) { - | --------- - has type `Bar<'1>` - | | + | --------- - -- lifetime `'1` introduced here + | | | + | | has type `Bar<'1>` | has type `&mut Foo<'_, '2>` LL | self.y = b.z | ^^^^^^^^^^^^ assignment requires that `'1` must outlive `'2` diff --git a/tests/ui/nll/issue-55394.stderr b/tests/ui/nll/issue-55394.stderr index 03382b668aa53..36fef319047b5 100644 --- a/tests/ui/nll/issue-55394.stderr +++ b/tests/ui/nll/issue-55394.stderr @@ -1,6 +1,8 @@ error: lifetime may not live long enough --> $DIR/issue-55394.rs:9:9 | +LL | impl Foo<'_> { + | -- lifetime `'2` introduced here LL | fn new(bar: &mut Bar) -> Self { | - ---- return type is `Foo<'2>` | | diff --git a/tests/ui/nll/type-alias-free-regions.stderr b/tests/ui/nll/type-alias-free-regions.stderr index 45fd5a2f1d657..d0a6454a3dac7 100644 --- a/tests/ui/nll/type-alias-free-regions.stderr +++ b/tests/ui/nll/type-alias-free-regions.stderr @@ -4,7 +4,9 @@ error: lifetime may not live long enough LL | impl<'a> FromBox<'a> for C<'a> { | -- lifetime `'a` defined here LL | fn from_box(b: Box) -> Self { - | - has type `Box>` + | - - lifetime `'1` introduced here + | | + | has type `Box>` LL | C { f: b } | ^^^^^^^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1` @@ -14,7 +16,9 @@ error: lifetime may not live long enough LL | impl<'a> FromTuple<'a> for C<'a> { | -- lifetime `'a` defined here LL | fn from_tuple(b: (B,)) -> Self { - | - has type `(Box<&'1 isize>,)` + | - - lifetime `'1` introduced here + | | + | has type `(Box<&'1 isize>,)` LL | C { f: Box::new(b.0) } | ^^^^^^^^^^^^^^^^^^^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1` diff --git a/tests/ui/object-lifetime/object-lifetime-default-from-box-error.stderr b/tests/ui/object-lifetime/object-lifetime-default-from-box-error.stderr index 05eb611081a41..5e9166bb9c1dc 100644 --- a/tests/ui/object-lifetime/object-lifetime-default-from-box-error.stderr +++ b/tests/ui/object-lifetime/object-lifetime-default-from-box-error.stderr @@ -2,7 +2,9 @@ error: lifetime may not live long enough --> $DIR/object-lifetime-default-from-box-error.rs:18:5 | LL | fn load(ss: &mut SomeStruct) -> Box { - | -- has type `&mut SomeStruct<'1>` + | -- ---------- lifetime `'1` introduced here + | | + | has type `&mut SomeStruct<'1>` ... LL | ss.r | ^^^^ returning this value requires that `'1` must outlive `'static` diff --git a/tests/ui/parser/recover/missing-dot-on-if-condition-expression.rs b/tests/ui/parser/recover/missing-dot-on-if-condition-expression.rs index c4a9ed66a8322..5e09f3e5a614c 100644 --- a/tests/ui/parser/recover/missing-dot-on-if-condition-expression.rs +++ b/tests/ui/parser/recover/missing-dot-on-if-condition-expression.rs @@ -47,6 +47,20 @@ fn foo8() { //~^ ERROR expected `{`, found `a` //~| HELP you might have meant to write a field access } +fn foo9() { + macro_rules! m { + (static a : () = $e:expr) => { + static a: () = $e; + }; + } + + m! { static a : () = { + let x = (vec![1, 2, 3],); + for _ in x 0 {} + //~^ ERROR expected `{`, found `0` + //~| HELP you might have meant to write a field access + } } +} struct S { a: A, diff --git a/tests/ui/parser/recover/missing-dot-on-if-condition-expression.stderr b/tests/ui/parser/recover/missing-dot-on-if-condition-expression.stderr index bfb72b9568281..22f1e1525172d 100644 --- a/tests/ui/parser/recover/missing-dot-on-if-condition-expression.stderr +++ b/tests/ui/parser/recover/missing-dot-on-if-condition-expression.stderr @@ -97,5 +97,19 @@ help: you might have meant to write a field access LL | for _ in x.a.b {} | + -error: aborting due to 9 previous errors +error: expected `{`, found `0` + --> $DIR/missing-dot-on-if-condition-expression.rs:59:20 + | +LL | (static a : () = $e:expr) => { + | ------- while parsing argument for this `expr` macro fragment +... +LL | for _ in x 0 {} + | ^ expected `{` + | +help: you might have meant to write a field access + | +LL | for _ in x.0 {} + | + + +error: aborting due to 10 previous errors diff --git a/tests/ui/reborrow/reborrow-generic-mut-field-aliasing.rs b/tests/ui/reborrow/reborrow-generic-mut-field-aliasing.rs new file mode 100644 index 0000000000000..c214e895ce428 --- /dev/null +++ b/tests/ui/reborrow/reborrow-generic-mut-field-aliasing.rs @@ -0,0 +1,18 @@ +#![feature(reborrow)] + +struct Wrap<'a, T>(&'a (), T); + +impl<'a> std::marker::Reborrow for Wrap<'a, &'static mut i32> {} + +fn get<'a, 'b>(x: Wrap<'a, &'b mut i32>) -> &'b mut i32 { + x.1 +} + +fn main() { + let mut x = 1; + let thing = Wrap(&(), &mut x); + let y = get(thing); + let z = get(thing); //~ ERROR cannot borrow `thing` as mutable more than once at a time + *y = 2; + *z = 3; +} diff --git a/tests/ui/reborrow/reborrow-generic-mut-field-aliasing.stderr b/tests/ui/reborrow/reborrow-generic-mut-field-aliasing.stderr new file mode 100644 index 0000000000000..a8d84ff29c015 --- /dev/null +++ b/tests/ui/reborrow/reborrow-generic-mut-field-aliasing.stderr @@ -0,0 +1,13 @@ +error[E0499]: cannot borrow `thing` as mutable more than once at a time + --> $DIR/reborrow-generic-mut-field-aliasing.rs:15:17 + | +LL | let y = get(thing); + | ----- first mutable borrow occurs here +LL | let z = get(thing); + | ^^^^^ second mutable borrow occurs here +LL | *y = 2; + | ------ first borrow later used here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/reborrow/reborrow-non-copy-field-double-use.rs b/tests/ui/reborrow/reborrow-non-copy-field-double-use.rs new file mode 100644 index 0000000000000..b3623774df975 --- /dev/null +++ b/tests/ui/reborrow/reborrow-non-copy-field-double-use.rs @@ -0,0 +1,16 @@ +#![feature(reborrow)] + +struct Wrap<'a>(&'a mut (), String); +//~^ ERROR the trait bound `String: Copy` is not satisfied + +impl<'a> std::marker::Reborrow for Wrap<'a> {} + +fn get(x: Wrap<'_>) -> String { + x.1 +} + +fn main() { + let x = Wrap(&mut (), String::from("a")); + let _y = get(x); + let _z = get(x); +} diff --git a/tests/ui/reborrow/reborrow-non-copy-field-double-use.stderr b/tests/ui/reborrow/reborrow-non-copy-field-double-use.stderr new file mode 100644 index 0000000000000..1eb1606930699 --- /dev/null +++ b/tests/ui/reborrow/reborrow-non-copy-field-double-use.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `String: Copy` is not satisfied + --> $DIR/reborrow-non-copy-field-double-use.rs:3:29 + | +LL | struct Wrap<'a>(&'a mut (), String); + | ^^^^^^ the trait `Copy` is not implemented for `String` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/regions/regions-infer-paramd-indirect.stderr b/tests/ui/regions/regions-infer-paramd-indirect.stderr index 4a1cd111936e1..639858b553239 100644 --- a/tests/ui/regions/regions-infer-paramd-indirect.stderr +++ b/tests/ui/regions/regions-infer-paramd-indirect.stderr @@ -5,7 +5,9 @@ LL | impl<'a> SetF<'a> for C<'a> { | -- lifetime `'a` defined here ... LL | fn set_f_bad(&mut self, b: Box) { - | - has type `Box>` + | - - lifetime `'1` introduced here + | | + | has type `Box>` LL | self.f = b; | ^^^^^^ assignment requires that `'1` must outlive `'a` diff --git a/tests/ui/regions/return-expr-with-implicit-trait-object-static-obligation.rs b/tests/ui/regions/return-expr-with-implicit-trait-object-static-obligation.rs new file mode 100644 index 0000000000000..b6e9eeaa3e0b1 --- /dev/null +++ b/tests/ui/regions/return-expr-with-implicit-trait-object-static-obligation.rs @@ -0,0 +1,180 @@ +// Detect. #78547. + +mod a { + // Originally reported case, where `dyn Trait` had implicit `'static` requirement. + // We ensure we point at `dyn Iterator` and we should be suggesting to add a named + // lifetime to `Thing`. + pub struct Thing { + chars: Box>, + } + + impl Thing { + pub fn new(string: &str) -> Self { + Thing { + chars: Box::new(string.chars()), //~ ERROR: lifetime may not live long enough + } + } + } +} + +mod b { + // Similar to above, but the `dyn Trait` has an explicit named bound on the type, but an + // implicit one in the `impl`. + // We ensure we point at `impl Thing<'_>` as introducing the unmet lifetime in `-> Self`. + pub struct Thing<'a> { + chars: Box + 'a>, + } + + impl Thing<'_> { + pub fn new(string: &str) -> Self { + Thing { //~ ERROR: lifetime may not live long enough + chars: Box::new(string.chars()), + } + } + } +} + +mod c { + // Ensure that we are handling tuple-structs. + pub struct Thing(Box>); + + impl Thing { + pub fn new(string: &str) -> Self { + Thing(Box::new(string.chars())) //~ ERROR: lifetime may not live long enough + } + } +} + +mod d { + // Ensure that we are handling tuple enum variants. + pub enum Thing { + Foo(Box>), + } + + impl Thing { + pub fn new(string: &str) -> Self { + Thing::Foo(Box::new(string.chars())) //~ ERROR: lifetime may not live long enough + } + } +} + +mod e { + // Ensure that we are handling struct enum variants. + pub enum Thing { + Foo { + chars: Box>, + } + } + + impl Thing { + pub fn new(string: &str) -> Self { + Thing::Foo { + chars: Box::new(string.chars()), //~ ERROR: lifetime may not live long enough + } + } + } +} + +mod f { + pub struct Thing<'a> { + chars: Box>, + other: &'a (), + } + + impl Thing<'_> { + pub fn new(string: &str) -> Self { + Thing { + chars: Box::new(string.chars()), //~ ERROR: lifetime may not live long enough + other: &(), + } + } + } +} + +mod g { + pub struct Thing<'a> { + chars: Box>, + other: &'a (), + } + + impl<'a> Thing<'a> { + pub fn new(string: &str) -> Self { + Thing { + chars: Box::new(string.chars()), //~ ERROR: lifetime may not live long enough + other: &(), + } + } + } +} + +mod h { + // Multiple lifetime failures on the same expression. We currently only talk about the first + // field's lifetime failure, and point at the first field in the definition. + pub struct Thing { + chars: Box>, + other_chars: Box>, + } + + impl Thing { + pub fn new(string: &str) -> Self { + Thing { + chars: Box::new(string.chars()), //~ ERROR: lifetime may not live long enough + other_chars: Box::new(string.chars()), + } + } + } +} + +mod i { + // Explicit check for more than one `dyn Trait` introducing the `'static` lifetime + pub struct Thing { + chars: (Box>, Box>), + } + + impl Thing { + pub fn new(string: &str) -> Self { + Thing { + chars: (Box::new(string.chars()), Box::new(string.chars())), //~ ERROR: lifetime may not live long enough + } + } + } +} + +mod j { + // Multiple returned values with the same problem. We currently ignore the second incident. + pub struct Thing { + chars: Box>, + } + + impl Thing { + pub fn new(string: &str) -> Self { + if true { + return Thing { + chars: Box::new(string.chars()), //~ ERROR: lifetime may not live long enough + }; + } + Thing { + chars: Box::new(string.chars()), + } + } + } +} + +mod k { + // Similar to `b`, but with a named lifetime in the `impl`. We flat out tell people to use the + // exisitng named lifetime in `fn new(&str)`. + pub struct Thing<'a> { + chars: Box + 'a>, + } + + impl<'a> Thing<'a> { + pub fn new(string: &str) -> Self { + Thing { //~ ERROR: explicit lifetime required in the type of `string` + chars: Box::new(string.chars()), + } + } + } +} + + +fn main() {} diff --git a/tests/ui/regions/return-expr-with-implicit-trait-object-static-obligation.stderr b/tests/ui/regions/return-expr-with-implicit-trait-object-static-obligation.stderr new file mode 100644 index 0000000000000..666eb8334959f --- /dev/null +++ b/tests/ui/regions/return-expr-with-implicit-trait-object-static-obligation.stderr @@ -0,0 +1,215 @@ +error: lifetime may not live long enough + --> $DIR/return-expr-with-implicit-trait-object-static-obligation.rs:14:24 + | +LL | pub fn new(string: &str) -> Self { + | - let's call the lifetime of this reference `'1` +LL | Thing { +LL | chars: Box::new(string.chars()), + | ^^^^^^^^^^^^^^^^^^^^^^^^ coercion requires that `'1` must outlive `'static` + | +note: this `dyn Trait` introduces an implicit `'static` obligation + --> $DIR/return-expr-with-implicit-trait-object-static-obligation.rs:8:20 + | +LL | pub struct Thing { +LL | chars: Box>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider introducing an explicit lifetime + | +LL ~ pub struct Thing<'a> { +LL ~ chars: Box + 'a>, + | + +error: lifetime may not live long enough + --> $DIR/return-expr-with-implicit-trait-object-static-obligation.rs:30:13 + | +LL | impl Thing<'_> { + | -- lifetime `'2` introduced here +LL | pub fn new(string: &str) -> Self { + | - ---- return type is `b::Thing<'2>` + | | + | let's call the lifetime of this reference `'1` +LL | / Thing { +LL | | chars: Box::new(string.chars()), +LL | | } + | |_____________^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + +error: lifetime may not live long enough + --> $DIR/return-expr-with-implicit-trait-object-static-obligation.rs:43:19 + | +LL | pub fn new(string: &str) -> Self { + | - let's call the lifetime of this reference `'1` +LL | Thing(Box::new(string.chars())) + | ^^^^^^^^^^^^^^^^^^^^^^^^ coercion requires that `'1` must outlive `'static` + | +note: this `dyn Trait` introduces an implicit `'static` obligation + --> $DIR/return-expr-with-implicit-trait-object-static-obligation.rs:39:26 + | +LL | pub struct Thing(Box>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider introducing an explicit lifetime + | +LL | pub struct Thing<'a>(Box + 'a>); + | ++++ ++++ + +error: lifetime may not live long enough + --> $DIR/return-expr-with-implicit-trait-object-static-obligation.rs:56:24 + | +LL | pub fn new(string: &str) -> Self { + | - let's call the lifetime of this reference `'1` +LL | Thing::Foo(Box::new(string.chars())) + | ^^^^^^^^^^^^^^^^^^^^^^^^ coercion requires that `'1` must outlive `'static` + | +note: this `dyn Trait` introduces an implicit `'static` obligation + --> $DIR/return-expr-with-implicit-trait-object-static-obligation.rs:51:17 + | +LL | pub enum Thing { +LL | Foo(Box>), + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider introducing an explicit lifetime + | +LL ~ pub enum Thing<'a> { +LL ~ Foo(Box + 'a>), + | + +error: lifetime may not live long enough + --> $DIR/return-expr-with-implicit-trait-object-static-obligation.rs:72:24 + | +LL | pub fn new(string: &str) -> Self { + | - let's call the lifetime of this reference `'1` +LL | Thing::Foo { +LL | chars: Box::new(string.chars()), + | ^^^^^^^^^^^^^^^^^^^^^^^^ coercion requires that `'1` must outlive `'static` + | +note: this `dyn Trait` introduces an implicit `'static` obligation + --> $DIR/return-expr-with-implicit-trait-object-static-obligation.rs:65:24 + | +LL | pub enum Thing { +LL | Foo { +LL | chars: Box>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider introducing an explicit lifetime + | +LL ~ pub enum Thing<'a> { +LL | Foo { +LL ~ chars: Box + 'a>, + | + +error: lifetime may not live long enough + --> $DIR/return-expr-with-implicit-trait-object-static-obligation.rs:87:24 + | +LL | pub fn new(string: &str) -> Self { + | - let's call the lifetime of this reference `'1` +LL | Thing { +LL | chars: Box::new(string.chars()), + | ^^^^^^^^^^^^^^^^^^^^^^^^ coercion requires that `'1` must outlive `'static` + | +note: this `dyn Trait` introduces an implicit `'static` obligation + --> $DIR/return-expr-with-implicit-trait-object-static-obligation.rs:80:20 + | +LL | pub struct Thing<'a> { +LL | chars: Box>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider using an explicit lifetime + | +LL | chars: Box + 'a>, + | ++++ + +error: lifetime may not live long enough + --> $DIR/return-expr-with-implicit-trait-object-static-obligation.rs:103:24 + | +LL | pub fn new(string: &str) -> Self { + | - let's call the lifetime of this reference `'1` +LL | Thing { +LL | chars: Box::new(string.chars()), + | ^^^^^^^^^^^^^^^^^^^^^^^^ coercion requires that `'1` must outlive `'static` + | +note: this `dyn Trait` introduces an implicit `'static` obligation + --> $DIR/return-expr-with-implicit-trait-object-static-obligation.rs:96:20 + | +LL | pub struct Thing<'a> { +LL | chars: Box>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider using an explicit lifetime + | +LL | chars: Box + 'a>, + | ++++ + +error: lifetime may not live long enough + --> $DIR/return-expr-with-implicit-trait-object-static-obligation.rs:121:24 + | +LL | pub fn new(string: &str) -> Self { + | - let's call the lifetime of this reference `'1` +LL | Thing { +LL | chars: Box::new(string.chars()), + | ^^^^^^^^^^^^^^^^^^^^^^^^ coercion requires that `'1` must outlive `'static` + | +note: this `dyn Trait` introduces an implicit `'static` obligation + --> $DIR/return-expr-with-implicit-trait-object-static-obligation.rs:114:20 + | +LL | pub struct Thing { +LL | chars: Box>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider introducing an explicit lifetime + | +LL ~ pub struct Thing<'a> { +LL ~ chars: Box + 'a>, + | + +error: lifetime may not live long enough + --> $DIR/return-expr-with-implicit-trait-object-static-obligation.rs:137:25 + | +LL | pub fn new(string: &str) -> Self { + | - let's call the lifetime of this reference `'1` +LL | Thing { +LL | chars: (Box::new(string.chars()), Box::new(string.chars())), + | ^^^^^^^^^^^^^^^^^^^^^^^^ coercion requires that `'1` must outlive `'static` + | +note: these `dyn Trait`s introduce an implicit `'static` obligation + --> $DIR/return-expr-with-implicit-trait-object-static-obligation.rs:131:21 + | +LL | pub struct Thing { +LL | chars: (Box>, Box>), + | ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider introducing an explicit lifetime + | +LL ~ pub struct Thing<'a> { +LL ~ chars: (Box + 'a>, Box + 'a>), + | + +error: lifetime may not live long enough + --> $DIR/return-expr-with-implicit-trait-object-static-obligation.rs:153:28 + | +LL | pub fn new(string: &str) -> Self { + | - let's call the lifetime of this reference `'1` +... +LL | chars: Box::new(string.chars()), + | ^^^^^^^^^^^^^^^^^^^^^^^^ coercion requires that `'1` must outlive `'static` + | +note: this `dyn Trait` introduces an implicit `'static` obligation + --> $DIR/return-expr-with-implicit-trait-object-static-obligation.rs:146:20 + | +LL | pub struct Thing { +LL | chars: Box>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider introducing an explicit lifetime + | +LL ~ pub struct Thing<'a> { +LL ~ chars: Box + 'a>, + | + +error[E0621]: explicit lifetime required in the type of `string` + --> $DIR/return-expr-with-implicit-trait-object-static-obligation.rs:172:13 + | +LL | / Thing { +LL | | chars: Box::new(string.chars()), +LL | | } + | |_____________^ lifetime `'a` required + | +help: add explicit lifetime `'a` to the type of `string` + | +LL | pub fn new(string: &'a str) -> Self { + | ++ + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr b/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr index 57527dd31df35..b76ffa0606c2a 100644 --- a/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr +++ b/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr @@ -32,8 +32,9 @@ error: lifetime may not live long enough --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:21:9 | LL | fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { - | -- ---- has type `Pin<&'1 Foo>` - | | + | -- ---- - lifetime `'1` introduced here + | | | + | | has type `Pin<&'1 Foo>` | lifetime `'a` defined here LL | arg | ^^^ method was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a` diff --git a/tests/ui/static/static-reference-to-fn-2.stderr b/tests/ui/static/static-reference-to-fn-2.stderr index 133d8ec2e1e51..ae80c8a7bd136 100644 --- a/tests/ui/static/static-reference-to-fn-2.stderr +++ b/tests/ui/static/static-reference-to-fn-2.stderr @@ -2,7 +2,9 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/static-reference-to-fn-2.rs:18:22 | LL | fn state1(self_: &mut StateMachineIter) -> Option<&'static str> { - | ----- has type `&mut StateMachineIter<'1>` + | ----- ---------------- lifetime `'1` introduced here + | | + | has type `&mut StateMachineIter<'1>` LL | self_.statefn = &id(state2 as StateMachineFunc); | -----------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- temporary value is freed at the end of this statement | | | @@ -13,7 +15,9 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/static-reference-to-fn-2.rs:24:22 | LL | fn state2(self_: &mut StateMachineIter) -> Option<(&'static str)> { - | ----- has type `&mut StateMachineIter<'1>` + | ----- ---------------- lifetime `'1` introduced here + | | + | has type `&mut StateMachineIter<'1>` LL | self_.statefn = &id(state3 as StateMachineFunc); | -----------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- temporary value is freed at the end of this statement | | | @@ -24,7 +28,9 @@ error[E0716]: temporary value dropped while borrowed --> $DIR/static-reference-to-fn-2.rs:30:22 | LL | fn state3(self_: &mut StateMachineIter) -> Option<(&'static str)> { - | ----- has type `&mut StateMachineIter<'1>` + | ----- ---------------- lifetime `'1` introduced here + | | + | has type `&mut StateMachineIter<'1>` LL | self_.statefn = &id(finished as StateMachineFunc); | -----------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- temporary value is freed at the end of this statement | | | diff --git a/tests/ui/transmutability/impl-transmute-from-returning-box.next.stderr b/tests/ui/transmutability/impl-transmute-from-returning-box.next.stderr new file mode 100644 index 0000000000000..eb3db28958cb1 --- /dev/null +++ b/tests/ui/transmutability/impl-transmute-from-returning-box.next.stderr @@ -0,0 +1,24 @@ +error[E0220]: associated type `Output` not found for `TransmuteFrom` + --> $DIR/impl-transmute-from-returning-box.rs:9:40 + | +LL | pub fn box_factory() -> impl std::mem::TransmuteFrom() { + | ^^^^^^^^^^^^^^^ associated type `Output` not found + +error[E0220]: associated type `Output` not found for `TransmuteFrom` + --> $DIR/impl-transmute-from-returning-box.rs:9:40 + | +LL | pub fn box_factory() -> impl std::mem::TransmuteFrom() { + | ^^^^^^^^^^^^^^^ associated type `Output` not found + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0277]: `()` cannot be safely transmuted into `Box<()>` + --> $DIR/impl-transmute-from-returning-box.rs:9:25 + | +LL | pub fn box_factory() -> impl std::mem::TransmuteFrom() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ analyzing the transmutability of `Box<()>` is not yet supported + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0220, E0277. +For more information about an error, try `rustc --explain E0220`. diff --git a/tests/ui/transmutability/impl-transmute-from-returning-box.old.stderr b/tests/ui/transmutability/impl-transmute-from-returning-box.old.stderr new file mode 100644 index 0000000000000..5c6e8a1686f65 --- /dev/null +++ b/tests/ui/transmutability/impl-transmute-from-returning-box.old.stderr @@ -0,0 +1,27 @@ +error[E0220]: associated type `Output` not found for `TransmuteFrom` + --> $DIR/impl-transmute-from-returning-box.rs:9:40 + | +LL | pub fn box_factory() -> impl std::mem::TransmuteFrom() { + | ^^^^^^^^^^^^^^^ associated type `Output` not found + +error[E0220]: associated type `Output` not found for `TransmuteFrom` + --> $DIR/impl-transmute-from-returning-box.rs:9:40 + | +LL | pub fn box_factory() -> impl std::mem::TransmuteFrom() { + | ^^^^^^^^^^^^^^^ associated type `Output` not found + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0277]: `()` cannot be safely transmuted into `Box<()>` + --> $DIR/impl-transmute-from-returning-box.rs:9:25 + | +LL | pub fn box_factory() -> impl std::mem::TransmuteFrom() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ analyzing the transmutability of `Box<()>` is not yet supported +... +LL | Box::new(()) + | ------------ return type was inferred to be `Box<()>` here + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0220, E0277. +For more information about an error, try `rustc --explain E0220`. diff --git a/tests/ui/transmutability/impl-transmute-from-returning-box.rs b/tests/ui/transmutability/impl-transmute-from-returning-box.rs new file mode 100644 index 0000000000000..7631acd96fa54 --- /dev/null +++ b/tests/ui/transmutability/impl-transmute-from-returning-box.rs @@ -0,0 +1,16 @@ +// Regression test for: https://github.com/rust-lang/rust/issues/154536 +//@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@ [next] compile-flags: -Znext-solver + +#![feature(transmutability)] +#![feature(unboxed_closures)] + +pub fn box_factory() -> impl std::mem::TransmuteFrom() { + //~^ ERROR: `()` cannot be safely transmuted into `Box<()>` + //~^^ ERROR: associated type `Output` not found for `TransmuteFrom` + //~^^^ ERROR: associated type `Output` not found for `TransmuteFrom` + Box::new(()) +} + +fn main() {} diff --git a/tests/ui/transmutability/with-fn-mut-and-impl-sized.next.stderr b/tests/ui/transmutability/with-fn-mut-and-impl-sized.next.stderr new file mode 100644 index 0000000000000..70bcfc07bb2d8 --- /dev/null +++ b/tests/ui/transmutability/with-fn-mut-and-impl-sized.next.stderr @@ -0,0 +1,21 @@ +error[E0107]: missing generics for struct `Ref` + --> $DIR/with-fn-mut-and-impl-sized.rs:11:22 + | +LL | fn delay C, C: std::mem::TransmuteFrom()>(make: Make) -> impl Sized {} + | ^^^ expected 1 generic argument + | +help: add missing generic argument + | +LL | fn delay) -> C, C: std::mem::TransmuteFrom()>(make: Make) -> impl Sized {} + | +++ + +error[E0220]: associated type `Output` not found for `TransmuteFrom` + --> $DIR/with-fn-mut-and-impl-sized.rs:11:46 + | +LL | fn delay C, C: std::mem::TransmuteFrom()>(make: Make) -> impl Sized {} + | ^^^^^^^^^^^^^^^ associated type `Output` not found + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0107, E0220. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/transmutability/with-fn-mut-and-impl-sized.old.stderr b/tests/ui/transmutability/with-fn-mut-and-impl-sized.old.stderr new file mode 100644 index 0000000000000..70bcfc07bb2d8 --- /dev/null +++ b/tests/ui/transmutability/with-fn-mut-and-impl-sized.old.stderr @@ -0,0 +1,21 @@ +error[E0107]: missing generics for struct `Ref` + --> $DIR/with-fn-mut-and-impl-sized.rs:11:22 + | +LL | fn delay C, C: std::mem::TransmuteFrom()>(make: Make) -> impl Sized {} + | ^^^ expected 1 generic argument + | +help: add missing generic argument + | +LL | fn delay) -> C, C: std::mem::TransmuteFrom()>(make: Make) -> impl Sized {} + | +++ + +error[E0220]: associated type `Output` not found for `TransmuteFrom` + --> $DIR/with-fn-mut-and-impl-sized.rs:11:46 + | +LL | fn delay C, C: std::mem::TransmuteFrom()>(make: Make) -> impl Sized {} + | ^^^^^^^^^^^^^^^ associated type `Output` not found + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0107, E0220. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/transmutability/with-fn-mut-and-impl-sized.rs b/tests/ui/transmutability/with-fn-mut-and-impl-sized.rs new file mode 100644 index 0000000000000..b98b573fcda11 --- /dev/null +++ b/tests/ui/transmutability/with-fn-mut-and-impl-sized.rs @@ -0,0 +1,17 @@ +// Regression test for: https://github.com/rust-lang/rust/issues/153357 +//@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@ [next] compile-flags: -Znext-solver + +#![feature(transmutability)] +#![feature(unboxed_closures)] + +use std::cell::Ref; + +fn delay C, C: std::mem::TransmuteFrom()>(make: Make) -> impl Sized {} +//~^ ERROR: missing generics for struct `Ref` +//~^^ ERROR: associated type `Output` not found for `TransmuteFrom` + +fn main() { + delay(|0| delay) +} diff --git a/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr b/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr index dbbee54c185bf..15894a0c09c6e 100644 --- a/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr +++ b/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr @@ -40,6 +40,12 @@ LL | >::add(1u32, 2); | this argument influences the return type of `add` note: method defined here --> $SRC_DIR/core/src/ops/arith.rs:LL:COL +note: method provided through this `impl` + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL + ::: $SRC_DIR/core/src/ops/arith.rs:LL:COL + | + = note: in this macro invocation + = note: this error originates in the macro `add_impl` (in Nightly builds, run with -Z macro-backtrace for more info) help: change the type of the numeric literal from `u32` to `i32` | LL - >::add(1u32, 2); @@ -63,6 +69,12 @@ LL | >::add(1, 2u32); | this argument influences the return type of `add` note: method defined here --> $SRC_DIR/core/src/ops/arith.rs:LL:COL +note: method provided through this `impl` + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL + ::: $SRC_DIR/core/src/ops/arith.rs:LL:COL + | + = note: in this macro invocation + = note: this error originates in the macro `add_impl` (in Nightly builds, run with -Z macro-backtrace for more info) help: change the type of the numeric literal from `u32` to `i32` | LL - >::add(1, 2u32);