check uniqueness of nested fields

This commit is contained in:
Frank King 2024-01-04 21:56:45 +08:00
parent 879a1e5713
commit 36d7e7fd3f
12 changed files with 1842 additions and 97 deletions

View File

@ -220,7 +220,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) walk_list!(self, visit_struct_field_def, fields)
} }
_ => visit::walk_ty(self, t), _ => visit::walk_ty(self, t),
} }

View File

@ -123,6 +123,25 @@ hir_analysis_field_already_declared =
.label = field already declared .label = field already declared
.previous_decl_label = `{$field_name}` first declared here .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_found_in_trait = function not found in this trait
hir_analysis_function_not_have_default_implementation = function doesn't have a default implementation hir_analysis_function_not_have_default_implementation = function doesn't have a default implementation

View File

@ -789,64 +789,100 @@ fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
} }
} }
/* #[derive(Clone, Copy)]
/// In a type definition, we check that unnamed field names are distinct. struct NestedSpan {
fn check_unnamed_fields_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>) { span: Span,
let mut seen_fields: FxHashMap<Ident, Option<Span>> = Default::default(); nested_field_span: Span,
fn check_fields_anon_adt_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, seen_fields: &mut FxHashMap<Ident, Option<Span>>) { }
let fields = match &item.kind {
hir::ItemKind::Struct(fields, _) | hir::ItemKind::Union(fields, _) => fields, #[derive(Clone, Copy)]
_ => return, enum FieldDeclSpan {
}; NotNested(Span),
for field in fields.fields() { Nested(NestedSpan),
if field.ident.name == kw::Underscore { }
if let hir::TyKind::AnonAdt(item_id) = field.ty.kind() {
let item = tcx.hir().item(item_id); impl From<Span> for FieldDeclSpan {
check_fields_anon_adt_defn(tcx, item, &mut *seen_fields); fn from(span: Span) -> Self {
} else { Self::NotNested(span)
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); impl From<NestedSpan> for FieldDeclSpan {
return; fn from(span: NestedSpan) -> Self {
} Self::Nested(span)
}; }
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); /// Check the uniqueness of fields across adt where there are
} /// nested fields imported from an unnamed field.
} fn check_field_uniqueness_in_nested_adt(
field_ty.flags() tcx: TyCtxt<'_>,
let inner_adt_def = field_ty.ty_adt_def().expect("expect an adt"); adt_def: ty::AdtDef<'_>,
check_fields_anon_adt_defn(tcx, adt_def, &mut *seen_fields); check: &mut impl FnMut(Ident, /* nested_field_span */ Span),
} else { ) {
let span = field.did.as_local().map(|did| { for field in adt_def.all_fields() {
let hir_id = tcx.hir().local_def_id_to_hir_id(did); if field.is_unnamed() {
tcx.hir().span(hir_id) // Here we don't care about the generic parameters, so `instantiate_identity` is enough.
}); match tcx.type_of(field.did).instantiate_identity().kind() {
match seen_fields.get(&ident.normalize_to_macros_2_0()).cloned() { ty::Adt(adt_def, _) => {
Some(Some(prev_span)) => { check_field_uniqueness_in_nested_adt(tcx, *adt_def, &mut *check);
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);
} }
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));
}
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( fn convert_variant(
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
@ -856,27 +892,61 @@ fn convert_variant(
def: &hir::VariantData<'_>, def: &hir::VariantData<'_>,
adt_kind: ty::AdtKind, adt_kind: ty::AdtKind,
parent_did: LocalDefId, parent_did: LocalDefId,
is_anonymous: bool,
) -> ty::VariantDef { ) -> ty::VariantDef {
let mut has_unnamed_fields = false; let mut has_unnamed_fields = false;
let mut seen_fields: FxHashMap<Ident, Span> = Default::default(); let mut seen_fields: FxHashMap<Ident, FieldDeclSpan> = Default::default();
let fields = def let fields = def
.fields() .fields()
.iter() .iter()
.inspect(|f| { .inspect(|f| {
// Skip the unnamed field here, we will check it later. has_unnamed_fields |= f.ident.name == kw::Underscore;
if f.ident.name == kw::Underscore { if !is_anonymous {
has_unnamed_fields = true; check_field_uniqueness(tcx, f, &mut |ident, field_decl| {
return; use FieldDeclSpan::*;
} let field_name = ident.name;
let dup_span = seen_fields.get(&f.ident.normalize_to_macros_2_0()).cloned(); let ident = ident.normalize_to_macros_2_0();
if let Some(prev_span) = dup_span { match (field_decl, seen_fields.get(&ident).copied()) {
tcx.dcx().emit_err(errors::FieldAlreadyDeclared { (NotNested(span), Some(NotNested(prev_span))) => {
field_name: f.ident, tcx.sess.emit_err(errors::FieldAlreadyDeclared::NotNested {
span: f.span, field_name,
prev_span, 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 { .map(|f| ty::FieldDef {
@ -937,6 +1007,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
&v.data, &v.data,
AdtKind::Enum, AdtKind::Enum,
def_id, def_id,
is_anonymous,
) )
}) })
.collect(); .collect();
@ -956,6 +1027,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
def, def,
adt_kind, adt_kind,
def_id, def_id,
is_anonymous,
)) ))
.collect(); .collect();

View File

@ -175,14 +175,51 @@ pub struct DropImplOnWrongItem {
} }
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(hir_analysis_field_already_declared, code = E0124)] pub enum FieldAlreadyDeclared {
pub struct FieldAlreadyDeclared { #[diag(hir_analysis_field_already_declared, code = E0124)]
pub field_name: Ident, NotNested {
#[primary_span] field_name: Symbol,
#[label] #[primary_span]
pub span: Span, #[label]
#[label(hir_analysis_previous_decl_label)] span: Span,
pub prev_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)] #[derive(Diagnostic)]

View File

@ -401,7 +401,7 @@ impl<'tcx> AdtDef<'tcx> {
} }
/// Returns an iterator over all fields contained /// Returns an iterator over all fields contained
/// by this ADT. /// by this ADT (nested unnamed fields are not expanded).
#[inline] #[inline]
pub fn all_fields(self) -> impl Iterator<Item = &'tcx FieldDef> + Clone { pub fn all_fields(self) -> impl Iterator<Item = &'tcx FieldDef> + Clone {
self.variants().iter().flat_map(|v| v.fields.iter()) self.variants().iter().flat_map(|v| v.fields.iter())

View File

@ -1387,6 +1387,11 @@ impl<'tcx> FieldDef {
pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident { pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident {
Ident::new(self.name, tcx.def_ident_span(self.did).unwrap()) 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)] #[derive(Debug, PartialEq, Eq)]

View File

@ -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() {}

File diff suppressed because it is too large Load Diff

View File

@ -2,8 +2,8 @@
#![feature(unnamed_fields)] #![feature(unnamed_fields)]
struct F { struct F {
field: struct { field: u8 }, //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields field1: struct { field2: u8 }, //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
_: struct { field: u8 }, _: struct { field3: u8 },
} }
struct G { struct G {
@ -11,8 +11,8 @@ struct G {
} }
union H { union H {
field: struct { field: u8 }, //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields field1: struct { field2: u8 }, //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
_: struct { field: u8 }, _: struct { field3: u8 },
} }
union I { union I {

View File

@ -1,8 +1,8 @@
error: anonymous structs are not allowed outside of unnamed struct or union fields 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 }, LL | field1: struct { field2: u8 },
| ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here | ^^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
error: unnamed fields can only have struct or union types error: unnamed fields can only have struct or union types
--> $DIR/restrict_anonymous_structs.rs:10:5 --> $DIR/restrict_anonymous_structs.rs:10:5
@ -11,10 +11,10 @@ LL | _: (u8, u8),
| ^ -------- not a struct or union | ^ -------- not a struct or union
error: anonymous structs are not allowed outside of unnamed struct or union fields 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 }, LL | field1: struct { field2: u8 },
| ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here | ^^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
error: unnamed fields can only have struct or union types error: unnamed fields can only have struct or union types
--> $DIR/restrict_anonymous_structs.rs:19:5 --> $DIR/restrict_anonymous_structs.rs:19:5

View File

@ -2,8 +2,8 @@
#![feature(unnamed_fields)] #![feature(unnamed_fields)]
struct F { struct F {
field: union { field: u8 }, //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields field1: union { field2: u8 }, //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields
_: union { field: u8 }, _: union { field3: u8 },
} }
struct G { struct G {
@ -11,8 +11,8 @@ struct G {
} }
union H { union H {
field: union { field: u8 }, //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields field1: union { field2: u8 }, //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields
_: union { field: u8 }, _: union { field3: u8 },
} }
union I { union I {

View File

@ -1,8 +1,8 @@
error: anonymous unions are not allowed outside of unnamed struct or union fields 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 }, LL | field1: union { field2: u8 },
| ^^^^^^^^^^^^^^^^^^^ anonymous union declared here | ^^^^^^^^^^^^^^^^^^^^ anonymous union declared here
error: unnamed fields can only have struct or union types error: unnamed fields can only have struct or union types
--> $DIR/restrict_anonymous_unions.rs:10:5 --> $DIR/restrict_anonymous_unions.rs:10:5
@ -11,10 +11,10 @@ LL | _: (u8, u8),
| ^ -------- not a struct or union | ^ -------- not a struct or union
error: anonymous unions are not allowed outside of unnamed struct or union fields 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 }, LL | field1: union { field2: u8 },
| ^^^^^^^^^^^^^^^^^^^ anonymous union declared here | ^^^^^^^^^^^^^^^^^^^^ anonymous union declared here
error: unnamed fields can only have struct or union types error: unnamed fields can only have struct or union types
--> $DIR/restrict_anonymous_unions.rs:19:5 --> $DIR/restrict_anonymous_unions.rs:19:5