From 879a1e571305a0fb35ef6cc4297f9230fca95be5 Mon Sep 17 00:00:00 2001 From: Frank King Date: Thu, 4 Jan 2024 21:53:06 +0800 Subject: [PATCH 1/8] Lower anonymous structs or unions to HIR --- compiler/rustc_ast/src/ast.rs | 4 +- compiler/rustc_ast/src/mut_visit.rs | 3 +- compiler/rustc_ast/src/visit.rs | 2 +- compiler/rustc_ast_lowering/src/item.rs | 5 +- compiler/rustc_ast_lowering/src/lib.rs | 54 +++++++++--- .../rustc_ast_passes/src/ast_validation.rs | 2 +- compiler/rustc_ast_pretty/src/pprust/state.rs | 4 +- compiler/rustc_hir/src/def.rs | 2 + compiler/rustc_hir/src/definitions.rs | 6 +- compiler/rustc_hir/src/hir.rs | 2 + compiler/rustc_hir/src/intravisit.rs | 3 + .../rustc_hir_analysis/src/astconv/mod.rs | 13 +++ compiler/rustc_hir_analysis/src/collect.rs | 82 +++++++++++++++++-- compiler/rustc_hir_pretty/src/lib.rs | 37 +++++---- compiler/rustc_metadata/src/rmeta/decoder.rs | 3 + compiler/rustc_middle/src/hir/map/mod.rs | 7 ++ compiler/rustc_middle/src/ty/adt.rs | 17 +++- compiler/rustc_middle/src/ty/context.rs | 10 ++- compiler/rustc_middle/src/ty/mod.rs | 19 ++++- compiler/rustc_parse/src/parser/ty.rs | 5 +- compiler/rustc_passes/src/hir_stats.rs | 1 + compiler/rustc_span/src/symbol.rs | 1 + .../src/typeid/typeid_itanium_cxx_abi.rs | 3 +- compiler/rustc_symbol_mangling/src/v0.rs | 3 +- .../src/solve/assembly/structural_traits.rs | 5 ++ .../src/traits/select/mod.rs | 10 +++ .../rustc_ty_utils/src/representability.rs | 3 +- src/librustdoc/clean/mod.rs | 10 +++ src/librustdoc/clean/types.rs | 4 + .../clippy/clippy_lints/src/dereference.rs | 1 + .../clippy/clippy_utils/src/hir_utils.rs | 3 +- src/tools/rustfmt/src/types.rs | 4 +- .../feature-gate-unnamed_fields.rs | 2 - .../feature-gate-unnamed_fields.stderr | 34 +------- .../restrict_anonymous_structs.rs | 5 -- .../restrict_anonymous_structs.stderr | 44 ++-------- .../restrict_anonymous_unions.rs | 5 -- .../restrict_anonymous_unions.stderr | 44 ++-------- 38 files changed, 288 insertions(+), 174 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 296a570de6b33..e41228bd501a9 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2107,9 +2107,9 @@ pub enum TyKind { /// A tuple (`(A, B, C, D,...)`). Tup(ThinVec>), /// An anonymous struct type i.e. `struct { foo: Type }` - AnonStruct(ThinVec), + AnonStruct(NodeId, ThinVec), /// An anonymous union type i.e. `union { bar: Type }` - AnonUnion(ThinVec), + AnonUnion(NodeId, ThinVec), /// A path (`module::module::...::Type`), optionally /// "qualified", e.g., ` as SomeTrait>::SomeType`. /// diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 90677151d2506..d482ada170ee3 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -514,7 +514,8 @@ pub fn noop_visit_ty(ty: &mut P, vis: &mut T) { visit_vec(bounds, |bound| vis.visit_param_bound(bound)); } TyKind::MacCall(mac) => vis.visit_mac_call(mac), - TyKind::AnonStruct(fields) | TyKind::AnonUnion(fields) => { + TyKind::AnonStruct(id, fields) | TyKind::AnonUnion(id, fields) => { + vis.visit_id(id); fields.flat_map_in_place(|field| vis.flat_map_field_def(field)); } } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 8d084ee29a7db..4aaaa0ba42457 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -450,7 +450,7 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) { TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err => {} TyKind::MacCall(mac) => visitor.visit_mac_call(mac), TyKind::Never | TyKind::CVarArgs => {} - TyKind::AnonStruct(ref fields, ..) | TyKind::AnonUnion(ref fields, ..) => { + TyKind::AnonStruct(_, ref fields) | TyKind::AnonUnion(_, ref fields) => { walk_list!(visitor, visit_field_def, fields) } } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index fb52f9cf58f26..933372fae4eb4 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -720,7 +720,10 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - fn lower_field_def(&mut self, (index, f): (usize, &FieldDef)) -> hir::FieldDef<'hir> { + pub(super) fn lower_field_def( + &mut self, + (index, f): (usize, &FieldDef), + ) -> hir::FieldDef<'hir> { let ty = if let TyKind::Path(qself, path) = &f.ty.kind { let t = self.lower_path_ty( &f.ty, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 5f7439060b3c9..7a07124225699 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1288,17 +1288,49 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { TyKind::Err => { hir::TyKind::Err(self.dcx().span_delayed_bug(t.span, "TyKind::Err lowered")) } - // FIXME(unnamed_fields): IMPLEMENTATION IN PROGRESS - #[allow(rustc::untranslatable_diagnostic)] - #[allow(rustc::diagnostic_outside_of_impl)] - TyKind::AnonStruct(ref _fields) => { - hir::TyKind::Err(self.dcx().span_err(t.span, "anonymous structs are unimplemented")) - } - // FIXME(unnamed_fields): IMPLEMENTATION IN PROGRESS - #[allow(rustc::untranslatable_diagnostic)] - #[allow(rustc::diagnostic_outside_of_impl)] - TyKind::AnonUnion(ref _fields) => { - hir::TyKind::Err(self.dcx().span_err(t.span, "anonymous unions are unimplemented")) + // Lower the anonymous structs or unions in a nested lowering context. + // + // ``` + // struct Foo { + // _: union { + // // ^__________________ <-- within the nested lowering context, + // /* fields */ // | we lower all fields defined into an + // } // | owner node of struct or union item + // // ^_____________________| + // } + // ``` + TyKind::AnonStruct(def_node_id, fields) | TyKind::AnonUnion(def_node_id, fields) => { + let (def_kind, item_kind): (DefKind, fn(_, _) -> _) = match t.kind { + TyKind::AnonStruct(..) => (DefKind::Struct, hir::ItemKind::Struct), + TyKind::AnonUnion(..) => (DefKind::Union, hir::ItemKind::Union), + _ => unreachable!(), + }; + let def_id = self.create_def( + self.current_hir_id_owner.def_id, + *def_node_id, + kw::Empty, + def_kind, + t.span, + ); + debug!(?def_id); + let owner_id = hir::OwnerId { def_id }; + self.with_hir_id_owner(*def_node_id, |this| { + let fields = this.arena.alloc_from_iter( + fields.iter().enumerate().map(|f| this.lower_field_def(f)), + ); + let span = t.span; + let variant_data = hir::VariantData::Struct(fields, false); + // FIXME: capture the generics from the outer adt. + let generics = hir::Generics::empty(); + hir::OwnerNode::Item(this.arena.alloc(hir::Item { + ident: Ident::new(kw::Empty, span), + owner_id, + kind: item_kind(variant_data, generics), + span: this.lower_span(span), + vis_span: this.lower_span(span.shrink_to_lo()), + })) + }); + hir::TyKind::AnonAdt(hir::ItemId { owner_id }) } TyKind::Slice(ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)), TyKind::Ptr(mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)), diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 9ea5d1ed5fa27..86597d20c1959 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -219,7 +219,7 @@ impl<'a> AstValidator<'a> { } } } - TyKind::AnonStruct(ref fields, ..) | TyKind::AnonUnion(ref fields, ..) => { + TyKind::AnonStruct(_, ref fields) | TyKind::AnonUnion(_, ref fields) => { walk_list!(self, visit_field_def, fields) } _ => visit::walk_ty(self, t), diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 731232bce65cb..cda746894e865 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1003,11 +1003,11 @@ impl<'a> State<'a> { } self.pclose(); } - ast::TyKind::AnonStruct(fields) => { + ast::TyKind::AnonStruct(_, fields) => { self.head("struct"); self.print_record_struct_body(fields, ty.span); } - ast::TyKind::AnonUnion(fields) => { + ast::TyKind::AnonUnion(_, fields) => { self.head("union"); self.print_record_struct_body(fields, ty.span); } diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 81ec7ddb629e3..f08ab4bfc096c 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -8,6 +8,7 @@ use rustc_data_structures::unord::UnordMap; use rustc_macros::HashStable_Generic; use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::hygiene::MacroKind; +use rustc_span::symbol::kw; use rustc_span::Symbol; use std::array::IntoIter; @@ -225,6 +226,7 @@ impl DefKind { pub fn def_path_data(self, name: Symbol) -> DefPathData { match self { + DefKind::Struct | DefKind::Union if name == kw::Empty => DefPathData::AnonAdt, DefKind::Mod | DefKind::Struct | DefKind::Union diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index 9fb1fc19bf4e4..b81ad8b194623 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -287,6 +287,8 @@ pub enum DefPathData { /// An existential `impl Trait` type node. /// Argument position `impl Trait` have a `TypeNs` with their pretty-printed name. OpaqueTy, + /// An anonymous struct or union type i.e. `struct { foo: Type }` or `union { bar: Type }` + AnonAdt, } impl Definitions { @@ -409,8 +411,9 @@ impl DefPathData { match *self { TypeNs(name) if name == kw::Empty => None, TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name), + Impl | ForeignMod | CrateRoot | Use | GlobalAsm | Closure | Ctor | AnonConst - | OpaqueTy => None, + | OpaqueTy | AnonAdt => None, } } @@ -431,6 +434,7 @@ impl DefPathData { Ctor => DefPathDataName::Anon { namespace: sym::constructor }, AnonConst => DefPathDataName::Anon { namespace: sym::constant }, OpaqueTy => DefPathDataName::Anon { namespace: sym::opaque }, + AnonAdt => DefPathDataName::Anon { namespace: sym::anon_adt }, } } } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index a7a1c69b9bed6..00b2f9844832c 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2587,6 +2587,8 @@ pub enum TyKind<'hir> { Never, /// A tuple (`(A, B, C, D, ...)`). Tup(&'hir [Ty<'hir>]), + /// An anonymous struct or union type i.e. `struct { foo: Type }` or `union { foo: Type }` + AnonAdt(ItemId), /// A path to a type definition (`module::module::...::Type`), or an /// associated type (e.g., ` as Trait>::Type` or `::Target`). /// diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 52e1109ff9215..e9337dd3586ea 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -852,6 +852,9 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) { } TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression), TyKind::Infer | TyKind::InferDelegation(..) | TyKind::Err(_) => {} + TyKind::AnonAdt(item_id) => { + visitor.visit_nested_item(item_id); + } } } diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 1ae3ebaebbbb7..a643614d33db5 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -2457,6 +2457,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { hir::TyKind::Tup(fields) => { Ty::new_tup_from_iter(tcx, fields.iter().map(|t| self.ast_ty_to_ty(t))) } + hir::TyKind::AnonAdt(item_id) => { + let did = item_id.owner_id.def_id; + let adt_def = tcx.adt_def(did); + let generics = tcx.generics_of(did); + + debug!("ast_ty_to_ty_inner(AnonAdt): generics={:?}", generics); + let args = ty::GenericArgs::for_item(tcx, did.to_def_id(), |param, _| { + tcx.mk_param_from_def(param) + }); + debug!("ast_ty_to_ty_inner(AnonAdt): args={:?}", args); + + Ty::new_adt(tcx, adt_def, tcx.mk_args(args)) + } hir::TyKind::BareFn(bf) => { require_c_abi_if_c_variadic(tcx, bf.decl, bf.abi, ast_ty.span); diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index f458ff01c104c..768b07069c838 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -789,6 +789,65 @@ fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) { } } +/* +/// In a type definition, we check that unnamed field names are distinct. +fn check_unnamed_fields_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>) { + let mut seen_fields: FxHashMap> = Default::default(); + fn check_fields_anon_adt_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, seen_fields: &mut FxHashMap>) { + let fields = match &item.kind { + hir::ItemKind::Struct(fields, _) | hir::ItemKind::Union(fields, _) => fields, + _ => return, + }; + for field in fields.fields() { + if field.ident.name == kw::Underscore { + if let hir::TyKind::AnonAdt(item_id) = field.ty.kind() { + let item = tcx.hir().item(item_id); + check_fields_anon_adt_defn(tcx, item, &mut *seen_fields); + } else { + let field_ty = match tcx.type_of(field.def_id).instantiate_identity().ty_adt_def() { + Some(adt_ty) => adt_ty, + None => { + tcx.sess.emit_err(err); + return; + } + }; + if let Some(def_id) = field_ty.did().as_local() { + let item = tcx.hir().item(hir::ItemId { owner_id: hir::OwnerId { def_id }}); + check_fields_anon_adt_defn(tcx, item, &mut *seen_fields); + } + } + field_ty.flags() + let inner_adt_def = field_ty.ty_adt_def().expect("expect an adt"); + check_fields_anon_adt_defn(tcx, adt_def, &mut *seen_fields); + } else { + let span = field.did.as_local().map(|did| { + let hir_id = tcx.hir().local_def_id_to_hir_id(did); + tcx.hir().span(hir_id) + }); + match seen_fields.get(&ident.normalize_to_macros_2_0()).cloned() { + Some(Some(prev_span)) => { + tcx.sess.emit_err(errors::FieldAlreadyDeclared { + field_name: ident, + span: f.span, + prev_span, + }); + } + Some(None) => { + tcx.sess.emit_err(errors::FieldAlreadyDeclared { + field_name: f.ident, + span: f.span, + prev_span, + }); + } + None => + seen_fields.insert(f.ident.normalize_to_macros_2_0(), f.span); + } + } + } + } +} + */ + fn convert_variant( tcx: TyCtxt<'_>, variant_did: Option, @@ -798,11 +857,17 @@ fn convert_variant( adt_kind: ty::AdtKind, parent_did: LocalDefId, ) -> ty::VariantDef { + let mut has_unnamed_fields = false; let mut seen_fields: FxHashMap = Default::default(); let fields = def .fields() .iter() - .map(|f| { + .inspect(|f| { + // Skip the unnamed field here, we will check it later. + if f.ident.name == kw::Underscore { + has_unnamed_fields = true; + return; + } let dup_span = seen_fields.get(&f.ident.normalize_to_macros_2_0()).cloned(); if let Some(prev_span) = dup_span { tcx.dcx().emit_err(errors::FieldAlreadyDeclared { @@ -813,12 +878,11 @@ fn convert_variant( } else { seen_fields.insert(f.ident.normalize_to_macros_2_0(), f.span); } - - ty::FieldDef { - did: f.def_id.to_def_id(), - name: f.ident.name, - vis: tcx.visibility(f.def_id), - } + }) + .map(|f| ty::FieldDef { + did: f.def_id.to_def_id(), + name: f.ident.name, + vis: tcx.visibility(f.def_id), }) .collect(); let recovered = match def { @@ -837,6 +901,7 @@ fn convert_variant( adt_kind == AdtKind::Struct && tcx.has_attr(parent_did, sym::non_exhaustive) || variant_did .is_some_and(|variant_did| tcx.has_attr(variant_did, sym::non_exhaustive)), + has_unnamed_fields, ) } @@ -847,6 +912,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> { bug!("expected ADT to be an item"); }; + let is_anonymous = item.ident.name == kw::Empty; let repr = tcx.repr_options_of_def(def_id.to_def_id()); let (kind, variants) = match &item.kind { ItemKind::Enum(def, _) => { @@ -897,7 +963,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> { } _ => bug!("{:?} is not an ADT", item.owner_id.def_id), }; - tcx.mk_adt_def(def_id.to_def_id(), kind, variants, repr) + tcx.mk_adt_def(def_id.to_def_id(), kind, variants, repr, is_anonymous) } fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef { diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index b90fa03a3dc01..8f8f747339b42 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -328,6 +328,7 @@ impl<'a> State<'a> { hir::TyKind::Infer | hir::TyKind::InferDelegation(..) => { self.word("_"); } + hir::TyKind::AnonAdt(..) => self.word("/* anonymous adt */"), } self.end() } @@ -728,26 +729,30 @@ impl<'a> State<'a> { } hir::VariantData::Struct { .. } => { self.print_where_clause(generics); - self.nbsp(); - self.bopen(); - self.hardbreak_if_not_bol(); - - for field in struct_def.fields() { - self.hardbreak_if_not_bol(); - self.maybe_print_comment(field.span.lo()); - self.print_outer_attributes(self.attrs(field.hir_id)); - self.print_ident(field.ident); - self.word_nbsp(":"); - self.print_type(field.ty); - self.word(","); - } - - self.bclose(span) + self.print_variant_struct(span, struct_def.fields()) } } } - fn print_variant(&mut self, v: &hir::Variant<'_>) { + fn print_variant_struct(&mut self, span: rustc_span::Span, fields: &[hir::FieldDef<'_>]) { + self.nbsp(); + self.bopen(); + self.hardbreak_if_not_bol(); + + for field in fields { + self.hardbreak_if_not_bol(); + self.maybe_print_comment(field.span.lo()); + self.print_outer_attributes(self.attrs(field.hir_id)); + self.print_ident(field.ident); + self.word_nbsp(":"); + self.print_type(field.ty); + self.word(","); + } + + self.bclose(span) + } + + pub fn print_variant(&mut self, v: &hir::Variant<'_>) { self.head(""); let generics = hir::Generics::empty(); self.print_struct(&v.data, generics, v.ident.name, v.span, false); diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 11cb1bb6d9e6e..72e9744295bc9 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1084,6 +1084,8 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { parent_did, false, data.is_non_exhaustive, + // FIXME: unnamed fields in crate metadata is unimplemented yet. + false, ), ) } @@ -1126,6 +1128,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { adt_kind, variants.into_iter().map(|(_, variant)| variant).collect(), repr, + false, ) } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 50817dd0a8093..8e1cb6a514f8a 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -756,6 +756,13 @@ impl<'hir> Map<'hir> { } } + pub fn expect_field(self, id: HirId) -> &'hir FieldDef<'hir> { + match self.tcx.hir_node(id) { + Node::Field(field) => field, + _ => bug!("expected field, found {}", self.node_to_string(id)), + } + } + pub fn expect_foreign_item(self, id: OwnerId) -> &'hir ForeignItem<'hir> { match self.tcx.hir_owner_node(id) { OwnerNode::ForeignItem(item) => item, diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 685c3e87dac1f..854046c9cebe8 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -50,6 +50,8 @@ bitflags! { const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 8; /// Indicates whether the type is `UnsafeCell`. const IS_UNSAFE_CELL = 1 << 9; + /// Indicates whether the type is anonymous. + const IS_ANONYMOUS = 1 << 10; } } rustc_data_structures::external_bitflags_debug! { AdtFlags } @@ -233,8 +235,12 @@ impl AdtDefData { kind: AdtKind, variants: IndexVec, repr: ReprOptions, + is_anonymous: bool, ) -> Self { - debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr); + debug!( + "AdtDef::new({:?}, {:?}, {:?}, {:?}, {:?})", + did, kind, variants, repr, is_anonymous + ); let mut flags = AdtFlags::NO_ADT_FLAGS; if kind == AdtKind::Enum && tcx.has_attr(did, sym::non_exhaustive) { @@ -267,6 +273,9 @@ impl AdtDefData { if Some(did) == tcx.lang_items().unsafe_cell_type() { flags |= AdtFlags::IS_UNSAFE_CELL; } + if is_anonymous { + flags |= AdtFlags::IS_ANONYMOUS; + } AdtDefData { did, variants, flags, repr } } @@ -365,6 +374,12 @@ impl<'tcx> AdtDef<'tcx> { self.flags().contains(AdtFlags::IS_MANUALLY_DROP) } + /// Returns `true` if this is an anonymous adt + #[inline] + pub fn is_anonymous(self) -> bool { + self.flags().contains(AdtFlags::IS_ANONYMOUS) + } + /// Returns `true` if this type has a destructor. pub fn has_dtor(self, tcx: TyCtxt<'tcx>) -> bool { self.destructor(tcx).is_some() diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index b747f0a4fb646..9a0eea6592fb1 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -715,8 +715,16 @@ impl<'tcx> TyCtxt<'tcx> { kind: AdtKind, variants: IndexVec, repr: ReprOptions, + is_anonymous: bool, ) -> ty::AdtDef<'tcx> { - self.mk_adt_def_from_data(ty::AdtDefData::new(self, did, kind, variants, repr)) + self.mk_adt_def_from_data(ty::AdtDefData::new( + self, + did, + kind, + variants, + repr, + is_anonymous, + )) } /// Allocates a read-only byte or string literal for `mir::interpret`. diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index c9137f374a238..3cbe8f287e1f3 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1130,6 +1130,8 @@ bitflags! { /// Indicates whether this variant was obtained as part of recovering from /// a syntactic error. May be incomplete or bogus. const IS_RECOVERED = 1 << 1; + /// Indicates whether this variant has unnamed fields. + const HAS_UNNAMED_FIELDS = 1 << 2; } } rustc_data_structures::external_bitflags_debug! { VariantFlags } @@ -1143,7 +1145,7 @@ pub struct VariantDef { /// `DefId` that identifies the variant's constructor. /// If this variant is a struct variant, then this is `None`. pub ctor: Option<(CtorKind, DefId)>, - /// Variant or struct name. + /// Variant or struct name, maybe empty for anonymous adt (struct or union). pub name: Symbol, /// Discriminant of this variant. pub discr: VariantDiscr, @@ -1180,11 +1182,12 @@ impl VariantDef { parent_did: DefId, recovered: bool, is_field_list_non_exhaustive: bool, + has_unnamed_fields: bool, ) -> Self { debug!( "VariantDef::new(name = {:?}, variant_did = {:?}, ctor = {:?}, discr = {:?}, - fields = {:?}, adt_kind = {:?}, parent_did = {:?})", - name, variant_did, ctor, discr, fields, adt_kind, parent_did, + fields = {:?}, adt_kind = {:?}, parent_did = {:?}, has_unnamed_fields = {:?})", + name, variant_did, ctor, discr, fields, adt_kind, parent_did, has_unnamed_fields, ); let mut flags = VariantFlags::NO_VARIANT_FLAGS; @@ -1196,6 +1199,10 @@ impl VariantDef { flags |= VariantFlags::IS_RECOVERED; } + if has_unnamed_fields { + flags |= VariantFlags::HAS_UNNAMED_FIELDS; + } + VariantDef { def_id: variant_did.unwrap_or(parent_did), ctor, name, discr, fields, flags } } @@ -1211,6 +1218,12 @@ impl VariantDef { self.flags.intersects(VariantFlags::IS_RECOVERED) } + /// Does this variant contains unnamed fields + #[inline] + pub fn has_unnamed_fields(&self) -> bool { + self.flags.intersects(VariantFlags::HAS_UNNAMED_FIELDS) + } + /// Computes the `Ident` of this variant by looking up the `Span` pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident { Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap()) diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 5fe54a536a7f1..157fb9e505af7 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -396,8 +396,9 @@ impl<'a> Parser<'a> { self.parse_record_struct_body(if is_union { "union" } else { "struct" }, lo, false)?; let span = lo.to(self.prev_token.span); self.sess.gated_spans.gate(sym::unnamed_fields, span); - // These can be rejected during AST validation in `deny_anon_struct_or_union`. - let kind = if is_union { TyKind::AnonUnion(fields) } else { TyKind::AnonStruct(fields) }; + let id = ast::DUMMY_NODE_ID; + let kind = + if is_union { TyKind::AnonUnion(id, fields) } else { TyKind::AnonStruct(id, fields) }; Ok(self.mk_ty(span, kind)) } diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index e94d8c4c932f9..d02e86dd45697 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -345,6 +345,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { BareFn, Never, Tup, + AnonAdt, Path, OpaqueDef, TraitObject, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index aa912c93c08c6..c2d02665ef52b 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -382,6 +382,7 @@ symbols! { and, and_then, anon, + anon_adt, anonymous_lifetime_in_impl_trait, any, append_const_msg, diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs index 9d1b92e106803..011d52bc65bed 100644 --- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs +++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs @@ -387,7 +387,8 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String { | hir::definitions::DefPathData::Use | hir::definitions::DefPathData::GlobalAsm | hir::definitions::DefPathData::MacroNs(..) - | hir::definitions::DefPathData::LifetimeNs(..) => { + | hir::definitions::DefPathData::LifetimeNs(..) + | hir::definitions::DefPathData::AnonAdt => { bug!("encode_ty_name: unexpected `{:?}`", disambiguated_data.data); } }); diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 530221555c52e..ce065efb4c625 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -748,7 +748,8 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { | DefPathData::GlobalAsm | DefPathData::Impl | DefPathData::MacroNs(_) - | DefPathData::LifetimeNs(_) => { + | DefPathData::LifetimeNs(_) + | DefPathData::AnonAdt => { bug!("symbol_names: unexpected DefPathData: {:?}", disambiguated_data.data) } }; diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index 819b070cf8b86..b320ded40a772 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -181,6 +181,11 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( | ty::Ref(_, _, Mutability::Not) | ty::Array(..) => Err(NoSolution), + // Check for anonymous adts. + ty::Adt(adt, generics) if adt.is_anonymous() => { + Ok(adt.all_fields().map(|f| f.ty(ecx.tcx(), generics)).collect()) + } + ty::Dynamic(..) | ty::Str | ty::Slice(_) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index ac6cfcdeb5950..c2f7d5160f68f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2212,6 +2212,16 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // FIXME(async_closures): These are never clone, for now. ty::CoroutineClosure(_, _) => None, + // `Copy` and `Clone` are automatically impelemented for an anonymous adt + // if all of its fields are `Copy` and `Clone` + ty::Adt(adt, args) if adt.is_anonymous() => { + // (*) binder moved here + Where( + obligation + .predicate + .rebind(adt.all_fields().map(|f| f.ty(self.tcx(), args)).collect()), + ) + } ty::Adt(..) | ty::Alias(..) | ty::Param(..) | ty::Placeholder(..) => { // Fallback to whatever user-defined impls exist in this case. diff --git a/compiler/rustc_ty_utils/src/representability.rs b/compiler/rustc_ty_utils/src/representability.rs index 70f1f099688b8..ade509123ac12 100644 --- a/compiler/rustc_ty_utils/src/representability.rs +++ b/compiler/rustc_ty_utils/src/representability.rs @@ -21,8 +21,7 @@ macro_rules! rtry { fn representability(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Representability { match tcx.def_kind(def_id) { DefKind::Struct | DefKind::Union | DefKind::Enum => { - let adt_def = tcx.adt_def(def_id); - for variant in adt_def.variants() { + for variant in tcx.adt_def(def_id).variants() { for field in variant.fields.iter() { rtry!(tcx.representability(field.did.expect_local())); } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 89977934cde9f..b697f945f2003 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1892,6 +1892,16 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T TyKind::BareFn(barefn) => BareFunction(Box::new(clean_bare_fn_ty(barefn, cx))), // Rustdoc handles `TyKind::Err`s by turning them into `Type::Infer`s. TyKind::Infer | TyKind::Err(_) | TyKind::Typeof(..) | TyKind::InferDelegation(..) => Infer, + TyKind::AnonAdt(item_id) => { + let path = external_path( + cx, + item_id.owner_id.def_id.to_def_id(), + false, + ThinVec::new(), + ty::Binder::dummy(ty::GenericArgs::empty()), + ); + Type::Path { path } + } } } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 6710193f9611a..324ce03dcfd70 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1511,6 +1511,10 @@ pub(crate) enum Type { /// An `impl Trait`: `impl TraitA + TraitB + ...` ImplTrait(Vec), + // /// An anonymous struct type i.e. `struct { foo: Type }` + // AnonStruct(VariantStruct), + // /// An anonymous union type i.e. `union { bar: Type }` + // AnonUnion(VariantStruct), } impl Type { diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index cdbb52f497b36..0ddfeaa0ae059 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -831,6 +831,7 @@ impl TyCoercionStability { | TyKind::Typeof(..) | TyKind::TraitObject(..) | TyKind::InferDelegation(..) + | TyKind::AnonAdt(..) | TyKind::Err(_) => Self::Reborrow, }; } diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 4fa93ad23c369..d50332e82da5b 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -515,6 +515,7 @@ impl HirEqInterExpr<'_, '_, '_> { (TyKind::Path(l), TyKind::Path(r)) => self.eq_qpath(l, r), (&TyKind::Tup(l), &TyKind::Tup(r)) => over(l, r, |l, r| self.eq_ty(l, r)), (&TyKind::Infer, &TyKind::Infer) => true, + (TyKind::AnonAdt(l_item_id), TyKind::AnonAdt(r_item_id)) => l_item_id == r_item_id, _ => false, } } @@ -1108,7 +1109,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { TyKind::Typeof(anon_const) => { self.hash_body(anon_const.body); }, - TyKind::Err(_) | TyKind::Infer | TyKind::Never | TyKind::InferDelegation(..) => {}, + TyKind::Err(_) | TyKind::Infer | TyKind::Never | TyKind::InferDelegation(..) | TyKind::AnonAdt(_) => {}, } } diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index cd2582e66be8f..aaef80f4aef94 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -806,8 +806,8 @@ impl Rewrite for ast::Ty { ast::TyKind::Tup(ref items) => { rewrite_tuple(context, items.iter(), self.span, shape, items.len() == 1) } - ast::TyKind::AnonStruct(_) => Some(context.snippet(self.span).to_owned()), - ast::TyKind::AnonUnion(_) => Some(context.snippet(self.span).to_owned()), + ast::TyKind::AnonStruct(..) => Some(context.snippet(self.span).to_owned()), + ast::TyKind::AnonUnion(..) => Some(context.snippet(self.span).to_owned()), ast::TyKind::Path(ref q_self, ref path) => { rewrite_path(context, PathContext::Type, q_self, path, shape) } diff --git a/tests/ui/feature-gates/feature-gate-unnamed_fields.rs b/tests/ui/feature-gates/feature-gate-unnamed_fields.rs index 4bbd0c83bfbca..6ee8de8956428 100644 --- a/tests/ui/feature-gates/feature-gate-unnamed_fields.rs +++ b/tests/ui/feature-gates/feature-gate-unnamed_fields.rs @@ -2,7 +2,6 @@ struct Foo { foo: u8, _: union { //~ ERROR unnamed fields are not yet fully implemented [E0658] //~^ ERROR unnamed fields are not yet fully implemented [E0658] - //~| ERROR anonymous unions are unimplemented bar: u8, baz: u16 } @@ -12,7 +11,6 @@ union Bar { foobar: u8, _: struct { //~ ERROR unnamed fields are not yet fully implemented [E0658] //~^ ERROR unnamed fields are not yet fully implemented [E0658] - //~| ERROR anonymous structs are unimplemented foobaz: u8, barbaz: u16 } diff --git a/tests/ui/feature-gates/feature-gate-unnamed_fields.stderr b/tests/ui/feature-gates/feature-gate-unnamed_fields.stderr index 82f08912bc843..8fa342c08ae29 100644 --- a/tests/ui/feature-gates/feature-gate-unnamed_fields.stderr +++ b/tests/ui/feature-gates/feature-gate-unnamed_fields.stderr @@ -14,7 +14,6 @@ error[E0658]: unnamed fields are not yet fully implemented LL | _: union { | ________^ LL | | -LL | | LL | | bar: u8, LL | | baz: u16 LL | | } @@ -25,7 +24,7 @@ LL | | } = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: unnamed fields are not yet fully implemented - --> $DIR/feature-gate-unnamed_fields.rs:13:5 + --> $DIR/feature-gate-unnamed_fields.rs:12:5 | LL | _: struct { | ^ @@ -35,12 +34,11 @@ LL | _: struct { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: unnamed fields are not yet fully implemented - --> $DIR/feature-gate-unnamed_fields.rs:13:8 + --> $DIR/feature-gate-unnamed_fields.rs:12:8 | LL | _: struct { | ________^ LL | | -LL | | LL | | foobaz: u8, LL | | barbaz: u16 LL | | } @@ -51,7 +49,7 @@ LL | | } = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: unnamed fields are not yet fully implemented - --> $DIR/feature-gate-unnamed_fields.rs:23:5 + --> $DIR/feature-gate-unnamed_fields.rs:21:5 | LL | _: S | ^ @@ -60,30 +58,6 @@ LL | _: S = help: add `#![feature(unnamed_fields)]` 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: anonymous unions are unimplemented - --> $DIR/feature-gate-unnamed_fields.rs:3:8 - | -LL | _: union { - | ________^ -LL | | -LL | | -LL | | bar: u8, -LL | | baz: u16 -LL | | } - | |_____^ - -error: anonymous structs are unimplemented - --> $DIR/feature-gate-unnamed_fields.rs:13:8 - | -LL | _: struct { - | ________^ -LL | | -LL | | -LL | | foobaz: u8, -LL | | barbaz: u16 -LL | | } - | |_____^ - -error: aborting due to 7 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/union/unnamed-fields/restrict_anonymous_structs.rs b/tests/ui/union/unnamed-fields/restrict_anonymous_structs.rs index 192bbba5a5b3a..76525ec0bb121 100644 --- a/tests/ui/union/unnamed-fields/restrict_anonymous_structs.rs +++ b/tests/ui/union/unnamed-fields/restrict_anonymous_structs.rs @@ -3,9 +3,7 @@ struct F { field: struct { field: u8 }, //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields - //~^ ERROR anonymous structs are unimplemented _: struct { field: u8 }, - //~^ ERROR anonymous structs are unimplemented } struct G { @@ -14,9 +12,7 @@ struct G { union H { field: struct { field: u8 }, //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields - //~^ ERROR anonymous structs are unimplemented _: struct { field: u8 }, - //~^ ERROR anonymous structs are unimplemented } union I { @@ -27,7 +23,6 @@ enum K { M { _ : struct { field: u8 }, //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields //~^ ERROR unnamed fields are not allowed outside of structs or unions - //~| ERROR anonymous structs are unimplemented }, N { _ : u8, //~ ERROR unnamed fields are not allowed outside of structs or unions diff --git a/tests/ui/union/unnamed-fields/restrict_anonymous_structs.stderr b/tests/ui/union/unnamed-fields/restrict_anonymous_structs.stderr index fd731766c01ff..846e3451a7175 100644 --- a/tests/ui/union/unnamed-fields/restrict_anonymous_structs.stderr +++ b/tests/ui/union/unnamed-fields/restrict_anonymous_structs.stderr @@ -5,25 +5,25 @@ LL | field: struct { field: u8 }, | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here error: unnamed fields can only have struct or union types - --> $DIR/restrict_anonymous_structs.rs:12:5 + --> $DIR/restrict_anonymous_structs.rs:10:5 | LL | _: (u8, u8), | ^ -------- not a struct or union error: anonymous structs are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_structs.rs:16:12 + --> $DIR/restrict_anonymous_structs.rs:14:12 | LL | field: struct { field: u8 }, | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here error: unnamed fields can only have struct or union types - --> $DIR/restrict_anonymous_structs.rs:23:5 + --> $DIR/restrict_anonymous_structs.rs:19:5 | LL | _: (u8, u8), | ^ -------- not a struct or union error: unnamed fields are not allowed outside of structs or unions - --> $DIR/restrict_anonymous_structs.rs:28:9 + --> $DIR/restrict_anonymous_structs.rs:24:9 | LL | _ : struct { field: u8 }, | -^^^^^^^^^^^^^^^^^^^^^^^ @@ -31,48 +31,18 @@ LL | _ : struct { field: u8 }, | unnamed field declared here error: anonymous structs are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_structs.rs:28:13 + --> $DIR/restrict_anonymous_structs.rs:24:13 | LL | _ : struct { field: u8 }, | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here error: unnamed fields are not allowed outside of structs or unions - --> $DIR/restrict_anonymous_structs.rs:33:9 + --> $DIR/restrict_anonymous_structs.rs:28:9 | LL | _ : u8, | -^^^^^ | | | unnamed field declared here -error: anonymous structs are unimplemented - --> $DIR/restrict_anonymous_structs.rs:5:12 - | -LL | field: struct { field: u8 }, - | ^^^^^^^^^^^^^^^^^^^^ - -error: anonymous structs are unimplemented - --> $DIR/restrict_anonymous_structs.rs:7:8 - | -LL | _: struct { field: u8 }, - | ^^^^^^^^^^^^^^^^^^^^ - -error: anonymous structs are unimplemented - --> $DIR/restrict_anonymous_structs.rs:16:12 - | -LL | field: struct { field: u8 }, - | ^^^^^^^^^^^^^^^^^^^^ - -error: anonymous structs are unimplemented - --> $DIR/restrict_anonymous_structs.rs:18:8 - | -LL | _: struct { field: u8 }, - | ^^^^^^^^^^^^^^^^^^^^ - -error: anonymous structs are unimplemented - --> $DIR/restrict_anonymous_structs.rs:28:13 - | -LL | _ : struct { field: u8 }, - | ^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 12 previous errors +error: aborting due to 7 previous errors diff --git a/tests/ui/union/unnamed-fields/restrict_anonymous_unions.rs b/tests/ui/union/unnamed-fields/restrict_anonymous_unions.rs index c69266089bba5..c049ba92ed2ad 100644 --- a/tests/ui/union/unnamed-fields/restrict_anonymous_unions.rs +++ b/tests/ui/union/unnamed-fields/restrict_anonymous_unions.rs @@ -3,9 +3,7 @@ struct F { field: union { field: u8 }, //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields - //~^ ERROR anonymous unions are unimplemented _: union { field: u8 }, - //~^ ERROR anonymous unions are unimplemented } struct G { @@ -14,9 +12,7 @@ struct G { union H { field: union { field: u8 }, //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields - //~^ ERROR anonymous unions are unimplemented _: union { field: u8 }, - //~^ ERROR anonymous unions are unimplemented } union I { @@ -27,7 +23,6 @@ enum K { M { _ : union { field: u8 }, //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields //~^ ERROR unnamed fields are not allowed outside of structs or unions - //~| ERROR anonymous unions are unimplemented }, N { _ : u8, //~ ERROR unnamed fields are not allowed outside of structs or unions diff --git a/tests/ui/union/unnamed-fields/restrict_anonymous_unions.stderr b/tests/ui/union/unnamed-fields/restrict_anonymous_unions.stderr index c65cad775a90c..c916e37a3e911 100644 --- a/tests/ui/union/unnamed-fields/restrict_anonymous_unions.stderr +++ b/tests/ui/union/unnamed-fields/restrict_anonymous_unions.stderr @@ -5,25 +5,25 @@ LL | field: union { field: u8 }, | ^^^^^^^^^^^^^^^^^^^ anonymous union declared here error: unnamed fields can only have struct or union types - --> $DIR/restrict_anonymous_unions.rs:12:5 + --> $DIR/restrict_anonymous_unions.rs:10:5 | LL | _: (u8, u8), | ^ -------- not a struct or union error: anonymous unions are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_unions.rs:16:12 + --> $DIR/restrict_anonymous_unions.rs:14:12 | LL | field: union { field: u8 }, | ^^^^^^^^^^^^^^^^^^^ anonymous union declared here error: unnamed fields can only have struct or union types - --> $DIR/restrict_anonymous_unions.rs:23:5 + --> $DIR/restrict_anonymous_unions.rs:19:5 | LL | _: (u8, u8), | ^ -------- not a struct or union error: unnamed fields are not allowed outside of structs or unions - --> $DIR/restrict_anonymous_unions.rs:28:9 + --> $DIR/restrict_anonymous_unions.rs:24:9 | LL | _ : union { field: u8 }, | -^^^^^^^^^^^^^^^^^^^^^^ @@ -31,48 +31,18 @@ LL | _ : union { field: u8 }, | unnamed field declared here error: anonymous unions are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_unions.rs:28:13 + --> $DIR/restrict_anonymous_unions.rs:24:13 | LL | _ : union { field: u8 }, | ^^^^^^^^^^^^^^^^^^^ anonymous union declared here error: unnamed fields are not allowed outside of structs or unions - --> $DIR/restrict_anonymous_unions.rs:33:9 + --> $DIR/restrict_anonymous_unions.rs:28:9 | LL | _ : u8, | -^^^^^ | | | unnamed field declared here -error: anonymous unions are unimplemented - --> $DIR/restrict_anonymous_unions.rs:5:12 - | -LL | field: union { field: u8 }, - | ^^^^^^^^^^^^^^^^^^^ - -error: anonymous unions are unimplemented - --> $DIR/restrict_anonymous_unions.rs:7:8 - | -LL | _: union { field: u8 }, - | ^^^^^^^^^^^^^^^^^^^ - -error: anonymous unions are unimplemented - --> $DIR/restrict_anonymous_unions.rs:16:12 - | -LL | field: union { field: u8 }, - | ^^^^^^^^^^^^^^^^^^^ - -error: anonymous unions are unimplemented - --> $DIR/restrict_anonymous_unions.rs:18:8 - | -LL | _: union { field: u8 }, - | ^^^^^^^^^^^^^^^^^^^ - -error: anonymous unions are unimplemented - --> $DIR/restrict_anonymous_unions.rs:28:13 - | -LL | _ : union { field: u8 }, - | ^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 12 previous errors +error: aborting due to 7 previous errors From 36d7e7fd3fee2a2e3e19f103d9595329093ab68e Mon Sep 17 00:00:00 2001 From: Frank King Date: Thu, 4 Jan 2024 21:56:45 +0800 Subject: [PATCH 2/8] check uniqueness of nested fields --- .../rustc_ast_passes/src/ast_validation.rs | 2 +- compiler/rustc_hir_analysis/messages.ftl | 19 + compiler/rustc_hir_analysis/src/collect.rs | 202 ++- compiler/rustc_hir_analysis/src/errors.rs | 53 +- compiler/rustc_middle/src/ty/adt.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 5 + .../unnamed-fields/field_uniqueness_check.rs | 328 +++++ .../field_uniqueness_check.stderr | 1284 +++++++++++++++++ .../restrict_anonymous_structs.rs | 8 +- .../restrict_anonymous_structs.stderr | 12 +- .../restrict_anonymous_unions.rs | 8 +- .../restrict_anonymous_unions.stderr | 12 +- 12 files changed, 1840 insertions(+), 95 deletions(-) create mode 100644 tests/ui/union/unnamed-fields/field_uniqueness_check.rs create mode 100644 tests/ui/union/unnamed-fields/field_uniqueness_check.stderr diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 86597d20c1959..d24dc44d2c52f 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -220,7 +220,7 @@ impl<'a> AstValidator<'a> { } } TyKind::AnonStruct(_, ref fields) | TyKind::AnonUnion(_, ref fields) => { - walk_list!(self, visit_field_def, fields) + walk_list!(self, visit_struct_field_def, fields) } _ => visit::walk_ty(self, t), } diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index d6f604c180bf6..662d859e99344 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -123,6 +123,25 @@ hir_analysis_field_already_declared = .label = field already declared .previous_decl_label = `{$field_name}` first declared here +hir_analysis_field_already_declared_both_nested = + field `{$field_name}` is already declared + .label = field `{$field_name}` declared in this unnamed field + .nested_field_decl_note = field `{$field_name}` declared here + .previous_decl_label = `{$field_name}` first declared here in this unnamed field + .previous_nested_field_decl_note = field `{$field_name}` first declared here + +hir_analysis_field_already_declared_current_nested = + field `{$field_name}` is already declared + .label = field `{$field_name}` declared in this unnamed field + .nested_field_decl_note = field `{$field_name}` declared here + .previous_decl_label = `{$field_name}` first declared here + +hir_analysis_field_already_declared_previous_nested = + field `{$field_name}` is already declared + .label = field already declared + .previous_decl_label = `{$field_name}` first declared here in this unnamed field + .previous_nested_field_decl_note = field `{$field_name}` first declared here + hir_analysis_function_not_found_in_trait = function not found in this trait hir_analysis_function_not_have_default_implementation = function doesn't have a default implementation diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 768b07069c838..12e7b5dbfce46 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -789,64 +789,100 @@ fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) { } } -/* -/// In a type definition, we check that unnamed field names are distinct. -fn check_unnamed_fields_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>) { - let mut seen_fields: FxHashMap> = Default::default(); - fn check_fields_anon_adt_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, seen_fields: &mut FxHashMap>) { - let fields = match &item.kind { - hir::ItemKind::Struct(fields, _) | hir::ItemKind::Union(fields, _) => fields, - _ => return, - }; - for field in fields.fields() { - if field.ident.name == kw::Underscore { - if let hir::TyKind::AnonAdt(item_id) = field.ty.kind() { - let item = tcx.hir().item(item_id); - check_fields_anon_adt_defn(tcx, item, &mut *seen_fields); - } else { - let field_ty = match tcx.type_of(field.def_id).instantiate_identity().ty_adt_def() { - Some(adt_ty) => adt_ty, - None => { - tcx.sess.emit_err(err); - return; - } - }; - if let Some(def_id) = field_ty.did().as_local() { - let item = tcx.hir().item(hir::ItemId { owner_id: hir::OwnerId { def_id }}); - check_fields_anon_adt_defn(tcx, item, &mut *seen_fields); - } +#[derive(Clone, Copy)] +struct NestedSpan { + span: Span, + nested_field_span: Span, +} + +#[derive(Clone, Copy)] +enum FieldDeclSpan { + NotNested(Span), + Nested(NestedSpan), +} + +impl From for FieldDeclSpan { + fn from(span: Span) -> Self { + Self::NotNested(span) + } +} + +impl From for FieldDeclSpan { + fn from(span: NestedSpan) -> Self { + Self::Nested(span) + } +} + +/// Check the uniqueness of fields across adt where there are +/// nested fields imported from an unnamed field. +fn check_field_uniqueness_in_nested_adt( + tcx: TyCtxt<'_>, + adt_def: ty::AdtDef<'_>, + check: &mut impl FnMut(Ident, /* nested_field_span */ Span), +) { + for field in adt_def.all_fields() { + if field.is_unnamed() { + // Here we don't care about the generic parameters, so `instantiate_identity` is enough. + match tcx.type_of(field.did).instantiate_identity().kind() { + ty::Adt(adt_def, _) => { + check_field_uniqueness_in_nested_adt(tcx, *adt_def, &mut *check); } - field_ty.flags() - let inner_adt_def = field_ty.ty_adt_def().expect("expect an adt"); - check_fields_anon_adt_defn(tcx, adt_def, &mut *seen_fields); - } else { - let span = field.did.as_local().map(|did| { - let hir_id = tcx.hir().local_def_id_to_hir_id(did); - tcx.hir().span(hir_id) - }); - match seen_fields.get(&ident.normalize_to_macros_2_0()).cloned() { - Some(Some(prev_span)) => { - tcx.sess.emit_err(errors::FieldAlreadyDeclared { - field_name: ident, - span: f.span, - prev_span, - }); - } - Some(None) => { - tcx.sess.emit_err(errors::FieldAlreadyDeclared { - field_name: f.ident, - span: f.span, - prev_span, - }); + ty_kind => bug!( + "Unexpected ty kind in check_field_uniqueness_in_nested_adt(): {ty_kind:?}" + ), + } + } else { + check(field.ident(tcx), tcx.def_span(field.did)); + } + } +} + +/// Check the uniqueness of fields in a struct variant, and recursively +/// check the nested fields if it is an unnamed field with type of an +/// annoymous adt. +fn check_field_uniqueness( + tcx: TyCtxt<'_>, + field: &hir::FieldDef<'_>, + check: &mut impl FnMut(Ident, FieldDeclSpan), +) { + if field.ident.name == kw::Underscore { + let ty_span = field.ty.span; + match &field.ty.kind { + hir::TyKind::AnonAdt(item_id) => { + match &tcx.hir_node(item_id.hir_id()).expect_item().kind { + hir::ItemKind::Struct(variant_data, ..) + | hir::ItemKind::Union(variant_data, ..) => { + variant_data + .fields() + .iter() + .for_each(|f| check_field_uniqueness(tcx, f, &mut *check)); } - None => - seen_fields.insert(f.ident.normalize_to_macros_2_0(), f.span); + item_kind => span_bug!( + ty_span, + "Unexpected item kind in check_field_uniqueness(): {item_kind:?}" + ), } } + hir::TyKind::Path(hir::QPath::Resolved(_, hir::Path { res, .. })) => { + check_field_uniqueness_in_nested_adt( + tcx, + tcx.adt_def(res.def_id()), + &mut |ident, nested_field_span| { + check(ident, NestedSpan { span: field.span, nested_field_span }.into()) + }, + ); + } + // Abort due to errors (there must be an error if an unnamed field + // has any type kind other than an anonymous adt or a named adt) + _ => { + debug_assert!(tcx.sess.has_errors().is_some()); + tcx.sess.abort_if_errors() + } } + return; } + check(field.ident, field.span.into()); } - */ fn convert_variant( tcx: TyCtxt<'_>, @@ -856,27 +892,61 @@ fn convert_variant( def: &hir::VariantData<'_>, adt_kind: ty::AdtKind, parent_did: LocalDefId, + is_anonymous: bool, ) -> ty::VariantDef { let mut has_unnamed_fields = false; - let mut seen_fields: FxHashMap = Default::default(); + let mut seen_fields: FxHashMap = Default::default(); let fields = def .fields() .iter() .inspect(|f| { - // Skip the unnamed field here, we will check it later. - if f.ident.name == kw::Underscore { - has_unnamed_fields = true; - return; - } - let dup_span = seen_fields.get(&f.ident.normalize_to_macros_2_0()).cloned(); - if let Some(prev_span) = dup_span { - tcx.dcx().emit_err(errors::FieldAlreadyDeclared { - field_name: f.ident, - span: f.span, - prev_span, + has_unnamed_fields |= f.ident.name == kw::Underscore; + if !is_anonymous { + check_field_uniqueness(tcx, f, &mut |ident, field_decl| { + use FieldDeclSpan::*; + let field_name = ident.name; + let ident = ident.normalize_to_macros_2_0(); + match (field_decl, seen_fields.get(&ident).copied()) { + (NotNested(span), Some(NotNested(prev_span))) => { + tcx.sess.emit_err(errors::FieldAlreadyDeclared::NotNested { + field_name, + span, + prev_span, + }); + } + (NotNested(span), Some(Nested(prev))) => { + tcx.sess.emit_err(errors::FieldAlreadyDeclared::PreviousNested { + field_name, + span, + prev_span: prev.span, + prev_nested_field_span: prev.nested_field_span, + }); + } + ( + Nested(NestedSpan { span, nested_field_span }), + Some(NotNested(prev_span)), + ) => { + tcx.sess.emit_err(errors::FieldAlreadyDeclared::CurrentNested { + field_name, + span, + nested_field_span, + prev_span, + }); + } + (Nested(NestedSpan { span, nested_field_span }), Some(Nested(prev))) => { + tcx.sess.emit_err(errors::FieldAlreadyDeclared::BothNested { + field_name, + span, + nested_field_span, + prev_span: prev.span, + prev_nested_field_span: prev.nested_field_span, + }); + } + (field_decl, None) => { + seen_fields.insert(ident, field_decl); + } + } }); - } else { - seen_fields.insert(f.ident.normalize_to_macros_2_0(), f.span); } }) .map(|f| ty::FieldDef { @@ -937,6 +1007,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> { &v.data, AdtKind::Enum, def_id, + is_anonymous, ) }) .collect(); @@ -956,6 +1027,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> { def, adt_kind, def_id, + is_anonymous, )) .collect(); diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index bec53693d6c94..1e172f1d9f017 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -175,14 +175,51 @@ pub struct DropImplOnWrongItem { } #[derive(Diagnostic)] -#[diag(hir_analysis_field_already_declared, code = E0124)] -pub struct FieldAlreadyDeclared { - pub field_name: Ident, - #[primary_span] - #[label] - pub span: Span, - #[label(hir_analysis_previous_decl_label)] - pub prev_span: Span, +pub enum FieldAlreadyDeclared { + #[diag(hir_analysis_field_already_declared, code = E0124)] + NotNested { + field_name: Symbol, + #[primary_span] + #[label] + span: Span, + #[label(hir_analysis_previous_decl_label)] + prev_span: Span, + }, + #[diag(hir_analysis_field_already_declared_current_nested)] + CurrentNested { + field_name: Symbol, + #[primary_span] + #[label] + span: Span, + #[note(hir_analysis_nested_field_decl_note)] + nested_field_span: Span, + #[label(hir_analysis_previous_decl_label)] + prev_span: Span, + }, + #[diag(hir_analysis_field_already_declared_previous_nested)] + PreviousNested { + field_name: Symbol, + #[primary_span] + #[label] + span: Span, + #[label(hir_analysis_previous_decl_label)] + prev_span: Span, + #[note(hir_analysis_previous_nested_field_decl_note)] + prev_nested_field_span: Span, + }, + #[diag(hir_analysis_field_already_declared_both_nested)] + BothNested { + field_name: Symbol, + #[primary_span] + #[label] + span: Span, + #[note(hir_analysis_nested_field_decl_note)] + nested_field_span: Span, + #[label(hir_analysis_previous_decl_label)] + prev_span: Span, + #[note(hir_analysis_previous_nested_field_decl_note)] + prev_nested_field_span: Span, + }, } #[derive(Diagnostic)] diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 854046c9cebe8..d07a53ee6794d 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -401,7 +401,7 @@ impl<'tcx> AdtDef<'tcx> { } /// Returns an iterator over all fields contained - /// by this ADT. + /// by this ADT (nested unnamed fields are not expanded). #[inline] pub fn all_fields(self) -> impl Iterator + Clone { self.variants().iter().flat_map(|v| v.fields.iter()) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 3cbe8f287e1f3..e73b9836174aa 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1387,6 +1387,11 @@ impl<'tcx> FieldDef { pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident { Ident::new(self.name, tcx.def_ident_span(self.did).unwrap()) } + + /// Returns whether the field is unnamed + pub fn is_unnamed(&self) -> bool { + self.name == rustc_span::symbol::kw::Underscore + } } #[derive(Debug, PartialEq, Eq)] diff --git a/tests/ui/union/unnamed-fields/field_uniqueness_check.rs b/tests/ui/union/unnamed-fields/field_uniqueness_check.rs new file mode 100644 index 0000000000000..3cc3621187530 --- /dev/null +++ b/tests/ui/union/unnamed-fields/field_uniqueness_check.rs @@ -0,0 +1,328 @@ +#![allow(incomplete_features)] +#![feature(unnamed_fields)] + +#[repr(C)] +struct Foo { + a: u8, +} + +#[repr(C)] +struct Bar { + _: union { + a: u8, + }, +} + + +// duplicated with a normal field +#[repr(C)] +union A { + // referent field + a: u8, + + // normal field + a: u8, //~ ERROR field `a` is already declared [E0124] + // nested field + _: struct { + a: u8, //~ ERROR field `a` is already declared [E0124] + a: u8, //~ ERROR field `a` is already declared [E0124] + }, + // more nested field + _: union { + _: struct { + a: u8, //~ ERROR field `a` is already declared [E0124] + }, + }, + // nested field in a named adt + _: Foo, //~ ERROR field `a` is already declared + _: Bar, //~ ERROR field `a` is already declared + // nested field in a named adt in an anoymous adt + _: struct { + _: Foo, //~ ERROR field `a` is already declared + _: Bar, //~ ERROR field `a` is already declared + }, +} + +// duplicated with a nested field +#[repr(C)] +struct B { + _: union { + // referent field + a: u8, + + // normal field (within the same anonymous adt) + a: u8, //~ ERROR field `a` is already declared [E0124] + // nested field (within the same anonymous adt) + _: struct { + a: u8, //~ ERROR field `a` is already declared [E0124] + }, + // more nested field (within the same anonymous adt) + _: union { + _: struct { + a: u8, //~ ERROR field `a` is already declared [E0124] + }, + }, + // nested field in a named adt (within the same anonymous adt) + _: Foo, //~ ERROR field `a` is already declared + _: Bar, //~ ERROR field `a` is already declared + // nested field in a named adt in an anoymous adt (within the same anonymous adt) + _: struct { + _: Foo, //~ ERROR field `a` is already declared + _: Bar, //~ ERROR field `a` is already declared + }, + }, + + // normal field + a: u8, //~ ERROR field `a` is already declared [E0124] + // nested field + _: struct { + a: u8, //~ ERROR field `a` is already declared [E0124] + }, + // more nested field + _: union { + _: struct { + a: u8, //~ ERROR field `a` is already declared [E0124] + }, + }, + // nested field in a named adt + _: Foo, //~ ERROR field `a` is already declared + _: Bar, //~ ERROR field `a` is already declared + // nested field in a named adt in an anoymous adt + _: struct { + _: Foo, //~ ERROR field `a` is already declared + _: Bar, //~ ERROR field `a` is already declared + }, +} + +// duplicated with a more nested field +#[repr(C)] +union C { + _: struct { + _: union { + // referent field + a: u8, + + // normal field (within the same anonymous adt) + a: u8, //~ ERROR field `a` is already declared [E0124] + // nested field (within the same anonymous adt) + _: struct { + a: u8, //~ ERROR field `a` is already declared [E0124] + }, + // more nested field (within the same anonymous adt) + _: union { + _: struct { + a: u8, //~ ERROR field `a` is already declared [E0124] + }, + }, + // nested field in a named adt (within the same anonymous adt) + _: Foo, //~ ERROR field `a` is already declared + _: Bar, //~ ERROR field `a` is already declared + // nested field in a named adt in an anoymous adt (within the same anonymous adt) + _: struct { + _: Foo, //~ ERROR field `a` is already declared + _: Bar, //~ ERROR field `a` is already declared + }, + }, + + // normal field (within the direct outer anonymous adt) + a: u8, //~ ERROR field `a` is already declared [E0124] + // nested field (within the direct outer anonymous adt) + _: struct { + a: u8, //~ ERROR field `a` is already declared [E0124] + }, + // more nested field (within the direct outer anonymous adt) + _: union { + _: struct { + a: u8, //~ ERROR field `a` is already declared [E0124] + }, + }, + // nested field in a named adt (within the direct outer anonymous adt) + _: Foo, //~ ERROR field `a` is already declared + _: Bar, //~ ERROR field `a` is already declared + // nested field in a named adt in an anoymous adt (within the direct outer anonymous adt) + _: struct { + _: Foo, //~ ERROR field `a` is already declared + _: Bar, //~ ERROR field `a` is already declared + }, + }, + // normal field + a: u8, //~ ERROR field `a` is already declared [E0124] + // nested field + _: union { + a: u8, //~ ERROR field `a` is already declared [E0124] + }, + // more nested field + _: struct { + _: union { + a: u8, //~ ERROR field `a` is already declared [E0124] + }, + }, + // nested field in a named adt + _: Foo, //~ ERROR field `a` is already declared + _: Bar, //~ ERROR field `a` is already declared + // nested field in a named adt in an anoymous adt + _: union { + _: Foo, //~ ERROR field `a` is already declared + _: Bar, //~ ERROR field `a` is already declared + }, +} + +// duplicated with a nested field in a named adt +#[repr(C)] +struct D { + // referent field `a` + _: Foo, + + // normal field + a: u8, //~ ERROR field `a` is already declared + // nested field + _: union { + a: u8, //~ ERROR field `a` is already declared + }, + // more nested field + _: struct { + _: union { + a: u8, //~ ERROR field `a` is already declared + }, + }, + // nested field in another named adt + _: Foo, //~ ERROR field `a` is already declared + _: Bar, //~ ERROR field `a` is already declared + // nested field in a named adt in an anoymous adt + _: union { + _: Foo, //~ ERROR field `a` is already declared + _: Bar, //~ ERROR field `a` is already declared + }, +} + +// duplicated with a nested field in a nested field of a named adt +#[repr(C)] +union D2 { + // referent field `a` + _: Bar, + + // normal field + a: u8, //~ ERROR field `a` is already declared + // nested field + _: union { + a: u8, //~ ERROR field `a` is already declared + }, + // more nested field + _: struct { + _: union { + a: u8, //~ ERROR field `a` is already declared + }, + }, + // nested field in another named adt + _: Foo, //~ ERROR field `a` is already declared + _: Bar, //~ ERROR field `a` is already declared + // nested field in a named adt in an anoymous adt + _: union { + _: Foo, //~ ERROR field `a` is already declared + _: Bar, //~ ERROR field `a` is already declared + }, +} + +// duplicated with a nested field in a named adt in an anonymous adt +#[repr(C)] +struct E { + _: struct { + // referent field `a` + _: Foo, + + // normal field (within the same anonymous adt) + a: u8, //~ ERROR field `a` is already declared + // nested field (within the same anonymous adt) + _: struct { + a: u8, //~ ERROR field `a` is already declared + }, + // more nested field (within the same anonymous adt) + _: union { + _: struct { + a: u8, //~ ERROR field `a` is already declared + }, + }, + // nested field in a named adt (within the same anonymous adt) + _: Foo, //~ ERROR field `a` is already declared + _: Bar, //~ ERROR field `a` is already declared + // nested field in a named adt in an anoymous adt (within the same anonymous adt) + _: struct { + _: Foo, //~ ERROR field `a` is already declared + _: Bar, //~ ERROR field `a` is already declared + }, + }, + + // normal field + a: u8, //~ ERROR field `a` is already declared + // nested field + _: union { + a: u8, //~ ERROR field `a` is already declared + }, + // more nested field + _: struct { + _: union { + a: u8, //~ ERROR field `a` is already declared + }, + }, + // nested field in another named adt + _: Foo, //~ ERROR field `a` is already declared + _: Bar, //~ ERROR field `a` is already declared + // nested field in a named adt in an anoymous adt + _: union { + _: Foo, //~ ERROR field `a` is already declared + _: Bar, //~ ERROR field `a` is already declared + }, +} + +// duplicated with a nested field in a named adt in an anonymous adt +#[repr(C)] +union E2 { + _: struct { + // referent field `a` + _: Bar, + + // normal field (within the same anonymous adt) + a: u8, //~ ERROR field `a` is already declared + // nested field (within the same anonymous adt) + _: struct { + a: u8, //~ ERROR field `a` is already declared + }, + // more nested field (within the same anonymous adt) + _: union { + _: struct { + a: u8, //~ ERROR field `a` is already declared + }, + }, + // nested field in a named adt (within the same anonymous adt) + _: Foo, //~ ERROR field `a` is already declared + _: Bar, //~ ERROR field `a` is already declared + // nested field in a named adt in an anoymous adt (within the same anonymous adt) + _: struct { + _: Foo, //~ ERROR field `a` is already declared + _: Bar, //~ ERROR field `a` is already declared + }, + }, + + // normal field + a: u8, //~ ERROR field `a` is already declared + // nested field + _: union { + a: u8, //~ ERROR field `a` is already declared + }, + // more nested field + _: struct { + _: union { + a: u8, //~ ERROR field `a` is already declared + }, + }, + // nested field in another named adt + _: Foo, //~ ERROR field `a` is already declared + _: Bar, //~ ERROR field `a` is already declared + // nested field in a named adt in an anoymous adt + _: union { + _: Foo, //~ ERROR field `a` is already declared + _: Bar, //~ ERROR field `a` is already declared + }, +} + +fn main() {} diff --git a/tests/ui/union/unnamed-fields/field_uniqueness_check.stderr b/tests/ui/union/unnamed-fields/field_uniqueness_check.stderr new file mode 100644 index 0000000000000..4dea0aa4233bf --- /dev/null +++ b/tests/ui/union/unnamed-fields/field_uniqueness_check.stderr @@ -0,0 +1,1284 @@ +error[E0124]: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:24:5 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | a: u8, + | ^^^^^ field already declared + +error[E0124]: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:27:9 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | a: u8, + | ^^^^^ field already declared + +error[E0124]: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:28:9 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | a: u8, + | ^^^^^ field already declared + +error[E0124]: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:33:13 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | a: u8, + | ^^^^^ field already declared + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:37:5 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | _: Foo, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:38:5 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | _: Bar, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:41:9 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | _: Foo, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:42:9 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | _: Bar, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ + +error[E0124]: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:54:9 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | a: u8, + | ^^^^^ field already declared + +error[E0124]: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:57:13 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | a: u8, + | ^^^^^ field already declared + +error[E0124]: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:62:17 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | a: u8, + | ^^^^^ field already declared + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:66:9 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | _: Foo, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:67:9 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | _: Bar, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:70:13 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | _: Foo, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:71:13 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | _: Bar, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ + +error[E0124]: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:76:5 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | a: u8, + | ^^^^^ field already declared + +error[E0124]: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:79:9 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | a: u8, + | ^^^^^ field already declared + +error[E0124]: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:84:13 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | a: u8, + | ^^^^^ field already declared + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:88:5 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | _: Foo, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:89:5 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | _: Bar, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:92:9 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | _: Foo, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:93:9 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | _: Bar, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ + +error[E0124]: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:106:13 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | a: u8, + | ^^^^^ field already declared + +error[E0124]: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:109:17 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | a: u8, + | ^^^^^ field already declared + +error[E0124]: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:114:21 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | a: u8, + | ^^^^^ field already declared + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:118:13 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | _: Foo, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:119:13 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | _: Bar, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:122:17 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | _: Foo, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:123:17 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | _: Bar, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ + +error[E0124]: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:128:9 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | a: u8, + | ^^^^^ field already declared + +error[E0124]: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:131:13 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | a: u8, + | ^^^^^ field already declared + +error[E0124]: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:136:17 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | a: u8, + | ^^^^^ field already declared + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:140:9 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | _: Foo, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:141:9 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | _: Bar, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:144:13 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | _: Foo, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:145:13 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | _: Bar, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ + +error[E0124]: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:149:5 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | a: u8, + | ^^^^^ field already declared + +error[E0124]: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:152:9 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | a: u8, + | ^^^^^ field already declared + +error[E0124]: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:157:13 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | a: u8, + | ^^^^^ field already declared + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:161:5 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | _: Foo, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:162:5 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | _: Bar, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:165:9 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | _: Foo, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:166:9 + | +LL | a: u8, + | ----- `a` first declared here +... +LL | _: Bar, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:177:5 + | +LL | _: Foo, + | ------ `a` first declared here in this unnamed field +... +LL | a: u8, + | ^^^^^ field already declared + | +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:180:9 + | +LL | _: Foo, + | ------ `a` first declared here in this unnamed field +... +LL | a: u8, + | ^^^^^ field already declared + | +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:185:13 + | +LL | _: Foo, + | ------ `a` first declared here in this unnamed field +... +LL | a: u8, + | ^^^^^ field already declared + | +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:189:5 + | +LL | _: Foo, + | ------ `a` first declared here in this unnamed field +... +LL | _: Foo, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:190:5 + | +LL | _: Foo, + | ------ `a` first declared here in this unnamed field +... +LL | _: Bar, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:193:9 + | +LL | _: Foo, + | ------ `a` first declared here in this unnamed field +... +LL | _: Foo, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:194:9 + | +LL | _: Foo, + | ------ `a` first declared here in this unnamed field +... +LL | _: Bar, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:205:5 + | +LL | _: Bar, + | ------ `a` first declared here in this unnamed field +... +LL | a: u8, + | ^^^^^ field already declared + | +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:208:9 + | +LL | _: Bar, + | ------ `a` first declared here in this unnamed field +... +LL | a: u8, + | ^^^^^ field already declared + | +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:213:13 + | +LL | _: Bar, + | ------ `a` first declared here in this unnamed field +... +LL | a: u8, + | ^^^^^ field already declared + | +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:217:5 + | +LL | _: Bar, + | ------ `a` first declared here in this unnamed field +... +LL | _: Foo, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:218:5 + | +LL | _: Bar, + | ------ `a` first declared here in this unnamed field +... +LL | _: Bar, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:221:9 + | +LL | _: Bar, + | ------ `a` first declared here in this unnamed field +... +LL | _: Foo, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:222:9 + | +LL | _: Bar, + | ------ `a` first declared here in this unnamed field +... +LL | _: Bar, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:234:9 + | +LL | _: Foo, + | ------ `a` first declared here in this unnamed field +... +LL | a: u8, + | ^^^^^ field already declared + | +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:237:13 + | +LL | _: Foo, + | ------ `a` first declared here in this unnamed field +... +LL | a: u8, + | ^^^^^ field already declared + | +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:242:17 + | +LL | _: Foo, + | ------ `a` first declared here in this unnamed field +... +LL | a: u8, + | ^^^^^ field already declared + | +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:246:9 + | +LL | _: Foo, + | ------ `a` first declared here in this unnamed field +... +LL | _: Foo, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:247:9 + | +LL | _: Foo, + | ------ `a` first declared here in this unnamed field +... +LL | _: Bar, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:250:13 + | +LL | _: Foo, + | ------ `a` first declared here in this unnamed field +... +LL | _: Foo, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:251:13 + | +LL | _: Foo, + | ------ `a` first declared here in this unnamed field +... +LL | _: Bar, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:256:5 + | +LL | _: Foo, + | ------ `a` first declared here in this unnamed field +... +LL | a: u8, + | ^^^^^ field already declared + | +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:259:9 + | +LL | _: Foo, + | ------ `a` first declared here in this unnamed field +... +LL | a: u8, + | ^^^^^ field already declared + | +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:264:13 + | +LL | _: Foo, + | ------ `a` first declared here in this unnamed field +... +LL | a: u8, + | ^^^^^ field already declared + | +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:268:5 + | +LL | _: Foo, + | ------ `a` first declared here in this unnamed field +... +LL | _: Foo, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:269:5 + | +LL | _: Foo, + | ------ `a` first declared here in this unnamed field +... +LL | _: Bar, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:272:9 + | +LL | _: Foo, + | ------ `a` first declared here in this unnamed field +... +LL | _: Foo, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:273:9 + | +LL | _: Foo, + | ------ `a` first declared here in this unnamed field +... +LL | _: Bar, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:285:9 + | +LL | _: Bar, + | ------ `a` first declared here in this unnamed field +... +LL | a: u8, + | ^^^^^ field already declared + | +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:288:13 + | +LL | _: Bar, + | ------ `a` first declared here in this unnamed field +... +LL | a: u8, + | ^^^^^ field already declared + | +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:293:17 + | +LL | _: Bar, + | ------ `a` first declared here in this unnamed field +... +LL | a: u8, + | ^^^^^ field already declared + | +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:297:9 + | +LL | _: Bar, + | ------ `a` first declared here in this unnamed field +... +LL | _: Foo, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:298:9 + | +LL | _: Bar, + | ------ `a` first declared here in this unnamed field +... +LL | _: Bar, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:301:13 + | +LL | _: Bar, + | ------ `a` first declared here in this unnamed field +... +LL | _: Foo, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:302:13 + | +LL | _: Bar, + | ------ `a` first declared here in this unnamed field +... +LL | _: Bar, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:307:5 + | +LL | _: Bar, + | ------ `a` first declared here in this unnamed field +... +LL | a: u8, + | ^^^^^ field already declared + | +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:310:9 + | +LL | _: Bar, + | ------ `a` first declared here in this unnamed field +... +LL | a: u8, + | ^^^^^ field already declared + | +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:315:13 + | +LL | _: Bar, + | ------ `a` first declared here in this unnamed field +... +LL | a: u8, + | ^^^^^ field already declared + | +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:319:5 + | +LL | _: Bar, + | ------ `a` first declared here in this unnamed field +... +LL | _: Foo, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:320:5 + | +LL | _: Bar, + | ------ `a` first declared here in this unnamed field +... +LL | _: Bar, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:323:9 + | +LL | _: Bar, + | ------ `a` first declared here in this unnamed field +... +LL | _: Foo, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:6:5 + | +LL | a: u8, + | ^^^^^ +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ + +error: field `a` is already declared + --> $DIR/field_uniqueness_check.rs:324:9 + | +LL | _: Bar, + | ------ `a` first declared here in this unnamed field +... +LL | _: Bar, + | ^^^^^^ field `a` declared in this unnamed field + | +note: field `a` declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ +note: field `a` first declared here + --> $DIR/field_uniqueness_check.rs:12:9 + | +LL | a: u8, + | ^^^^^ + +error: aborting due to 85 previous errors + +For more information about this error, try `rustc --explain E0124`. diff --git a/tests/ui/union/unnamed-fields/restrict_anonymous_structs.rs b/tests/ui/union/unnamed-fields/restrict_anonymous_structs.rs index 76525ec0bb121..03545ed7b18e2 100644 --- a/tests/ui/union/unnamed-fields/restrict_anonymous_structs.rs +++ b/tests/ui/union/unnamed-fields/restrict_anonymous_structs.rs @@ -2,8 +2,8 @@ #![feature(unnamed_fields)] struct F { - field: struct { field: u8 }, //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields - _: struct { field: u8 }, + field1: struct { field2: u8 }, //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields + _: struct { field3: u8 }, } struct G { @@ -11,8 +11,8 @@ struct G { } union H { - field: struct { field: u8 }, //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields - _: struct { field: u8 }, + field1: struct { field2: u8 }, //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields + _: struct { field3: u8 }, } union I { diff --git a/tests/ui/union/unnamed-fields/restrict_anonymous_structs.stderr b/tests/ui/union/unnamed-fields/restrict_anonymous_structs.stderr index 846e3451a7175..3b3890af771db 100644 --- a/tests/ui/union/unnamed-fields/restrict_anonymous_structs.stderr +++ b/tests/ui/union/unnamed-fields/restrict_anonymous_structs.stderr @@ -1,8 +1,8 @@ error: anonymous structs are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_structs.rs:5:12 + --> $DIR/restrict_anonymous_structs.rs:5:13 | -LL | field: struct { field: u8 }, - | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here +LL | field1: struct { field2: u8 }, + | ^^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here error: unnamed fields can only have struct or union types --> $DIR/restrict_anonymous_structs.rs:10:5 @@ -11,10 +11,10 @@ LL | _: (u8, u8), | ^ -------- not a struct or union error: anonymous structs are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_structs.rs:14:12 + --> $DIR/restrict_anonymous_structs.rs:14:13 | -LL | field: struct { field: u8 }, - | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here +LL | field1: struct { field2: u8 }, + | ^^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here error: unnamed fields can only have struct or union types --> $DIR/restrict_anonymous_structs.rs:19:5 diff --git a/tests/ui/union/unnamed-fields/restrict_anonymous_unions.rs b/tests/ui/union/unnamed-fields/restrict_anonymous_unions.rs index c049ba92ed2ad..9ffe71b28c292 100644 --- a/tests/ui/union/unnamed-fields/restrict_anonymous_unions.rs +++ b/tests/ui/union/unnamed-fields/restrict_anonymous_unions.rs @@ -2,8 +2,8 @@ #![feature(unnamed_fields)] struct F { - field: union { field: u8 }, //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields - _: union { field: u8 }, + field1: union { field2: u8 }, //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields + _: union { field3: u8 }, } struct G { @@ -11,8 +11,8 @@ struct G { } union H { - field: union { field: u8 }, //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields - _: union { field: u8 }, + field1: union { field2: u8 }, //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields + _: union { field3: u8 }, } union I { diff --git a/tests/ui/union/unnamed-fields/restrict_anonymous_unions.stderr b/tests/ui/union/unnamed-fields/restrict_anonymous_unions.stderr index c916e37a3e911..f8679aad2d7e6 100644 --- a/tests/ui/union/unnamed-fields/restrict_anonymous_unions.stderr +++ b/tests/ui/union/unnamed-fields/restrict_anonymous_unions.stderr @@ -1,8 +1,8 @@ error: anonymous unions are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_unions.rs:5:12 + --> $DIR/restrict_anonymous_unions.rs:5:13 | -LL | field: union { field: u8 }, - | ^^^^^^^^^^^^^^^^^^^ anonymous union declared here +LL | field1: union { field2: u8 }, + | ^^^^^^^^^^^^^^^^^^^^ anonymous union declared here error: unnamed fields can only have struct or union types --> $DIR/restrict_anonymous_unions.rs:10:5 @@ -11,10 +11,10 @@ LL | _: (u8, u8), | ^ -------- not a struct or union error: anonymous unions are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_unions.rs:14:12 + --> $DIR/restrict_anonymous_unions.rs:14:13 | -LL | field: union { field: u8 }, - | ^^^^^^^^^^^^^^^^^^^ anonymous union declared here +LL | field1: union { field2: u8 }, + | ^^^^^^^^^^^^^^^^^^^^ anonymous union declared here error: unnamed fields can only have struct or union types --> $DIR/restrict_anonymous_unions.rs:19:5 From 0c0df4efe09072013067fc5829996cc53f5c9bd3 Mon Sep 17 00:00:00 2001 From: Frank King Date: Thu, 4 Jan 2024 21:45:06 +0800 Subject: [PATCH 3/8] Lowering field access for anonymous adts --- compiler/rustc_ast_lowering/src/lib.rs | 27 +++--- compiler/rustc_hir_analysis/src/collect.rs | 26 ++++-- compiler/rustc_hir_typeck/src/expr.rs | 54 ++++++++---- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 10 ++- compiler/rustc_hir_typeck/src/pat.rs | 3 +- compiler/rustc_hir_typeck/src/writeback.rs | 5 ++ compiler/rustc_middle/src/query/erase.rs | 1 + compiler/rustc_middle/src/query/mod.rs | 4 + .../rustc_middle/src/ty/typeck_results.rs | 19 ++++ compiler/rustc_mir_build/src/thir/cx/expr.rs | 20 +++-- .../rustc_resolve/src/build_reduced_graph.rs | 88 ++++++++++++++----- compiler/rustc_resolve/src/def_collector.rs | 15 +++- compiler/rustc_resolve/src/lib.rs | 6 ++ .../src/solve/assembly/structural_traits.rs | 2 +- .../src/traits/select/mod.rs | 4 +- ...d_access.bar.SimplifyCfg-initial.after.mir | 61 +++++++++++++ ...d_access.foo.SimplifyCfg-initial.after.mir | 59 +++++++++++++ tests/mir-opt/unnamed-fields/field_access.rs | 56 ++++++++++++ 18 files changed, 390 insertions(+), 70 deletions(-) create mode 100644 tests/mir-opt/unnamed-fields/field_access.bar.SimplifyCfg-initial.after.mir create mode 100644 tests/mir-opt/unnamed-fields/field_access.foo.SimplifyCfg-initial.after.mir create mode 100644 tests/mir-opt/unnamed-fields/field_access.rs diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 7a07124225699..480072ce705aa 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1299,33 +1299,28 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // // ^_____________________| // } // ``` - TyKind::AnonStruct(def_node_id, fields) | TyKind::AnonUnion(def_node_id, fields) => { - let (def_kind, item_kind): (DefKind, fn(_, _) -> _) = match t.kind { - TyKind::AnonStruct(..) => (DefKind::Struct, hir::ItemKind::Struct), - TyKind::AnonUnion(..) => (DefKind::Union, hir::ItemKind::Union), - _ => unreachable!(), - }; - let def_id = self.create_def( - self.current_hir_id_owner.def_id, - *def_node_id, - kw::Empty, - def_kind, - t.span, - ); + TyKind::AnonStruct(node_id, fields) | TyKind::AnonUnion(node_id, fields) => { + // Here its `def_id` is created in `build_reduced_graph`. + let def_id = self.local_def_id(*node_id); debug!(?def_id); let owner_id = hir::OwnerId { def_id }; - self.with_hir_id_owner(*def_node_id, |this| { + self.with_hir_id_owner(*node_id, |this| { let fields = this.arena.alloc_from_iter( fields.iter().enumerate().map(|f| this.lower_field_def(f)), ); let span = t.span; - let variant_data = hir::VariantData::Struct(fields, false); + let variant_data = hir::VariantData::Struct { fields, recovered: false }; // FIXME: capture the generics from the outer adt. let generics = hir::Generics::empty(); + let kind = match t.kind { + TyKind::AnonStruct(..) => hir::ItemKind::Struct(variant_data, generics), + TyKind::AnonUnion(..) => hir::ItemKind::Union(variant_data, generics), + _ => unreachable!(), + }; hir::OwnerNode::Item(this.arena.alloc(hir::Item { ident: Ident::new(kw::Empty, span), owner_id, - kind: item_kind(variant_data, generics), + kind, span: this.lower_span(span), vis_span: this.lower_span(span.shrink_to_lo()), })) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 12e7b5dbfce46..15ddbd84b2c11 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -31,6 +31,7 @@ use rustc_middle::ty::util::{Discr, IntTypeExt}; use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, ToPredicate, Ty, TyCtxt}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; +use rustc_target::abi::FieldIdx; use rustc_target::spec::abi; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName; @@ -84,6 +85,7 @@ pub fn provide(providers: &mut Providers) { coroutine_for_closure, collect_mod_item_types, is_type_alias_impl_trait, + find_field, ..*providers }; } @@ -875,8 +877,8 @@ fn check_field_uniqueness( // Abort due to errors (there must be an error if an unnamed field // has any type kind other than an anonymous adt or a named adt) _ => { - debug_assert!(tcx.sess.has_errors().is_some()); - tcx.sess.abort_if_errors() + debug_assert!(tcx.dcx().has_errors().is_some()); + tcx.dcx().abort_if_errors() } } return; @@ -884,6 +886,18 @@ fn check_field_uniqueness( check(field.ident, field.span.into()); } +fn find_field(tcx: TyCtxt<'_>, (def_id, ident): (DefId, Ident)) -> Option { + tcx.adt_def(def_id).non_enum_variant().fields.iter_enumerated().find_map(|(idx, field)| { + if field.is_unnamed() { + let field_ty = tcx.type_of(field.did).instantiate_identity(); + let adt_def = field_ty.ty_adt_def().expect("expect Adt for unnamed field"); + tcx.find_field((adt_def.did(), ident)).map(|_| idx) + } else { + (field.ident(tcx).normalize_to_macros_2_0() == ident).then_some(idx) + } + }) +} + fn convert_variant( tcx: TyCtxt<'_>, variant_did: Option, @@ -908,14 +922,14 @@ fn convert_variant( let ident = ident.normalize_to_macros_2_0(); match (field_decl, seen_fields.get(&ident).copied()) { (NotNested(span), Some(NotNested(prev_span))) => { - tcx.sess.emit_err(errors::FieldAlreadyDeclared::NotNested { + tcx.dcx().emit_err(errors::FieldAlreadyDeclared::NotNested { field_name, span, prev_span, }); } (NotNested(span), Some(Nested(prev))) => { - tcx.sess.emit_err(errors::FieldAlreadyDeclared::PreviousNested { + tcx.dcx().emit_err(errors::FieldAlreadyDeclared::PreviousNested { field_name, span, prev_span: prev.span, @@ -926,7 +940,7 @@ fn convert_variant( Nested(NestedSpan { span, nested_field_span }), Some(NotNested(prev_span)), ) => { - tcx.sess.emit_err(errors::FieldAlreadyDeclared::CurrentNested { + tcx.dcx().emit_err(errors::FieldAlreadyDeclared::CurrentNested { field_name, span, nested_field_span, @@ -934,7 +948,7 @@ fn convert_variant( }); } (Nested(NestedSpan { span, nested_field_span }), Some(Nested(prev))) => { - tcx.sess.emit_err(errors::FieldAlreadyDeclared::BothNested { + tcx.dcx().emit_err(errors::FieldAlreadyDeclared::BothNested { field_name, span, nested_field_span, diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 31c97aab7fb83..8e8dcdaa10556 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1721,7 +1721,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ident = tcx.adjust_ident(field.ident, variant.def_id); let field_type = if let Some((i, v_field)) = remaining_fields.remove(&ident) { seen_fields.insert(ident, field.span); - self.write_field_index(field.hir_id, i); + // FIXME: handle nested fields + self.write_field_index(field.hir_id, i, Vec::new()); // We don't look at stability attributes on // struct-like enums (yet...), but it's definitely not @@ -2367,24 +2368,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let body_hir_id = self.tcx.local_def_id_to_hir_id(self.body_id); let (ident, def_scope) = self.tcx.adjust_ident_and_get_scope(field, base_def.did(), body_hir_id); - let fields = &base_def.non_enum_variant().fields; - if let Some((index, field)) = fields - .iter_enumerated() - .find(|(_, f)| f.ident(self.tcx).normalize_to_macros_2_0() == ident) - { + let mut adt_def = *base_def; + let mut last_ty = None; + let mut nested_fields = Vec::new(); + let mut index = None; + while let Some(idx) = self.tcx.find_field((adt_def.did(), ident)) { + let &mut first_idx = index.get_or_insert(idx); + let field = &adt_def.non_enum_variant().fields[idx]; let field_ty = self.field_ty(expr.span, field, args); - // Save the index of all fields regardless of their visibility in case - // of error recovery. - self.write_field_index(expr.hir_id, index); - let adjustments = self.adjust_steps(&autoderef); - if field.vis.is_accessible_from(def_scope, self.tcx) { - self.apply_adjustments(base, adjustments); - self.register_predicates(autoderef.into_obligations()); + if let Some(ty) = last_ty { + nested_fields.push((ty, idx)); + } + if field.ident(self.tcx).normalize_to_macros_2_0() == ident { + // Save the index of all fields regardless of their visibility in case + // of error recovery. + self.write_field_index(expr.hir_id, first_idx, nested_fields); + let adjustments = self.adjust_steps(&autoderef); + if field.vis.is_accessible_from(def_scope, self.tcx) { + self.apply_adjustments(base, adjustments); + self.register_predicates(autoderef.into_obligations()); - self.tcx.check_stability(field.did, Some(expr.hir_id), expr.span, None); - return field_ty; + self.tcx.check_stability( + field.did, + Some(expr.hir_id), + expr.span, + None, + ); + return field_ty; + } + private_candidate = Some((adjustments, base_def.did())); + break; } - private_candidate = Some((adjustments, base_def.did())); + last_ty = Some(field_ty); + adt_def = field_ty.ty_adt_def().expect("expect Adt for unnamed field"); } } ty::Tuple(tys) => { @@ -2395,7 +2411,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.apply_adjustments(base, adjustments); self.register_predicates(autoderef.into_obligations()); - self.write_field_index(expr.hir_id, FieldIdx::from_usize(index)); + self.write_field_index( + expr.hir_id, + FieldIdx::from_usize(index), + Vec::new(), + ); return field_ty; } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 7eb421ca8f5a9..165937de2471f 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -145,8 +145,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn write_field_index(&self, hir_id: hir::HirId, index: FieldIdx) { + pub fn write_field_index( + &self, + hir_id: hir::HirId, + index: FieldIdx, + nested_fields: Vec<(Ty<'tcx>, FieldIdx)>, + ) { self.typeck_results.borrow_mut().field_indices_mut().insert(hir_id, index); + if !nested_fields.is_empty() { + self.typeck_results.borrow_mut().nested_fields_mut().insert(hir_id, nested_fields); + } } #[instrument(level = "debug", skip(self))] diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 67aa92185852f..5026fbe4b8066 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -1389,7 +1389,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { field_map .get(&ident) .map(|(i, f)| { - self.write_field_index(field.hir_id, *i); + // FIXME: handle nested fields + self.write_field_index(field.hir_id, *i, Vec::new()); self.tcx.check_stability(f.did, Some(pat.hir_id), span, None); self.field_ty(span, f, args) }) diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 94f6c06157efe..e48939d8f8bc5 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -596,6 +596,11 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { { self.typeck_results.field_indices_mut().insert(hir_id, index); } + if let Some(nested_fields) = + self.fcx.typeck_results.borrow_mut().nested_fields_mut().remove(hir_id) + { + self.typeck_results.nested_fields_mut().insert(hir_id, nested_fields); + } } #[instrument(skip(self, span), level = "debug")] diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index a272a51f32747..7039749b1b729 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -238,6 +238,7 @@ trivial! { Option, Option, Option, + Option, Option, Option, Result<(), rustc_errors::ErrorGuaranteed>, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 938fba0ed0981..e9f61a5427031 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -2217,6 +2217,10 @@ rustc_queries! { desc { "whether the item should be made inlinable across crates" } separate_provide_extern } + + query find_field((def_id, ident): (DefId, rustc_span::symbol::Ident)) -> Option { + desc { |tcx| "find the index of maybe nested field `{ident}` in `{}`", tcx.def_path_str(def_id) } + } } rustc_query_append! { define_callbacks! } diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index ad41a674dd8cd..be91474b98831 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -44,6 +44,12 @@ pub struct TypeckResults<'tcx> { /// belongs, but it may not exist if it's a tuple field (`tuple.0`). field_indices: ItemLocalMap, + /// Resolved types and indices for the nested fields' accesses of `obj.field` (expanded + /// to `obj._(1)._(2).field` in THIR). This map only stores the intermediate type + /// of `obj._(1)` and index of `_(1)._(2)`, and the type of `_(1)._(2)`, and the index of + /// `_(2).field`. + nested_fields: ItemLocalMap, FieldIdx)>>, + /// Stores the types for various nodes in the AST. Note that this table /// is not guaranteed to be populated outside inference. See /// typeck::check::fn_ctxt for details. @@ -214,6 +220,7 @@ impl<'tcx> TypeckResults<'tcx> { hir_owner, type_dependent_defs: Default::default(), field_indices: Default::default(), + nested_fields: Default::default(), user_provided_types: Default::default(), user_provided_sigs: Default::default(), node_types: Default::default(), @@ -285,6 +292,18 @@ impl<'tcx> TypeckResults<'tcx> { self.field_indices().get(id).cloned() } + pub fn nested_fields(&self) -> LocalTableInContext<'_, Vec<(Ty<'tcx>, FieldIdx)>> { + LocalTableInContext { hir_owner: self.hir_owner, data: &self.nested_fields } + } + + pub fn nested_fields_mut(&mut self) -> LocalTableInContextMut<'_, Vec<(Ty<'tcx>, FieldIdx)>> { + LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.nested_fields } + } + + pub fn nested_field_tys_and_indices(&self, id: hir::HirId) -> &[(Ty<'tcx>, FieldIdx)] { + self.nested_fields().get(id).map_or(&[], Vec::as_slice) + } + pub fn user_provided_types(&self) -> LocalTableInContext<'_, CanonicalUserType<'tcx>> { LocalTableInContext { hir_owner: self.hir_owner, data: &self.user_provided_types } } diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 35adcc33480ca..79719f6f4cce5 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -734,11 +734,21 @@ impl<'tcx> Cx<'tcx> { }); ExprKind::Loop { body } } - hir::ExprKind::Field(source, ..) => ExprKind::Field { - lhs: self.mirror_expr(source), - variant_index: FIRST_VARIANT, - name: self.typeck_results.field_index(expr.hir_id), - }, + hir::ExprKind::Field(source, ..) => { + let mut kind = ExprKind::Field { + lhs: self.mirror_expr(source), + variant_index: FIRST_VARIANT, + name: self.typeck_results.field_index(expr.hir_id), + }; + let nested_field_tys_and_indices = + self.typeck_results.nested_field_tys_and_indices(expr.hir_id); + for &(ty, idx) in nested_field_tys_and_indices { + let expr = Expr { temp_lifetime, ty, span: source.span, kind }; + let lhs = self.thir.exprs.push(expr); + kind = ExprKind::Field { lhs, variant_index: FIRST_VARIANT, name: idx }; + } + kind + } hir::ExprKind::Cast(source, cast_ty) => { // Check for a user-given type annotation on this `cast` let user_provided_types = self.typeck_results.user_provided_types(); diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 7eb7c8c2bca22..6bb9c22b04d42 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -313,18 +313,17 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } } - fn insert_field_def_ids(&mut self, def_id: LocalDefId, vdata: &ast::VariantData) { - if vdata.fields().iter().any(|field| field.is_placeholder) { + fn insert_field_def_ids(&mut self, def_id: LocalDefId, fields: &[ast::FieldDef]) { + if fields.iter().any(|field| field.is_placeholder) { // The fields are not expanded yet. return; } - let def_ids = vdata.fields().iter().map(|field| self.r.local_def_id(field.id).to_def_id()); + let def_ids = fields.iter().map(|field| self.r.local_def_id(field.id).to_def_id()); self.r.field_def_ids.insert(def_id, self.r.tcx.arena.alloc_from_iter(def_ids)); } - fn insert_field_visibilities_local(&mut self, def_id: DefId, vdata: &ast::VariantData) { - let field_vis = vdata - .fields() + fn insert_field_visibilities_local(&mut self, def_id: DefId, fields: &[ast::FieldDef]) { + let field_vis = fields .iter() .map(|field| field.vis.span.until(field.ident.map_or(field.ty.span, |i| i.span))) .collect(); @@ -629,6 +628,50 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } } + fn build_reduced_graph_for_fields( + &mut self, + fields: &[ast::FieldDef], + ident: Ident, + def_id: LocalDefId, + adt_res: Res, + adt_vis: ty::Visibility, + adt_span: Span, + ) { + let parent_scope = &self.parent_scope; + let parent = parent_scope.module; + let expansion = parent_scope.expansion; + + // Define a name in the type namespace if it is not anonymous. + self.r.define(parent, ident, TypeNS, (adt_res, adt_vis, adt_span, expansion)); + self.r.feed_visibility(def_id, adt_vis); + + // Record field names for error reporting. + self.insert_field_def_ids(def_id, fields); + self.insert_field_visibilities_local(def_id.to_def_id(), fields); + + for field in fields { + match &field.ty.kind { + ast::TyKind::AnonStruct(id, nested_fields) + | ast::TyKind::AnonUnion(id, nested_fields) => { + let local_def_id = self.r.local_def_id(*id); + let def_id = local_def_id.to_def_id(); + let def_kind = self.r.tcx.def_kind(local_def_id); + let res = Res::Def(def_kind, def_id); + self.build_reduced_graph_for_fields( + &nested_fields, + Ident::empty(), + local_def_id, + res, + // Anonymous adts inherit visibility from their parent adts. + adt_vis, + field.span, + ); + } + _ => {} + } + } + } + /// Constructs the reduced graph for one item. fn build_reduced_graph_for_item(&mut self, item: &'b Item) { let parent_scope = &self.parent_scope; @@ -716,12 +759,14 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { // These items live in both the type and value namespaces. ItemKind::Struct(ref vdata, _) => { - // Define a name in the type namespace. - self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion)); - - // Record field names for error reporting. - self.insert_field_def_ids(local_def_id, vdata); - self.insert_field_visibilities_local(def_id, vdata); + self.build_reduced_graph_for_fields( + vdata.fields(), + ident, + local_def_id, + res, + vis, + sp, + ); // If this is a tuple or unit struct, define a name // in the value namespace as well. @@ -755,7 +800,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, sp, expansion)); self.r.feed_visibility(ctor_def_id, ctor_vis); // We need the field visibility spans also for the constructor for E0603. - self.insert_field_visibilities_local(ctor_def_id.to_def_id(), vdata); + self.insert_field_visibilities_local(ctor_def_id.to_def_id(), vdata.fields()); self.r .struct_constructors @@ -764,11 +809,14 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } ItemKind::Union(ref vdata, _) => { - self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion)); - - // Record field names for error reporting. - self.insert_field_def_ids(local_def_id, vdata); - self.insert_field_visibilities_local(def_id, vdata); + self.build_reduced_graph_for_fields( + vdata.fields(), + ident, + local_def_id, + res, + vis, + sp, + ); } // These items do not add names to modules. @@ -1461,8 +1509,8 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { } // Record field names for error reporting. - self.insert_field_def_ids(def_id, &variant.data); - self.insert_field_visibilities_local(def_id.to_def_id(), &variant.data); + self.insert_field_def_ids(def_id, variant.data.fields()); + self.insert_field_visibilities_local(def_id.to_def_id(), variant.data.fields()); visit::walk_variant(self, variant); } diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 42ace9bb22fa9..08b1c88873e7b 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -324,8 +324,21 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { } fn visit_ty(&mut self, ty: &'a Ty) { - match ty.kind { + match &ty.kind { TyKind::MacCall(..) => self.visit_macro_invoc(ty.id), + TyKind::AnonStruct(node_id, fields) | TyKind::AnonUnion(node_id, fields) => { + let def_kind = match &ty.kind { + TyKind::AnonStruct(..) => DefKind::Struct, + TyKind::AnonUnion(..) => DefKind::Union, + _ => unreachable!(), + }; + let def_id = self.create_def(*node_id, kw::Empty, def_kind, ty.span); + self.with_parent(def_id, |this| { + for f in fields { + this.visit_field_def(f); + } + }); + } _ => visit::walk_ty(self, ty), } } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 6c0f2b893474e..6b07bfdec671f 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1016,6 +1016,8 @@ pub struct Resolver<'a, 'tcx> { binding_parent_modules: FxHashMap, Module<'a>>, underscore_disambiguator: u32, + /// Disambiguator for anonymous adts. + empty_disambiguator: u32, /// Maps glob imports to the names of items actually imported. glob_map: FxHashMap>, @@ -1367,6 +1369,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { module_children: Default::default(), trait_map: NodeMap::default(), underscore_disambiguator: 0, + empty_disambiguator: 0, empty_module, module_map, block_map: Default::default(), @@ -1734,6 +1737,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let disambiguator = if ident.name == kw::Underscore { self.underscore_disambiguator += 1; self.underscore_disambiguator + } else if ident.name == kw::Empty { + self.empty_disambiguator += 1; + self.empty_disambiguator } else { 0 }; diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index b320ded40a772..e2d5eaded3f3d 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -183,7 +183,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( // Check for anonymous adts. ty::Adt(adt, generics) if adt.is_anonymous() => { - Ok(adt.all_fields().map(|f| f.ty(ecx.tcx(), generics)).collect()) + Ok(adt.non_enum_variant().fields.iter().map(|f| f.ty(ecx.tcx(), generics)).collect()) } ty::Dynamic(..) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index c2f7d5160f68f..43ab476056af6 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2212,14 +2212,14 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // FIXME(async_closures): These are never clone, for now. ty::CoroutineClosure(_, _) => None, - // `Copy` and `Clone` are automatically impelemented for an anonymous adt + // `Copy` and `Clone` are automatically implemented for an anonymous adt // if all of its fields are `Copy` and `Clone` ty::Adt(adt, args) if adt.is_anonymous() => { // (*) binder moved here Where( obligation .predicate - .rebind(adt.all_fields().map(|f| f.ty(self.tcx(), args)).collect()), + .rebind(adt.non_enum_variant().fields.iter().map(|f| f.ty(self.tcx(), args)).collect()), ) } diff --git a/tests/mir-opt/unnamed-fields/field_access.bar.SimplifyCfg-initial.after.mir b/tests/mir-opt/unnamed-fields/field_access.bar.SimplifyCfg-initial.after.mir new file mode 100644 index 0000000000000..2a57b272f9beb --- /dev/null +++ b/tests/mir-opt/unnamed-fields/field_access.bar.SimplifyCfg-initial.after.mir @@ -0,0 +1,61 @@ +// MIR for `bar` after SimplifyCfg-initial + +fn bar(_1: Bar) -> () { + debug bar => _1; + let mut _0: (); + let _2: (); + let mut _3: u8; + let _4: (); + let mut _5: i8; + let _6: (); + let mut _7: bool; + let _8: (); + let mut _9: [u8; 1]; + scope 1 { + } + + bb0: { + StorageLive(_2); + StorageLive(_3); + _3 = (_1.0: u8); + _2 = access::(move _3) -> [return: bb1, unwind: bb5]; + } + + bb1: { + StorageDead(_3); + StorageDead(_2); + StorageLive(_4); + StorageLive(_5); + _5 = ((_1.1: Bar::_::{anon_adt#0}).0: i8); + _4 = access::(move _5) -> [return: bb2, unwind: bb5]; + } + + bb2: { + StorageDead(_5); + StorageDead(_4); + StorageLive(_6); + StorageLive(_7); + _7 = ((_1.1: Bar::_::{anon_adt#0}).1: bool); + _6 = access::(move _7) -> [return: bb3, unwind: bb5]; + } + + bb3: { + StorageDead(_7); + StorageDead(_6); + StorageLive(_8); + StorageLive(_9); + _9 = (((_1.2: Bar::_::{anon_adt#0}).0: Bar::_::{anon_adt#0}::_::{anon_adt#0}).0: [u8; 1]); + _8 = access::<[u8; 1]>(move _9) -> [return: bb4, unwind: bb5]; + } + + bb4: { + StorageDead(_9); + StorageDead(_8); + _0 = const (); + return; + } + + bb5 (cleanup): { + resume; + } +} diff --git a/tests/mir-opt/unnamed-fields/field_access.foo.SimplifyCfg-initial.after.mir b/tests/mir-opt/unnamed-fields/field_access.foo.SimplifyCfg-initial.after.mir new file mode 100644 index 0000000000000..8b10a6f13ceda --- /dev/null +++ b/tests/mir-opt/unnamed-fields/field_access.foo.SimplifyCfg-initial.after.mir @@ -0,0 +1,59 @@ +// MIR for `foo` after SimplifyCfg-initial + +fn foo(_1: Foo) -> () { + debug foo => _1; + let mut _0: (); + let _2: (); + let mut _3: u8; + let _4: (); + let mut _5: i8; + let _6: (); + let mut _7: bool; + let _8: (); + let mut _9: [u8; 1]; + + bb0: { + StorageLive(_2); + StorageLive(_3); + _3 = (_1.0: u8); + _2 = access::(move _3) -> [return: bb1, unwind: bb5]; + } + + bb1: { + StorageDead(_3); + StorageDead(_2); + StorageLive(_4); + StorageLive(_5); + _5 = ((_1.1: Foo::_::{anon_adt#0}).0: i8); + _4 = access::(move _5) -> [return: bb2, unwind: bb5]; + } + + bb2: { + StorageDead(_5); + StorageDead(_4); + StorageLive(_6); + StorageLive(_7); + _7 = ((_1.1: Foo::_::{anon_adt#0}).1: bool); + _6 = access::(move _7) -> [return: bb3, unwind: bb5]; + } + + bb3: { + StorageDead(_7); + StorageDead(_6); + StorageLive(_8); + StorageLive(_9); + _9 = (((_1.2: Foo::_::{anon_adt#0}).0: Foo::_::{anon_adt#0}::_::{anon_adt#0}).0: [u8; 1]); + _8 = access::<[u8; 1]>(move _9) -> [return: bb4, unwind: bb5]; + } + + bb4: { + StorageDead(_9); + StorageDead(_8); + _0 = const (); + return; + } + + bb5 (cleanup): { + resume; + } +} diff --git a/tests/mir-opt/unnamed-fields/field_access.rs b/tests/mir-opt/unnamed-fields/field_access.rs new file mode 100644 index 0000000000000..3d33ca26875ba --- /dev/null +++ b/tests/mir-opt/unnamed-fields/field_access.rs @@ -0,0 +1,56 @@ +// skip-filecheck +// EMIT_MIR field_access.foo.SimplifyCfg-initial.after.mir +// EMIT_MIR field_access.bar.SimplifyCfg-initial.after.mir + +#![allow(incomplete_features)] +#![feature(unnamed_fields)] + +#[repr(C)] +struct Foo { + a: u8, + _: struct { + b: i8, + c: bool, + }, + _: struct { + _: struct { + d: [u8; 1], + } + } +} + +#[repr(C)] +union Bar { + a: u8, + _: union { + b: i8, + c: bool, + }, + _: union { + _: union { + d: [u8; 1], + } + } +} + + +fn access(_: T) {} + +fn foo(foo: Foo) { + access(foo.a); + access(foo.b); + access(foo.c); + access(foo.d); +} + +fn bar(bar: Bar) { + unsafe { + access(bar.a); + access(bar.b); + access(bar.c); + access(bar.d); + } +} + + +fn main() {} From 7d012e8f19591f224b25cabf64d9da2bb2e08166 Mon Sep 17 00:00:00 2001 From: Frank King Date: Sat, 6 Jan 2024 15:52:22 +0800 Subject: [PATCH 4/8] Add rustfmt test from #117942 --- src/tools/rustfmt/tests/target/anonymous-types.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/tools/rustfmt/tests/target/anonymous-types.rs b/src/tools/rustfmt/tests/target/anonymous-types.rs index 8e08c314ed1fb..e8c2d83878c26 100644 --- a/src/tools/rustfmt/tests/target/anonymous-types.rs +++ b/src/tools/rustfmt/tests/target/anonymous-types.rs @@ -16,4 +16,16 @@ struct Foo { e: f32, } +// Test for https://github.com/rust-lang/rust/issues/117942 +struct Foo { + _: union { + #[rustfmt::skip] + f: String, + }, + #[rustfmt::skip] + _: struct { + g: i32, + }, +} + fn main() {} From 7660d6bf2c4e02b4f809b99f35c0f290e6171d45 Mon Sep 17 00:00:00 2001 From: Frank King Date: Sat, 6 Jan 2024 18:22:37 +0800 Subject: [PATCH 5/8] Check representation of unnamed fields --- compiler/rustc_hir_analysis/messages.ftl | 11 ++ .../rustc_hir_analysis/src/check/check.rs | 49 ++++++++ compiler/rustc_hir_analysis/src/collect.rs | 6 +- compiler/rustc_hir_analysis/src/errors.rs | 30 +++++ compiler/rustc_resolve/src/def_collector.rs | 31 ++--- .../src/traits/select/mod.rs | 8 +- ...d_access.bar.SimplifyCfg-initial.after.mir | 6 +- ...d_access.foo.SimplifyCfg-initial.after.mir | 6 +- .../feature-gate-unnamed_fields.rs | 5 + .../feature-gate-unnamed_fields.stderr | 10 +- tests/ui/union/unnamed-fields/repr_check.rs | 69 +++++++++++ .../ui/union/unnamed-fields/repr_check.stderr | 108 ++++++++++++++++++ 12 files changed, 309 insertions(+), 30 deletions(-) create mode 100644 tests/ui/union/unnamed-fields/repr_check.rs create mode 100644 tests/ui/union/unnamed-fields/repr_check.stderr diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 662d859e99344..cf1a42c928521 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -439,6 +439,17 @@ hir_analysis_typeof_reserved_keyword_used = hir_analysis_unconstrained_opaque_type = unconstrained opaque type .note = `{$name}` must be used in combination with a concrete type within the same {$what} +hir_analysis_unnamed_fields_repr_field_defined = unnamed field defined here + +hir_analysis_unnamed_fields_repr_field_missing_repr_c = + named type of unnamed field must have `#[repr(C)]` representation + .label = unnamed field defined here + .field_ty_label = `{$field_ty}` defined here + +hir_analysis_unnamed_fields_repr_missing_repr_c = + {$adt_kind} with unnamed fields must have `#[repr(C)]` representation + .label = {$adt_kind} `{$adt_name}` defined here + hir_analysis_unrecognized_atomic_operation = unrecognized atomic operation function: `{$op}` .label = unrecognized atomic operation diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 7250dc81faf8b..3cbd67a482cd1 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -80,6 +80,7 @@ fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId) { check_transparent(tcx, def); check_packed(tcx, span, def); + check_unnamed_fields(tcx, def); } fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId) { @@ -89,6 +90,54 @@ fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId) { check_transparent(tcx, def); check_union_fields(tcx, span, def_id); check_packed(tcx, span, def); + check_unnamed_fields(tcx, def); +} + +/// Check the representation of adts with unnamed fields. +fn check_unnamed_fields(tcx: TyCtxt<'_>, def: ty::AdtDef<'_>) { + if def.is_enum() { + return; + } + let variant = def.non_enum_variant(); + if !variant.has_unnamed_fields() { + return; + } + if !def.is_anonymous() { + let adt_kind = def.descr(); + let span = tcx.def_span(def.did()); + let unnamed_fields = variant + .fields + .iter() + .filter(|f| f.is_unnamed()) + .map(|f| { + let span = tcx.def_span(f.did); + errors::UnnamedFieldsReprFieldDefined { span } + }) + .collect::>(); + debug_assert_ne!(unnamed_fields.len(), 0, "expect unnamed fields in this adt"); + let adt_name = tcx.item_name(def.did()); + if !def.repr().c() { + tcx.dcx().emit_err(errors::UnnamedFieldsRepr::MissingReprC { + span, + adt_kind, + adt_name, + unnamed_fields, + }); + } + } + for field in variant.fields.iter().filter(|f| f.is_unnamed()) { + let field_ty = tcx.type_of(field.did).instantiate_identity(); + if let Some(adt) = field_ty.ty_adt_def() + && !adt.is_anonymous() + && !adt.repr().c() + { + tcx.dcx().emit_err(errors::UnnamedFieldsRepr::FieldMissingReprC { + span: tcx.def_span(field.did), + field_ty_span: tcx.def_span(adt.did()), + field_ty, + }); + } + } } /// Check that the fields of the `union` do not need dropping. diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 15ddbd84b2c11..45938eacd6520 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -997,7 +997,11 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> { }; let is_anonymous = item.ident.name == kw::Empty; - let repr = tcx.repr_options_of_def(def_id.to_def_id()); + let repr = if is_anonymous { + tcx.adt_def(tcx.local_parent(def_id)).repr() + } else { + tcx.repr_options_of_def(def_id.to_def_id()) + }; let (kind, variants) = match &item.kind { ItemKind::Enum(def, _) => { let mut distance_from_explicit = 0; diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 1e172f1d9f017..f7fa3263eaa15 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1571,3 +1571,33 @@ pub(crate) enum UnusedGenericParameterHelp { #[help(hir_analysis_unused_generic_parameter_ty_alias_help)] TyAlias { param_name: Ident }, } + +#[derive(Diagnostic)] +pub enum UnnamedFieldsRepr<'a> { + #[diag(hir_analysis_unnamed_fields_repr_missing_repr_c)] + MissingReprC { + #[primary_span] + #[label] + span: Span, + adt_kind: &'static str, + adt_name: Symbol, + #[subdiagnostic] + unnamed_fields: Vec, + }, + #[diag(hir_analysis_unnamed_fields_repr_field_missing_repr_c)] + FieldMissingReprC { + #[primary_span] + #[label] + span: Span, + #[label(hir_analysis_field_ty_label)] + field_ty_span: Span, + field_ty: Ty<'a>, + }, +} + +#[derive(Subdiagnostic)] +#[note(hir_analysis_unnamed_fields_repr_field_defined)] +pub struct UnnamedFieldsReprFieldDefined { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 08b1c88873e7b..45aea585f97a4 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -80,6 +80,22 @@ impl<'a, 'b, 'tcx> DefCollector<'a, 'b, 'tcx> { let name = field.ident.map_or_else(|| sym::integer(index(self)), |ident| ident.name); let def = self.create_def(field.id, name, DefKind::Field, field.span); self.with_parent(def, |this| visit::walk_field_def(this, field)); + self.visit_anon_adt(&field.ty); + } + } + + fn visit_anon_adt(&mut self, ty: &'a Ty) { + let def_kind = match &ty.kind { + TyKind::AnonStruct(..) => DefKind::Struct, + TyKind::AnonUnion(..) => DefKind::Union, + _ => return, + }; + match &ty.kind { + TyKind::AnonStruct(node_id, _) | TyKind::AnonUnion(node_id, _) => { + let def_id = self.create_def(*node_id, kw::Empty, def_kind, ty.span); + self.with_parent(def_id, |this| visit::walk_ty(this, ty)); + } + _ => {} } } @@ -326,19 +342,8 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { fn visit_ty(&mut self, ty: &'a Ty) { match &ty.kind { TyKind::MacCall(..) => self.visit_macro_invoc(ty.id), - TyKind::AnonStruct(node_id, fields) | TyKind::AnonUnion(node_id, fields) => { - let def_kind = match &ty.kind { - TyKind::AnonStruct(..) => DefKind::Struct, - TyKind::AnonUnion(..) => DefKind::Union, - _ => unreachable!(), - }; - let def_id = self.create_def(*node_id, kw::Empty, def_kind, ty.span); - self.with_parent(def_id, |this| { - for f in fields { - this.visit_field_def(f); - } - }); - } + // Anonymous structs or unions are visited later after defined. + TyKind::AnonStruct(..) | TyKind::AnonUnion(..) => {} _ => visit::walk_ty(self, ty), } } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 43ab476056af6..60453f5ab9c1d 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2216,11 +2216,9 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // if all of its fields are `Copy` and `Clone` ty::Adt(adt, args) if adt.is_anonymous() => { // (*) binder moved here - Where( - obligation - .predicate - .rebind(adt.non_enum_variant().fields.iter().map(|f| f.ty(self.tcx(), args)).collect()), - ) + Where(obligation.predicate.rebind( + adt.non_enum_variant().fields.iter().map(|f| f.ty(self.tcx(), args)).collect(), + )) } ty::Adt(..) | ty::Alias(..) | ty::Param(..) | ty::Placeholder(..) => { diff --git a/tests/mir-opt/unnamed-fields/field_access.bar.SimplifyCfg-initial.after.mir b/tests/mir-opt/unnamed-fields/field_access.bar.SimplifyCfg-initial.after.mir index 2a57b272f9beb..8edc7b5df88f9 100644 --- a/tests/mir-opt/unnamed-fields/field_access.bar.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/unnamed-fields/field_access.bar.SimplifyCfg-initial.after.mir @@ -26,7 +26,7 @@ fn bar(_1: Bar) -> () { StorageDead(_2); StorageLive(_4); StorageLive(_5); - _5 = ((_1.1: Bar::_::{anon_adt#0}).0: i8); + _5 = ((_1.1: Bar::{anon_adt#0}).0: i8); _4 = access::(move _5) -> [return: bb2, unwind: bb5]; } @@ -35,7 +35,7 @@ fn bar(_1: Bar) -> () { StorageDead(_4); StorageLive(_6); StorageLive(_7); - _7 = ((_1.1: Bar::_::{anon_adt#0}).1: bool); + _7 = ((_1.1: Bar::{anon_adt#0}).1: bool); _6 = access::(move _7) -> [return: bb3, unwind: bb5]; } @@ -44,7 +44,7 @@ fn bar(_1: Bar) -> () { StorageDead(_6); StorageLive(_8); StorageLive(_9); - _9 = (((_1.2: Bar::_::{anon_adt#0}).0: Bar::_::{anon_adt#0}::_::{anon_adt#0}).0: [u8; 1]); + _9 = (((_1.2: Bar::{anon_adt#1}).0: Bar::{anon_adt#1}::{anon_adt#0}).0: [u8; 1]); _8 = access::<[u8; 1]>(move _9) -> [return: bb4, unwind: bb5]; } diff --git a/tests/mir-opt/unnamed-fields/field_access.foo.SimplifyCfg-initial.after.mir b/tests/mir-opt/unnamed-fields/field_access.foo.SimplifyCfg-initial.after.mir index 8b10a6f13ceda..d48a969f06ebd 100644 --- a/tests/mir-opt/unnamed-fields/field_access.foo.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/unnamed-fields/field_access.foo.SimplifyCfg-initial.after.mir @@ -24,7 +24,7 @@ fn foo(_1: Foo) -> () { StorageDead(_2); StorageLive(_4); StorageLive(_5); - _5 = ((_1.1: Foo::_::{anon_adt#0}).0: i8); + _5 = ((_1.1: Foo::{anon_adt#0}).0: i8); _4 = access::(move _5) -> [return: bb2, unwind: bb5]; } @@ -33,7 +33,7 @@ fn foo(_1: Foo) -> () { StorageDead(_4); StorageLive(_6); StorageLive(_7); - _7 = ((_1.1: Foo::_::{anon_adt#0}).1: bool); + _7 = ((_1.1: Foo::{anon_adt#0}).1: bool); _6 = access::(move _7) -> [return: bb3, unwind: bb5]; } @@ -42,7 +42,7 @@ fn foo(_1: Foo) -> () { StorageDead(_6); StorageLive(_8); StorageLive(_9); - _9 = (((_1.2: Foo::_::{anon_adt#0}).0: Foo::_::{anon_adt#0}::_::{anon_adt#0}).0: [u8; 1]); + _9 = (((_1.2: Foo::{anon_adt#1}).0: Foo::{anon_adt#1}::{anon_adt#0}).0: [u8; 1]); _8 = access::<[u8; 1]>(move _9) -> [return: bb4, unwind: bb5]; } diff --git a/tests/ui/feature-gates/feature-gate-unnamed_fields.rs b/tests/ui/feature-gates/feature-gate-unnamed_fields.rs index 6ee8de8956428..302a9bbeb4518 100644 --- a/tests/ui/feature-gates/feature-gate-unnamed_fields.rs +++ b/tests/ui/feature-gates/feature-gate-unnamed_fields.rs @@ -1,3 +1,4 @@ +#[repr(C)] struct Foo { foo: u8, _: union { //~ ERROR unnamed fields are not yet fully implemented [E0658] @@ -7,6 +8,7 @@ struct Foo { } } +#[repr(C)] union Bar { foobar: u8, _: struct { //~ ERROR unnamed fields are not yet fully implemented [E0658] @@ -16,7 +18,10 @@ union Bar { } } +#[repr(C)] struct S; + +#[repr(C)] struct Baz { _: S //~ ERROR unnamed fields are not yet fully implemented [E0658] } diff --git a/tests/ui/feature-gates/feature-gate-unnamed_fields.stderr b/tests/ui/feature-gates/feature-gate-unnamed_fields.stderr index 8fa342c08ae29..bc9e95bab989a 100644 --- a/tests/ui/feature-gates/feature-gate-unnamed_fields.stderr +++ b/tests/ui/feature-gates/feature-gate-unnamed_fields.stderr @@ -1,5 +1,5 @@ error[E0658]: unnamed fields are not yet fully implemented - --> $DIR/feature-gate-unnamed_fields.rs:3:5 + --> $DIR/feature-gate-unnamed_fields.rs:4:5 | LL | _: union { | ^ @@ -9,7 +9,7 @@ LL | _: union { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: unnamed fields are not yet fully implemented - --> $DIR/feature-gate-unnamed_fields.rs:3:8 + --> $DIR/feature-gate-unnamed_fields.rs:4:8 | LL | _: union { | ________^ @@ -24,7 +24,7 @@ LL | | } = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: unnamed fields are not yet fully implemented - --> $DIR/feature-gate-unnamed_fields.rs:12:5 + --> $DIR/feature-gate-unnamed_fields.rs:14:5 | LL | _: struct { | ^ @@ -34,7 +34,7 @@ LL | _: struct { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: unnamed fields are not yet fully implemented - --> $DIR/feature-gate-unnamed_fields.rs:12:8 + --> $DIR/feature-gate-unnamed_fields.rs:14:8 | LL | _: struct { | ________^ @@ -49,7 +49,7 @@ LL | | } = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: unnamed fields are not yet fully implemented - --> $DIR/feature-gate-unnamed_fields.rs:21:5 + --> $DIR/feature-gate-unnamed_fields.rs:26:5 | LL | _: S | ^ diff --git a/tests/ui/union/unnamed-fields/repr_check.rs b/tests/ui/union/unnamed-fields/repr_check.rs new file mode 100644 index 0000000000000..b50b54b20afe6 --- /dev/null +++ b/tests/ui/union/unnamed-fields/repr_check.rs @@ -0,0 +1,69 @@ +#![allow(incomplete_features)] +#![feature(unnamed_fields)] + +struct A { //~ ERROR struct with unnamed fields must have `#[repr(C)]` representation + //~^ NOTE struct `A` defined here + _: struct { //~ NOTE unnamed field defined here + a: i32, + }, + _: struct { //~ NOTE unnamed field defined here + _: struct { + b: i32, + }, + }, +} + +union B { //~ ERROR union with unnamed fields must have `#[repr(C)]` representation + //~^ NOTE union `B` defined here + _: union { //~ NOTE unnamed field defined here + a: i32, + }, + _: union { //~ NOTE unnamed field defined here + _: union { + b: i32, + }, + }, +} + +#[derive(Clone, Copy)] +#[repr(C)] +struct Foo {} + +#[derive(Clone, Copy)] +struct Bar {} +//~^ `Bar` defined here +//~| `Bar` defined here +//~| `Bar` defined here +//~| `Bar` defined here + +struct C { //~ ERROR struct with unnamed fields must have `#[repr(C)]` representation + //~^ NOTE struct `C` defined here + _: Foo, //~ NOTE unnamed field defined here +} + +union D { //~ ERROR union with unnamed fields must have `#[repr(C)]` representation + //~^ NOTE union `D` defined here + _: Foo, //~ NOTE unnamed field defined here +} + +#[repr(C)] +struct E { + _: Bar, //~ ERROR named type of unnamed field must have `#[repr(C)]` representation + //~^ NOTE unnamed field defined here + _: struct { + _: Bar, //~ ERROR named type of unnamed field must have `#[repr(C)]` representation + //~^ NOTE unnamed field defined here + }, +} + +#[repr(C)] +union F { + _: Bar, //~ ERROR named type of unnamed field must have `#[repr(C)]` representation + //~^ NOTE unnamed field defined here + _: union { + _: Bar, //~ ERROR named type of unnamed field must have `#[repr(C)]` representation + //~^ NOTE unnamed field defined here + }, +} + +fn main() {} diff --git a/tests/ui/union/unnamed-fields/repr_check.stderr b/tests/ui/union/unnamed-fields/repr_check.stderr new file mode 100644 index 0000000000000..ca6a1f3a7800d --- /dev/null +++ b/tests/ui/union/unnamed-fields/repr_check.stderr @@ -0,0 +1,108 @@ +error: struct with unnamed fields must have `#[repr(C)]` representation + --> $DIR/repr_check.rs:4:1 + | +LL | struct A { + | ^^^^^^^^ struct `A` defined here + | +note: unnamed field defined here + --> $DIR/repr_check.rs:6:5 + | +LL | / _: struct { +LL | | a: i32, +LL | | }, + | |_____^ +note: unnamed field defined here + --> $DIR/repr_check.rs:9:5 + | +LL | / _: struct { +LL | | _: struct { +LL | | b: i32, +LL | | }, +LL | | }, + | |_____^ + +error: union with unnamed fields must have `#[repr(C)]` representation + --> $DIR/repr_check.rs:16:1 + | +LL | union B { + | ^^^^^^^ union `B` defined here + | +note: unnamed field defined here + --> $DIR/repr_check.rs:18:5 + | +LL | / _: union { +LL | | a: i32, +LL | | }, + | |_____^ +note: unnamed field defined here + --> $DIR/repr_check.rs:21:5 + | +LL | / _: union { +LL | | _: union { +LL | | b: i32, +LL | | }, +LL | | }, + | |_____^ + +error: struct with unnamed fields must have `#[repr(C)]` representation + --> $DIR/repr_check.rs:39:1 + | +LL | struct C { + | ^^^^^^^^ struct `C` defined here + | +note: unnamed field defined here + --> $DIR/repr_check.rs:41:5 + | +LL | _: Foo, + | ^^^^^^ + +error: union with unnamed fields must have `#[repr(C)]` representation + --> $DIR/repr_check.rs:44:1 + | +LL | union D { + | ^^^^^^^ union `D` defined here + | +note: unnamed field defined here + --> $DIR/repr_check.rs:46:5 + | +LL | _: Foo, + | ^^^^^^ + +error: named type of unnamed field must have `#[repr(C)]` representation + --> $DIR/repr_check.rs:51:5 + | +LL | struct Bar {} + | ---------- `Bar` defined here +... +LL | _: Bar, + | ^^^^^^ unnamed field defined here + +error: named type of unnamed field must have `#[repr(C)]` representation + --> $DIR/repr_check.rs:54:9 + | +LL | struct Bar {} + | ---------- `Bar` defined here +... +LL | _: Bar, + | ^^^^^^ unnamed field defined here + +error: named type of unnamed field must have `#[repr(C)]` representation + --> $DIR/repr_check.rs:61:5 + | +LL | struct Bar {} + | ---------- `Bar` defined here +... +LL | _: Bar, + | ^^^^^^ unnamed field defined here + +error: named type of unnamed field must have `#[repr(C)]` representation + --> $DIR/repr_check.rs:64:9 + | +LL | struct Bar {} + | ---------- `Bar` defined here +... +LL | _: Bar, + | ^^^^^^ unnamed field defined here + +error: aborting due to 8 previous errors + From 822d6dc5fd01356a8d07cfeb06b2a0a244bfe2da Mon Sep 17 00:00:00 2001 From: Frank King Date: Thu, 18 Jan 2024 14:35:14 +0800 Subject: [PATCH 6/8] Fix compile error in rustdoc. --- src/librustdoc/clean/mod.rs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index b697f945f2003..0b705df2a6064 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1892,15 +1892,8 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T TyKind::BareFn(barefn) => BareFunction(Box::new(clean_bare_fn_ty(barefn, cx))), // Rustdoc handles `TyKind::Err`s by turning them into `Type::Infer`s. TyKind::Infer | TyKind::Err(_) | TyKind::Typeof(..) | TyKind::InferDelegation(..) => Infer, - TyKind::AnonAdt(item_id) => { - let path = external_path( - cx, - item_id.owner_id.def_id.to_def_id(), - false, - ThinVec::new(), - ty::Binder::dummy(ty::GenericArgs::empty()), - ); - Type::Path { path } + TyKind::AnonAdt(..) => { + unimplemented!("Anonymous structs or unions are not supported yet") } } } From 2b04ca94bb06c6913b8b14ba267b3d64b23e3c4d Mon Sep 17 00:00:00 2001 From: Frank King Date: Sat, 20 Jan 2024 12:55:21 +0800 Subject: [PATCH 7/8] Add `#[derive(Clone, Copy)]` to anonymous adts Fix the `AssertBoundIsClone` error for anonymous adts. --- compiler/rustc_ast/src/ast.rs | 4 + .../src/deriving/clone.rs | 4 +- .../rustc_builtin_macros/src/deriving/mod.rs | 2 + .../unnamed-fields/field_uniqueness_check.rs | 9 + .../field_uniqueness_check.stderr | 350 +++++++++--------- 5 files changed, 193 insertions(+), 176 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index e41228bd501a9..098e2606a3be9 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2161,6 +2161,10 @@ impl TyKind { None } } + + pub fn is_anon_adt(&self) -> bool { + matches!(self, TyKind::AnonStruct(..) | TyKind::AnonUnion(..)) + } } /// Syntax used to declare a trait object. diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index 7bf19f6116686..267405ac32e24 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -110,7 +110,9 @@ fn cs_clone_simple( && !seen_type_names.insert(name) { // Already produced an assertion for this type. - } else { + // Anonymous structs or unions must be eliminated as they cannot be + // type parameters. + } else if !field.ty.kind.is_anon_adt() { // let _: AssertParamIsClone; super::assert_ty_bounds( cx, diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs index a6f3252e7be16..8a3375cba9dc1 100644 --- a/compiler/rustc_builtin_macros/src/deriving/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs @@ -123,6 +123,8 @@ fn assert_ty_bounds( span: Span, assert_path: &[Symbol], ) { + // Deny anonymous structs or unions to avoid wierd errors. + assert!(!ty.kind.is_anon_adt(), "Anonymous structs or unions cannot be type parameters"); // Generate statement `let _: assert_path;`. let span = cx.with_def_site_ctxt(span); let assert_path = cx.path_all(span, true, cx.std_path(assert_path), vec![GenericArg::Type(ty)]); diff --git a/tests/ui/union/unnamed-fields/field_uniqueness_check.rs b/tests/ui/union/unnamed-fields/field_uniqueness_check.rs index 3cc3621187530..ddb951aa06cac 100644 --- a/tests/ui/union/unnamed-fields/field_uniqueness_check.rs +++ b/tests/ui/union/unnamed-fields/field_uniqueness_check.rs @@ -1,11 +1,13 @@ #![allow(incomplete_features)] #![feature(unnamed_fields)] +#[derive(Clone, Copy)] #[repr(C)] struct Foo { a: u8, } +#[derive(Clone, Copy)] #[repr(C)] struct Bar { _: union { @@ -15,6 +17,7 @@ struct Bar { // duplicated with a normal field +#[derive(Clone, Copy)] #[repr(C)] union A { // referent field @@ -44,6 +47,7 @@ union A { } // duplicated with a nested field +#[derive(Clone, Copy)] #[repr(C)] struct B { _: union { @@ -95,6 +99,7 @@ struct B { } // duplicated with a more nested field +#[derive(Clone, Copy)] #[repr(C)] union C { _: struct { @@ -168,6 +173,7 @@ union C { } // duplicated with a nested field in a named adt +#[derive(Clone, Copy)] #[repr(C)] struct D { // referent field `a` @@ -196,6 +202,7 @@ struct D { } // duplicated with a nested field in a nested field of a named adt +#[derive(Clone, Copy)] #[repr(C)] union D2 { // referent field `a` @@ -224,6 +231,7 @@ union D2 { } // duplicated with a nested field in a named adt in an anonymous adt +#[derive(Clone, Copy)] #[repr(C)] struct E { _: struct { @@ -276,6 +284,7 @@ struct E { // duplicated with a nested field in a named adt in an anonymous adt #[repr(C)] +#[derive(Clone, Copy)] union E2 { _: struct { // referent field `a` diff --git a/tests/ui/union/unnamed-fields/field_uniqueness_check.stderr b/tests/ui/union/unnamed-fields/field_uniqueness_check.stderr index 4dea0aa4233bf..5773d3bb03931 100644 --- a/tests/ui/union/unnamed-fields/field_uniqueness_check.stderr +++ b/tests/ui/union/unnamed-fields/field_uniqueness_check.stderr @@ -1,5 +1,5 @@ error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:24:5 + --> $DIR/field_uniqueness_check.rs:27:5 | LL | a: u8, | ----- `a` first declared here @@ -8,7 +8,7 @@ LL | a: u8, | ^^^^^ field already declared error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:27:9 + --> $DIR/field_uniqueness_check.rs:30:9 | LL | a: u8, | ----- `a` first declared here @@ -17,7 +17,7 @@ LL | a: u8, | ^^^^^ field already declared error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:28:9 + --> $DIR/field_uniqueness_check.rs:31:9 | LL | a: u8, | ----- `a` first declared here @@ -26,7 +26,7 @@ LL | a: u8, | ^^^^^ field already declared error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:33:13 + --> $DIR/field_uniqueness_check.rs:36:13 | LL | a: u8, | ----- `a` first declared here @@ -35,7 +35,7 @@ LL | a: u8, | ^^^^^ field already declared error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:37:5 + --> $DIR/field_uniqueness_check.rs:40:5 | LL | a: u8, | ----- `a` first declared here @@ -44,13 +44,13 @@ LL | _: Foo, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:38:5 + --> $DIR/field_uniqueness_check.rs:41:5 | LL | a: u8, | ----- `a` first declared here @@ -59,13 +59,13 @@ LL | _: Bar, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:41:9 + --> $DIR/field_uniqueness_check.rs:44:9 | LL | a: u8, | ----- `a` first declared here @@ -74,13 +74,13 @@ LL | _: Foo, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:42:9 + --> $DIR/field_uniqueness_check.rs:45:9 | LL | a: u8, | ----- `a` first declared here @@ -89,13 +89,13 @@ LL | _: Bar, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:54:9 + --> $DIR/field_uniqueness_check.rs:58:9 | LL | a: u8, | ----- `a` first declared here @@ -104,7 +104,7 @@ LL | a: u8, | ^^^^^ field already declared error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:57:13 + --> $DIR/field_uniqueness_check.rs:61:13 | LL | a: u8, | ----- `a` first declared here @@ -113,7 +113,7 @@ LL | a: u8, | ^^^^^ field already declared error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:62:17 + --> $DIR/field_uniqueness_check.rs:66:17 | LL | a: u8, | ----- `a` first declared here @@ -122,7 +122,7 @@ LL | a: u8, | ^^^^^ field already declared error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:66:9 + --> $DIR/field_uniqueness_check.rs:70:9 | LL | a: u8, | ----- `a` first declared here @@ -131,13 +131,13 @@ LL | _: Foo, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:67:9 + --> $DIR/field_uniqueness_check.rs:71:9 | LL | a: u8, | ----- `a` first declared here @@ -146,13 +146,13 @@ LL | _: Bar, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:70:13 + --> $DIR/field_uniqueness_check.rs:74:13 | LL | a: u8, | ----- `a` first declared here @@ -161,13 +161,13 @@ LL | _: Foo, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:71:13 + --> $DIR/field_uniqueness_check.rs:75:13 | LL | a: u8, | ----- `a` first declared here @@ -176,13 +176,13 @@ LL | _: Bar, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:76:5 + --> $DIR/field_uniqueness_check.rs:80:5 | LL | a: u8, | ----- `a` first declared here @@ -191,7 +191,7 @@ LL | a: u8, | ^^^^^ field already declared error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:79:9 + --> $DIR/field_uniqueness_check.rs:83:9 | LL | a: u8, | ----- `a` first declared here @@ -200,7 +200,7 @@ LL | a: u8, | ^^^^^ field already declared error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:84:13 + --> $DIR/field_uniqueness_check.rs:88:13 | LL | a: u8, | ----- `a` first declared here @@ -209,7 +209,7 @@ LL | a: u8, | ^^^^^ field already declared error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:88:5 + --> $DIR/field_uniqueness_check.rs:92:5 | LL | a: u8, | ----- `a` first declared here @@ -218,13 +218,13 @@ LL | _: Foo, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:89:5 + --> $DIR/field_uniqueness_check.rs:93:5 | LL | a: u8, | ----- `a` first declared here @@ -233,13 +233,13 @@ LL | _: Bar, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:92:9 + --> $DIR/field_uniqueness_check.rs:96:9 | LL | a: u8, | ----- `a` first declared here @@ -248,13 +248,13 @@ LL | _: Foo, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:93:9 + --> $DIR/field_uniqueness_check.rs:97:9 | LL | a: u8, | ----- `a` first declared here @@ -263,13 +263,13 @@ LL | _: Bar, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:106:13 + --> $DIR/field_uniqueness_check.rs:111:13 | LL | a: u8, | ----- `a` first declared here @@ -278,7 +278,7 @@ LL | a: u8, | ^^^^^ field already declared error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:109:17 + --> $DIR/field_uniqueness_check.rs:114:17 | LL | a: u8, | ----- `a` first declared here @@ -287,7 +287,7 @@ LL | a: u8, | ^^^^^ field already declared error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:114:21 + --> $DIR/field_uniqueness_check.rs:119:21 | LL | a: u8, | ----- `a` first declared here @@ -296,7 +296,7 @@ LL | a: u8, | ^^^^^ field already declared error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:118:13 + --> $DIR/field_uniqueness_check.rs:123:13 | LL | a: u8, | ----- `a` first declared here @@ -305,13 +305,13 @@ LL | _: Foo, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:119:13 + --> $DIR/field_uniqueness_check.rs:124:13 | LL | a: u8, | ----- `a` first declared here @@ -320,13 +320,13 @@ LL | _: Bar, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:122:17 + --> $DIR/field_uniqueness_check.rs:127:17 | LL | a: u8, | ----- `a` first declared here @@ -335,13 +335,13 @@ LL | _: Foo, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:123:17 + --> $DIR/field_uniqueness_check.rs:128:17 | LL | a: u8, | ----- `a` first declared here @@ -350,13 +350,13 @@ LL | _: Bar, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:128:9 + --> $DIR/field_uniqueness_check.rs:133:9 | LL | a: u8, | ----- `a` first declared here @@ -365,7 +365,7 @@ LL | a: u8, | ^^^^^ field already declared error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:131:13 + --> $DIR/field_uniqueness_check.rs:136:13 | LL | a: u8, | ----- `a` first declared here @@ -374,7 +374,7 @@ LL | a: u8, | ^^^^^ field already declared error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:136:17 + --> $DIR/field_uniqueness_check.rs:141:17 | LL | a: u8, | ----- `a` first declared here @@ -383,7 +383,7 @@ LL | a: u8, | ^^^^^ field already declared error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:140:9 + --> $DIR/field_uniqueness_check.rs:145:9 | LL | a: u8, | ----- `a` first declared here @@ -392,13 +392,13 @@ LL | _: Foo, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:141:9 + --> $DIR/field_uniqueness_check.rs:146:9 | LL | a: u8, | ----- `a` first declared here @@ -407,13 +407,13 @@ LL | _: Bar, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:144:13 + --> $DIR/field_uniqueness_check.rs:149:13 | LL | a: u8, | ----- `a` first declared here @@ -422,13 +422,13 @@ LL | _: Foo, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:145:13 + --> $DIR/field_uniqueness_check.rs:150:13 | LL | a: u8, | ----- `a` first declared here @@ -437,13 +437,13 @@ LL | _: Bar, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:149:5 + --> $DIR/field_uniqueness_check.rs:154:5 | LL | a: u8, | ----- `a` first declared here @@ -452,7 +452,7 @@ LL | a: u8, | ^^^^^ field already declared error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:152:9 + --> $DIR/field_uniqueness_check.rs:157:9 | LL | a: u8, | ----- `a` first declared here @@ -461,7 +461,7 @@ LL | a: u8, | ^^^^^ field already declared error[E0124]: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:157:13 + --> $DIR/field_uniqueness_check.rs:162:13 | LL | a: u8, | ----- `a` first declared here @@ -470,7 +470,7 @@ LL | a: u8, | ^^^^^ field already declared error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:161:5 + --> $DIR/field_uniqueness_check.rs:166:5 | LL | a: u8, | ----- `a` first declared here @@ -479,13 +479,13 @@ LL | _: Foo, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:162:5 + --> $DIR/field_uniqueness_check.rs:167:5 | LL | a: u8, | ----- `a` first declared here @@ -494,13 +494,13 @@ LL | _: Bar, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:165:9 + --> $DIR/field_uniqueness_check.rs:170:9 | LL | a: u8, | ----- `a` first declared here @@ -509,13 +509,13 @@ LL | _: Foo, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:166:9 + --> $DIR/field_uniqueness_check.rs:171:9 | LL | a: u8, | ----- `a` first declared here @@ -524,13 +524,13 @@ LL | _: Bar, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:177:5 + --> $DIR/field_uniqueness_check.rs:183:5 | LL | _: Foo, | ------ `a` first declared here in this unnamed field @@ -539,13 +539,13 @@ LL | a: u8, | ^^^^^ field already declared | note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:180:9 + --> $DIR/field_uniqueness_check.rs:186:9 | LL | _: Foo, | ------ `a` first declared here in this unnamed field @@ -554,13 +554,13 @@ LL | a: u8, | ^^^^^ field already declared | note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:185:13 + --> $DIR/field_uniqueness_check.rs:191:13 | LL | _: Foo, | ------ `a` first declared here in this unnamed field @@ -569,13 +569,13 @@ LL | a: u8, | ^^^^^ field already declared | note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:189:5 + --> $DIR/field_uniqueness_check.rs:195:5 | LL | _: Foo, | ------ `a` first declared here in this unnamed field @@ -584,18 +584,18 @@ LL | _: Foo, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:190:5 + --> $DIR/field_uniqueness_check.rs:196:5 | LL | _: Foo, | ------ `a` first declared here in this unnamed field @@ -604,18 +604,18 @@ LL | _: Bar, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:193:9 + --> $DIR/field_uniqueness_check.rs:199:9 | LL | _: Foo, | ------ `a` first declared here in this unnamed field @@ -624,18 +624,18 @@ LL | _: Foo, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:194:9 + --> $DIR/field_uniqueness_check.rs:200:9 | LL | _: Foo, | ------ `a` first declared here in this unnamed field @@ -644,18 +644,18 @@ LL | _: Bar, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:205:5 + --> $DIR/field_uniqueness_check.rs:212:5 | LL | _: Bar, | ------ `a` first declared here in this unnamed field @@ -664,13 +664,13 @@ LL | a: u8, | ^^^^^ field already declared | note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:208:9 + --> $DIR/field_uniqueness_check.rs:215:9 | LL | _: Bar, | ------ `a` first declared here in this unnamed field @@ -679,13 +679,13 @@ LL | a: u8, | ^^^^^ field already declared | note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:213:13 + --> $DIR/field_uniqueness_check.rs:220:13 | LL | _: Bar, | ------ `a` first declared here in this unnamed field @@ -694,13 +694,13 @@ LL | a: u8, | ^^^^^ field already declared | note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:217:5 + --> $DIR/field_uniqueness_check.rs:224:5 | LL | _: Bar, | ------ `a` first declared here in this unnamed field @@ -709,18 +709,18 @@ LL | _: Foo, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:218:5 + --> $DIR/field_uniqueness_check.rs:225:5 | LL | _: Bar, | ------ `a` first declared here in this unnamed field @@ -729,18 +729,18 @@ LL | _: Bar, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:221:9 + --> $DIR/field_uniqueness_check.rs:228:9 | LL | _: Bar, | ------ `a` first declared here in this unnamed field @@ -749,18 +749,18 @@ LL | _: Foo, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:222:9 + --> $DIR/field_uniqueness_check.rs:229:9 | LL | _: Bar, | ------ `a` first declared here in this unnamed field @@ -769,18 +769,18 @@ LL | _: Bar, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:234:9 + --> $DIR/field_uniqueness_check.rs:242:9 | LL | _: Foo, | ------ `a` first declared here in this unnamed field @@ -789,13 +789,13 @@ LL | a: u8, | ^^^^^ field already declared | note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:237:13 + --> $DIR/field_uniqueness_check.rs:245:13 | LL | _: Foo, | ------ `a` first declared here in this unnamed field @@ -804,13 +804,13 @@ LL | a: u8, | ^^^^^ field already declared | note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:242:17 + --> $DIR/field_uniqueness_check.rs:250:17 | LL | _: Foo, | ------ `a` first declared here in this unnamed field @@ -819,13 +819,13 @@ LL | a: u8, | ^^^^^ field already declared | note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:246:9 + --> $DIR/field_uniqueness_check.rs:254:9 | LL | _: Foo, | ------ `a` first declared here in this unnamed field @@ -834,18 +834,18 @@ LL | _: Foo, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:247:9 + --> $DIR/field_uniqueness_check.rs:255:9 | LL | _: Foo, | ------ `a` first declared here in this unnamed field @@ -854,18 +854,18 @@ LL | _: Bar, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:250:13 + --> $DIR/field_uniqueness_check.rs:258:13 | LL | _: Foo, | ------ `a` first declared here in this unnamed field @@ -874,18 +874,18 @@ LL | _: Foo, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:251:13 + --> $DIR/field_uniqueness_check.rs:259:13 | LL | _: Foo, | ------ `a` first declared here in this unnamed field @@ -894,18 +894,18 @@ LL | _: Bar, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:256:5 + --> $DIR/field_uniqueness_check.rs:264:5 | LL | _: Foo, | ------ `a` first declared here in this unnamed field @@ -914,13 +914,13 @@ LL | a: u8, | ^^^^^ field already declared | note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:259:9 + --> $DIR/field_uniqueness_check.rs:267:9 | LL | _: Foo, | ------ `a` first declared here in this unnamed field @@ -929,13 +929,13 @@ LL | a: u8, | ^^^^^ field already declared | note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:264:13 + --> $DIR/field_uniqueness_check.rs:272:13 | LL | _: Foo, | ------ `a` first declared here in this unnamed field @@ -944,13 +944,13 @@ LL | a: u8, | ^^^^^ field already declared | note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:268:5 + --> $DIR/field_uniqueness_check.rs:276:5 | LL | _: Foo, | ------ `a` first declared here in this unnamed field @@ -959,18 +959,18 @@ LL | _: Foo, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:269:5 + --> $DIR/field_uniqueness_check.rs:277:5 | LL | _: Foo, | ------ `a` first declared here in this unnamed field @@ -979,18 +979,18 @@ LL | _: Bar, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:272:9 + --> $DIR/field_uniqueness_check.rs:280:9 | LL | _: Foo, | ------ `a` first declared here in this unnamed field @@ -999,18 +999,18 @@ LL | _: Foo, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:273:9 + --> $DIR/field_uniqueness_check.rs:281:9 | LL | _: Foo, | ------ `a` first declared here in this unnamed field @@ -1019,18 +1019,18 @@ LL | _: Bar, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:285:9 + --> $DIR/field_uniqueness_check.rs:294:9 | LL | _: Bar, | ------ `a` first declared here in this unnamed field @@ -1039,13 +1039,13 @@ LL | a: u8, | ^^^^^ field already declared | note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:288:13 + --> $DIR/field_uniqueness_check.rs:297:13 | LL | _: Bar, | ------ `a` first declared here in this unnamed field @@ -1054,13 +1054,13 @@ LL | a: u8, | ^^^^^ field already declared | note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:293:17 + --> $DIR/field_uniqueness_check.rs:302:17 | LL | _: Bar, | ------ `a` first declared here in this unnamed field @@ -1069,13 +1069,13 @@ LL | a: u8, | ^^^^^ field already declared | note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:297:9 + --> $DIR/field_uniqueness_check.rs:306:9 | LL | _: Bar, | ------ `a` first declared here in this unnamed field @@ -1084,18 +1084,18 @@ LL | _: Foo, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:298:9 + --> $DIR/field_uniqueness_check.rs:307:9 | LL | _: Bar, | ------ `a` first declared here in this unnamed field @@ -1104,18 +1104,18 @@ LL | _: Bar, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:301:13 + --> $DIR/field_uniqueness_check.rs:310:13 | LL | _: Bar, | ------ `a` first declared here in this unnamed field @@ -1124,18 +1124,18 @@ LL | _: Foo, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:302:13 + --> $DIR/field_uniqueness_check.rs:311:13 | LL | _: Bar, | ------ `a` first declared here in this unnamed field @@ -1144,18 +1144,18 @@ LL | _: Bar, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:307:5 + --> $DIR/field_uniqueness_check.rs:316:5 | LL | _: Bar, | ------ `a` first declared here in this unnamed field @@ -1164,13 +1164,13 @@ LL | a: u8, | ^^^^^ field already declared | note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:310:9 + --> $DIR/field_uniqueness_check.rs:319:9 | LL | _: Bar, | ------ `a` first declared here in this unnamed field @@ -1179,13 +1179,13 @@ LL | a: u8, | ^^^^^ field already declared | note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:315:13 + --> $DIR/field_uniqueness_check.rs:324:13 | LL | _: Bar, | ------ `a` first declared here in this unnamed field @@ -1194,13 +1194,13 @@ LL | a: u8, | ^^^^^ field already declared | note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:319:5 + --> $DIR/field_uniqueness_check.rs:328:5 | LL | _: Bar, | ------ `a` first declared here in this unnamed field @@ -1209,18 +1209,18 @@ LL | _: Foo, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:320:5 + --> $DIR/field_uniqueness_check.rs:329:5 | LL | _: Bar, | ------ `a` first declared here in this unnamed field @@ -1229,18 +1229,18 @@ LL | _: Bar, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:323:9 + --> $DIR/field_uniqueness_check.rs:332:9 | LL | _: Bar, | ------ `a` first declared here in this unnamed field @@ -1249,18 +1249,18 @@ LL | _: Foo, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:6:5 + --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ error: field `a` is already declared - --> $DIR/field_uniqueness_check.rs:324:9 + --> $DIR/field_uniqueness_check.rs:333:9 | LL | _: Bar, | ------ `a` first declared here in this unnamed field @@ -1269,12 +1269,12 @@ LL | _: Bar, | ^^^^^^ field `a` declared in this unnamed field | note: field `a` declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ note: field `a` first declared here - --> $DIR/field_uniqueness_check.rs:12:9 + --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ From 0dbd6e9572c7c2bac7922116d6cd9357177ccbc9 Mon Sep 17 00:00:00 2001 From: Frank King Date: Mon, 29 Jan 2024 15:08:11 +0800 Subject: [PATCH 8/8] Improve some codes according to the reviews - improve diagnostics of field uniqueness check and representation check - simplify the implementation of field uniqueness check - remove some useless codes and improvement neatness --- compiler/rustc_hir_analysis/messages.ftl | 5 + .../rustc_hir_analysis/src/check/check.rs | 6 +- compiler/rustc_hir_analysis/src/collect.rs | 232 ++++----- compiler/rustc_hir_analysis/src/errors.rs | 20 + .../rustc_resolve/src/build_reduced_graph.rs | 10 +- .../src/solve/assembly/structural_traits.rs | 5 - src/librustdoc/clean/types.rs | 4 - .../field_uniqueness_check.stderr | 450 ++++++++++++++++++ .../ui/union/unnamed-fields/repr_check.stderr | 44 ++ 9 files changed, 655 insertions(+), 121 deletions(-) diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index cf1a42c928521..537b7d9470d2e 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -136,6 +136,9 @@ hir_analysis_field_already_declared_current_nested = .nested_field_decl_note = field `{$field_name}` declared here .previous_decl_label = `{$field_name}` first declared here +hir_analysis_field_already_declared_nested_help = + fields from the type of this unnamed field are considered fields of the outer type + hir_analysis_field_already_declared_previous_nested = field `{$field_name}` is already declared .label = field already declared @@ -445,10 +448,12 @@ hir_analysis_unnamed_fields_repr_field_missing_repr_c = named type of unnamed field must have `#[repr(C)]` representation .label = unnamed field defined here .field_ty_label = `{$field_ty}` defined here + .suggestion = add `#[repr(C)]` to this {$field_adt_kind} hir_analysis_unnamed_fields_repr_missing_repr_c = {$adt_kind} with unnamed fields must have `#[repr(C)]` representation .label = {$adt_kind} `{$adt_name}` defined here + .suggestion = add `#[repr(C)]` to this {$adt_kind} hir_analysis_unrecognized_atomic_operation = unrecognized atomic operation function: `{$op}` diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 3cbd67a482cd1..f55cba2707c5b 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -122,6 +122,7 @@ fn check_unnamed_fields(tcx: TyCtxt<'_>, def: ty::AdtDef<'_>) { adt_kind, adt_name, unnamed_fields, + sugg_span: span.shrink_to_lo(), }); } } @@ -131,10 +132,13 @@ fn check_unnamed_fields(tcx: TyCtxt<'_>, def: ty::AdtDef<'_>) { && !adt.is_anonymous() && !adt.repr().c() { + let field_ty_span = tcx.def_span(adt.did()); tcx.dcx().emit_err(errors::UnnamedFieldsRepr::FieldMissingReprC { span: tcx.def_span(field.did), - field_ty_span: tcx.def_span(adt.did()), + field_ty_span, field_ty, + field_adt_kind: adt.descr(), + sugg_span: field_ty_span.shrink_to_lo(), }); } } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 45938eacd6520..d92e1a141516d 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -791,12 +791,30 @@ fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) { } } +fn find_field(tcx: TyCtxt<'_>, (def_id, ident): (DefId, Ident)) -> Option { + tcx.adt_def(def_id).non_enum_variant().fields.iter_enumerated().find_map(|(idx, field)| { + if field.is_unnamed() { + let field_ty = tcx.type_of(field.did).instantiate_identity(); + let adt_def = field_ty.ty_adt_def().expect("expect Adt for unnamed field"); + tcx.find_field((adt_def.did(), ident)).map(|_| idx) + } else { + (field.ident(tcx).normalize_to_macros_2_0() == ident).then_some(idx) + } + }) +} + #[derive(Clone, Copy)] struct NestedSpan { span: Span, nested_field_span: Span, } +impl NestedSpan { + fn to_field_already_declared_nested_help(&self) -> errors::FieldAlreadyDeclaredNestedHelp { + errors::FieldAlreadyDeclaredNestedHelp { span: self.span } + } +} + #[derive(Clone, Copy)] enum FieldDeclSpan { NotNested(Span), @@ -815,87 +833,131 @@ impl From for FieldDeclSpan { } } -/// Check the uniqueness of fields across adt where there are -/// nested fields imported from an unnamed field. -fn check_field_uniqueness_in_nested_adt( - tcx: TyCtxt<'_>, - adt_def: ty::AdtDef<'_>, - check: &mut impl FnMut(Ident, /* nested_field_span */ Span), -) { - for field in adt_def.all_fields() { - if field.is_unnamed() { - // Here we don't care about the generic parameters, so `instantiate_identity` is enough. - match tcx.type_of(field.did).instantiate_identity().kind() { - ty::Adt(adt_def, _) => { - check_field_uniqueness_in_nested_adt(tcx, *adt_def, &mut *check); +struct FieldUniquenessCheckContext<'tcx> { + tcx: TyCtxt<'tcx>, + seen_fields: FxHashMap, +} + +impl<'tcx> FieldUniquenessCheckContext<'tcx> { + fn new(tcx: TyCtxt<'tcx>) -> Self { + Self { tcx, seen_fields: FxHashMap::default() } + } + + /// Check if a given field `ident` declared at `field_decl` has been declared elsewhere before. + fn check_field_decl(&mut self, ident: Ident, field_decl: FieldDeclSpan) { + use FieldDeclSpan::*; + let field_name = ident.name; + let ident = ident.normalize_to_macros_2_0(); + match (field_decl, self.seen_fields.get(&ident).copied()) { + (NotNested(span), Some(NotNested(prev_span))) => { + self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::NotNested { + field_name, + span, + prev_span, + }); + } + (NotNested(span), Some(Nested(prev))) => { + self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::PreviousNested { + field_name, + span, + prev_span: prev.span, + prev_nested_field_span: prev.nested_field_span, + prev_help: prev.to_field_already_declared_nested_help(), + }); + } + ( + Nested(current @ NestedSpan { span, nested_field_span, .. }), + Some(NotNested(prev_span)), + ) => { + self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::CurrentNested { + field_name, + span, + nested_field_span, + help: current.to_field_already_declared_nested_help(), + prev_span, + }); + } + (Nested(current @ NestedSpan { span, nested_field_span }), Some(Nested(prev))) => { + self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::BothNested { + field_name, + span, + nested_field_span, + help: current.to_field_already_declared_nested_help(), + prev_span: prev.span, + prev_nested_field_span: prev.nested_field_span, + prev_help: prev.to_field_already_declared_nested_help(), + }); + } + (field_decl, None) => { + self.seen_fields.insert(ident, field_decl); + } + } + } + + /// Check the uniqueness of fields across adt where there are + /// nested fields imported from an unnamed field. + fn check_field_in_nested_adt(&mut self, adt_def: ty::AdtDef<'_>, unnamed_field_span: Span) { + for field in adt_def.all_fields() { + if field.is_unnamed() { + // Here we don't care about the generic parameters, so `instantiate_identity` is enough. + match self.tcx.type_of(field.did).instantiate_identity().kind() { + ty::Adt(adt_def, _) => { + self.check_field_in_nested_adt(*adt_def, unnamed_field_span); + } + ty_kind => span_bug!( + self.tcx.def_span(field.did), + "Unexpected TyKind in FieldUniquenessCheckContext::check_field_in_nested_adt(): {ty_kind:?}" + ), } - ty_kind => bug!( - "Unexpected ty kind in check_field_uniqueness_in_nested_adt(): {ty_kind:?}" - ), + } else { + self.check_field_decl( + field.ident(self.tcx), + NestedSpan { + span: unnamed_field_span, + nested_field_span: self.tcx.def_span(field.did), + } + .into(), + ); } - } else { - check(field.ident(tcx), tcx.def_span(field.did)); } } -} -/// Check the uniqueness of fields in a struct variant, and recursively -/// check the nested fields if it is an unnamed field with type of an -/// annoymous adt. -fn check_field_uniqueness( - tcx: TyCtxt<'_>, - field: &hir::FieldDef<'_>, - check: &mut impl FnMut(Ident, FieldDeclSpan), -) { - if field.ident.name == kw::Underscore { - let ty_span = field.ty.span; + /// Check the uniqueness of fields in a struct variant, and recursively + /// check the nested fields if it is an unnamed field with type of an + /// annoymous adt. + fn check_field(&mut self, field: &hir::FieldDef<'_>) { + if field.ident.name != kw::Underscore { + self.check_field_decl(field.ident, field.span.into()); + return; + } match &field.ty.kind { hir::TyKind::AnonAdt(item_id) => { - match &tcx.hir_node(item_id.hir_id()).expect_item().kind { + match &self.tcx.hir_node(item_id.hir_id()).expect_item().kind { hir::ItemKind::Struct(variant_data, ..) | hir::ItemKind::Union(variant_data, ..) => { - variant_data - .fields() - .iter() - .for_each(|f| check_field_uniqueness(tcx, f, &mut *check)); + variant_data.fields().iter().for_each(|f| self.check_field(f)); } item_kind => span_bug!( - ty_span, - "Unexpected item kind in check_field_uniqueness(): {item_kind:?}" + field.ty.span, + "Unexpected ItemKind in FieldUniquenessCheckContext::check_field(): {item_kind:?}" ), } } hir::TyKind::Path(hir::QPath::Resolved(_, hir::Path { res, .. })) => { - check_field_uniqueness_in_nested_adt( - tcx, - tcx.adt_def(res.def_id()), - &mut |ident, nested_field_span| { - check(ident, NestedSpan { span: field.span, nested_field_span }.into()) - }, - ); + self.check_field_in_nested_adt(self.tcx.adt_def(res.def_id()), field.span); } // Abort due to errors (there must be an error if an unnamed field // has any type kind other than an anonymous adt or a named adt) - _ => { - debug_assert!(tcx.dcx().has_errors().is_some()); - tcx.dcx().abort_if_errors() + ty_kind => { + self.tcx.dcx().span_delayed_bug( + field.ty.span, + format!("Unexpected TyKind in FieldUniquenessCheckContext::check_field(): {ty_kind:?}"), + ); + // FIXME: errors during AST validation should abort the compilation before reaching here. + self.tcx.dcx().abort_if_errors(); } } - return; } - check(field.ident, field.span.into()); -} - -fn find_field(tcx: TyCtxt<'_>, (def_id, ident): (DefId, Ident)) -> Option { - tcx.adt_def(def_id).non_enum_variant().fields.iter_enumerated().find_map(|(idx, field)| { - if field.is_unnamed() { - let field_ty = tcx.type_of(field.did).instantiate_identity(); - let adt_def = field_ty.ty_adt_def().expect("expect Adt for unnamed field"); - tcx.find_field((adt_def.did(), ident)).map(|_| idx) - } else { - (field.ident(tcx).normalize_to_macros_2_0() == ident).then_some(idx) - } - }) } fn convert_variant( @@ -909,58 +971,16 @@ fn convert_variant( is_anonymous: bool, ) -> ty::VariantDef { let mut has_unnamed_fields = false; - let mut seen_fields: FxHashMap = Default::default(); + let mut field_uniqueness_check_ctx = FieldUniquenessCheckContext::new(tcx); let fields = def .fields() .iter() .inspect(|f| { has_unnamed_fields |= f.ident.name == kw::Underscore; + // We only check named ADT here because anonymous ADTs are checked inside + // the nammed ADT in which they are defined. if !is_anonymous { - check_field_uniqueness(tcx, f, &mut |ident, field_decl| { - use FieldDeclSpan::*; - let field_name = ident.name; - let ident = ident.normalize_to_macros_2_0(); - match (field_decl, seen_fields.get(&ident).copied()) { - (NotNested(span), Some(NotNested(prev_span))) => { - tcx.dcx().emit_err(errors::FieldAlreadyDeclared::NotNested { - field_name, - span, - prev_span, - }); - } - (NotNested(span), Some(Nested(prev))) => { - tcx.dcx().emit_err(errors::FieldAlreadyDeclared::PreviousNested { - field_name, - span, - prev_span: prev.span, - prev_nested_field_span: prev.nested_field_span, - }); - } - ( - Nested(NestedSpan { span, nested_field_span }), - Some(NotNested(prev_span)), - ) => { - tcx.dcx().emit_err(errors::FieldAlreadyDeclared::CurrentNested { - field_name, - span, - nested_field_span, - prev_span, - }); - } - (Nested(NestedSpan { span, nested_field_span }), Some(Nested(prev))) => { - tcx.dcx().emit_err(errors::FieldAlreadyDeclared::BothNested { - field_name, - span, - nested_field_span, - prev_span: prev.span, - prev_nested_field_span: prev.nested_field_span, - }); - } - (field_decl, None) => { - seen_fields.insert(ident, field_decl); - } - } - }); + field_uniqueness_check_ctx.check_field(f); } }) .map(|f| ty::FieldDef { diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index f7fa3263eaa15..6e163cff7ed93 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -193,6 +193,8 @@ pub enum FieldAlreadyDeclared { span: Span, #[note(hir_analysis_nested_field_decl_note)] nested_field_span: Span, + #[subdiagnostic] + help: FieldAlreadyDeclaredNestedHelp, #[label(hir_analysis_previous_decl_label)] prev_span: Span, }, @@ -206,6 +208,8 @@ pub enum FieldAlreadyDeclared { prev_span: Span, #[note(hir_analysis_previous_nested_field_decl_note)] prev_nested_field_span: Span, + #[subdiagnostic] + prev_help: FieldAlreadyDeclaredNestedHelp, }, #[diag(hir_analysis_field_already_declared_both_nested)] BothNested { @@ -215,13 +219,24 @@ pub enum FieldAlreadyDeclared { span: Span, #[note(hir_analysis_nested_field_decl_note)] nested_field_span: Span, + #[subdiagnostic] + help: FieldAlreadyDeclaredNestedHelp, #[label(hir_analysis_previous_decl_label)] prev_span: Span, #[note(hir_analysis_previous_nested_field_decl_note)] prev_nested_field_span: Span, + #[subdiagnostic] + prev_help: FieldAlreadyDeclaredNestedHelp, }, } +#[derive(Subdiagnostic)] +#[help(hir_analysis_field_already_declared_nested_help)] +pub struct FieldAlreadyDeclaredNestedHelp { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(hir_analysis_copy_impl_on_type_with_dtor, code = E0184)] pub struct CopyImplOnTypeWithDtor { @@ -1583,6 +1598,8 @@ pub enum UnnamedFieldsRepr<'a> { adt_name: Symbol, #[subdiagnostic] unnamed_fields: Vec, + #[suggestion(code = "#[repr(C)]\n")] + sugg_span: Span, }, #[diag(hir_analysis_unnamed_fields_repr_field_missing_repr_c)] FieldMissingReprC { @@ -1592,6 +1609,9 @@ pub enum UnnamedFieldsRepr<'a> { #[label(hir_analysis_field_ty_label)] field_ty_span: Span, field_ty: Ty<'a>, + field_adt_kind: &'static str, + #[suggestion(code = "#[repr(C)]\n")] + sugg_span: Span, }, } diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 6bb9c22b04d42..469d15e421434 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -628,7 +628,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } } - fn build_reduced_graph_for_fields( + fn build_reduced_graph_for_struct_variant( &mut self, fields: &[ast::FieldDef], ident: Ident, @@ -657,14 +657,14 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { let def_id = local_def_id.to_def_id(); let def_kind = self.r.tcx.def_kind(local_def_id); let res = Res::Def(def_kind, def_id); - self.build_reduced_graph_for_fields( + self.build_reduced_graph_for_struct_variant( &nested_fields, Ident::empty(), local_def_id, res, // Anonymous adts inherit visibility from their parent adts. adt_vis, - field.span, + field.ty.span, ); } _ => {} @@ -759,7 +759,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { // These items live in both the type and value namespaces. ItemKind::Struct(ref vdata, _) => { - self.build_reduced_graph_for_fields( + self.build_reduced_graph_for_struct_variant( vdata.fields(), ident, local_def_id, @@ -809,7 +809,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } ItemKind::Union(ref vdata, _) => { - self.build_reduced_graph_for_fields( + self.build_reduced_graph_for_struct_variant( vdata.fields(), ident, local_def_id, diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index e2d5eaded3f3d..819b070cf8b86 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -181,11 +181,6 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( | ty::Ref(_, _, Mutability::Not) | ty::Array(..) => Err(NoSolution), - // Check for anonymous adts. - ty::Adt(adt, generics) if adt.is_anonymous() => { - Ok(adt.non_enum_variant().fields.iter().map(|f| f.ty(ecx.tcx(), generics)).collect()) - } - ty::Dynamic(..) | ty::Str | ty::Slice(_) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 324ce03dcfd70..6710193f9611a 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1511,10 +1511,6 @@ pub(crate) enum Type { /// An `impl Trait`: `impl TraitA + TraitB + ...` ImplTrait(Vec), - // /// An anonymous struct type i.e. `struct { foo: Type }` - // AnonStruct(VariantStruct), - // /// An anonymous union type i.e. `union { bar: Type }` - // AnonUnion(VariantStruct), } impl Type { diff --git a/tests/ui/union/unnamed-fields/field_uniqueness_check.stderr b/tests/ui/union/unnamed-fields/field_uniqueness_check.stderr index 5773d3bb03931..11978386843a4 100644 --- a/tests/ui/union/unnamed-fields/field_uniqueness_check.stderr +++ b/tests/ui/union/unnamed-fields/field_uniqueness_check.stderr @@ -48,6 +48,11 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:40:5 + | +LL | _: Foo, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:41:5 @@ -63,6 +68,11 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:41:5 + | +LL | _: Bar, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:44:9 @@ -78,6 +88,11 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:44:9 + | +LL | _: Foo, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:45:9 @@ -93,6 +108,11 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:45:9 + | +LL | _: Bar, + | ^^^^^^ error[E0124]: field `a` is already declared --> $DIR/field_uniqueness_check.rs:58:9 @@ -135,6 +155,11 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:70:9 + | +LL | _: Foo, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:71:9 @@ -150,6 +175,11 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:71:9 + | +LL | _: Bar, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:74:13 @@ -165,6 +195,11 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:74:13 + | +LL | _: Foo, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:75:13 @@ -180,6 +215,11 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:75:13 + | +LL | _: Bar, + | ^^^^^^ error[E0124]: field `a` is already declared --> $DIR/field_uniqueness_check.rs:80:5 @@ -222,6 +262,11 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:92:5 + | +LL | _: Foo, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:93:5 @@ -237,6 +282,11 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:93:5 + | +LL | _: Bar, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:96:9 @@ -252,6 +302,11 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:96:9 + | +LL | _: Foo, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:97:9 @@ -267,6 +322,11 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:97:9 + | +LL | _: Bar, + | ^^^^^^ error[E0124]: field `a` is already declared --> $DIR/field_uniqueness_check.rs:111:13 @@ -309,6 +369,11 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:123:13 + | +LL | _: Foo, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:124:13 @@ -324,6 +389,11 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:124:13 + | +LL | _: Bar, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:127:17 @@ -339,6 +409,11 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:127:17 + | +LL | _: Foo, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:128:17 @@ -354,6 +429,11 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:128:17 + | +LL | _: Bar, + | ^^^^^^ error[E0124]: field `a` is already declared --> $DIR/field_uniqueness_check.rs:133:9 @@ -396,6 +476,11 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:145:9 + | +LL | _: Foo, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:146:9 @@ -411,6 +496,11 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:146:9 + | +LL | _: Bar, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:149:13 @@ -426,6 +516,11 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:149:13 + | +LL | _: Foo, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:150:13 @@ -441,6 +536,11 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:150:13 + | +LL | _: Bar, + | ^^^^^^ error[E0124]: field `a` is already declared --> $DIR/field_uniqueness_check.rs:154:5 @@ -483,6 +583,11 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:166:5 + | +LL | _: Foo, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:167:5 @@ -498,6 +603,11 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:167:5 + | +LL | _: Bar, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:170:9 @@ -513,6 +623,11 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:170:9 + | +LL | _: Foo, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:171:9 @@ -528,6 +643,11 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:171:9 + | +LL | _: Bar, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:183:5 @@ -543,6 +663,11 @@ note: field `a` first declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:180:5 + | +LL | _: Foo, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:186:9 @@ -558,6 +683,11 @@ note: field `a` first declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:180:5 + | +LL | _: Foo, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:191:13 @@ -573,6 +703,11 @@ note: field `a` first declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:180:5 + | +LL | _: Foo, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:195:5 @@ -588,11 +723,21 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:195:5 + | +LL | _: Foo, + | ^^^^^^ note: field `a` first declared here --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:180:5 + | +LL | _: Foo, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:196:5 @@ -608,11 +753,21 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:196:5 + | +LL | _: Bar, + | ^^^^^^ note: field `a` first declared here --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:180:5 + | +LL | _: Foo, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:199:9 @@ -628,11 +783,21 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:199:9 + | +LL | _: Foo, + | ^^^^^^ note: field `a` first declared here --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:180:5 + | +LL | _: Foo, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:200:9 @@ -648,11 +813,21 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:200:9 + | +LL | _: Bar, + | ^^^^^^ note: field `a` first declared here --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:180:5 + | +LL | _: Foo, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:212:5 @@ -668,6 +843,11 @@ note: field `a` first declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:209:5 + | +LL | _: Bar, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:215:9 @@ -683,6 +863,11 @@ note: field `a` first declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:209:5 + | +LL | _: Bar, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:220:13 @@ -698,6 +883,11 @@ note: field `a` first declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:209:5 + | +LL | _: Bar, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:224:5 @@ -713,11 +903,21 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:224:5 + | +LL | _: Foo, + | ^^^^^^ note: field `a` first declared here --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:209:5 + | +LL | _: Bar, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:225:5 @@ -733,11 +933,21 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:225:5 + | +LL | _: Bar, + | ^^^^^^ note: field `a` first declared here --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:209:5 + | +LL | _: Bar, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:228:9 @@ -753,11 +963,21 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:228:9 + | +LL | _: Foo, + | ^^^^^^ note: field `a` first declared here --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:209:5 + | +LL | _: Bar, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:229:9 @@ -773,11 +993,21 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:229:9 + | +LL | _: Bar, + | ^^^^^^ note: field `a` first declared here --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:209:5 + | +LL | _: Bar, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:242:9 @@ -793,6 +1023,11 @@ note: field `a` first declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:239:9 + | +LL | _: Foo, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:245:13 @@ -808,6 +1043,11 @@ note: field `a` first declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:239:9 + | +LL | _: Foo, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:250:17 @@ -823,6 +1063,11 @@ note: field `a` first declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:239:9 + | +LL | _: Foo, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:254:9 @@ -838,11 +1083,21 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:254:9 + | +LL | _: Foo, + | ^^^^^^ note: field `a` first declared here --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:239:9 + | +LL | _: Foo, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:255:9 @@ -858,11 +1113,21 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:255:9 + | +LL | _: Bar, + | ^^^^^^ note: field `a` first declared here --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:239:9 + | +LL | _: Foo, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:258:13 @@ -878,11 +1143,21 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:258:13 + | +LL | _: Foo, + | ^^^^^^ note: field `a` first declared here --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:239:9 + | +LL | _: Foo, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:259:13 @@ -898,11 +1173,21 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:259:13 + | +LL | _: Bar, + | ^^^^^^ note: field `a` first declared here --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:239:9 + | +LL | _: Foo, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:264:5 @@ -918,6 +1203,11 @@ note: field `a` first declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:239:9 + | +LL | _: Foo, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:267:9 @@ -933,6 +1223,11 @@ note: field `a` first declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:239:9 + | +LL | _: Foo, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:272:13 @@ -948,6 +1243,11 @@ note: field `a` first declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:239:9 + | +LL | _: Foo, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:276:5 @@ -963,11 +1263,21 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:276:5 + | +LL | _: Foo, + | ^^^^^^ note: field `a` first declared here --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:239:9 + | +LL | _: Foo, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:277:5 @@ -983,11 +1293,21 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:277:5 + | +LL | _: Bar, + | ^^^^^^ note: field `a` first declared here --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:239:9 + | +LL | _: Foo, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:280:9 @@ -1003,11 +1323,21 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:280:9 + | +LL | _: Foo, + | ^^^^^^ note: field `a` first declared here --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:239:9 + | +LL | _: Foo, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:281:9 @@ -1023,11 +1353,21 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:281:9 + | +LL | _: Bar, + | ^^^^^^ note: field `a` first declared here --> $DIR/field_uniqueness_check.rs:7:5 | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:239:9 + | +LL | _: Foo, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:294:9 @@ -1043,6 +1383,11 @@ note: field `a` first declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:291:9 + | +LL | _: Bar, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:297:13 @@ -1058,6 +1403,11 @@ note: field `a` first declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:291:9 + | +LL | _: Bar, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:302:17 @@ -1073,6 +1423,11 @@ note: field `a` first declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:291:9 + | +LL | _: Bar, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:306:9 @@ -1088,11 +1443,21 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:306:9 + | +LL | _: Foo, + | ^^^^^^ note: field `a` first declared here --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:291:9 + | +LL | _: Bar, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:307:9 @@ -1108,11 +1473,21 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:307:9 + | +LL | _: Bar, + | ^^^^^^ note: field `a` first declared here --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:291:9 + | +LL | _: Bar, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:310:13 @@ -1128,11 +1503,21 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:310:13 + | +LL | _: Foo, + | ^^^^^^ note: field `a` first declared here --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:291:9 + | +LL | _: Bar, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:311:13 @@ -1148,11 +1533,21 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:311:13 + | +LL | _: Bar, + | ^^^^^^ note: field `a` first declared here --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:291:9 + | +LL | _: Bar, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:316:5 @@ -1168,6 +1563,11 @@ note: field `a` first declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:291:9 + | +LL | _: Bar, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:319:9 @@ -1183,6 +1583,11 @@ note: field `a` first declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:291:9 + | +LL | _: Bar, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:324:13 @@ -1198,6 +1603,11 @@ note: field `a` first declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:291:9 + | +LL | _: Bar, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:328:5 @@ -1213,11 +1623,21 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:328:5 + | +LL | _: Foo, + | ^^^^^^ note: field `a` first declared here --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:291:9 + | +LL | _: Bar, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:329:5 @@ -1233,11 +1653,21 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:329:5 + | +LL | _: Bar, + | ^^^^^^ note: field `a` first declared here --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:291:9 + | +LL | _: Bar, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:332:9 @@ -1253,11 +1683,21 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:332:9 + | +LL | _: Foo, + | ^^^^^^ note: field `a` first declared here --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:291:9 + | +LL | _: Bar, + | ^^^^^^ error: field `a` is already declared --> $DIR/field_uniqueness_check.rs:333:9 @@ -1273,11 +1713,21 @@ note: field `a` declared here | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:333:9 + | +LL | _: Bar, + | ^^^^^^ note: field `a` first declared here --> $DIR/field_uniqueness_check.rs:14:9 | LL | a: u8, | ^^^^^ +help: fields from the type of this unnamed field are considered fields of the outer type + --> $DIR/field_uniqueness_check.rs:291:9 + | +LL | _: Bar, + | ^^^^^^ error: aborting due to 85 previous errors diff --git a/tests/ui/union/unnamed-fields/repr_check.stderr b/tests/ui/union/unnamed-fields/repr_check.stderr index ca6a1f3a7800d..324968b126413 100644 --- a/tests/ui/union/unnamed-fields/repr_check.stderr +++ b/tests/ui/union/unnamed-fields/repr_check.stderr @@ -20,6 +20,11 @@ LL | | b: i32, LL | | }, LL | | }, | |_____^ +help: add `#[repr(C)]` to this struct + | +LL + #[repr(C)] +LL | struct A { + | error: union with unnamed fields must have `#[repr(C)]` representation --> $DIR/repr_check.rs:16:1 @@ -43,6 +48,11 @@ LL | | b: i32, LL | | }, LL | | }, | |_____^ +help: add `#[repr(C)]` to this union + | +LL + #[repr(C)] +LL | union B { + | error: struct with unnamed fields must have `#[repr(C)]` representation --> $DIR/repr_check.rs:39:1 @@ -55,6 +65,11 @@ note: unnamed field defined here | LL | _: Foo, | ^^^^^^ +help: add `#[repr(C)]` to this struct + | +LL + #[repr(C)] +LL | struct C { + | error: union with unnamed fields must have `#[repr(C)]` representation --> $DIR/repr_check.rs:44:1 @@ -67,6 +82,11 @@ note: unnamed field defined here | LL | _: Foo, | ^^^^^^ +help: add `#[repr(C)]` to this union + | +LL + #[repr(C)] +LL | union D { + | error: named type of unnamed field must have `#[repr(C)]` representation --> $DIR/repr_check.rs:51:5 @@ -76,6 +96,12 @@ LL | struct Bar {} ... LL | _: Bar, | ^^^^^^ unnamed field defined here + | +help: add `#[repr(C)]` to this struct + | +LL + #[repr(C)] +LL | struct Bar {} + | error: named type of unnamed field must have `#[repr(C)]` representation --> $DIR/repr_check.rs:54:9 @@ -85,6 +111,12 @@ LL | struct Bar {} ... LL | _: Bar, | ^^^^^^ unnamed field defined here + | +help: add `#[repr(C)]` to this struct + | +LL + #[repr(C)] +LL | struct Bar {} + | error: named type of unnamed field must have `#[repr(C)]` representation --> $DIR/repr_check.rs:61:5 @@ -94,6 +126,12 @@ LL | struct Bar {} ... LL | _: Bar, | ^^^^^^ unnamed field defined here + | +help: add `#[repr(C)]` to this struct + | +LL + #[repr(C)] +LL | struct Bar {} + | error: named type of unnamed field must have `#[repr(C)]` representation --> $DIR/repr_check.rs:64:9 @@ -103,6 +141,12 @@ LL | struct Bar {} ... LL | _: Bar, | ^^^^^^ unnamed field defined here + | +help: add `#[repr(C)]` to this struct + | +LL + #[repr(C)] +LL | struct Bar {} + | error: aborting due to 8 previous errors