diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index f2061f3088a25..4510543e9a252 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -3562,6 +3562,7 @@ impl Item { | ItemKind::DelegationMac(_) | ItemKind::MacroDef(..) => None, ItemKind::Static(_) => None, + ItemKind::AutoImpl(_) => None, ItemKind::Const(i) => Some(&i.generics), ItemKind::Fn(i) => Some(&i.generics), ItemKind::TyAlias(i) => Some(&i.generics), @@ -3705,6 +3706,14 @@ pub struct Impl { pub items: ThinVec>, } +#[derive(Clone, Encodable, Decodable, Debug)] +pub struct AutoImpl { + pub generics: Generics, + pub constness: Const, + pub of_trait: Box, + pub items: ThinVec>, +} + #[derive(Clone, Encodable, Decodable, Debug)] pub struct TraitImplHeader { pub defaultness: Defaultness, @@ -3857,6 +3866,8 @@ pub enum ItemKind { /// /// E.g., `impl Foo { .. }` or `impl Trait for Foo { .. }`. Impl(Impl), + /// An `auto impl` implementation, such as a supertrait `auto impl`. + AutoImpl(Box), /// A macro invocation. /// /// E.g., `foo!(..)`. @@ -3893,6 +3904,7 @@ impl ItemKind { | ItemKind::ForeignMod(_) | ItemKind::GlobalAsm(_) | ItemKind::Impl(_) + | ItemKind::AutoImpl(_) | ItemKind::MacCall(_) | ItemKind::DelegationMac(_) => None, } @@ -3905,7 +3917,12 @@ impl ItemKind { Use(..) | Static(..) | Const(..) | Fn(..) | Mod(..) | GlobalAsm(..) | TyAlias(..) | Struct(..) | Union(..) | Trait(..) | TraitAlias(..) | MacroDef(..) | Delegation(..) | DelegationMac(..) => "a", - ExternCrate(..) | ForeignMod(..) | MacCall(..) | Enum(..) | Impl { .. } => "an", + ExternCrate(..) + | ForeignMod(..) + | MacCall(..) + | Enum(..) + | Impl { .. } + | AutoImpl { .. } => "an", } } @@ -3928,6 +3945,7 @@ impl ItemKind { ItemKind::MacCall(..) => "item macro invocation", ItemKind::MacroDef(..) => "macro definition", ItemKind::Impl { .. } => "implementation", + ItemKind::AutoImpl { .. } => "`auto` implementation", ItemKind::Delegation(..) => "delegated function", ItemKind::DelegationMac(..) => "delegation", } @@ -3975,6 +3993,8 @@ pub enum AssocItemKind { Delegation(Box), /// An associated list or glob delegation item. DelegationMac(Box), + /// An `auto impl` item + AutoImpl(Box), } impl AssocItemKind { @@ -3985,7 +4005,9 @@ impl AssocItemKind { | AssocItemKind::Type(box TyAlias { ident, .. }) | AssocItemKind::Delegation(box Delegation { ident, .. }) => Some(ident), - AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(_) => None, + AssocItemKind::MacCall(_) + | AssocItemKind::DelegationMac(_) + | AssocItemKind::AutoImpl(_) => None, } } @@ -3993,7 +4015,11 @@ impl AssocItemKind { match *self { Self::Const(box ConstItem { defaultness, .. }) | Self::Fn(box Fn { defaultness, .. }) - | Self::Type(box TyAlias { defaultness, .. }) => defaultness, + | Self::Type(box TyAlias { defaultness, .. }) + | Self::AutoImpl(box AutoImpl { + of_trait: box TraitImplHeader { defaultness, .. }, + .. + }) => defaultness, Self::MacCall(..) | Self::Delegation(..) | Self::DelegationMac(..) => { Defaultness::Final } @@ -4010,6 +4036,7 @@ impl From for ItemKind { AssocItemKind::MacCall(a) => ItemKind::MacCall(a), AssocItemKind::Delegation(delegation) => ItemKind::Delegation(delegation), AssocItemKind::DelegationMac(delegation) => ItemKind::DelegationMac(delegation), + AssocItemKind::AutoImpl(ai) => ItemKind::AutoImpl(ai), } } } @@ -4025,6 +4052,7 @@ impl TryFrom for AssocItemKind { ItemKind::MacCall(a) => AssocItemKind::MacCall(a), ItemKind::Delegation(d) => AssocItemKind::Delegation(d), ItemKind::DelegationMac(d) => AssocItemKind::DelegationMac(d), + ItemKind::AutoImpl(ai) => AssocItemKind::AutoImpl(ai), _ => return Err(item_kind), }) } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index dde773fd147da..aa432ddbcbe14 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -551,6 +551,7 @@ macro_rules! common_visitor_and_walkers { //fn visit_assoc_item(AssocItem, _ctxt: AssocCtxt); fn visit_assoc_item_constraint(AssocItemConstraint); fn visit_attribute(Attribute); + fn visit_auto_impl(AutoImpl); fn visit_block(Block); //fn visit_nested_use_tree((UseTree, NodeId)); fn visit_capture_by(CaptureBy); @@ -836,6 +837,8 @@ macro_rules! common_visitor_and_walkers { visit_visitable!($($mut)? vis, ident, generics, variant_data), ItemKind::Impl(impl_) => visit_visitable!($($mut)? vis, impl_), + ItemKind::AutoImpl(auto_impl_) => + visit_visitable!($($mut)? vis, auto_impl_), ItemKind::Trait(trait_) => visit_visitable!($($mut)? vis, trait_), ItemKind::TraitAlias(box TraitAlias { constness, ident, generics, bounds}) => { @@ -881,6 +884,8 @@ macro_rules! common_visitor_and_walkers { visit_visitable!($($mut)? vis, delegation), AssocItemKind::DelegationMac(dm) => visit_visitable!($($mut)? vis, dm), + AssocItemKind::AutoImpl(ai) => + visit_visitable!($($mut)? vis, ai), } V::Result::output() } @@ -945,6 +950,17 @@ macro_rules! common_visitor_and_walkers { V::Result::output() }); + impl_walkable!(|&$($mut)? $($lt)? self: AutoImpl, vis: &mut V| { + let AutoImpl { generics, of_trait, items, constness } = self; + let TraitImplHeader { defaultness, safety, polarity, trait_ref } = &$($mut)? **of_trait; + + try_visit!(vis.visit_generics(generics)); + visit_visitable!($($mut)? vis, defaultness, safety, constness, polarity, trait_ref); + + visit_visitable_with!($($mut)? vis, items, AssocCtxt::Impl { of_trait: true }); + V::Result::output() + }); + // Special case to call `visit_method_receiver_expr`. impl_walkable!(|&$($mut)? $($lt)? self: MethodCall, vis: &mut V| { let MethodCall { seg, receiver, args, span } = self; diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index f5b7065247a08..562dca4c05b41 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -11,6 +11,7 @@ use rustc_hir::{ use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::span_bug; use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; +use rustc_session::parse::feature_err; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::{DUMMY_SP, DesugaringKind, Ident, Span, Symbol, kw, sym}; use smallvec::{SmallVec, smallvec}; @@ -388,6 +389,7 @@ impl<'hir> LoweringContext<'_, 'hir> { constness, }) } + ItemKind::AutoImpl(box AutoImpl { .. }) => todo!("we should implement lowering to HIR"), ItemKind::Trait(box Trait { constness, is_auto, @@ -887,6 +889,48 @@ impl<'hir> LoweringContext<'_, 'hir> { true, ) } + AssocItemKind::AutoImpl(ai) => { + let tcx = self.tcx; + if !tcx.features().supertrait_auto_impl() { + feature_err( + &tcx.sess, + sym::supertrait_auto_impl, + i.span, + "feature is under construction", + ) + .emit(); + } + let generics = tcx.arena.alloc(hir::Generics { + has_where_clause_predicates: false, + params: &[], + predicates: &[], + where_clause_span: DUMMY_SP, + span: DUMMY_SP, + }); + ( + Ident::dummy(), + &*generics, + hir::TraitItemKind::AutoImpl( + tcx.arena.alloc(self.lower_poly_trait_ref_inner( + &ai.generics.params, + &TraitBoundModifiers { + constness: BoundConstness::Never, + asyncness: BoundAsyncness::Normal, + polarity: match ai.of_trait.polarity { + ImplPolarity::Positive => BoundPolarity::Positive, + ImplPolarity::Negative(span) => BoundPolarity::Negative(span), + }, + }, + &ai.of_trait.trait_ref, + ai.of_trait.trait_ref.path.span, + RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::SuperTrait), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + )), + &[], + ), + false, + ) + } AssocItemKind::Type(box TyAlias { ident, generics, @@ -1090,6 +1134,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ), ) } + AssocItemKind::AutoImpl(_) => todo!(), AssocItemKind::Delegation(box delegation) => { let delegation_results = self.lower_delegation(delegation, i.id, is_in_trait_impl); ( diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 1f36454ec861a..f49e243eacfd3 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2074,6 +2074,26 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { PolyTraitRef { bound_generic_params, modifiers, trait_ref, span, parens: _ }: &PolyTraitRef, rbp: RelaxedBoundPolicy<'_>, itctx: ImplTraitContext, + ) -> hir::PolyTraitRef<'hir> { + self.lower_poly_trait_ref_inner( + bound_generic_params, + modifiers, + trait_ref, + *span, + rbp, + itctx, + ) + } + + #[instrument(level = "debug", skip(self))] + fn lower_poly_trait_ref_inner( + &mut self, + bound_generic_params: &[GenericParam], + modifiers: &TraitBoundModifiers, + trait_ref: &TraitRef, + span: Span, + rbp: RelaxedBoundPolicy<'_>, + itctx: ImplTraitContext, ) -> hir::PolyTraitRef<'hir> { let bound_generic_params = self.lower_lifetime_binder(trait_ref.ref_id, bound_generic_params); @@ -2081,14 +2101,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let modifiers = self.lower_trait_bound_modifiers(*modifiers); if let ast::BoundPolarity::Maybe(_) = modifiers.polarity { - self.validate_relaxed_bound(trait_ref, *span, rbp); + self.validate_relaxed_bound(trait_ref, span, rbp); } hir::PolyTraitRef { bound_generic_params, modifiers, trait_ref, - span: self.lower_span(*span), + span: self.lower_span(span), } } diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index c7cbf34dedb9b..2a859285a8226 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -1,7 +1,7 @@ use ast::StaticItem; use itertools::{Itertools, Position}; use rustc_ast::{self as ast, ModKind, TraitAlias}; -use rustc_span::Ident; +use rustc_span::{Ident, Span}; use crate::pp::BoxMarker; use crate::pp::Breaks::Inconsistent; @@ -350,6 +350,32 @@ impl<'a> State<'a> { let empty = item.attrs.is_empty() && items.is_empty(); self.bclose(item.span, empty, cb); } + ast::ItemKind::AutoImpl(box ast::AutoImpl { generics, of_trait, items, constness }) => { + let (cb, ib) = self.head(""); + self.print_visibility(&item.vis); + + let &ast::TraitImplHeader { defaultness, safety, polarity, ref trait_ref } = + &**of_trait; + self.print_defaultness(defaultness); + self.print_safety(safety); + self.word("auto"); + self.word("impl"); + self.print_generic_params(&generics.params); + self.print_constness(*constness); + if let ast::ImplPolarity::Negative(_) = polarity { + self.word("!"); + } + self.print_trait_ref(trait_ref); + + self.space(); + self.bopen(ib); + self.print_inner_attributes(&item.attrs); + for impl_item in items { + self.print_assoc_item(impl_item); + } + let empty = item.attrs.is_empty() && items.is_empty(); + self.bclose(item.span, empty, cb); + } ast::ItemKind::Trait(box ast::Trait { constness, safety, @@ -601,6 +627,9 @@ impl<'a> State<'a> { self.word(";"); } } + ast::AssocItemKind::AutoImpl(ai) => { + self.print_assoc_auto_impl(&item.attrs, ai, item.span) + } ast::AssocItemKind::Delegation(deleg) => self.print_delegation( &item.attrs, vis, @@ -621,6 +650,29 @@ impl<'a> State<'a> { self.ann.post(self, AnnNode::SubItem(id)) } + fn print_assoc_auto_impl(&mut self, attrs: &[ast::Attribute], ai: &ast::AutoImpl, span: Span) { + let (cb, ib) = self.head(""); + let &ast::TraitImplHeader { defaultness, safety, polarity, ref trait_ref } = &*ai.of_trait; + self.print_defaultness(defaultness); + self.print_safety(safety); + self.word("auto"); + self.word("impl"); + self.print_constness(ai.constness); + if let ast::ImplPolarity::Negative(_) = polarity { + self.word("!"); + } + self.print_trait_ref(trait_ref); + + self.space(); + self.bopen(ib); + self.print_inner_attributes(&attrs); + for impl_item in &ai.items { + self.print_assoc_item(impl_item); + } + let empty = attrs.is_empty() && ai.items.is_empty(); + self.bclose(span, empty, cb); + } + fn print_delegation( &mut self, attrs: &[ast::Attribute], diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 813d2fced865d..da24e93e4a8b4 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -647,6 +647,8 @@ declare_features! ( (unstable, string_deref_patterns, "1.67.0", Some(87121)), /// Allows `super let` statements. (unstable, super_let, "1.88.0", Some(139076)), + /// Allows supertraits to be implemented with automatic defaults + (unstable, supertrait_auto_impl, "CURRENT_RUSTC_VERSION", Some(99999)), /// Allows subtrait items to shadow supertrait items. (unstable, supertrait_item_shadowing, "1.86.0", Some(89151)), /// Allows the use of target_feature when a function is marked inline(always). diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 95abe5c40dd43..bf65721337c39 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -117,6 +117,8 @@ pub enum DefKind { AssocTy, /// Type parameter: the `T` in `struct Vec { ... }` TyParam, + /// Automatic supertrait implementation, an `auto impl` block + AutoImpl, // Value namespace Fn, @@ -238,6 +240,7 @@ impl DefKind { DefKind::ExternCrate => "extern crate", DefKind::GlobalAsm => "global assembly block", DefKind::SyntheticCoroutineBody => "synthetic mir body", + DefKind::AutoImpl => "auto impl", } } @@ -297,6 +300,7 @@ impl DefKind { | DefKind::ForeignMod | DefKind::GlobalAsm | DefKind::Impl { .. } + | DefKind::AutoImpl | DefKind::OpaqueTy | DefKind::SyntheticCoroutineBody => None, } @@ -339,6 +343,7 @@ impl DefKind { DefKind::OpaqueTy => DefPathData::OpaqueTy, DefKind::GlobalAsm => DefPathData::GlobalAsm, DefKind::Impl { .. } => DefPathData::Impl, + DefKind::AutoImpl => DefPathData::AutoImpl, DefKind::Closure => DefPathData::Closure, DefKind::SyntheticCoroutineBody => DefPathData::SyntheticCoroutineBody, } @@ -382,6 +387,7 @@ impl DefKind { | DefKind::Fn | DefKind::ForeignTy | DefKind::Impl { .. } + | DefKind::AutoImpl | DefKind::InlineConst | DefKind::OpaqueTy | DefKind::Static { .. } @@ -430,6 +436,7 @@ impl DefKind { | DefKind::ForeignMod | DefKind::OpaqueTy | DefKind::Impl { .. } + | DefKind::AutoImpl | DefKind::Field | DefKind::TyParam | DefKind::ConstParam @@ -474,6 +481,7 @@ impl DefKind { | DefKind::Field | DefKind::LifetimeParam | DefKind::GlobalAsm + | DefKind::AutoImpl | DefKind::Impl { .. } => false, } } diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index 07d5bcdd6ee92..63058d3fc9633 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -280,6 +280,8 @@ pub enum DefPathData { // Different kinds of items and item-like things: /// An impl. Impl, + /// An `auto impl` directive + AutoImpl, /// An `extern` block. ForeignMod, /// A `use` item. @@ -461,6 +463,7 @@ impl DefPathData { DesugaredAnonymousLifetime => Some(kw::UnderscoreLifetime), Impl + | AutoImpl | ForeignMod | CrateRoot | Use @@ -485,6 +488,7 @@ impl DefPathData { DesugaredAnonymousLifetime => Some(kw::UnderscoreLifetime), Impl + | AutoImpl | ForeignMod | CrateRoot | Use @@ -506,7 +510,7 @@ impl DefPathData { | OpaqueLifetime(name) => DefPathDataName::Named(name), // Note that this does not show up in user print-outs. CrateRoot => DefPathDataName::Anon { namespace: kw::Crate }, - Impl => DefPathDataName::Anon { namespace: kw::Impl }, + Impl | AutoImpl => DefPathDataName::Anon { namespace: kw::Impl }, ForeignMod => DefPathDataName::Anon { namespace: kw::Extern }, Use => DefPathDataName::Anon { namespace: kw::Use }, GlobalAsm => DefPathDataName::Anon { namespace: sym::global_asm }, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index db88de828aafd..ced4cae7d6e3d 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3134,6 +3134,8 @@ pub enum TraitItemKind<'hir> { /// An associated type with (possibly empty) bounds and optional concrete /// type. Type(GenericBounds<'hir>, Option<&'hir Ty<'hir>>), + /// An `auto impl` directive + AutoImpl(&'hir PolyTraitRef<'hir>, &'hir [ImplItem<'hir>]), } // The bodies for items are stored "out of line", in a separate @@ -3213,6 +3215,10 @@ pub enum ImplItemKind<'hir> { Fn(FnSig<'hir>, BodyId), /// An associated type. Type(&'hir Ty<'hir>), + /// An `auto impl` implementation + AutoImpl(&'hir PolyTraitRef<'hir>, &'hir [ImplItem<'hir>]), + /// An `extern impl` directive + ExternImpl(&'hir PolyTraitRef<'hir>), } /// A constraint on an associated item. diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 0b83e7239a992..ecf3d787a6924 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -1255,6 +1255,10 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>( walk_list!(visitor, visit_param_bound, bounds); visit_opt!(visitor, visit_ty_unambig, default); } + TraitItemKind::AutoImpl(trait_ref, items) => { + try_visit!(visitor.visit_poly_trait_ref(trait_ref)); + walk_list!(visitor, visit_impl_item, items); + } } V::Result::output() } @@ -1299,6 +1303,12 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>( impl_item.owner_id.def_id, ), ImplItemKind::Type(ref ty) => visitor.visit_ty_unambig(ty), + ImplItemKind::AutoImpl(trait_ref, items) => { + try_visit!(visitor.visit_poly_trait_ref(trait_ref)); + walk_list!(visitor, visit_impl_item, items); + V::Result::output() + } + ImplItemKind::ExternImpl(poly_trait_ref) => visitor.visit_poly_trait_ref(poly_trait_ref), } } diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs index 87953321af3fc..99bd362eaf93b 100644 --- a/compiler/rustc_hir/src/target.rs +++ b/compiler/rustc_hir/src/target.rs @@ -33,6 +33,7 @@ pub enum MethodKind { Inherent, } +/// A descriptor of supported kinds of target for attributes #[derive(Copy, Clone, PartialEq, Debug, Eq, HashStable_Generic)] pub enum Target { ExternCrate, @@ -53,6 +54,8 @@ pub enum Target { Trait, TraitAlias, Impl { of_trait: bool }, + AutoImpl, + ExternImpl, Expression, Statement, Arm, @@ -84,7 +87,11 @@ rustc_error_messages::into_diag_arg_using_display!(Target); impl Target { pub fn is_associated_item(self) -> bool { match self { - Target::AssocConst | Target::AssocTy | Target::Method(_) => true, + Target::AssocConst + | Target::AssocTy + | Target::Method(_) + | Target::AutoImpl + | Target::ExternImpl => true, Target::ExternCrate | Target::Use | Target::Static @@ -182,6 +189,7 @@ impl Target { ast::ItemKind::Trait(..) => Target::Trait, ast::ItemKind::TraitAlias(..) => Target::TraitAlias, ast::ItemKind::Impl(ref i) => Target::Impl { of_trait: i.of_trait.is_some() }, + ast::ItemKind::AutoImpl(..) => Target::Impl { of_trait: true }, ast::ItemKind::MacCall(..) => Target::MacroCall, ast::ItemKind::MacroDef(..) => Target::MacroDef, ast::ItemKind::Delegation(..) => Target::Delegation { mac: false }, @@ -208,6 +216,7 @@ impl Target { Target::Method(MethodKind::Trait { body: true }) } TraitItemKind::Type(..) => Target::AssocTy, + TraitItemKind::AutoImpl(..) => Target::AutoImpl, } } @@ -252,6 +261,7 @@ impl Target { AssocItemKind::Delegation(_) => Target::Delegation { mac: false }, AssocItemKind::DelegationMac(_) => Target::Delegation { mac: true }, AssocItemKind::MacCall(_) => Target::MacroCall, + AssocItemKind::AutoImpl(_) => Target::Impl { of_trait: true }, } } @@ -283,6 +293,8 @@ impl Target { Target::Trait => "trait", Target::TraitAlias => "trait alias", Target::Impl { .. } => "implementation block", + Target::AutoImpl => "automatic trait implementation block", + Target::ExternImpl => "external trait implementation block", Target::Expression => "expression", Target::Statement => "statement", Target::Arm => "match arm", @@ -334,6 +346,8 @@ impl Target { Target::TraitAlias => "trait aliases", Target::Impl { of_trait: false } => "inherent impl blocks", Target::Impl { of_trait: true } => "trait impl blocks", + Target::AutoImpl => "automatic trait implementation blocks", + Target::ExternImpl => "external trait implementation blocks", Target::Expression => "expressions", Target::Statement => "statements", Target::Arm => "match arms", diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index e124dfeb72840..5c7983524d644 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -478,7 +478,7 @@ fn best_definition_site_of_opaque<'tcx>( return Some(span); } } - ty::AssocKind::Type { .. } => {} + ty::AssocKind::Type { .. } | ty::AssocKind::AutoImpl => {} } } @@ -817,6 +817,18 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), } } } + DefKind::AutoImpl => { + if !tcx.features().supertrait_auto_impl() { + return Err(feature_err( + &tcx.sess, + sym::supertrait_auto_impl, + tcx.def_span(def_id), + "feature is under construction", + ) + .emit()); + } + todo!() + } DefKind::Trait => { tcx.ensure_ok().generics_of(def_id); tcx.ensure_ok().trait_def(def_id); @@ -1228,6 +1240,7 @@ fn check_impl_items_against_trait<'tcx>( } ty::AssocKind::Const { .. } => {} ty::AssocKind::Type { .. } => {} + ty::AssocKind::AutoImpl => {} } } diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 6a07d2988fdfc..3c4b151b2a8dc 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -18,7 +18,8 @@ use rustc_middle::ty::{ TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Upcast, }; use rustc_middle::{bug, span_bug}; -use rustc_span::{DUMMY_SP, Span}; +use rustc_session::parse::feature_err; +use rustc_span::{DUMMY_SP, Span, sym}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::regions::InferCtxtRegionExt; @@ -48,6 +49,18 @@ pub(super) fn compare_impl_item( ty::AssocKind::Const { .. } => { compare_impl_const(tcx, impl_item, trait_item, impl_trait_ref) } + ty::AssocKind::AutoImpl => { + if !tcx.features().supertrait_auto_impl() { + return Err(feature_err( + &tcx.sess, + sym::supertrait_auto_impl, + tcx.def_span(impl_item_def_id), + "feature is under construction", + ) + .emit()); + } + todo!() + } } } diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index f1c84a14de306..2068851c851d5 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -566,6 +566,7 @@ fn suggestion_signature<'tcx>( .unwrap_or_else(|| "value".to_string()); format!("const {}: {} = {};", name, ty, val) } + ty::AssocKind::AutoImpl => todo!(), } } diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 06738d99bf562..bd4722a80fa70 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -431,6 +431,8 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) { ) } ty::AssocKind::Const { .. } => None, + // This does not change judgement on GAT + ty::AssocKind::AutoImpl => continue, }; if let Some(item_required_bounds) = item_required_bounds { @@ -986,6 +988,9 @@ pub(crate) fn check_associated_item( } Ok(()) } + ty::AssocKind::AutoImpl => { + todo!() + } } }) } @@ -2285,6 +2290,7 @@ fn lint_redundant_lifetimes<'tcx>( | DefKind::TraitAlias | DefKind::Fn | DefKind::Const + | DefKind::AutoImpl | DefKind::Impl { of_trait: _ } => { // Proceed } diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 3d2f0466cad08..cf83046963de4 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -409,14 +409,15 @@ fn param_default_policy(node: Node<'_>) -> Option { _ => return None, }, Node::TraitItem(item) => match item.kind { - // Re. GATs and GACs (generic_const_items), we're not bound by backward compatibility. TraitItemKind::Const(..) | TraitItemKind::Type(..) => ParamDefaultPolicy::Forbidden, TraitItemKind::Fn(..) => ParamDefaultPolicy::FutureCompatForbidden, + TraitItemKind::AutoImpl(..) => ParamDefaultPolicy::Forbidden, }, Node::ImplItem(item) => match item.kind { - // Re. GATs and GACs (generic_const_items), we're not bound by backward compatibility. ImplItemKind::Const(..) | ImplItemKind::Type(..) => ParamDefaultPolicy::Forbidden, ImplItemKind::Fn(..) => ParamDefaultPolicy::FutureCompatForbidden, + ImplItemKind::AutoImpl(..) => ParamDefaultPolicy::Forbidden, + ImplItemKind::ExternImpl(..) => ParamDefaultPolicy::Forbidden, }, // Generic params are (semantically) invalid on foreign items. Still, for maximum forward // compatibility, let's hard-reject defaults on them. 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 14e48594c006c..c9b6ba673d97b 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -848,6 +848,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { Const(_, _) => self.visit_early(trait_item.hir_id(), trait_item.generics, |this| { intravisit::walk_trait_item(this, trait_item) }), + AutoImpl(_poly_trait_ref, _items) => todo!(), } } @@ -865,6 +866,8 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { Const(_, _) => self.visit_early(impl_item.hir_id(), impl_item.generics, |this| { intravisit::walk_impl_item(this, impl_item) }), + AutoImpl(_poly_trait_ref, _items) => todo!(), + ExternImpl(_poly_trait_ref) => todo!(), } } diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 9f87381887b30..1e24ebbbc63a7 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -177,6 +177,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ TraitItemKind::Type(_, None) => { span_bug!(item.span, "associated type missing default"); } + TraitItemKind::AutoImpl(_poly_trait_ref, _impl_items) => todo!(), }, Node::ImplItem(item) => match item.kind { @@ -206,6 +207,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ icx.lower_ty(ty) } + ImplItemKind::AutoImpl(_poly_trait_ref, _impl_items) => todo!(), + ImplItemKind::ExternImpl(_poly_trait_ref) => todo!(), }, Node::Item(item) => match item.kind { diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs index 03216d009c2e7..6fba164914449 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -37,7 +37,7 @@ pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type( locator.check(assoc_id.expect_local()) } // Associated types don't have bodies, so they can't constrain hidden types - ty::AssocKind::Type { .. } => {} + ty::AssocKind::Type { .. } | ty::AssocKind::AutoImpl => {} } } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 600684d4f5147..1c7fe2da8abc9 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -1812,5 +1812,7 @@ pub(crate) fn assoc_tag_str(assoc_tag: ty::AssocTag) -> &'static str { ty::AssocTag::Fn => "function", ty::AssocTag::Const => "constant", ty::AssocTag::Type => "type", + ty::AssocTag::AutoImpl => "automatic implementation", + ty::AssocTag::ExternImpl => "external implementation", } } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index c881c77f38f15..09d75e6a65e07 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -1502,7 +1502,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) .emit()); } - ty::AssocTag::Fn => unreachable!(), + ty::AssocTag::Fn | ty::AssocTag::AutoImpl | ty::AssocTag::ExternImpl => { + unreachable!() + } } } @@ -2349,6 +2351,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | DefKind::InlineConst | DefKind::Field | DefKind::Impl { .. } + | DefKind::AutoImpl | DefKind::Closure | DefKind::ExternCrate | DefKind::GlobalAsm diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs index cadbc54c34108..48ae83c7b5e85 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs @@ -112,7 +112,9 @@ pub(crate) fn enforce_impl_lifetime_params_are_constrained( vec![] } } - ty::AssocKind::Fn { .. } | ty::AssocKind::Const { .. } => vec![], + ty::AssocKind::Fn { .. } + | ty::AssocKind::Const { .. } + | ty::AssocKind::AutoImpl => vec![], } }) .collect(); diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index b818a697960ac..d6c54476f8f6a 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -798,18 +798,25 @@ impl<'a> State<'a> { } } - fn print_poly_trait_ref(&mut self, t: &hir::PolyTraitRef<'_>) { - let hir::TraitBoundModifiers { constness, polarity } = t.modifiers; + fn print_constness_modifier(&mut self, constness: &hir::BoundConstness) { match constness { hir::BoundConstness::Never => {} hir::BoundConstness::Always(_) => self.word("const"), hir::BoundConstness::Maybe(_) => self.word("[const]"), } + } + fn print_polarity_modifier(&mut self, polarity: &hir::BoundPolarity) { match polarity { hir::BoundPolarity::Positive => {} hir::BoundPolarity::Negative(_) => self.word("!"), hir::BoundPolarity::Maybe(_) => self.word("?"), } + } + + fn print_poly_trait_ref(&mut self, t: &hir::PolyTraitRef<'_>) { + let hir::TraitBoundModifiers { constness, polarity } = t.modifiers; + self.print_constness_modifier(&constness); + self.print_polarity_modifier(&polarity); self.print_formal_generic_params(t.bound_generic_params); self.print_trait_ref(&t.trait_ref); } @@ -951,6 +958,30 @@ impl<'a> State<'a> { self.end(cb); self.ann.nested(self, Nested::Body(body)); } + hir::TraitItemKind::AutoImpl(poly_trait_ref, impl_items) => { + let (cb, ib) = self.head(""); + self.word_nbsp("auto"); + self.word("impl"); + if !poly_trait_ref.bound_generic_params.is_empty() { + self.print_generic_params(poly_trait_ref.bound_generic_params); + } + self.nbsp(); + self.print_constness_modifier(&poly_trait_ref.modifiers.constness); + self.print_polarity_modifier(&poly_trait_ref.modifiers.polarity); + self.print_trait_ref(&poly_trait_ref.trait_ref); + if impl_items.is_empty() { + self.word(";"); + } else { + self.nbsp(); + self.word("{"); + for ii in impl_items { + self.print_impl_item(ii); + } + self.word("}"); + } + self.end(ib); + self.end(cb); + } hir::TraitItemKind::Type(bounds, default) => { self.print_associated_type(ti.ident, ti.generics, Some(bounds), default); } @@ -979,6 +1010,45 @@ impl<'a> State<'a> { hir::ImplItemKind::Type(ty) => { self.print_associated_type(ii.ident, ii.generics, None, Some(ty)); } + hir::ImplItemKind::AutoImpl(poly_trait_ref, impl_items) => { + let (cb, ib) = self.head(""); + self.word_nbsp("auto"); + self.word_nbsp("impl"); + if !poly_trait_ref.bound_generic_params.is_empty() { + self.print_generic_params(poly_trait_ref.bound_generic_params); + } + self.nbsp(); + self.print_constness_modifier(&poly_trait_ref.modifiers.constness); + self.print_polarity_modifier(&poly_trait_ref.modifiers.polarity); + self.print_trait_ref(&poly_trait_ref.trait_ref); + if impl_items.is_empty() { + self.word(";"); + } else { + self.nbsp(); + self.word("{"); + for ii in impl_items { + self.print_impl_item(ii); + } + self.word("}"); + } + self.end(ib); + self.end(cb); + } + hir::ImplItemKind::ExternImpl(poly_trait_ref) => { + let (cb, ib) = self.head(""); + self.word_nbsp("extern"); + self.word_nbsp("impl"); + if !poly_trait_ref.bound_generic_params.is_empty() { + self.print_generic_params(poly_trait_ref.bound_generic_params); + } + self.nbsp(); + self.print_constness_modifier(&poly_trait_ref.modifiers.constness); + self.print_polarity_modifier(&poly_trait_ref.modifiers.polarity); + self.print_trait_ref(&poly_trait_ref.trait_ref); + self.word(";"); + self.end(ib); + self.end(cb); + } } self.ann.post(self, AnnNode::SubItem(ii.hir_id())) } diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index a8457134031c9..36fffcab97b09 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -2443,7 +2443,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { match self.mode { Mode::MethodCall => item.is_method(), Mode::Path => match item.kind { - ty::AssocKind::Type { .. } => false, + ty::AssocKind::Type { .. } | ty::AssocKind::AutoImpl => false, ty::AssocKind::Fn { .. } | ty::AssocKind::Const { .. } => true, }, } diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs index 64166255fa485..5c7637443423a 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs @@ -291,11 +291,14 @@ impl<'tcx> DirtyCleanVisitor<'tcx> { TraitItemKind::Fn(..) => ("Node::TraitItem", LABELS_FN_IN_TRAIT), TraitItemKind::Const(..) => ("NodeTraitConst", LABELS_CONST_IN_TRAIT), TraitItemKind::Type(..) => ("NodeTraitType", LABELS_CONST_IN_TRAIT), + TraitItemKind::AutoImpl(..) => todo!(), }, HirNode::ImplItem(item) => match item.kind { ImplItemKind::Fn(..) => ("Node::ImplItem", LABELS_FN_IN_IMPL), ImplItemKind::Const(..) => ("NodeImplConst", LABELS_CONST_IN_IMPL), ImplItemKind::Type(..) => ("NodeImplType", LABELS_CONST_IN_IMPL), + ImplItemKind::AutoImpl(..) => todo!(), + ImplItemKind::ExternImpl(..) => todo!(), }, _ => self.tcx.dcx().emit_fatal(errors::UndefinedCleanDirty { span: attr.span(), diff --git a/compiler/rustc_lint/src/lifetime_syntax.rs b/compiler/rustc_lint/src/lifetime_syntax.rs index 0cac91c234080..d47e517b74572 100644 --- a/compiler/rustc_lint/src/lifetime_syntax.rs +++ b/compiler/rustc_lint/src/lifetime_syntax.rs @@ -94,6 +94,7 @@ impl<'tcx> LateLintPass<'tcx> for LifetimeSyntax { hir::TraitItemKind::Const(..) => {} hir::TraitItemKind::Fn(fn_sig, _trait_fn) => check_fn_like(cx, fn_sig.decl), hir::TraitItemKind::Type(..) => {} + hir::TraitItemKind::AutoImpl(..) => todo!(), } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index dca9ed2ef74fb..30d880cd509aa 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -928,6 +928,7 @@ fn should_encode_span(def_kind: DefKind) -> bool { | DefKind::OpaqueTy | DefKind::Field | DefKind::Impl { .. } + | DefKind::AutoImpl | DefKind::Closure | DefKind::SyntheticCoroutineBody => true, DefKind::ForeignMod | DefKind::GlobalAsm => false, @@ -953,6 +954,7 @@ fn should_encode_attrs(def_kind: DefKind) -> bool { | DefKind::AssocConst | DefKind::Macro(_) | DefKind::Field + | DefKind::AutoImpl | DefKind::Impl { .. } => true, // Tools may want to be able to detect their tool lints on // closures from upstream crates, too. This is used by @@ -983,6 +985,7 @@ fn should_encode_expn_that_defined(def_kind: DefKind) -> bool { | DefKind::Enum | DefKind::Variant | DefKind::Trait + | DefKind::AutoImpl | DefKind::Impl { .. } => true, DefKind::TyAlias | DefKind::ForeignTy @@ -1042,6 +1045,7 @@ fn should_encode_visibility(def_kind: DefKind) -> bool { | DefKind::OpaqueTy | DefKind::GlobalAsm | DefKind::Impl { .. } + | DefKind::AutoImpl | DefKind::Closure | DefKind::ExternCrate | DefKind::SyntheticCoroutineBody => false, @@ -1069,6 +1073,7 @@ fn should_encode_stability(def_kind: DefKind) -> bool { | DefKind::Enum | DefKind::Union | DefKind::Impl { .. } + | DefKind::AutoImpl | DefKind::Trait | DefKind::TraitAlias | DefKind::Macro(..) @@ -1164,6 +1169,7 @@ fn should_encode_variances<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: Def | DefKind::Const | DefKind::ForeignMod | DefKind::Impl { .. } + | DefKind::AutoImpl | DefKind::Trait | DefKind::TraitAlias | DefKind::Macro(..) @@ -1201,6 +1207,7 @@ fn should_encode_generics(def_kind: DefKind) -> bool { | DefKind::InlineConst | DefKind::OpaqueTy | DefKind::Impl { .. } + | DefKind::AutoImpl | DefKind::Field | DefKind::TyParam | DefKind::Closure @@ -1230,6 +1237,7 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) -> | DefKind::TyAlias | DefKind::ForeignTy | DefKind::Impl { .. } + | DefKind::AutoImpl | DefKind::AssocFn | DefKind::AssocConst | DefKind::Closure @@ -1293,6 +1301,7 @@ fn should_encode_fn_sig(def_kind: DefKind) -> bool { | DefKind::OpaqueTy | DefKind::ForeignTy | DefKind::Impl { .. } + | DefKind::AutoImpl | DefKind::AssocConst | DefKind::Closure | DefKind::ConstParam @@ -1332,6 +1341,7 @@ fn should_encode_constness(def_kind: DefKind) -> bool { | DefKind::TyAlias | DefKind::OpaqueTy | DefKind::Impl { .. } + | DefKind::AutoImpl | DefKind::ForeignTy | DefKind::ConstParam | DefKind::InlineConst @@ -1369,6 +1379,7 @@ fn should_encode_const(def_kind: DefKind) -> bool { | DefKind::OpaqueTy | DefKind::ForeignTy | DefKind::Impl { .. } + | DefKind::AutoImpl | DefKind::AssocFn | DefKind::Closure | DefKind::ConstParam diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index fca413cdad8ca..0d60454e9b4ec 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -170,6 +170,7 @@ fixed_size_enum! { ( GlobalAsm ) ( Impl { of_trait: false } ) ( Impl { of_trait: true } ) + ( AutoImpl ) ( Closure ) ( Static { safety: hir::Safety::Unsafe, mutability: ast::Mutability::Not, nested: false } ) ( Static { safety: hir::Safety::Safe, mutability: ast::Mutability::Not, nested: false } ) diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs index 430cd329408f5..e9dc0bbafdabe 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -712,6 +712,8 @@ impl<'tcx> TyCtxt<'tcx> { _ => "method", }, ImplItemKind::Type(_) => "associated type", + ImplItemKind::AutoImpl(..) => "automatic implementation", + ImplItemKind::ExternImpl(..) => "external implementation", }; format!("{id} ({kind} `{}` in {})", ii.ident, path_str(ii.owner_id.def_id)) } @@ -723,6 +725,7 @@ impl<'tcx> TyCtxt<'tcx> { _ => "trait method", }, TraitItemKind::Type(..) => "associated type", + TraitItemKind::AutoImpl(..) => "automatic implementation", }; format!("{id} ({kind} `{}` in {})", ti.ident, path_str(ti.owner_id.def_id)) diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index 5e20bc142ffe6..500833d5ad316 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -32,6 +32,7 @@ impl AssocItem { ty::AssocKind::Type { data: AssocTypeData::Rpitit(_) } => None, ty::AssocKind::Const { name } => Some(name), ty::AssocKind::Fn { name, .. } => Some(name), + ty::AssocKind::AutoImpl => None, } } @@ -122,6 +123,7 @@ impl AssocItem { ty::AssocKind::Const { name } => { format!("const {}: {:?};", name, tcx.type_of(self.def_id).instantiate_identity()) } + AssocKind::AutoImpl => "automatic impl".into(), } } @@ -131,12 +133,13 @@ impl AssocItem { ty::AssocKind::Fn { has_self: true, .. } => "method", ty::AssocKind::Fn { has_self: false, .. } => "associated function", ty::AssocKind::Type { .. } => "associated type", + ty::AssocKind::AutoImpl => "automatic implementation", } } pub fn namespace(&self) -> Namespace { match self.kind { - ty::AssocKind::Type { .. } => Namespace::TypeNS, + ty::AssocKind::Type { .. } | ty::AssocKind::AutoImpl => Namespace::TypeNS, ty::AssocKind::Const { .. } | ty::AssocKind::Fn { .. } => Namespace::ValueNS, } } @@ -146,6 +149,7 @@ impl AssocItem { AssocKind::Const { .. } => DefKind::AssocConst, AssocKind::Fn { .. } => DefKind::AssocFn, AssocKind::Type { .. } => DefKind::AssocTy, + AssocKind::AutoImpl => DefKind::AutoImpl, } } pub fn is_type(&self) -> bool { @@ -165,6 +169,7 @@ impl AssocItem { AssocKind::Const { .. } => AssocTag::Const, AssocKind::Fn { .. } => AssocTag::Fn, AssocKind::Type { .. } => AssocTag::Type, + AssocKind::AutoImpl => AssocTag::AutoImpl, } } @@ -187,12 +192,13 @@ pub enum AssocKind { Const { name: Symbol }, Fn { name: Symbol, has_self: bool }, Type { data: AssocTypeData }, + AutoImpl, } impl AssocKind { pub fn namespace(&self) -> Namespace { match *self { - ty::AssocKind::Type { .. } => Namespace::TypeNS, + ty::AssocKind::Type { .. } | ty::AssocKind::AutoImpl { .. } => Namespace::TypeNS, ty::AssocKind::Const { .. } | ty::AssocKind::Fn { .. } => Namespace::ValueNS, } } @@ -202,6 +208,7 @@ impl AssocKind { AssocKind::Const { .. } => DefKind::AssocConst, AssocKind::Fn { .. } => DefKind::AssocFn, AssocKind::Type { .. } => DefKind::AssocTy, + AssocKind::AutoImpl {} => DefKind::AutoImpl, } } } @@ -213,16 +220,20 @@ impl std::fmt::Display for AssocKind { AssocKind::Fn { has_self: false, .. } => write!(f, "associated function"), AssocKind::Const { .. } => write!(f, "associated const"), AssocKind::Type { .. } => write!(f, "associated type"), + AssocKind::AutoImpl => write!(f, "automatic implementation"), } } } -// Like `AssocKind`, but just the tag, no fields. Used in various kinds of matching. +/// Like `AssocKind`, but just the tag, no fields. +/// Used in various kinds of matching. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum AssocTag { Const, Fn, Type, + AutoImpl, + ExternImpl, } /// A list of `ty::AssocItem`s in definition order that allows for efficient lookup by name. diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index d3914d2aee74c..2e39b047e1ce3 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2149,7 +2149,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn is_conditionally_const(self, def_id: impl Into) -> bool { let def_id: DefId = def_id.into(); match self.def_kind(def_id) { - DefKind::Impl { of_trait: true } => { + DefKind::Impl { of_trait: true } | DefKind::AutoImpl => { let header = self.impl_trait_header(def_id); header.constness == hir::Constness::Const && self.is_const_trait(header.trait_ref.skip_binder().def_id) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index d8f16ef5561db..bcd5e96b091b4 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -675,6 +675,7 @@ impl<'tcx> Ty<'tcx> { | DefKind::LifetimeParam | DefKind::GlobalAsm | DefKind::Impl { .. } + | DefKind::AutoImpl | DefKind::Closure | DefKind::SyntheticCoroutineBody => { bug!("not an adt: {def:?} ({:?})", tcx.def_kind(def.did())) diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 86991f047e46d..68568977a9a7d 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -210,7 +210,7 @@ impl<'a> Parser<'a> { fn_parse_mode: FnParseMode, case: Case, ) -> PResult<'a, Option> { - let check_pub = def == &Defaultness::Final; + let check_pub = matches!(def, Defaultness::Final); let mut def_ = || mem::replace(def, Defaultness::Final); let info = if !self.is_use_closure() && self.eat_keyword_case(exp!(Use), case) { @@ -286,6 +286,11 @@ impl<'a> Parser<'a> { // UNION ITEM self.bump(); // `union` self.parse_item_union()? + } else if self.check_keyword(exp!(Unsafe)) + && self.is_keyword_ahead(1, &[kw::Auto, kw::Impl]) + || self.check_keyword(exp!(Auto)) && self.is_keyword_ahead(1, &[kw::Impl]) + { + self.parse_item_auto_impl(attrs)? } else if self.is_builtin() { // BUILTIN# ITEM return self.parse_item_builtin(); @@ -700,6 +705,50 @@ impl<'a> Parser<'a> { Ok(ItemKind::Impl(Impl { generics, of_trait, self_ty, items: impl_items, constness })) } + fn parse_item_auto_impl(&mut self, attrs: &mut AttrVec) -> PResult<'a, ItemKind> { + let safety = self.parse_safety(Case::Sensitive); + self.psess.gated_spans.gate(sym::supertrait_auto_impl, self.token.span); + assert!(self.eat_keyword(exp!(Auto))); + assert!(self.eat_keyword(exp!(Impl))); + + let generics = if self.choose_generics_over_qpath(0) { + self.parse_generics()? + } else { + let mut generics = Generics::default(); + // impl A for B {} + // /\ this is where `generics.span` should point when there are no type params. + generics.span = self.prev_token.span.shrink_to_hi(); + generics + }; + + let polarity = self.parse_polarity(); + + let constness = self.parse_constness(Case::Sensitive); + if let Const::Yes(span) = constness { + self.psess.gated_spans.gate(sym::const_trait_impl, span); + } + + let target_trait = self.parse_ty()?; + + let items = self.parse_semi_or_item_list(attrs, |p| p.parse_impl_item(ForceCollect::No))?; + + let path = if let TyKind::Path(None, path) = target_trait.kind { + path + } else { + return Err(self.dcx().create_err(errors::ExpectedTraitInTraitImplFoundType { + span: target_trait.span, + })); + }; + let trait_ref = TraitRef { path, ref_id: target_trait.id }; + let of_trait = Box::new(TraitImplHeader { + defaultness: Defaultness::Final, + safety, + polarity, + trait_ref, + }); + Ok(ItemKind::AutoImpl(Box::new(AutoImpl { items, of_trait, constness, generics }))) + } + fn parse_item_delegation(&mut self) -> PResult<'a, ItemKind> { let span = self.token.span; self.expect_keyword(exp!(Reuse))?; @@ -756,16 +805,35 @@ impl<'a> Parser<'a> { fn parse_item_list( &mut self, attrs: &mut AttrVec, - mut parse_item: impl FnMut(&mut Parser<'a>) -> PResult<'a, Option>>, + parse_item: impl FnMut(&mut Parser<'a>) -> PResult<'a, Option>>, ) -> PResult<'a, ThinVec> { - let open_brace_span = self.token.span; - // Recover `impl Ty;` instead of `impl Ty {}` if self.token == TokenKind::Semi { self.dcx().emit_err(errors::UseEmptyBlockNotSemi { span: self.token.span }); self.bump(); return Ok(ThinVec::new()); } + self.parse_item_list_inner(attrs, parse_item) + } + + fn parse_semi_or_item_list( + &mut self, + attrs: &mut AttrVec, + parse_item: impl FnMut(&mut Parser<'a>) -> PResult<'a, Option>>, + ) -> PResult<'a, ThinVec> { + if self.eat_noexpect(&TokenKind::Semi) { + Ok(ThinVec::new()) + } else { + self.parse_item_list_inner(attrs, parse_item) + } + } + + fn parse_item_list_inner( + &mut self, + attrs: &mut AttrVec, + mut parse_item: impl FnMut(&mut Parser<'a>) -> PResult<'a, Option>>, + ) -> PResult<'a, ThinVec> { + let open_brace_span = self.token.span; self.expect(exp!(OpenBrace))?; attrs.extend(self.parse_inner_attributes()?); diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 58e55211c671c..23d16cebf5310 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -72,6 +72,8 @@ fn target_from_impl_item<'tcx>(tcx: TyCtxt<'tcx>, impl_item: &hir::ImplItem<'_>) } } hir::ImplItemKind::Type(..) => Target::AssocTy, + hir::ImplItemKind::AutoImpl(_poly_trait_ref, _impl_items) => Target::AutoImpl, + hir::ImplItemKind::ExternImpl(_poly_trait_ref) => Target::ExternImpl, } } @@ -827,6 +829,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | Target::Trait | Target::TraitAlias | Target::Method(..) + | Target::AutoImpl + | Target::ExternImpl | Target::ForeignFn | Target::ForeignStatic | Target::ForeignTy diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 705d1b9e38408..757772ed3c14c 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -50,6 +50,7 @@ fn should_explore(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { | DefKind::Macro(_) | DefKind::GlobalAsm | DefKind::Impl { .. } + | DefKind::AutoImpl | DefKind::OpaqueTy | DefKind::AnonConst | DefKind::InlineConst diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs index fe50b730256b7..4513a4439ee12 100644 --- a/compiler/rustc_passes/src/input_stats.rs +++ b/compiler/rustc_passes/src/input_stats.rs @@ -462,7 +462,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { fn visit_trait_item(&mut self, ti: &'v hir::TraitItem<'v>) { record_variants!( (self, ti, ti.kind, Some(ti.hir_id()), hir, TraitItem, TraitItemKind), - [Const, Fn, Type] + [Const, Fn, Type, AutoImpl] ); hir_visit::walk_trait_item(self, ti) } @@ -475,7 +475,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { fn visit_impl_item(&mut self, ii: &'v hir::ImplItem<'v>) { record_variants!( (self, ii, ii.kind, Some(ii.hir_id()), hir, ImplItem, ImplItemKind), - [Const, Fn, Type] + [Const, Fn, Type, AutoImpl, ExternImpl] ); hir_visit::walk_impl_item(self, ii) } @@ -584,6 +584,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { Trait, TraitAlias, Impl, + AutoImpl, MacCall, MacroDef, Delegation, @@ -717,7 +718,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { fn visit_assoc_item(&mut self, i: &'v ast::AssocItem, ctxt: ast_visit::AssocCtxt) { record_variants!( (self, i, i.kind, None, ast, AssocItem, AssocItemKind), - [Const, Fn, Type, MacCall, Delegation, DelegationMac] + [Const, Fn, Type, MacCall, Delegation, DelegationMac, AutoImpl] ); ast_visit::walk_assoc_item(self, i, ctxt); } diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index 141a60a8ec3f9..f832e8110b298 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -288,6 +288,7 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> { ast::ItemKind::Trait(_) => Target::Trait, ast::ItemKind::TraitAlias(..) => Target::TraitAlias, ast::ItemKind::Impl(imp_) => Target::Impl { of_trait: imp_.of_trait.is_some() }, + ast::ItemKind::AutoImpl(..) => Target::Impl { of_trait: true }, ast::ItemKind::MacroDef(..) => Target::MacroDef, ast::ItemKind::MacCall(_) | ast::ItemKind::DelegationMac(_) => { unreachable!("macros should have been expanded") @@ -342,6 +343,11 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> { } ast::AssocItemKind::Const(ct) => (Target::AssocConst, Some(&ct.generics)), ast::AssocItemKind::Type(ty) => (Target::AssocTy, Some(&ty.generics)), + ast::AssocItemKind::AutoImpl(_) => { + // An language item shall not be applied to some `auto impl`. + // Therein lie all concrete implementors anyway. + return; + } ast::AssocItemKind::MacCall(_) | ast::AssocItemKind::DelegationMac(_) => { unreachable!("macros should have been expanded") } diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index acb64bc6990b6..ecf2e2b761991 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -146,12 +146,15 @@ impl<'tcx> ReachableContext<'tcx> { }, Node::TraitItem(trait_method) => match trait_method.kind { hir::TraitItemKind::Const(_, ref default) => default.is_some(), - hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)) => true, + hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)) + | hir::TraitItemKind::AutoImpl(..) => true, hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_)) | hir::TraitItemKind::Type(..) => false, }, Node::ImplItem(impl_item) => match impl_item.kind { - hir::ImplItemKind::Const(..) => true, + hir::ImplItemKind::Const(..) + | hir::ImplItemKind::AutoImpl(..) + | hir::ImplItemKind::ExternImpl(..) => true, hir::ImplItemKind::Fn(..) => { recursively_reachable(self.tcx, impl_item.hir_id().owner.to_def_id()) } @@ -250,6 +253,7 @@ impl<'tcx> ReachableContext<'tcx> { Node::TraitItem(trait_method) => { match trait_method.kind { hir::TraitItemKind::Const(_, None) + | hir::TraitItemKind::AutoImpl(..) | hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_)) => { // Keep going, nothing to get exported } @@ -269,7 +273,9 @@ impl<'tcx> ReachableContext<'tcx> { self.visit_nested_body(body) } } - hir::ImplItemKind::Type(_) => {} + hir::ImplItemKind::Type(_) + | hir::ImplItemKind::AutoImpl(..) + | hir::ImplItemKind::ExternImpl(..) => {} }, Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure(&hir::Closure { body, .. }), diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 8656ec6e39aed..ac511d939cb0c 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -632,6 +632,7 @@ impl<'tcx> EmbargoVisitor<'tcx> { | DefKind::Field | DefKind::GlobalAsm | DefKind::Impl { .. } + | DefKind::AutoImpl | DefKind::Closure | DefKind::SyntheticCoroutineBody => (), } @@ -694,47 +695,10 @@ impl<'tcx> EmbargoVisitor<'tcx> { } } DefKind::Impl { of_trait } => { - // Type inference is very smart sometimes. It can make an impl reachable even some - // components of its type or trait are unreachable. E.g. methods of - // `impl ReachableTrait for ReachableTy { ... }` - // can be usable from other crates (#57264). So we skip args when calculating - // reachability and consider an impl reachable if its "shallow" type and trait are - // reachable. - // - // The assumption we make here is that type-inference won't let you use an impl - // without knowing both "shallow" version of its self type and "shallow" version of - // its trait if it exists (which require reaching the `DefId`s in them). - let item_ev = EffectiveVisibility::of_impl::( - owner_id.def_id, - of_trait, - self.tcx, - &self.effective_visibilities, - ); - - self.update_eff_vis(owner_id.def_id, item_ev, None, Level::Direct); - - { - let mut reach = self.reach(owner_id.def_id, item_ev); - reach.generics().predicates().ty(); - if of_trait { - reach.trait_ref(); - } - } - - for assoc_item in self.tcx.associated_items(owner_id).in_definition_order() { - if assoc_item.is_impl_trait_in_trait() { - continue; - } - - let def_id = assoc_item.def_id.expect_local(); - let max_vis = - if of_trait { None } else { Some(self.tcx.local_visibility(def_id)) }; - self.update_eff_vis(def_id, item_ev, max_vis, Level::Direct); - - if let Some(impl_item_ev) = self.get(def_id) { - self.reach(def_id, impl_item_ev).generics().predicates().ty(); - } - } + self.check_impl(owner_id, of_trait); + } + DefKind::AutoImpl => { + self.check_impl(owner_id, true); } DefKind::Enum => { if let Some(item_ev) = item_ev { @@ -808,6 +772,49 @@ impl<'tcx> EmbargoVisitor<'tcx> { } } } + + fn check_impl(&mut self, owner_id: OwnerId, of_trait: bool) { + // Type inference is very smart sometimes. It can make an impl reachable even some + // components of its type or trait are unreachable. E.g. methods of + // `impl ReachableTrait for ReachableTy { ... }` + // can be usable from other crates (#57264). So we skip args when calculating + // reachability and consider an impl reachable if its "shallow" type and trait are + // reachable. + // + // The assumption we make here is that type-inference won't let you use an impl + // without knowing both "shallow" version of its self type and "shallow" version of + // its trait if it exists (which require reaching the `DefId`s in them). + let item_ev = EffectiveVisibility::of_impl::( + owner_id.def_id, + of_trait, + self.tcx, + &self.effective_visibilities, + ); + + self.update_eff_vis(owner_id.def_id, item_ev, None, Level::Direct); + + { + let mut reach = self.reach(owner_id.def_id, item_ev); + reach.generics().predicates().ty(); + if of_trait { + reach.trait_ref(); + } + } + + for assoc_item in self.tcx.associated_items(owner_id).in_definition_order() { + if assoc_item.is_impl_trait_in_trait() { + continue; + } + + let def_id = assoc_item.def_id.expect_local(); + let max_vis = if of_trait { None } else { Some(self.tcx.local_visibility(def_id)) }; + self.update_eff_vis(def_id, item_ev, max_vis, Level::Direct); + + if let Some(impl_item_ev) = self.get(def_id) { + self.reach(def_id, impl_item_ev).generics().predicates().ty(); + } + } + } } impl ReachEverythingInTheInterfaceVisitor<'_, '_> { @@ -1587,6 +1594,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> { let (check_ty, is_assoc_ty) = match item.kind { ty::AssocKind::Const { .. } | ty::AssocKind::Fn { .. } => (true, false), ty::AssocKind::Type { .. } => (item.defaultness(self.tcx).has_value(), true), + ty::AssocKind::AutoImpl => return, }; check.in_assoc_ty = is_assoc_ty; diff --git a/compiler/rustc_public/src/mir/pretty.rs b/compiler/rustc_public/src/mir/pretty.rs index d80e227f5a9ce..ba040dc4f9163 100644 --- a/compiler/rustc_public/src/mir/pretty.rs +++ b/compiler/rustc_public/src/mir/pretty.rs @@ -25,6 +25,7 @@ impl Display for AssocKind { AssocKind::Fn { has_self: false, .. } => write!(f, "associated function"), AssocKind::Const { .. } => write!(f, "associated const"), AssocKind::Type { .. } => write!(f, "associated type"), + AssocKind::AutoImpl => write!(f, "automatic implementation"), } } } diff --git a/compiler/rustc_public/src/ty.rs b/compiler/rustc_public/src/ty.rs index f24d98f7e5521..62c56f36cc740 100644 --- a/compiler/rustc_public/src/ty.rs +++ b/compiler/rustc_public/src/ty.rs @@ -1639,6 +1639,7 @@ pub enum AssocKind { Const { name: Symbol }, Fn { name: Symbol, has_self: bool }, Type { data: AssocTypeData }, + AutoImpl, } #[derive(Clone, Debug, Eq, PartialEq, Serialize)] diff --git a/compiler/rustc_public/src/unstable/convert/stable/ty.rs b/compiler/rustc_public/src/unstable/convert/stable/ty.rs index 36fc5724d51a9..68bdf5934ae80 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/ty.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/ty.rs @@ -1063,6 +1063,7 @@ impl<'tcx> Stable<'tcx> for ty::AssocKind { } }, }, + ty::AssocKind::AutoImpl => AssocKind::AutoImpl, } } } diff --git a/compiler/rustc_public/src/unstable/mod.rs b/compiler/rustc_public/src/unstable/mod.rs index 72b14cfa072ae..3796552555ab1 100644 --- a/compiler/rustc_public/src/unstable/mod.rs +++ b/compiler/rustc_public/src/unstable/mod.rs @@ -109,6 +109,7 @@ pub(crate) fn new_item_kind(kind: DefKind) -> ItemKind { | DefKind::Field | DefKind::LifetimeParam | DefKind::Impl { .. } + | DefKind::AutoImpl | DefKind::GlobalAsm => { unreachable!("Not a valid item kind: {kind:?}"); } diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index 1569c175948e1..52994eb227dfc 100644 --- a/compiler/rustc_resolve/messages.ftl +++ b/compiler/rustc_resolve/messages.ftl @@ -41,6 +41,9 @@ resolve_attempt_to_use_non_constant_value_in_constant_without_suggestion = resolve_attributes_starting_with_rustc_are_reserved = attributes starting with `rustc` are reserved for use by the `rustc` compiler +resolve_auto_impl_outside_trait_or_impl_trait = + `auto impl` is outside a `trait` block or trait-`impl` block + resolve_binding_in_never_pattern = never patterns cannot contain variable bindings .suggestion = use a wildcard `_` instead diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index cd12d5ad10cf7..42200a2ca892d 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -9,7 +9,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, + self as ast, AssocItem, AssocItemKind, AutoImpl, Block, ConstItem, Delegation, Fn, ForeignItem, ForeignItemKind, Inline, Item, ItemKind, NodeId, StaticItem, StmtKind, TraitAlias, TyAlias, }; use rustc_attr_parsing as attr; @@ -28,7 +28,7 @@ use rustc_middle::{bug, span_bug}; use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind}; use rustc_span::{Ident, Macros20NormalizedIdent, Span, Symbol, kw, sym}; use thin_vec::ThinVec; -use tracing::debug; +use tracing::{debug, instrument}; use crate::Namespace::{MacroNS, TypeNS, ValueNS}; use crate::def_collector::collect_definitions; @@ -58,6 +58,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } + #[instrument(level = "debug", skip(self, parent))] fn define_local( &mut self, parent: Module<'ra>, @@ -300,6 +301,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { | DefKind::GlobalAsm | DefKind::Closure | DefKind::SyntheticCoroutineBody + | DefKind::AutoImpl | DefKind::Impl { .. }, _, ) @@ -925,7 +927,10 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } // These items do not add names to modules. - ItemKind::Impl { .. } | ItemKind::ForeignMod(..) | ItemKind::GlobalAsm(..) => {} + ItemKind::Impl(..) + | ItemKind::AutoImpl(..) + | ItemKind::ForeignMod(..) + | ItemKind::GlobalAsm(..) => {} ItemKind::MacroDef(..) | ItemKind::MacCall(_) | ItemKind::DelegationMac(..) => { unreachable!() @@ -1412,6 +1417,11 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> { | AssocItemKind::Fn(box Fn { ident, .. }) | AssocItemKind::Delegation(box Delegation { ident, .. }) => (ident, ValueNS), + AssocItemKind::AutoImpl(box AutoImpl { .. }) => { + // This should be dummy id + (Ident::new(kw::Underscore, rustc_span::DUMMY_SP), TypeNS) + } + AssocItemKind::Type(box TyAlias { ident, .. }) => (ident, TypeNS), AssocItemKind::MacCall(_) => { @@ -1450,7 +1460,10 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> { self.r.feed_visibility(feed, vis); } - if ctxt == AssocCtxt::Trait { + if let AssocItemKind::AutoImpl(_) = item.kind { + // We do not define any local names. + // We will now recursively descend into `auto impl` + } else if let AssocCtxt::Trait = ctxt { let parent = self.parent_scope.module; let expansion = self.parent_scope.expansion; self.r.define_local(parent, ident, ns, self.res(def_id), vis, item.span, expansion); diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index ea64a1e6c64dd..01d16b811bca7 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -11,7 +11,7 @@ use rustc_hir::def_id::LocalDefId; use rustc_middle::span_bug; use rustc_span::hygiene::LocalExpnId; use rustc_span::{Span, Symbol, sym}; -use tracing::debug; +use tracing::{debug, instrument}; use crate::{ImplTraitContext, InvocationParent, Resolver}; @@ -33,6 +33,7 @@ struct DefCollector<'a, 'ra, 'tcx> { } impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { + #[instrument(level = "debug", skip(self))] fn create_def( &mut self, node_id: NodeId, @@ -41,10 +42,7 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { span: Span, ) -> LocalDefId { let parent_def = self.invocation_parent.parent_def; - debug!( - "create_def(node_id={:?}, def_kind={:?}, parent_def={:?})", - node_id, def_kind, parent_def - ); + debug!(?parent_def); self.resolver .create_def( parent_def, @@ -107,6 +105,8 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { let mut opt_macro_data = None; let def_kind = match &i.kind { ItemKind::Impl(i) => DefKind::Impl { of_trait: i.of_trait.is_some() }, + // Can we return early? `auto impl` outside an `impl` is not allowed. + ItemKind::AutoImpl(..) => DefKind::AutoImpl, ItemKind::ForeignMod(..) => DefKind::ForeignMod, ItemKind::Mod(..) => DefKind::Mod, ItemKind::Trait(..) => DefKind::Trait, @@ -335,17 +335,22 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { } fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) { - let (ident, def_kind) = match &i.kind { + let (name, def_kind) = match &i.kind { AssocItemKind::Fn(box Fn { ident, .. }) - | AssocItemKind::Delegation(box Delegation { ident, .. }) => (*ident, DefKind::AssocFn), - AssocItemKind::Const(box ConstItem { ident, .. }) => (*ident, DefKind::AssocConst), - AssocItemKind::Type(box TyAlias { ident, .. }) => (*ident, DefKind::AssocTy), + | AssocItemKind::Delegation(box Delegation { ident, .. }) => { + (Some(ident.name), DefKind::AssocFn) + } + AssocItemKind::Const(box ConstItem { ident, .. }) => { + (Some(ident.name), DefKind::AssocConst) + } + AssocItemKind::Type(box TyAlias { ident, .. }) => (Some(ident.name), DefKind::AssocTy), + AssocItemKind::AutoImpl(_) => (None, DefKind::AutoImpl), AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => { return self.visit_macro_invoc(i.id); } }; - let def = self.create_def(i.id, Some(ident.name), def_kind, i.span); + let def = self.create_def(i.id, name, def_kind, i.span); self.with_parent(def, |this| visit::walk_assoc_item(this, i, ctxt)); } diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs index fe6e5b8e6eb6a..e317c52f85fe1 100644 --- a/compiler/rustc_resolve/src/effective_visibilities.rs +++ b/compiler/rustc_resolve/src/effective_visibilities.rs @@ -234,7 +234,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> // If it's a mod, also make the visitor walk all of its items match item.kind { // Resolved in rustc_privacy when types are available - ast::ItemKind::Impl(..) => return, + ast::ItemKind::Impl(..) | ast::ItemKind::AutoImpl(..) => return, // Should be unreachable at this stage ast::ItemKind::MacCall(..) | ast::ItemKind::DelegationMac(..) => panic!( diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index eace729473e21..fa034c10bc841 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -105,6 +105,13 @@ pub(crate) struct MethodNotMemberOfTrait { pub(crate) sub: Option, } +#[derive(Diagnostic)] +#[diag(resolve_auto_impl_outside_trait_or_impl_trait)] +pub(crate) struct AutoImplOutsideTraitOrImplTrait { + #[primary_span] + pub(crate) span: Span, +} + #[derive(Subdiagnostic)] #[suggestion( resolve_associated_fn_with_similar_name_exists, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index a92bc77b5b508..e3ac0e6e32814 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2754,6 +2754,13 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.diag_metadata.current_impl_items = None; } + ItemKind::AutoImpl(..) => { + self.r + .tcx() + .dcx() + .emit_err(errors::AutoImplOutsideTraitOrImplTrait { span: item.span }); + } + ItemKind::Trait(box Trait { ref generics, ref bounds, ref items, .. }) => { // Create a new rib for the trait-wide type parameters. self.with_generic_param_rib( @@ -2916,6 +2923,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } } + #[instrument(level = "debug", skip(self, f))] fn with_generic_param_rib( &mut self, params: &[GenericParam], @@ -2927,7 +2935,6 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ) where F: FnOnce(&mut Self), { - debug!("with_generic_param_rib"); let lifetime_kind = LifetimeRibKind::Generics { binder, span: generics_span, kind: generics_kind }; @@ -3226,6 +3233,20 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.resolve_define_opaques(define_opaque); } + AssocItemKind::AutoImpl(_ai) => { + let tcx = self.r.tcx(); + if !tcx.features().supertrait_auto_impl() { + feature_err( + &tcx.sess, + sym::supertrait_auto_impl, + item.span, + "feature is under construction", + ) + .emit(); + return; + } + todo!() + } AssocItemKind::Delegation(delegation) => { self.with_generic_param_rib( &[], @@ -3296,6 +3317,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.with_self_rib_ns(TypeNS, self_res, f) } + #[instrument(level = "debug", skip(self))] fn resolve_implementation( &mut self, attrs: &[ast::Attribute], @@ -3305,7 +3327,6 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { item_id: NodeId, impl_items: &'ast [Box], ) { - debug!("resolve_implementation"); // If applicable, create a rib for the type parameters. self.with_generic_param_rib( &generics.params, @@ -3507,6 +3528,20 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ); self.diag_metadata.in_non_gat_assoc_type = None; } + AssocItemKind::AutoImpl(_) => { + let tcx = self.r.tcx(); + if !tcx.features().supertrait_auto_impl() { + feature_err( + &tcx.sess, + sym::supertrait_auto_impl, + item.span, + "feature is under construction", + ) + .emit(); + return; + } + todo!() + } AssocItemKind::Delegation(box delegation) => { debug!("resolve_implementation AssocItemKind::Delegation"); self.with_generic_param_rib( @@ -3632,6 +3667,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { AssocItemKind::Const(..) => (E0323, "const"), AssocItemKind::Fn(..) => (E0324, "method"), AssocItemKind::Type(..) => (E0325, "type"), + AssocItemKind::AutoImpl(..) => (E0325, "auto impl"), AssocItemKind::Delegation(..) => (E0324, "method"), AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => { span_bug!(span, "unexpanded macro") @@ -5340,6 +5376,7 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { } ItemKind::Mod(..) + | ItemKind::AutoImpl(..) | ItemKind::Static(..) | ItemKind::Use(..) | ItemKind::ExternCrate(..) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index da58c923695dd..1478d3b14c86d 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -2463,7 +2463,9 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { AssocSuggestion::MethodWithSelf { called } } ast::AssocItemKind::Delegation(..) => AssocSuggestion::AssocFn { called }, - ast::AssocItemKind::MacCall(_) | ast::AssocItemKind::DelegationMac(..) => { + ast::AssocItemKind::AutoImpl(_) + | ast::AssocItemKind::MacCall(_) + | ast::AssocItemKind::DelegationMac(..) => { continue; } }); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 7ce70ee9af8d4..5d180d579da53 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1311,6 +1311,7 @@ pub struct ResolverArenas<'ra> { } impl<'ra> ResolverArenas<'ra> { + /// Create a binding to a resolved name `res`, with a visibility `vis` fn new_res_binding( &'ra self, res: Res, diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs index 60b3b42989b78..617ac4b36c118 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs @@ -706,7 +706,7 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String { for disambiguated_data in &def_path.data { s.push('N'); s.push_str(match disambiguated_data.data { - hir::definitions::DefPathData::Impl => "I", // Not specified in v0's + hir::definitions::DefPathData::Impl | hir::definitions::DefPathData::AutoImpl => "I", // Not specified in v0's hir::definitions::DefPathData::ForeignMod => "F", // Not specified in v0's hir::definitions::DefPathData::TypeNs(..) => "t", hir::definitions::DefPathData::ValueNs(..) => "v", diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index cd730ede4ba1f..463854fb3f9c4 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -2206,6 +2206,7 @@ symbols! { sub_with_overflow, suggestion, super_let, + supertrait_auto_impl, supertrait_item_shadowing, sym, sync, diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 4880a79ea9cf8..0beff7e872e2f 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -888,6 +888,7 @@ impl<'tcx> Printer<'tcx> for V0SymbolMangler<'tcx> { DefPathData::CrateRoot | DefPathData::Use | DefPathData::Impl + | DefPathData::AutoImpl | DefPathData::MacroNs(_) | DefPathData::LifetimeNs(_) | DefPathData::DesugaredAnonymousLifetime diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs index eb72f71382ef9..f5b4ca9d19b0e 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -369,6 +369,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // This is already covered by E0223, but this following single match // arm doesn't hurt here. ty::AssocKind::Type { .. } => ("refer to the", "type"), + ty::AssocKind::AutoImpl => unreachable!(), }; // Replace the more general E0283 with a more specific error diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index 6ab92531e4eff..fdcca80413047 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -352,6 +352,9 @@ pub fn dyn_compatibility_violations_for_assoc_item( Vec::new() } } + ty::AssocKind::AutoImpl => { + vec![] + } } } diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index 84f52e7fc9d26..99a4309f1194c 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -95,6 +95,7 @@ fn associated_item_from_trait_item( hir::TraitItemKind::Type { .. } => { ty::AssocKind::Type { data: ty::AssocTypeData::Normal(name) } } + hir::TraitItemKind::AutoImpl(..) => ty::AssocKind::AutoImpl, }; ty::AssocItem { kind, def_id: owner_id.to_def_id(), container: ty::AssocContainer::Trait } @@ -111,6 +112,8 @@ fn associated_item_from_impl_item(tcx: TyCtxt<'_>, impl_item: &hir::ImplItem<'_> hir::ImplItemKind::Type { .. } => { ty::AssocKind::Type { data: ty::AssocTypeData::Normal(name) } } + hir::ImplItemKind::AutoImpl(..) => todo!(), + hir::ImplItemKind::ExternImpl(..) => todo!(), }; let container = match impl_item.impl_kind { diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index 990120db9726b..6d8f723385e73 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -7,7 +7,7 @@ use rustc_hir::def_id::LocalDefId; use rustc_middle::query::Providers; use rustc_middle::ty::{self, Ty, TyCtxt, fold_regions}; use rustc_middle::{bug, span_bug}; -use rustc_span::Span; +use rustc_span::{DUMMY_SP, Span}; pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { @@ -55,6 +55,11 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' let mut impl_spans = impl_spans(tcx, def_id); tcx.arena.alloc_from_iter(tys.into_iter().map(|ty| (ty, impl_spans.next().unwrap()))) } + DefKind::AutoImpl => { + let trait_ref = tcx.impl_trait_ref(def_id); + let impl_spans = impl_spans(tcx, def_id).chain(iter::repeat(DUMMY_SP)); + tcx.arena.alloc_from_iter(trait_ref.skip_binder().args.types().zip(impl_spans)) + } DefKind::AssocTy if let Some(data) = tcx.opt_rpitit_info(def_id.to_def_id()) => { match data { ty::ImplTraitInTraitData::Trait { fn_def_id, .. } => { diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index 445021801beff..5614d1c6567e3 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -333,6 +333,7 @@ fn opaque_types_defined_by<'tcx>( | DefKind::ForeignMod | DefKind::Field | DefKind::LifetimeParam + | DefKind::AutoImpl | DefKind::Impl { .. } => { span_bug!( tcx.def_span(item), diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs index 07f379d3f9a8f..1bf7b2da83400 100644 --- a/compiler/rustc_ty_utils/src/sig_types.rs +++ b/compiler/rustc_ty_utils/src/sig_types.rs @@ -100,6 +100,22 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( try_visit!(visitor.visit(span, pred)); } } + DefKind::AutoImpl => { + todo!() + // if of_trait { + // let span = tcx.hir_node_by_def_id(item).expect_item().expect_impl().of_trait.unwrap().trait_ref.path.span; + // let args = &tcx.impl_trait_ref(item).instantiate_identity().args[1..]; + // try_visit!(visitor.visit(span, args)); + // } + // let span = match tcx.hir_node_by_def_id(item).ty() { + // Some(ty) => ty.span, + // _ => tcx.def_span(item), + // }; + // try_visit!(visitor.visit(span, tcx.type_of(item).instantiate_identity())); + // for (pred, span) in tcx.explicit_predicates_of(item).instantiate_identity(tcx) { + // try_visit!(visitor.visit(span, pred)); + // } + } DefKind::TraitAlias | DefKind::Trait => { for (pred, span) in tcx.explicit_predicates_of(item).instantiate_identity(tcx) { try_visit!(visitor.visit(span, pred)); diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 189d3a70ad626..f1b9bf5666da1 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -528,6 +528,8 @@ pub(crate) fn build_impl( hir::ImplItemKind::Const(..) => ty::AssocTag::Const, hir::ImplItemKind::Fn(..) => ty::AssocTag::Fn, hir::ImplItemKind::Type(..) => ty::AssocTag::Type, + hir::ImplItemKind::AutoImpl(..) => ty::AssocTag::AutoImpl, + hir::ImplItemKind::ExternImpl(..) => ty::AssocTag::ExternImpl, }; let trait_item = tcx .associated_items(associated_trait.def_id) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 38b12405ea821..6ce6ee2bec7dd 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1237,6 +1237,7 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext let bounds = bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(); RequiredAssocTypeItem(generics, bounds) } + hir::TraitItemKind::AutoImpl(..) => todo!(), }; Item::from_def_id_and_parts(local_did, Some(trait_item.ident.name), inner, cx) }) @@ -1277,6 +1278,8 @@ pub(crate) fn clean_impl_item<'tcx>( Vec::new(), ) } + hir::ImplItemKind::AutoImpl(_poly_trait_ref, _impl_items) => todo!(), + hir::ImplItemKind::ExternImpl(_poly_trait_ref) => todo!(), }; Item::from_def_id_and_parts(local_did, Some(impl_.ident.name), inner, cx) @@ -1503,6 +1506,7 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo ) } } + ty::AssocKind::AutoImpl => todo!(), }; Item::from_def_id_and_parts(assoc_item.def_id, Some(assoc_item.name()), kind, cx) diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs index d3923e3e31166..75a4d44df3793 100644 --- a/src/librustdoc/formats/item_type.rs +++ b/src/librustdoc/formats/item_type.rs @@ -192,6 +192,7 @@ impl ItemType { | DefKind::LifetimeParam | DefKind::GlobalAsm | DefKind::Impl { .. } + | DefKind::AutoImpl | DefKind::Closure | DefKind::SyntheticCoroutineBody => Self::ForeignType, } diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 4e4f21bf926fe..4a16211730eb9 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -2085,7 +2085,7 @@ fn resolution_failure( | TraitAlias | TyParam | Static { .. } => "associated item", - Impl { .. } | GlobalAsm | SyntheticCoroutineBody => { + Impl { .. } | GlobalAsm | SyntheticCoroutineBody | AutoImpl => { unreachable!("not a path") } } diff --git a/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs b/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs index 454026e80ab30..7827587b5bfd3 100644 --- a/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs +++ b/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs @@ -478,6 +478,7 @@ fn convert_assoc_item_kind(cx: &LateContext<'_>, owner_id: OwnerId) -> SourceIte AssocKind::Const { .. } => Const, AssocKind::Type { .. } => Type, AssocKind::Fn { .. } => Fn, + AssocKind::AutoImpl => todo!(), } } diff --git a/src/tools/clippy/clippy_lints/src/manual_float_methods.rs b/src/tools/clippy/clippy_lints/src/manual_float_methods.rs index a81c4dc6a7931..79618f683f05a 100644 --- a/src/tools/clippy/clippy_lints/src/manual_float_methods.rs +++ b/src/tools/clippy/clippy_lints/src/manual_float_methods.rs @@ -115,6 +115,7 @@ fn is_not_const(tcx: TyCtxt<'_>, def_id: DefId) -> bool { | DefKind::ForeignMod | DefKind::GlobalAsm | DefKind::Impl { .. } + | DefKind::AutoImpl | DefKind::OpaqueTy | DefKind::SyntheticCoroutineBody | DefKind::TyParam => true, diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs index c308f2a345852..16c8a852453e3 100644 --- a/src/tools/clippy/clippy_lints/src/missing_inline.rs +++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs @@ -118,7 +118,9 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { for &tit in trait_items { let tit_ = cx.tcx.hir_trait_item(tit); match tit_.kind { - hir::TraitItemKind::Const(..) | hir::TraitItemKind::Type(..) => {}, + hir::TraitItemKind::Const(..) + | hir::TraitItemKind::Type(..) + | hir::TraitItemKind::AutoImpl(..) => {}, hir::TraitItemKind::Fn(..) => { if cx.tcx.defaultness(tit.owner_id).has_value() { // trait method with default body needs inline in case @@ -167,7 +169,10 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { let desc = match impl_item.kind { hir::ImplItemKind::Fn(..) => "a method", - hir::ImplItemKind::Const(..) | hir::ImplItemKind::Type(_) => return, + hir::ImplItemKind::Const(..) + | hir::ImplItemKind::Type(_) + | hir::ImplItemKind::AutoImpl(..) + | hir::ImplItemKind::ExternImpl(..) => return, }; let assoc_item = cx.tcx.associated_item(impl_item.owner_id); diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs index 7018146f184b2..13e32d99a044d 100644 --- a/src/tools/clippy/clippy_lints/src/types/mod.rs +++ b/src/tools/clippy/clippy_lints/src/types/mod.rs @@ -484,7 +484,10 @@ impl<'tcx> LateLintPass<'tcx> for Types { // Methods are covered by check_fn. // Type aliases are ignored because oftentimes it's impossible to // make type alias declaration in trait simpler, see #1013 - ImplItemKind::Fn(..) | ImplItemKind::Type(..) => (), + ImplItemKind::Fn(..) + | ImplItemKind::Type(..) + | ImplItemKind::AutoImpl(..) + | ImplItemKind::ExternImpl(..) => (), } } @@ -524,7 +527,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { self.check_fn_decl(cx, sig.decl, context); } }, - TraitItemKind::Type(..) => (), + TraitItemKind::Type(..) | TraitItemKind::AutoImpl(..) => (), } } diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs index 544218e09930a..0c3921b301b3b 100644 --- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs +++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs @@ -279,6 +279,7 @@ fn trait_item_search_pat(item: &TraitItem<'_>) -> (Pat, Pat) { TraitItemKind::Const(..) => (Pat::Str("const"), Pat::Str(";")), TraitItemKind::Type(..) => (Pat::Str("type"), Pat::Str(";")), TraitItemKind::Fn(sig, ..) => (fn_header_search_pat(sig.header), Pat::Str("")), + TraitItemKind::AutoImpl(_poly_trait_ref, _impl_items) => todo!(), } } @@ -287,6 +288,8 @@ fn impl_item_search_pat(item: &ImplItem<'_>) -> (Pat, Pat) { ImplItemKind::Const(..) => (Pat::Str("const"), Pat::Str(";")), ImplItemKind::Type(..) => (Pat::Str("type"), Pat::Str(";")), ImplItemKind::Fn(sig, ..) => (fn_header_search_pat(sig.header), Pat::Str("")), + ImplItemKind::AutoImpl(_poly_trait_ref, _impl_items) => todo!(), + ImplItemKind::ExternImpl(_poly_trait_ref) => todo!(), }; if let ImplItemImplKind::Inherent { vis_span, .. } = item.impl_kind && !vis_span.is_empty() diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index d1778f324c6aa..034c93f8ecf8c 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -759,11 +759,13 @@ impl<'a> FmtVisitor<'a> { } (Const(ca), Const(cb)) => ca.ident.as_str().cmp(cb.ident.as_str()), (MacCall(..), MacCall(..)) => Ordering::Equal, - (Fn(..), Fn(..)) | (Delegation(..), Delegation(..)) => { - a.span.lo().cmp(&b.span.lo()) - } + (AutoImpl(..), AutoImpl(..)) + | (Fn(..), Fn(..)) + | (Delegation(..), Delegation(..)) => a.span.lo().cmp(&b.span.lo()), (Type(ty), _) if is_type(&ty.ty) => Ordering::Less, (_, Type(ty)) if is_type(&ty.ty) => Ordering::Greater, + (AutoImpl(..), _) => Ordering::Less, + (_, AutoImpl(..)) => Ordering::Greater, (Type(..), _) => Ordering::Less, (_, Type(..)) => Ordering::Greater, (Const(..), _) => Ordering::Less, @@ -806,10 +808,67 @@ pub(crate) fn format_impl( generics, self_ty, items, + of_trait, + constness, .. } = iimpl; + format_impl_inner( + context, + item, + offset, + generics, + of_trait.as_deref(), + *constness, + Some(&**self_ty), + self_ty.span.hi(), + items, + ) +} + +pub(crate) fn format_auto_impl( + context: &RewriteContext<'_>, + item: &ast::Item, + iimpl: &ast::AutoImpl, + offset: Indent, +) -> Option { + let ast::AutoImpl { + generics, + items, + of_trait, + constness, + } = iimpl; + let impl_head_end = of_trait.trait_ref.path.span.hi(); + format_impl_inner( + context, + item, + offset, + generics, + Some(&**of_trait), + *constness, + None, + impl_head_end, + items, + ) +} + +/// `impl_header_end` points at the 1-past-end of proper `impl` header. +/// For instance, in case of `impl Trait for Type {`, `impl_header_end` points at +/// the space coming right after the token `Type`. +fn format_impl_inner( + context: &RewriteContext<'_>, + item: &ast::Item, + offset: Indent, + generics: &ast::Generics, + of_trait: Option<&ast::TraitImplHeader>, + constness: ast::Const, + self_ty: Option<&ast::Ty>, + impl_header_end: BytePos, + items: &[Box], +) -> Option { let mut result = String::with_capacity(128); - let ref_and_type = format_impl_ref_and_type(context, item, iimpl, offset)?; + let ref_and_type = format_impl_ref_and_type( + context, item, generics, of_trait, self_ty, constness, offset, + )?; let sep = offset.to_string_with_newline(context.config); result.push_str(&ref_and_type); @@ -832,7 +891,7 @@ pub(crate) fn format_impl( option.allow_single_line(); } - let missing_span = mk_sp(self_ty.span.hi(), item.span.hi()); + let missing_span = mk_sp(impl_header_end, item.span.hi()); let where_span_end = context.snippet_provider.opt_span_before(missing_span, "{"); let where_clause_str = rewrite_where_clause( context, @@ -842,7 +901,7 @@ pub(crate) fn format_impl( false, "{", where_span_end, - self_ty.span.hi(), + impl_header_end, option, ) .ok()?; @@ -852,7 +911,7 @@ pub(crate) fn format_impl( if generics.where_clause.predicates.is_empty() { if let Some(hi) = where_span_end { match recover_missing_comment_in_span( - mk_sp(self_ty.span.hi(), hi), + mk_sp(impl_header_end, hi), Shape::indented(offset, context.config), context, last_line_width(&result), @@ -865,7 +924,7 @@ pub(crate) fn format_impl( } } - if is_impl_single_line(context, items.as_slice(), &result, &where_clause_str, item)? { + if is_impl_single_line(context, items, &result, &where_clause_str, item)? { result.push_str(&where_clause_str); if where_clause_str.contains('\n') { // If there is only one where-clause predicate @@ -901,7 +960,7 @@ pub(crate) fn format_impl( result.push('{'); // this is an impl body snippet(impl SampleImpl { /* here */ }) - let lo = max(self_ty.span.hi(), generics.where_clause.span.hi()); + let lo = max(impl_header_end, generics.where_clause.span.hi()); let snippet = context.snippet(mk_sp(lo, item.span.hi())); let open_pos = snippet.find_uncommented("{")? + 1; @@ -953,25 +1012,21 @@ fn is_impl_single_line( fn format_impl_ref_and_type( context: &RewriteContext<'_>, item: &ast::Item, - iimpl: &ast::Impl, + generics: &ast::Generics, + of_trait: Option<&ast::TraitImplHeader>, + self_ty: Option<&ast::Ty>, + constness: ast::Const, offset: Indent, ) -> Option { - let ast::Impl { - generics, - of_trait, - self_ty, - items: _, - constness, - } = iimpl; let mut result = String::with_capacity(128); result.push_str(&format_visibility(context, &item.vis)); - if let Some(of_trait) = of_trait.as_deref() { + if let Some(of_trait) = of_trait { result.push_str(format_defaultness(of_trait.defaultness)); result.push_str(format_safety(of_trait.safety)); } else { - result.push_str(format_constness_right(*constness)); + result.push_str(format_constness_right(constness)); } let shape = if context.config.style_edition() >= StyleEdition::Edition2024 { @@ -988,7 +1043,7 @@ fn format_impl_ref_and_type( let trait_ref_overhead; if let Some(of_trait) = of_trait.as_deref() { - result.push_str(format_constness_right(*constness)); + result.push_str(format_constness_right(constness)); let polarity_str = match of_trait.polarity { ast::ImplPolarity::Negative(_) => "!", ast::ImplPolarity::Positive => "", @@ -1020,15 +1075,18 @@ fn format_impl_ref_and_type( let used_space = last_line_width(&result) + trait_ref_overhead + curly_brace_overhead; // 1 = space before the type. let budget = context.budget(used_space + 1); - if let Some(self_ty_str) = self_ty.rewrite(context, Shape::legacy(budget, offset)) { - if !self_ty_str.contains('\n') { - if of_trait.is_some() { - result.push_str(" for "); - } else { - result.push(' '); + // TODO(@dingxiangfei2009): rewrite this in let-chain once we finish migrating to Edition 2024 + if let Some(self_ty) = self_ty { + if let Some(self_ty_str) = self_ty.rewrite(context, Shape::legacy(budget, offset)) { + if !self_ty_str.contains('\n') { + if of_trait.is_some() { + result.push_str(" for "); + } else { + result.push(' '); + } + result.push_str(&self_ty_str); + return Some(result); } - result.push_str(&self_ty_str); - return Some(result); } } @@ -1045,7 +1103,9 @@ fn format_impl_ref_and_type( IndentStyle::Visual => new_line_offset + trait_ref_overhead, IndentStyle::Block => new_line_offset, }; - result.push_str(&*self_ty.rewrite(context, Shape::legacy(budget, type_offset))?); + if let Some(self_ty) = self_ty { + result.push_str(&*self_ty.rewrite(context, Shape::legacy(budget, type_offset))?); + } Some(result) } diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs index c521b497a2d99..4c05ef5029032 100644 --- a/src/tools/rustfmt/src/visitor.rs +++ b/src/tools/rustfmt/src/visitor.rs @@ -11,8 +11,9 @@ use crate::comment::{CodeCharKind, CommentCodeSlices, contains_comment, rewrite_ use crate::config::{BraceStyle, Config, MacroSelector, StyleEdition}; use crate::coverage::transform_missing_snippet; use crate::items::{ - FnBraceStyle, FnSig, ItemVisitorKind, StaticParts, StructParts, format_impl, format_trait, - format_trait_alias, is_mod_decl, is_use_item, rewrite_extern_crate, rewrite_type_alias, + FnBraceStyle, FnSig, ItemVisitorKind, StaticParts, StructParts, format_auto_impl, format_impl, + format_trait, format_trait_alias, is_mod_decl, is_use_item, rewrite_extern_crate, + rewrite_type_alias, }; use crate::macros::{MacroPosition, macro_style, rewrite_macro, rewrite_macro_def}; use crate::modules::Module; @@ -492,6 +493,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let rw = self.with_context(|ctx| format_impl(ctx, item, iimpl, block_indent)); self.push_rewrite(item.span, rw); } + ast::ItemKind::AutoImpl(ref aimpl) => { + let block_indent = self.block_indent; + let rw = + self.with_context(|ctx| format_auto_impl(ctx, item, aimpl, block_indent)); + self.push_rewrite(item.span, rw); + } ast::ItemKind::Trait(..) => { let block_indent = self.block_indent; let rw = self.with_context(|ctx| format_trait(ctx, item, block_indent)); diff --git a/tests/ui/enum-discriminant/wrapping_niche.stderr b/tests/ui/enum-discriminant/wrapping_niche.stderr index e3e1755e14dd4..741ca45b0d9b9 100644 --- a/tests/ui/enum-discriminant/wrapping_niche.stderr +++ b/tests/ui/enum-discriminant/wrapping_niche.stderr @@ -61,7 +61,7 @@ error: layout_of(UnsignedAroundZero) = Layout { }, max_repr_align: None, unadjusted_abi_align: Align(2 bytes), - randomization_seed: 9885373149222004003, + randomization_seed: 7121270564429706562, }, Layout { size: Size(2 bytes), @@ -82,7 +82,7 @@ error: layout_of(UnsignedAroundZero) = Layout { }, max_repr_align: None, unadjusted_abi_align: Align(2 bytes), - randomization_seed: 9885373149222004003, + randomization_seed: 7121270564429706562, }, Layout { size: Size(2 bytes), @@ -103,13 +103,13 @@ error: layout_of(UnsignedAroundZero) = Layout { }, max_repr_align: None, unadjusted_abi_align: Align(2 bytes), - randomization_seed: 9885373149222004003, + randomization_seed: 7121270564429706562, }, ], }, max_repr_align: None, unadjusted_abi_align: Align(2 bytes), - randomization_seed: 2648004449468912780, + randomization_seed: 10038338184009274632, } --> $DIR/wrapping_niche.rs:8:1 | @@ -179,7 +179,7 @@ error: layout_of(SignedAroundZero) = Layout { }, max_repr_align: None, unadjusted_abi_align: Align(2 bytes), - randomization_seed: 2684536712112553499, + randomization_seed: 6066804703076516501, }, Layout { size: Size(2 bytes), @@ -200,7 +200,7 @@ error: layout_of(SignedAroundZero) = Layout { }, max_repr_align: None, unadjusted_abi_align: Align(2 bytes), - randomization_seed: 2684536712112553499, + randomization_seed: 6066804703076516501, }, Layout { size: Size(2 bytes), @@ -221,13 +221,13 @@ error: layout_of(SignedAroundZero) = Layout { }, max_repr_align: None, unadjusted_abi_align: Align(2 bytes), - randomization_seed: 2684536712112553499, + randomization_seed: 6066804703076516501, }, ], }, max_repr_align: None, unadjusted_abi_align: Align(2 bytes), - randomization_seed: 10738146848450213996, + randomization_seed: 5820474738596514388, } --> $DIR/wrapping_niche.rs:17:1 | diff --git a/tests/ui/feature-gates/feature-gate-supertrait-auto-impl.rs b/tests/ui/feature-gates/feature-gate-supertrait-auto-impl.rs new file mode 100644 index 0000000000000..fb21180ace06b --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-supertrait-auto-impl.rs @@ -0,0 +1,9 @@ +trait Supertrait {} +trait Subtrait: Supertrait { + auto impl Supertrait; + //~^ ERROR feature is under construction + //~| ERROR feature is under construction + //~| ERROR feature is under construction +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-supertrait-auto-impl.stderr b/tests/ui/feature-gates/feature-gate-supertrait-auto-impl.stderr new file mode 100644 index 0000000000000..08c0ec210c742 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-supertrait-auto-impl.stderr @@ -0,0 +1,35 @@ +error[E0658]: feature is under construction + --> $DIR/feature-gate-supertrait-auto-impl.rs:3:5 + | +LL | auto impl Supertrait; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #99999 for more information + = help: add `#![feature(supertrait_auto_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: feature is under construction + --> $DIR/feature-gate-supertrait-auto-impl.rs:3:5 + | +LL | auto impl Supertrait; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #99999 for more information + = help: add `#![feature(supertrait_auto_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0658]: feature is under construction + --> $DIR/feature-gate-supertrait-auto-impl.rs:3:5 + | +LL | auto impl Supertrait; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #99999 for more information + = help: add `#![feature(supertrait_auto_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/symbol-names/basic.legacy.stderr b/tests/ui/symbol-names/basic.legacy.stderr index a028f4331725e..af887bfff9b67 100644 --- a/tests/ui/symbol-names/basic.legacy.stderr +++ b/tests/ui/symbol-names/basic.legacy.stderr @@ -1,10 +1,10 @@ -error: symbol-name(_ZN5basic4main17h1dddcfd03744167fE) +error: symbol-name(_ZN5basic4main17h24d8c9fda04e0efcE) --> $DIR/basic.rs:8:1 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(basic::main::h1dddcfd03744167f) +error: demangling(basic::main::h24d8c9fda04e0efc) --> $DIR/basic.rs:8:1 | LL | #[rustc_symbol_name] diff --git a/tests/ui/symbol-names/issue-60925.legacy.stderr b/tests/ui/symbol-names/issue-60925.legacy.stderr index 14cbd877d9f8a..a827391fc99e2 100644 --- a/tests/ui/symbol-names/issue-60925.legacy.stderr +++ b/tests/ui/symbol-names/issue-60925.legacy.stderr @@ -1,10 +1,10 @@ -error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h4b3099ec5dc5d306E) +error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17had7710e18fe13ebbE) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(issue_60925::foo::Foo::foo::h4b3099ec5dc5d306) +error: demangling(issue_60925::foo::Foo::foo::had7710e18fe13ebb) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] diff --git a/tests/ui/thir-print/thir-tree-match.stdout b/tests/ui/thir-print/thir-tree-match.stdout index 8a2bad56c126a..07bb5d0d30d09 100644 --- a/tests/ui/thir-print/thir-tree-match.stdout +++ b/tests/ui/thir-print/thir-tree-match.stdout @@ -95,7 +95,7 @@ body: did: DefId(0:10 ~ thir_tree_match[fcf8]::Foo) variants: [VariantDef { def_id: DefId(0:11 ~ thir_tree_match[fcf8]::Foo::FooOne), ctor: Some((Fn, DefId(0:12 ~ thir_tree_match[fcf8]::Foo::FooOne::{constructor#0}))), name: "FooOne", discr: Relative(0), fields: [FieldDef { did: DefId(0:13 ~ thir_tree_match[fcf8]::Foo::FooOne::0), name: "0", vis: Restricted(DefId(0:0 ~ thir_tree_match[fcf8])), safety: Safe, value: None }], tainted: None, flags: }, VariantDef { def_id: DefId(0:14 ~ thir_tree_match[fcf8]::Foo::FooTwo), ctor: Some((Const, DefId(0:15 ~ thir_tree_match[fcf8]::Foo::FooTwo::{constructor#0}))), name: "FooTwo", discr: Relative(1), fields: [], tainted: None, flags: }] flags: IS_ENUM - repr: ReprOptions { int: None, align: None, pack: None, flags: , field_shuffle_seed: 13397682652773712997 } + repr: ReprOptions { int: None, align: None, pack: None, flags: , field_shuffle_seed: 14690699100600655163 } args: [] variant_index: 0 subpatterns: [ @@ -109,7 +109,7 @@ body: did: DefId(0:3 ~ thir_tree_match[fcf8]::Bar) variants: [VariantDef { def_id: DefId(0:4 ~ thir_tree_match[fcf8]::Bar::First), ctor: Some((Const, DefId(0:5 ~ thir_tree_match[fcf8]::Bar::First::{constructor#0}))), name: "First", discr: Relative(0), fields: [], tainted: None, flags: }, VariantDef { def_id: DefId(0:6 ~ thir_tree_match[fcf8]::Bar::Second), ctor: Some((Const, DefId(0:7 ~ thir_tree_match[fcf8]::Bar::Second::{constructor#0}))), name: "Second", discr: Relative(1), fields: [], tainted: None, flags: }, VariantDef { def_id: DefId(0:8 ~ thir_tree_match[fcf8]::Bar::Third), ctor: Some((Const, DefId(0:9 ~ thir_tree_match[fcf8]::Bar::Third::{constructor#0}))), name: "Third", discr: Relative(2), fields: [], tainted: None, flags: }] flags: IS_ENUM - repr: ReprOptions { int: None, align: None, pack: None, flags: , field_shuffle_seed: 7908585036048874241 } + repr: ReprOptions { int: None, align: None, pack: None, flags: , field_shuffle_seed: 6644017360006562866 } args: [] variant_index: 0 subpatterns: [] @@ -157,7 +157,7 @@ body: did: DefId(0:10 ~ thir_tree_match[fcf8]::Foo) variants: [VariantDef { def_id: DefId(0:11 ~ thir_tree_match[fcf8]::Foo::FooOne), ctor: Some((Fn, DefId(0:12 ~ thir_tree_match[fcf8]::Foo::FooOne::{constructor#0}))), name: "FooOne", discr: Relative(0), fields: [FieldDef { did: DefId(0:13 ~ thir_tree_match[fcf8]::Foo::FooOne::0), name: "0", vis: Restricted(DefId(0:0 ~ thir_tree_match[fcf8])), safety: Safe, value: None }], tainted: None, flags: }, VariantDef { def_id: DefId(0:14 ~ thir_tree_match[fcf8]::Foo::FooTwo), ctor: Some((Const, DefId(0:15 ~ thir_tree_match[fcf8]::Foo::FooTwo::{constructor#0}))), name: "FooTwo", discr: Relative(1), fields: [], tainted: None, flags: }] flags: IS_ENUM - repr: ReprOptions { int: None, align: None, pack: None, flags: , field_shuffle_seed: 13397682652773712997 } + repr: ReprOptions { int: None, align: None, pack: None, flags: , field_shuffle_seed: 14690699100600655163 } args: [] variant_index: 0 subpatterns: [ @@ -209,7 +209,7 @@ body: did: DefId(0:10 ~ thir_tree_match[fcf8]::Foo) variants: [VariantDef { def_id: DefId(0:11 ~ thir_tree_match[fcf8]::Foo::FooOne), ctor: Some((Fn, DefId(0:12 ~ thir_tree_match[fcf8]::Foo::FooOne::{constructor#0}))), name: "FooOne", discr: Relative(0), fields: [FieldDef { did: DefId(0:13 ~ thir_tree_match[fcf8]::Foo::FooOne::0), name: "0", vis: Restricted(DefId(0:0 ~ thir_tree_match[fcf8])), safety: Safe, value: None }], tainted: None, flags: }, VariantDef { def_id: DefId(0:14 ~ thir_tree_match[fcf8]::Foo::FooTwo), ctor: Some((Const, DefId(0:15 ~ thir_tree_match[fcf8]::Foo::FooTwo::{constructor#0}))), name: "FooTwo", discr: Relative(1), fields: [], tainted: None, flags: }] flags: IS_ENUM - repr: ReprOptions { int: None, align: None, pack: None, flags: , field_shuffle_seed: 13397682652773712997 } + repr: ReprOptions { int: None, align: None, pack: None, flags: , field_shuffle_seed: 14690699100600655163 } args: [] variant_index: 1 subpatterns: []