diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 5755ae8a8bc47..b5a1f8ac2b519 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -2108,9 +2108,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 10b2025f93783..9287e4b0a98e4 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 27f1b84f37251..2c457058b2782 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -441,7 +441,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 7c05724f64c95..c55961c21fcca 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -680,7 +680,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 d9663d50c595c..c15a7be130227 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -1326,18 +1326,42 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
TyKind::Err => {
hir::TyKind::Err(self.tcx.sess.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.tcx.sess.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.tcx.sess.span_err(t.span, "anonymous unions are unimplemented"),
- ),
+ TyKind::AnonStruct(def_node_id, fields) | TyKind::AnonUnion(def_node_id, fields) => {
+ let def_kind = match t.kind {
+ TyKind::AnonStruct(..) => DefKind::Struct,
+ TyKind::AnonUnion(..) => DefKind::Union,
+ _ => unreachable!(),
+ };
+ let def_id = self.create_def(
+ self.current_hir_id_owner.def_id,
+ *def_node_id,
+ sym::anon,
+ 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);
+ let generics = hir::Generics::empty();
+ let kind = match &t.kind {
+ TyKind::AnonStruct(..) => hir::ItemKind::Struct(variant_data, generics),
+ _ => hir::ItemKind::Union(variant_data, generics),
+ };
+ hir::OwnerNode::Item(this.arena.alloc(hir::Item {
+ ident: Ident::with_dummy_span(sym::anon),
+ owner_id,
+ kind,
+ 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)),
TyKind::Ref(region, mt) => {
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 59cf18c24597e..43fea6d91924c 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -198,7 +198,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 4a2a693862b13..9b48d4529a780 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -987,11 +987,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 258d6710bc57f..c982229815020 100644
--- a/compiler/rustc_hir/src/def.rs
+++ b/compiler/rustc_hir/src/def.rs
@@ -8,6 +8,7 @@ use rustc_data_structures::stable_hasher::ToStableHashKey;
use rustc_macros::HashStable_Generic;
use rustc_span::def_id::{DefId, LocalDefId};
use rustc_span::hygiene::MacroKind;
+use rustc_span::symbol::sym;
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 == sym::anon => 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 d222325475d33..eef54a8562f41 100644
--- a/compiler/rustc_hir/src/definitions.rs
+++ b/compiler/rustc_hir/src/definitions.rs
@@ -282,6 +282,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 {
@@ -404,8 +406,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,
}
}
@@ -426,6 +429,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 },
}
}
}
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 01508375b1ace..1af8754fcd77a 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2543,6 +2543,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 9cf1db166a581..bc293a716dba6 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -862,6 +862,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::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 caae6fa4f065e..9399efb1667ad 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -2426,6 +2426,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 fdd6424a19e2d..e6b53ac1f1d80 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -781,6 +781,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,
@@ -790,11 +849,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.sess.emit_err(errors::FieldAlreadyDeclared {
@@ -805,12 +870,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 {
@@ -829,6 +893,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,
)
}
@@ -839,6 +904,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
bug!();
};
+ let is_anonymous = item.ident.name == sym::anon;
let repr = tcx.repr_options_of_def(def_id.to_def_id());
let (kind, variants) = match &item.kind {
ItemKind::Enum(def, _) => {
@@ -889,7 +955,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
}
_ => bug!(),
};
- 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 8701626058d43..9f6e2da5c91d4 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -323,6 +323,7 @@ impl<'a> State<'a> {
hir::TyKind::Infer => {
self.word("_");
}
+ hir::TyKind::AnonAdt(..) => self.word("/* anonymous adt */"),
}
self.end()
}
@@ -743,26 +744,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 24ab4f94d5c5b..b6ff2622048d5 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -1088,6 +1088,8 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
parent_did,
false,
data.is_non_exhaustive,
+ // FIXME: unnamed fields in crate metadata is unimplemented yet.
+ false,
),
)
}
@@ -1130,6 +1132,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 598c26de23f1c..ffb2f4f3869d3 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -780,6 +780,13 @@ impl<'hir> Map<'hir> {
}
}
+ pub fn expect_field(self, id: HirId) -> &'hir FieldDef<'hir> {
+ match self.tcx.opt_hir_node(id) {
+ Some(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(id) {
Some(Owner { node: OwnerNode::ForeignItem(item), .. }) => item,
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs
index 1d9a25628b047..daf8a76f35291 100644
--- a/compiler/rustc_middle/src/ty/adt.rs
+++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -49,6 +49,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;
}
}
@@ -231,8 +233,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) {
@@ -265,6 +271,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 }
}
@@ -363,6 +372,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 d027a193f6367..c494683d6ef2a 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -720,8 +720,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 71ff7021ca5de..4655413fa14d7 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -1781,6 +1781,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;
}
}
@@ -1793,7 +1795,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,
@@ -1830,11 +1832,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;
@@ -1846,6 +1849,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 }
}
@@ -1861,6 +1868,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 da8cc05ff66e8..180aeba4dc1c9 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -407,8 +407,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 85969b72d2397..1ffa11214898d 100644
--- a/compiler/rustc_passes/src/hir_stats.rs
+++ b/compiler/rustc_passes/src/hir_stats.rs
@@ -348,6 +348,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
BareFn,
Never,
Tup,
+ AnonAdt,
Path,
OpaqueDef,
TraitObject,
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 3d673f2f1ec04..2a265c0415e28 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 e002e345ae689..f7e39872fd0d7 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -781,7 +781,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 f442e2a08a811..19a7a29d5dc4b 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
@@ -174,6 +174,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 7f31a2529f5c2..3a9cb995f2f94 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -2231,6 +2231,16 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
}
}
+ // Anonymous adts are automatically impelemented `Copy` and `Clone`
+ ty::Adt(adt, args) if adt.flags().contains(ty::AdtFlags::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.
None
diff --git a/compiler/rustc_ty_utils/src/representability.rs b/compiler/rustc_ty_utils/src/representability.rs
index 3aaa2e73bb805..fb62c727b66a4 100644
--- a/compiler/rustc_ty_utils/src/representability.rs
+++ b/compiler/rustc_ty_utils/src/representability.rs
@@ -23,8 +23,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 ff0bfda759cf2..5cc12df0ed5da 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1882,6 +1882,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(..) => 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 150625c6d920f..7aa6a9523a03f 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 aaef163ad554b..204526a085f59 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -830,6 +830,7 @@ impl TyCoercionStability {
| TyKind::Infer
| TyKind::Typeof(..)
| TyKind::TraitObject(..)
+ | 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 e610ed930505b..75e7290757ede 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -525,6 +525,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,
}
}
@@ -1126,7 +1127,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
TyKind::Typeof(anon_const) => {
self.hash_body(anon_const.body);
},
- TyKind::Err(_) | TyKind::Infer | TyKind::Never => {},
+ TyKind::Err(_) | TyKind::Infer | TyKind::Never | TyKind::AnonAdt(_) => {},
}
}
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 f026f2c3600b3..b5bfe27ba3663 100644
--- a/tests/ui/feature-gates/feature-gate-unnamed_fields.stderr
+++ b/tests/ui/feature-gates/feature-gate-unnamed_fields.stderr
@@ -13,7 +13,6 @@ error[E0658]: unnamed fields are not yet fully implemented
LL | _: union {
| ________^
LL | |
-LL | |
LL | | bar: u8,
LL | | baz: u16
LL | | }
@@ -23,7 +22,7 @@ LL | | }
= help: add `#![feature(unnamed_fields)]` to the crate attributes to enable
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 {
| ^
@@ -32,12 +31,11 @@ LL | _: struct {
= help: add `#![feature(unnamed_fields)]` to the crate attributes to enable
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 | | }
@@ -47,7 +45,7 @@ LL | | }
= help: add `#![feature(unnamed_fields)]` to the crate attributes to enable
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
| ^
@@ -55,30 +53,6 @@ LL | _: S
= note: see issue #49804 for more information
= help: add `#![feature(unnamed_fields)]` to the crate attributes to enable
-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