diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index e93351bcf7125..430ffded2e87a 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -3540,8 +3540,9 @@ impl Item { ItemKind::Const(i) => Some(&i.generics), ItemKind::Fn(i) => Some(&i.generics), ItemKind::TyAlias(i) => Some(&i.generics), - ItemKind::TraitAlias(_, generics, _) - | ItemKind::Enum(_, generics, _) + ItemKind::TraitAlias(i) => Some(&i.generics), + + ItemKind::Enum(_, generics, _) | ItemKind::Struct(_, generics, _) | ItemKind::Union(_, generics, _) => Some(&generics), ItemKind::Trait(i) => Some(&i.generics), @@ -3623,6 +3624,15 @@ impl Default for FnHeader { } } +#[derive(Clone, Encodable, Decodable, Debug, Walkable)] +pub struct TraitAlias { + pub constness: Const, + pub ident: Ident, + pub generics: Generics, + #[visitable(extra = BoundKind::Bound)] + pub bounds: GenericBounds, +} + #[derive(Clone, Encodable, Decodable, Debug, Walkable)] pub struct Trait { pub constness: Const, @@ -3798,7 +3808,7 @@ pub enum ItemKind { /// Trait alias. /// /// E.g., `trait Foo = Bar + Quux;`. - TraitAlias(Ident, Generics, GenericBounds), + TraitAlias(Box), /// An implementation. /// /// E.g., `impl Foo { .. }` or `impl Trait for Foo { .. }`. @@ -3831,7 +3841,7 @@ impl ItemKind { | ItemKind::Struct(ident, ..) | ItemKind::Union(ident, ..) | ItemKind::Trait(box Trait { ident, .. }) - | ItemKind::TraitAlias(ident, ..) + | ItemKind::TraitAlias(box TraitAlias { ident, .. }) | ItemKind::MacroDef(ident, _) | ItemKind::Delegation(box Delegation { ident, .. }) => Some(ident), @@ -3888,7 +3898,7 @@ impl ItemKind { | Self::Struct(_, generics, _) | Self::Union(_, generics, _) | Self::Trait(box Trait { generics, .. }) - | Self::TraitAlias(_, generics, _) + | Self::TraitAlias(box TraitAlias { generics, .. }) | Self::Impl(Impl { generics, .. }) => Some(generics), _ => None, } @@ -4050,8 +4060,8 @@ mod size_asserts { static_assert_size!(GenericBound, 88); static_assert_size!(Generics, 40); static_assert_size!(Impl, 64); - static_assert_size!(Item, 144); - static_assert_size!(ItemKind, 80); + static_assert_size!(Item, 136); + static_assert_size!(ItemKind, 72); static_assert_size!(LitKind, 24); static_assert_size!(Local, 96); static_assert_size!(MetaItemLit, 40); diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 03e5a6edeece5..d850698f47b08 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -833,8 +833,8 @@ macro_rules! common_visitor_and_walkers { visit_visitable!($($mut)? vis, impl_), ItemKind::Trait(trait_) => visit_visitable!($($mut)? vis, trait_), - ItemKind::TraitAlias(ident, generics, bounds) => { - visit_visitable!($($mut)? vis, ident, generics); + ItemKind::TraitAlias(box TraitAlias { constness, ident, generics, bounds}) => { + visit_visitable!($($mut)? vis, constness, ident, generics); visit_visitable_with!($($mut)? vis, bounds, BoundKind::Bound) } ItemKind::MacCall(m) => diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 8527108f70419..177f33c0d8f1c 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -415,7 +415,8 @@ impl<'hir> LoweringContext<'_, 'hir> { ); hir::ItemKind::Trait(constness, *is_auto, safety, ident, generics, bounds, items) } - ItemKind::TraitAlias(ident, generics, bounds) => { + ItemKind::TraitAlias(box TraitAlias { constness, ident, generics, bounds }) => { + let constness = self.lower_constness(*constness); let ident = self.lower_ident(*ident); let (generics, bounds) = self.lower_generics( generics, @@ -429,7 +430,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ) }, ); - hir::ItemKind::TraitAlias(ident, generics, bounds) + hir::ItemKind::TraitAlias(constness, ident, generics, bounds) } ItemKind::MacroDef(ident, MacroDef { body, macro_rules }) => { let ident = self.lower_ident(*ident); diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 93f8b74ad561f..6b218f34363dd 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1192,6 +1192,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> { walk_list!(this, visit_assoc_item, items, AssocCtxt::Trait); }); } + ItemKind::TraitAlias(box TraitAlias { constness, generics, bounds, .. }) => { + let disallowed = matches!(constness, ast::Const::No) + .then(|| TildeConstReason::Trait { span: item.span }); + self.with_tilde_const(disallowed, |this| { + this.visit_generics(generics); + walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits) + }); + } ItemKind::Mod(safety, ident, mod_kind) => { if let &Safety::Unsafe(span) = safety { self.dcx().emit_err(errors::UnsafeItem { span, kind: "module" }); diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 3412660863407..294d03a83b161 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -1,7 +1,6 @@ use ast::StaticItem; use itertools::{Itertools, Position}; -use rustc_ast as ast; -use rustc_ast::ModKind; +use rustc_ast::{self as ast, ModKind, TraitAlias}; use rustc_span::Ident; use crate::pp::BoxMarker; @@ -386,8 +385,11 @@ impl<'a> State<'a> { let empty = item.attrs.is_empty() && items.is_empty(); self.bclose(item.span, empty, cb); } - ast::ItemKind::TraitAlias(ident, generics, bounds) => { - let (cb, ib) = self.head(visibility_qualified(&item.vis, "trait")); + ast::ItemKind::TraitAlias(box TraitAlias { constness, ident, generics, bounds }) => { + let (cb, ib) = self.head(""); + self.print_visibility(&item.vis); + self.print_constness(*constness); + self.word_nbsp("trait"); self.print_ident(*ident); self.print_generic_params(&generics.params); self.nbsp(); diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index d26e289bc0d28..ac7ad669b4611 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -4151,8 +4151,8 @@ impl<'hir> Item<'hir> { ItemKind::Trait(constness, is_auto, safety, ident, generics, bounds, items), (*constness, *is_auto, *safety, *ident, generics, bounds, items); - expect_trait_alias, (Ident, &'hir Generics<'hir>, GenericBounds<'hir>), - ItemKind::TraitAlias(ident, generics, bounds), (*ident, generics, bounds); + expect_trait_alias, (Constness, Ident, &'hir Generics<'hir>, GenericBounds<'hir>), + ItemKind::TraitAlias(constness, ident, generics, bounds), (*constness, *ident, generics, bounds); expect_impl, &Impl<'hir>, ItemKind::Impl(imp), imp; } @@ -4329,7 +4329,7 @@ pub enum ItemKind<'hir> { &'hir [TraitItemId], ), /// A trait alias. - TraitAlias(Ident, &'hir Generics<'hir>, GenericBounds<'hir>), + TraitAlias(Constness, Ident, &'hir Generics<'hir>, GenericBounds<'hir>), /// An implementation, e.g., `impl Trait for Foo { .. }`. Impl(Impl<'hir>), @@ -4374,7 +4374,7 @@ impl ItemKind<'_> { | ItemKind::Struct(ident, ..) | ItemKind::Union(ident, ..) | ItemKind::Trait(_, _, _, ident, ..) - | ItemKind::TraitAlias(ident, ..) => Some(ident), + | ItemKind::TraitAlias(_, ident, ..) => Some(ident), ItemKind::Use(_, UseKind::Glob | UseKind::ListStem) | ItemKind::ForeignMod { .. } @@ -4392,7 +4392,7 @@ impl ItemKind<'_> { | ItemKind::Struct(_, generics, _) | ItemKind::Union(_, generics, _) | ItemKind::Trait(_, _, _, _, generics, _, _) - | ItemKind::TraitAlias(_, generics, _) + | ItemKind::TraitAlias(_, _, generics, _) | ItemKind::Impl(Impl { generics, .. }) => generics, _ => return None, }) diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 48b5200019b37..232178ee403a6 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -626,7 +626,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V:: walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_trait_item_ref, trait_item_refs); } - ItemKind::TraitAlias(ident, ref generics, bounds) => { + ItemKind::TraitAlias(_constness, ident, ref generics, bounds) => { try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_generics(generics)); walk_list!(visitor, visit_param_bound, bounds); diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 89ab710ff8218..1386070e3d9b6 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -847,7 +847,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef { hir::ItemKind::Trait(constness, is_auto, safety, ..) => { (constness, false, is_auto == hir::IsAuto::Yes, safety) } - hir::ItemKind::TraitAlias(..) => (hir::Constness::NotConst, true, false, hir::Safety::Safe), + hir::ItemKind::TraitAlias(constness, ..) => (constness, true, false, hir::Safety::Safe), _ => span_bug!(item.span, "trait_def_of_item invoked on non-trait"), }; diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 79aaa0cb79701..2eefe1eb3e922 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -167,7 +167,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen } } ItemKind::Trait(_, _, _, _, _, self_bounds, ..) - | ItemKind::TraitAlias(_, _, self_bounds) => { + | ItemKind::TraitAlias(_, _, _, self_bounds) => { is_trait = Some((self_bounds, item.span)); } _ => {} @@ -654,7 +654,7 @@ pub(super) fn implied_predicates_with_filter<'tcx>( let (generics, superbounds) = match item.kind { hir::ItemKind::Trait(.., generics, supertraits, _) => (generics, supertraits), - hir::ItemKind::TraitAlias(_, generics, supertraits) => (generics, supertraits), + hir::ItemKind::TraitAlias(_, _, generics, supertraits) => (generics, supertraits), _ => span_bug!(item.span, "super_predicates invoked on non-trait"), }; @@ -1032,7 +1032,10 @@ pub(super) fn const_conditions<'tcx>( hir::ItemKind::Impl(impl_) => (impl_.generics, None, false), hir::ItemKind::Fn { generics, .. } => (generics, None, false), hir::ItemKind::Trait(_, _, _, _, generics, supertraits, _) => { - (generics, Some((item.owner_id.def_id, supertraits)), false) + (generics, Some((Some(item.owner_id.def_id), supertraits)), false) + } + hir::ItemKind::TraitAlias(_, _, generics, supertraits) => { + (generics, Some((None, supertraits)), false) } _ => bug!("const_conditions called on wrong item: {def_id:?}"), }, @@ -1089,12 +1092,14 @@ pub(super) fn const_conditions<'tcx>( } if let Some((def_id, supertraits)) = trait_def_id_and_supertraits { - // We've checked above that the trait is conditionally const. - bounds.push(( - ty::Binder::dummy(ty::TraitRef::identity(tcx, def_id.to_def_id())) - .to_host_effect_clause(tcx, ty::BoundConstness::Maybe), - DUMMY_SP, - )); + if let Some(def_id) = def_id { + // We've checked above that the trait is conditionally const. + bounds.push(( + ty::Binder::dummy(ty::TraitRef::identity(tcx, def_id.to_def_id())) + .to_host_effect_clause(tcx, ty::BoundConstness::Maybe), + DUMMY_SP, + )); + } icx.lowerer().lower_bounds( tcx.types.self_param, @@ -1143,13 +1148,14 @@ pub(super) fn explicit_implied_const_bounds<'tcx>( span_bug!(tcx.def_span(def_id), "RPITIT in impl should not have item bounds") } None => match tcx.hir_node_by_def_id(def_id) { - Node::Item(hir::Item { kind: hir::ItemKind::Trait(..), .. }) => { - implied_predicates_with_filter( - tcx, - def_id.to_def_id(), - PredicateFilter::SelfConstIfConst, - ) - } + Node::Item(hir::Item { + kind: hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..), + .. + }) => implied_predicates_with_filter( + tcx, + def_id.to_def_id(), + PredicateFilter::SelfConstIfConst, + ), Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Type(..), .. }) | Node::OpaqueTy(_) => { explicit_item_bounds_with_filter(tcx, def_id, PredicateFilter::ConstIfConst) diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 8133f9f68234b..14e48594c006c 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -632,7 +632,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { | hir::ItemKind::Struct(_, generics, _) | hir::ItemKind::Union(_, generics, _) | hir::ItemKind::Trait(_, _, _, _, generics, ..) - | hir::ItemKind::TraitAlias(_, generics, ..) + | hir::ItemKind::TraitAlias(_, _, generics, ..) | hir::ItemKind::Impl(hir::Impl { generics, .. }) => { // These kinds of items have only early-bound lifetime parameters. self.visit_early(item.hir_id(), generics, |this| intravisit::walk_item(this, item)); diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index f7bbc2e51f4cf..12d981396c8a4 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -765,8 +765,10 @@ impl<'a> State<'a> { } self.bclose(item.span, cb); } - hir::ItemKind::TraitAlias(ident, generics, bounds) => { - let (cb, ib) = self.head("trait"); + hir::ItemKind::TraitAlias(constness, ident, generics, bounds) => { + let (cb, ib) = self.head(""); + self.print_constness(constness); + self.word_nbsp("trait"); self.print_ident(ident); self.print_generic_params(generics.params); self.nbsp(); diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 09361f046ea89..8e9c6eb046aed 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1596,7 +1596,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Node::Item(hir::Item { kind: hir::ItemKind::Trait(_, _, _, ident, ..) - | hir::ItemKind::TraitAlias(ident, ..), + | hir::ItemKind::TraitAlias(_, ident, ..), .. }) // We may also encounter unsatisfied GAT or method bounds diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index aeb15a3de312e..c9fdb61e9c2cb 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -288,7 +288,15 @@ pub(crate) fn run_in_thread_pool_with_globals< pool.install(|| f(current_gcx.into_inner(), proxy)) }, ) - .unwrap() + .unwrap_or_else(|err| { + let mut diag = thread_builder_diag.early_struct_fatal(format!( + "failed to spawn compiler thread pool: could not create {threads} threads ({err})", + )); + diag.help( + "try lowering `-Z threads` or checking the operating system's resource limits", + ); + diag.emit(); + }) }) }) } diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index 7f643a551bb70..b90abe0a24f15 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -160,7 +160,9 @@ impl EarlyLintPass for NonCamelCaseTypes { ast::ItemKind::Trait(box ast::Trait { ident, .. }) => { self.check_case(cx, "trait", ident) } - ast::ItemKind::TraitAlias(ident, _, _) => self.check_case(cx, "trait alias", ident), + ast::ItemKind::TraitAlias(box ast::TraitAlias { ident, .. }) => { + self.check_case(cx, "trait alias", ident) + } // N.B. This check is only for inherent associated types, so that we don't lint against // trait impls where we should have warned for the trait definition already. diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 93d0c77c1daee..905874f05628f 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2101,7 +2101,7 @@ impl<'tcx> TyCtxt<'tcx> { DefKind::Fn | DefKind::Ctor(_, CtorKind::Fn) => { self.constness(def_id) == hir::Constness::Const } - DefKind::Trait => self.is_const_trait(def_id), + DefKind::TraitAlias | DefKind::Trait => self.is_const_trait(def_id), DefKind::AssocTy => { let parent_def_id = self.parent(def_id); match self.def_kind(parent_def_id) { @@ -2144,7 +2144,6 @@ impl<'tcx> TyCtxt<'tcx> { | DefKind::Variant | DefKind::TyAlias | DefKind::ForeignTy - | DefKind::TraitAlias | DefKind::TyParam | DefKind::Const | DefKind::ConstParam diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs index 695a29e58a5e7..2036129d54e44 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -196,10 +196,35 @@ where } fn consider_trait_alias_candidate( - _ecx: &mut EvalCtxt<'_, D>, - _goal: Goal, + ecx: &mut EvalCtxt<'_, D>, + goal: Goal, ) -> Result, NoSolution> { - unreachable!("trait aliases are never const") + let cx = ecx.cx(); + + ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { + let where_clause_bounds = cx + .predicates_of(goal.predicate.def_id().into()) + .iter_instantiated(cx, goal.predicate.trait_ref.args) + .map(|p| goal.with(cx, p)); + + let const_conditions = cx + .const_conditions(goal.predicate.def_id().into()) + .iter_instantiated(cx, goal.predicate.trait_ref.args) + .map(|bound_trait_ref| { + goal.with( + cx, + bound_trait_ref.to_host_effect_clause(cx, goal.predicate.constness), + ) + }); + // While you could think of trait aliases to have a single builtin impl + // which uses its implied trait bounds as where-clauses, using + // `GoalSource::ImplWhereClause` here would be incorrect, as we also + // impl them, which means we're "stepping out of the impl constructor" + // again. To handle this, we treat these cycles as ambiguous for now. + ecx.add_goals(GoalSource::Misc, where_clause_bounds); + ecx.add_goals(GoalSource::Misc, const_conditions); + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }) } fn consider_builtin_sizedness_candidates( diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 52a35c98a98b5..1862900077f0f 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -863,7 +863,6 @@ parse_too_short_hex_escape = numeric character escape is too short parse_trailing_vert_not_allowed = a trailing `{$token}` is not allowed in an or-pattern parse_trait_alias_cannot_be_auto = trait aliases cannot be `auto` -parse_trait_alias_cannot_be_const = trait aliases cannot be `const` parse_trait_alias_cannot_be_unsafe = trait aliases cannot be `unsafe` parse_trait_impl_modifier_in_inherent_impl = inherent impls cannot be {$modifier_name} diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 6d536aa850b3d..a35c5c304d95e 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1999,14 +1999,6 @@ pub(crate) struct TraitAliasCannotBeAuto { pub span: Span, } -#[derive(Diagnostic)] -#[diag(parse_trait_alias_cannot_be_const)] -pub(crate) struct TraitAliasCannotBeConst { - #[primary_span] - #[label(parse_trait_alias_cannot_be_const)] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(parse_trait_alias_cannot_be_unsafe)] pub(crate) struct TraitAliasCannotBeUnsafe { diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 11eae9e2d903e..4bb0d05c4f37c 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -943,9 +943,6 @@ impl<'a> Parser<'a> { self.expect_semi()?; let whole_span = lo.to(self.prev_token.span); - if let Const::Yes(_) = constness { - self.dcx().emit_err(errors::TraitAliasCannotBeConst { span: whole_span }); - } if is_auto == IsAuto::Yes { self.dcx().emit_err(errors::TraitAliasCannotBeAuto { span: whole_span }); } @@ -955,7 +952,7 @@ impl<'a> Parser<'a> { self.psess.gated_spans.gate(sym::trait_alias, whole_span); - Ok(ItemKind::TraitAlias(ident, generics, bounds)) + Ok(ItemKind::TraitAlias(Box::new(TraitAlias { constness, ident, generics, bounds }))) } else { // It's a normal trait. generics.where_clause = self.parse_where_clause()?; diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 877b5ad93bfca..6d34587684bb3 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -125,9 +125,13 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { ) => { self.check_def_id(def_id); } - _ if self.in_pat => {} Res::PrimTy(..) | Res::SelfCtor(..) | Res::Local(..) => {} Res::Def(DefKind::Ctor(CtorOf::Variant, ..), ctor_def_id) => { + // Using a variant in patterns should not make the variant live, + // since we can just remove the match arm that matches the pattern + if self.in_pat { + return; + } let variant_id = self.tcx.parent(ctor_def_id); let enum_id = self.tcx.parent(variant_id); self.check_def_id(enum_id); @@ -136,6 +140,11 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { } } Res::Def(DefKind::Variant, variant_id) => { + // Using a variant in patterns should not make the variant live, + // since we can just remove the match arm that matches the pattern + if self.in_pat { + return; + } let enum_id = self.tcx.parent(variant_id); self.check_def_id(enum_id); if !self.ignore_variant_stack.contains(&variant_id) { diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 88fbc6dcb6650..886ffcffbb4d9 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -10,7 +10,7 @@ use std::sync::Arc; use rustc_ast::visit::{self, AssocCtxt, Visitor, WalkItemKind}; use rustc_ast::{ self as ast, AssocItem, AssocItemKind, Block, ConstItem, Delegation, Fn, ForeignItem, - ForeignItemKind, Inline, Item, ItemKind, NodeId, StaticItem, StmtKind, TyAlias, + ForeignItemKind, Inline, Item, ItemKind, NodeId, StaticItem, StmtKind, TraitAlias, TyAlias, }; use rustc_attr_parsing as attr; use rustc_attr_parsing::AttributeParser; @@ -844,7 +844,8 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } // These items live in the type namespace. - ItemKind::TyAlias(box TyAlias { ident, .. }) | ItemKind::TraitAlias(ident, ..) => { + ItemKind::TyAlias(box TyAlias { ident, .. }) + | ItemKind::TraitAlias(box TraitAlias { ident, .. }) => { self.r.define_local(parent, ident, TypeNS, res, vis, sp, expansion); } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index fd7ace368aa67..e3051dc38eca2 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2645,7 +2645,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ); } - ItemKind::TraitAlias(_, ref generics, ref bounds) => { + ItemKind::TraitAlias(box TraitAlias { ref generics, ref bounds, .. }) => { // Create a new rib for the trait-wide type parameters. self.with_generic_param_rib( &generics.params, @@ -5164,7 +5164,7 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { | ItemKind::Union(_, generics, _) | ItemKind::Impl(Impl { generics, .. }) | ItemKind::Trait(box Trait { generics, .. }) - | ItemKind::TraitAlias(_, generics, _) => { + | ItemKind::TraitAlias(box TraitAlias { generics, .. }) => { if let ItemKind::Fn(box Fn { sig, .. }) = &item.kind { self.collect_fn_info(sig.header, &sig.decl, item.id, &item.attrs); } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs index ded5969e83c5c..8e4c7cec0dcf0 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs @@ -476,9 +476,8 @@ pub fn report_dyn_incompatibility<'tcx>( let trait_str = tcx.def_path_str(trait_def_id); let trait_span = tcx.hir_get_if_local(trait_def_id).and_then(|node| match node { hir::Node::Item(item) => match item.kind { - hir::ItemKind::Trait(_, _, _, ident, ..) | hir::ItemKind::TraitAlias(ident, _, _) => { - Some(ident.span) - } + hir::ItemKind::Trait(_, _, _, ident, ..) + | hir::ItemKind::TraitAlias(_, ident, _, _) => Some(ident.span), _ => unreachable!(), }, _ => None, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 4ecc48d6cc40f..cd0dbb4d87f99 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -364,7 +364,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { | hir::ItemKind::Fn { generics, .. } | hir::ItemKind::TyAlias(_, generics, _) | hir::ItemKind::Const(_, generics, _, _) - | hir::ItemKind::TraitAlias(_, generics, _), + | hir::ItemKind::TraitAlias(_, _, generics, _), .. }) | hir::Node::TraitItem(hir::TraitItem { generics, .. }) @@ -444,7 +444,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { | hir::ItemKind::Fn { generics, .. } | hir::ItemKind::TyAlias(_, generics, _) | hir::ItemKind::Const(_, generics, _, _) - | hir::ItemKind::TraitAlias(_, generics, _), + | hir::ItemKind::TraitAlias(_, _, generics, _), .. }) if finder.can_suggest_bound(generics) => { // Missing generic type parameter bound. diff --git a/compiler/rustc_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs index c29e3281f2248..d661c585d68e8 100644 --- a/compiler/rustc_trait_selection/src/traits/effects.rs +++ b/compiler/rustc_trait_selection/src/traits/effects.rs @@ -69,6 +69,12 @@ pub fn evaluate_host_effect_obligation<'tcx>( Err(EvaluationFailure::NoSolution) => {} } + match evaluate_host_effect_from_trait_alias(selcx, obligation) { + Ok(result) => return Ok(result), + Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous), + Err(EvaluationFailure::NoSolution) => {} + } + Err(EvaluationFailure::NoSolution) } @@ -593,3 +599,37 @@ fn evaluate_host_effect_from_selection_candidate<'tcx>( } }) } + +fn evaluate_host_effect_from_trait_alias<'tcx>( + selcx: &mut SelectionContext<'_, 'tcx>, + obligation: &HostEffectObligation<'tcx>, +) -> Result>, EvaluationFailure> { + let tcx = selcx.tcx(); + let def_id = obligation.predicate.def_id(); + if !tcx.trait_is_alias(def_id) { + return Err(EvaluationFailure::NoSolution); + } + + Ok(tcx + .const_conditions(def_id) + .instantiate(tcx, obligation.predicate.trait_ref.args) + .into_iter() + .map(|(trait_ref, span)| { + Obligation::new( + tcx, + obligation.cause.clone().derived_host_cause( + ty::Binder::dummy(obligation.predicate), + |derived| { + ObligationCauseCode::ImplDerivedHost(Box::new(ImplDerivedHostCause { + derived, + impl_def_id: def_id, + span, + })) + }, + ), + obligation.param_env, + trait_ref.to_host_effect_clause(tcx, obligation.predicate.constness), + ) + }) + .collect()) +} diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 52915abca1504..e1b3ff92a07b8 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1965,6 +1965,9 @@ Please disable assertions with `rust.debug-assertions = false`. cmd.arg("--default-codegen-backend") .arg(builder.config.default_codegen_backend(test_compiler.host).name()); } + if builder.config.cmd.bypass_ignore_backends() { + cmd.arg("--bypass-ignore-backends"); + } if builder.build.config.llvm_enzyme { cmd.arg("--has-enzyme"); diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs index 9e408505933d3..bf089d25ffec8 100644 --- a/src/bootstrap/src/core/config/flags.rs +++ b/src/bootstrap/src/core/config/flags.rs @@ -422,6 +422,9 @@ pub enum Subcommand { #[arg(long)] /// Use a different codegen backend when running tests. test_codegen_backend: Option, + #[arg(long)] + /// Ignore `//@ ignore-backends` directives. + bypass_ignore_backends: bool, }, /// Build and run some test suites *in Miri* Miri { @@ -668,6 +671,13 @@ impl Subcommand { _ => None, } } + + pub fn bypass_ignore_backends(&self) -> bool { + match self { + Subcommand::Test { bypass_ignore_backends, .. } => *bypass_ignore_backends, + _ => false, + } + } } /// Returns the shell completion for a given shell, if the result differs from the current diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md index 12ceef0c928de..045c8c71f9cd2 100644 --- a/src/doc/rustc-dev-guide/src/tests/directives.md +++ b/src/doc/rustc-dev-guide/src/tests/directives.md @@ -207,7 +207,9 @@ settings: on `wasm32-unknown-unknown` target because the target does not support the `proc-macro` crate type. - `needs-target-std` — ignores if target platform does not have std support. -- `ignore-backends` — ignores the listed backends, separated by whitespace characters. +- `ignore-backends` — ignores the listed backends, separated by whitespace characters. Please note + that this directive can be overriden with the `--bypass-ignore-backends=[BACKEND]` command line + flag. - `needs-backends` — only runs the test if current codegen backend is listed. The following directives will check LLVM support: diff --git a/src/etc/completions/x.fish b/src/etc/completions/x.fish index 544f9b97237cb..a837be680dcdd 100644 --- a/src/etc/completions/x.fish +++ b/src/etc/completions/x.fish @@ -336,6 +336,7 @@ complete -c x -n "__fish_x_using_subcommand test" -l force-rerun -d 'rerun tests complete -c x -n "__fish_x_using_subcommand test" -l only-modified -d 'only run tests that result has been changed' complete -c x -n "__fish_x_using_subcommand test" -l rustfix-coverage -d 'enable this to generate a Rustfix coverage file, which is saved in `//rustfix_missing_coverage.txt`' complete -c x -n "__fish_x_using_subcommand test" -l no-capture -d 'don\'t capture stdout/stderr of tests' +complete -c x -n "__fish_x_using_subcommand test" -l bypass-ignore-backends -d 'Ignore `//@ ignore-backends` directives' complete -c x -n "__fish_x_using_subcommand test" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x -n "__fish_x_using_subcommand test" -s i -l incremental -d 'use incremental compilation' complete -c x -n "__fish_x_using_subcommand test" -l include-default-paths -d 'include default paths in addition to the provided ones' diff --git a/src/etc/completions/x.ps1 b/src/etc/completions/x.ps1 index b03acf930f70d..1a02adbddfea7 100644 --- a/src/etc/completions/x.ps1 +++ b/src/etc/completions/x.ps1 @@ -383,6 +383,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--only-modified', '--only-modified', [CompletionResultType]::ParameterName, 'only run tests that result has been changed') [CompletionResult]::new('--rustfix-coverage', '--rustfix-coverage', [CompletionResultType]::ParameterName, 'enable this to generate a Rustfix coverage file, which is saved in `//rustfix_missing_coverage.txt`') [CompletionResult]::new('--no-capture', '--no-capture', [CompletionResultType]::ParameterName, 'don''t capture stdout/stderr of tests') + [CompletionResult]::new('--bypass-ignore-backends', '--bypass-ignore-backends', [CompletionResultType]::ParameterName, 'Ignore `//@ ignore-backends` directives') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') diff --git a/src/etc/completions/x.py.fish b/src/etc/completions/x.py.fish index 08e4cd26ce887..63b7987fb290e 100644 --- a/src/etc/completions/x.py.fish +++ b/src/etc/completions/x.py.fish @@ -336,6 +336,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand test" -l force-rerun -d 'rerun complete -c x.py -n "__fish_x.py_using_subcommand test" -l only-modified -d 'only run tests that result has been changed' complete -c x.py -n "__fish_x.py_using_subcommand test" -l rustfix-coverage -d 'enable this to generate a Rustfix coverage file, which is saved in `//rustfix_missing_coverage.txt`' complete -c x.py -n "__fish_x.py_using_subcommand test" -l no-capture -d 'don\'t capture stdout/stderr of tests' +complete -c x.py -n "__fish_x.py_using_subcommand test" -l bypass-ignore-backends -d 'Ignore `//@ ignore-backends` directives' complete -c x.py -n "__fish_x.py_using_subcommand test" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x.py -n "__fish_x.py_using_subcommand test" -s i -l incremental -d 'use incremental compilation' complete -c x.py -n "__fish_x.py_using_subcommand test" -l include-default-paths -d 'include default paths in addition to the provided ones' diff --git a/src/etc/completions/x.py.ps1 b/src/etc/completions/x.py.ps1 index 3d95d88af4955..cac70f722098f 100644 --- a/src/etc/completions/x.py.ps1 +++ b/src/etc/completions/x.py.ps1 @@ -383,6 +383,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--only-modified', '--only-modified', [CompletionResultType]::ParameterName, 'only run tests that result has been changed') [CompletionResult]::new('--rustfix-coverage', '--rustfix-coverage', [CompletionResultType]::ParameterName, 'enable this to generate a Rustfix coverage file, which is saved in `//rustfix_missing_coverage.txt`') [CompletionResult]::new('--no-capture', '--no-capture', [CompletionResultType]::ParameterName, 'don''t capture stdout/stderr of tests') + [CompletionResult]::new('--bypass-ignore-backends', '--bypass-ignore-backends', [CompletionResultType]::ParameterName, 'Ignore `//@ ignore-backends` directives') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') diff --git a/src/etc/completions/x.py.sh b/src/etc/completions/x.py.sh index 8ff0eaf35c89a..cff17f431d33d 100644 --- a/src/etc/completions/x.py.sh +++ b/src/etc/completions/x.py.sh @@ -3875,7 +3875,7 @@ _x.py() { return 0 ;; x.py__test) - opts="-v -i -j -h --no-fail-fast --test-args --compiletest-rustc-args --no-doc --doc --bless --extra-checks --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --no-capture --test-codegen-backend --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --no-fail-fast --test-args --compiletest-rustc-args --no-doc --doc --bless --extra-checks --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --no-capture --test-codegen-backend --bypass-ignore-backends --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 diff --git a/src/etc/completions/x.py.zsh b/src/etc/completions/x.py.zsh index 9d2d73e582ec6..47cdaf97befcc 100644 --- a/src/etc/completions/x.py.zsh +++ b/src/etc/completions/x.py.zsh @@ -383,6 +383,7 @@ _arguments "${_arguments_options[@]}" : \ '--only-modified[only run tests that result has been changed]' \ '--rustfix-coverage[enable this to generate a Rustfix coverage file, which is saved in \`//rustfix_missing_coverage.txt\`]' \ '--no-capture[don'\''t capture stdout/stderr of tests]' \ +'--bypass-ignore-backends[Ignore \`//@ ignore-backends\` directives]' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ diff --git a/src/etc/completions/x.sh b/src/etc/completions/x.sh index c1b73fb7c9e34..700617bfeba0e 100644 --- a/src/etc/completions/x.sh +++ b/src/etc/completions/x.sh @@ -3875,7 +3875,7 @@ _x() { return 0 ;; x__test) - opts="-v -i -j -h --no-fail-fast --test-args --compiletest-rustc-args --no-doc --doc --bless --extra-checks --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --no-capture --test-codegen-backend --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --no-fail-fast --test-args --compiletest-rustc-args --no-doc --doc --bless --extra-checks --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --no-capture --test-codegen-backend --bypass-ignore-backends --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 diff --git a/src/etc/completions/x.zsh b/src/etc/completions/x.zsh index 29237ef9bf8fd..b960be4a1b10a 100644 --- a/src/etc/completions/x.zsh +++ b/src/etc/completions/x.zsh @@ -383,6 +383,7 @@ _arguments "${_arguments_options[@]}" : \ '--only-modified[only run tests that result has been changed]' \ '--rustfix-coverage[enable this to generate a Rustfix coverage file, which is saved in \`//rustfix_missing_coverage.txt\`]' \ '--no-capture[don'\''t capture stdout/stderr of tests]' \ +'--bypass-ignore-backends[Ignore \`//@ ignore-backends\` directives]' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 75291e9cd7207..725869c6caf5d 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2827,7 +2827,7 @@ fn clean_maybe_renamed_item<'tcx>( variants: def.variants.iter().map(|v| clean_variant(v, cx)).collect(), generics: clean_generics(generics, cx), }), - ItemKind::TraitAlias(_, generics, bounds) => TraitAliasItem(TraitAlias { + ItemKind::TraitAlias(_, _, generics, bounds) => TraitAliasItem(TraitAlias { generics: clean_generics(generics, cx), bounds: bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(), }), diff --git a/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs index 76f5fdfaa8dcf..22767901614e1 100644 --- a/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs +++ b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs @@ -528,7 +528,7 @@ impl LateLintPass<'_> for ItemNameRepetitions { | ItemKind::Macro(ident, ..) | ItemKind::Static(_, ident, ..) | ItemKind::Trait(_, _, _, ident, ..) - | ItemKind::TraitAlias(ident, ..) + | ItemKind::TraitAlias(_, ident, ..) | ItemKind::TyAlias(ident, ..) | ItemKind::Union(ident, ..) | ItemKind::Use(_, UseKind::Single(ident)) => ident, diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs index 22b74ab16d615..839b46325b5ea 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs @@ -473,8 +473,24 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { && over(lb, rb, eq_generic_bound) && over(lis, ris, |l, r| eq_item(l, r, eq_assoc_item_kind)) }, - (TraitAlias(li, lg, lb), TraitAlias(ri, rg, rb)) => { - eq_id(*li, *ri) && eq_generics(lg, rg) && over(lb, rb, eq_generic_bound) + ( + TraitAlias(box ast::TraitAlias { + ident: li, + generics: lg, + bounds: lb, + constness: lc, + }), + TraitAlias(box ast::TraitAlias { + ident: ri, + generics: rg, + bounds: rb, + constness: rc, + }), + ) => { + matches!(lc, ast::Const::No) == matches!(rc, ast::Const::No) + && eq_id(*li, *ri) + && eq_generics(lg, rg) + && over(lb, rb, eq_generic_bound) }, ( Impl(ast::Impl { diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 8e47d51ee4dbd..1f893fecb54b0 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -710,6 +710,8 @@ pub struct Config { pub default_codegen_backend: CodegenBackend, /// Name/path of the backend to use instead of `default_codegen_backend`. pub override_codegen_backend: Option, + /// Whether to ignore `//@ ignore-backends`. + pub bypass_ignore_backends: bool, } impl Config { diff --git a/src/tools/compiletest/src/directives.rs b/src/tools/compiletest/src/directives.rs index 0318ed2b3d119..5988f59fd92f7 100644 --- a/src/tools/compiletest/src/directives.rs +++ b/src/tools/compiletest/src/directives.rs @@ -1493,7 +1493,7 @@ fn ignore_backends(config: &Config, line: &DirectiveLine<'_>) -> IgnoreDecision } } }) { - if config.default_codegen_backend == backend { + if !config.bypass_ignore_backends && config.default_codegen_backend == backend { return IgnoreDecision::Ignore { reason: format!("{} backend is marked as ignore", backend.as_str()), }; diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 11a462c3d44a6..b524017e4dadd 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -217,7 +217,8 @@ fn parse_config(args: Vec) -> Config { "override-codegen-backend", "the codegen backend to use instead of the default one", "CODEGEN BACKEND [NAME | PATH]", - ); + ) + .optflag("", "bypass-ignore-backends", "ignore `//@ ignore-backends` directives"); let (argv0, args_) = args.split_first().unwrap(); if args.len() == 1 || args[1] == "-h" || args[1] == "--help" { @@ -484,6 +485,7 @@ fn parse_config(args: Vec) -> Config { default_codegen_backend, override_codegen_backend, + bypass_ignore_backends: matches.opt_present("bypass-ignore-backends"), } } diff --git a/src/tools/compiletest/src/rustdoc_gui_test.rs b/src/tools/compiletest/src/rustdoc_gui_test.rs index 4bd3531f4b433..60a7e6d47d2fb 100644 --- a/src/tools/compiletest/src/rustdoc_gui_test.rs +++ b/src/tools/compiletest/src/rustdoc_gui_test.rs @@ -138,5 +138,6 @@ fn incomplete_config_for_rustdoc_gui_test() -> Config { minicore_path: Default::default(), default_codegen_backend: CodegenBackend::Llvm, override_codegen_backend: None, + bypass_ignore_backends: Default::default(), } } diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index a2e89c10a4803..ecaa4670f61d2 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -1375,22 +1375,21 @@ impl<'a> Rewrite for TraitAliasBounds<'a> { pub(crate) fn format_trait_alias( context: &RewriteContext<'_>, - ident: symbol::Ident, + ta: &ast::TraitAlias, vis: &ast::Visibility, - generics: &ast::Generics, - generic_bounds: &ast::GenericBounds, shape: Shape, ) -> Option { - let alias = rewrite_ident(context, ident); + let alias = rewrite_ident(context, ta.ident); // 6 = "trait ", 2 = " =" let g_shape = shape.offset_left(6)?.sub_width(2)?; - let generics_str = rewrite_generics(context, alias, generics, g_shape).ok()?; + let generics_str = rewrite_generics(context, alias, &ta.generics, g_shape).ok()?; let vis_str = format_visibility(context, vis); - let lhs = format!("{vis_str}trait {generics_str} ="); + let constness = format_constness(ta.constness); + let lhs = format!("{vis_str}{constness}trait {generics_str} ="); // 1 = ";" let trait_alias_bounds = TraitAliasBounds { - generic_bounds, - generics, + generic_bounds: &ta.bounds, + generics: &ta.generics, }; rewrite_assign_rhs( context, diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs index a3acbb218ff29..c521b497a2d99 100644 --- a/src/tools/rustfmt/src/visitor.rs +++ b/src/tools/rustfmt/src/visitor.rs @@ -497,16 +497,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let rw = self.with_context(|ctx| format_trait(ctx, item, block_indent)); self.push_rewrite(item.span, rw); } - ast::ItemKind::TraitAlias(ident, ref generics, ref generic_bounds) => { + ast::ItemKind::TraitAlias(ref ta) => { let shape = Shape::indented(self.block_indent, self.config); - let rw = format_trait_alias( - &self.get_context(), - ident, - &item.vis, - generics, - generic_bounds, - shape, - ); + let rw = format_trait_alias(&self.get_context(), ta, &item.vis, shape); self.push_rewrite(item.span, rw); } ast::ItemKind::ExternCrate(..) => { diff --git a/src/tools/rustfmt/tests/source/trait.rs b/src/tools/rustfmt/tests/source/trait.rs index b6db9e1590d41..1970646f7770c 100644 --- a/src/tools/rustfmt/tests/source/trait.rs +++ b/src/tools/rustfmt/tests/source/trait.rs @@ -181,3 +181,5 @@ trait Visible { pub fn f(); pub fn g() {} } + +const trait Foomp = Hash; \ No newline at end of file diff --git a/src/tools/rustfmt/tests/target/const_trait.rs b/src/tools/rustfmt/tests/target/const_trait.rs new file mode 100644 index 0000000000000..c4c88b17fc500 --- /dev/null +++ b/src/tools/rustfmt/tests/target/const_trait.rs @@ -0,0 +1,5 @@ +#![feature(trait_alias, const_trait_impl)] + +const trait Bar {} + +const trait Foo = Bar; diff --git a/src/tools/rustfmt/tests/target/trait.rs b/src/tools/rustfmt/tests/target/trait.rs index 7f067991b267b..7a65b13d629e7 100644 --- a/src/tools/rustfmt/tests/target/trait.rs +++ b/src/tools/rustfmt/tests/target/trait.rs @@ -218,3 +218,5 @@ trait Visible { pub fn f(); pub fn g() {} } + +const trait Foomp = Hash; diff --git a/tests/ui/consts/trait_alias.fail.stderr b/tests/ui/consts/trait_alias.fail.stderr new file mode 100644 index 0000000000000..16675206a7a4b --- /dev/null +++ b/tests/ui/consts/trait_alias.fail.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `T: [const] Baz` is not satisfied + --> $DIR/trait_alias.rs:24:11 + | +LL | x.baz(); + | ^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/trait_alias.next_fail.stderr b/tests/ui/consts/trait_alias.next_fail.stderr new file mode 100644 index 0000000000000..16675206a7a4b --- /dev/null +++ b/tests/ui/consts/trait_alias.next_fail.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `T: [const] Baz` is not satisfied + --> $DIR/trait_alias.rs:24:11 + | +LL | x.baz(); + | ^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/trait_alias.rs b/tests/ui/consts/trait_alias.rs new file mode 100644 index 0000000000000..3d9a60cefc7cc --- /dev/null +++ b/tests/ui/consts/trait_alias.rs @@ -0,0 +1,31 @@ +#![feature(trait_alias, const_trait_impl)] +//@ revisions: next_pass next_fail pass fail +//@[next_pass] compile-flags: -Znext-solver +//@[next_fail] compile-flags: -Znext-solver +//@[next_pass] check-pass +//@[pass] check-pass + +const trait Bar { + fn bar(&self) {} +} +const trait Baz { + fn baz(&self) {} +} + +impl const Bar for () {} +impl const Baz for () {} + +const trait Foo = [const] Bar + Baz; + +const fn foo(x: &T) { + x.bar(); + #[cfg(any(fail, next_fail))] + { + x.baz(); + //[fail,next_fail]~^ ERROR: the trait bound `T: [const] Baz` is not satisfied + } +} + +const _: () = foo(&()); + +fn main() {} diff --git a/tests/ui/consts/trait_alias_method_call.rs b/tests/ui/consts/trait_alias_method_call.rs new file mode 100644 index 0000000000000..75c51f8f031b1 --- /dev/null +++ b/tests/ui/consts/trait_alias_method_call.rs @@ -0,0 +1,31 @@ +//! Test that we do not need to handle host effects in `expand_trait_aliases` + +#![feature(trait_alias, const_trait_impl)] +//@ check-pass + +mod foo { + pub const trait Bar { + fn bar(&self) {} + } + pub const trait Baz { + fn baz(&self) {} + } + + impl const Bar for () {} + impl const Baz for () {} + + pub const trait Foo = [const] Bar + Baz; +} + +use foo::Foo as _; + + +const _: () = { + // Ok via `[const] Bar` on `Foo` + ().bar(); + // Also works, because everything is fully concrete, so we're ignoring that + // `Baz` is not a const trait bound of `Foo`. + ().baz(); +}; + +fn main() {} diff --git a/tests/ui/lint/dead-code/inferred-generic-arg.rs b/tests/ui/lint/dead-code/inferred-generic-arg.rs new file mode 100644 index 0000000000000..106d6e7763c8b --- /dev/null +++ b/tests/ui/lint/dead-code/inferred-generic-arg.rs @@ -0,0 +1,16 @@ +//@ check-pass + +#![deny(dead_code)] + +#[derive(Default)] +struct Test { + +} + +fn main() { + if let Some::(test) = magic::() { } +} + +fn magic() -> Option { + Some(T::default()) +} diff --git a/tests/ui/stats/input-stats.stderr b/tests/ui/stats/input-stats.stderr index 18862eeef06eb..ef5039485df62 100644 --- a/tests/ui/stats/input-stats.stderr +++ b/tests/ui/stats/input-stats.stderr @@ -2,14 +2,14 @@ ast-stats ================================================================ ast-stats POST EXPANSION AST STATS: input_stats ast-stats Name Accumulated Size Count Item Size ast-stats ---------------------------------------------------------------- -ast-stats Item 1_584 (NN.N%) 11 144 -ast-stats - Enum 144 (NN.N%) 1 -ast-stats - ExternCrate 144 (NN.N%) 1 -ast-stats - ForeignMod 144 (NN.N%) 1 -ast-stats - Impl 144 (NN.N%) 1 -ast-stats - Trait 144 (NN.N%) 1 -ast-stats - Fn 288 (NN.N%) 2 -ast-stats - Use 576 (NN.N%) 4 +ast-stats Item 1_496 (NN.N%) 11 136 +ast-stats - Enum 136 (NN.N%) 1 +ast-stats - ExternCrate 136 (NN.N%) 1 +ast-stats - ForeignMod 136 (NN.N%) 1 +ast-stats - Impl 136 (NN.N%) 1 +ast-stats - Trait 136 (NN.N%) 1 +ast-stats - Fn 272 (NN.N%) 2 +ast-stats - Use 544 (NN.N%) 4 ast-stats Ty 896 (NN.N%) 14 64 ast-stats - Ptr 64 (NN.N%) 1 ast-stats - Ref 64 (NN.N%) 1 @@ -57,7 +57,7 @@ ast-stats GenericArgs 40 (NN.N%) 1 40 ast-stats - AngleBracketed 40 (NN.N%) 1 ast-stats Crate 40 (NN.N%) 1 40 ast-stats ---------------------------------------------------------------- -ast-stats Total 7_528 129 +ast-stats Total 7_440 129 ast-stats ================================================================ hir-stats ================================================================ hir-stats HIR STATS: input_stats