check uniqueness of nested fields
This commit is contained in:
parent
879a1e5713
commit
36d7e7fd3f
@ -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),
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -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)]
|
||||||
|
@ -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())
|
||||||
|
@ -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)]
|
||||||
|
328
tests/ui/union/unnamed-fields/field_uniqueness_check.rs
Normal file
328
tests/ui/union/unnamed-fields/field_uniqueness_check.rs
Normal 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() {}
|
1284
tests/ui/union/unnamed-fields/field_uniqueness_check.stderr
Normal file
1284
tests/ui/union/unnamed-fields/field_uniqueness_check.stderr
Normal file
File diff suppressed because it is too large
Load Diff
@ -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 {
|
||||||
|
@ -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
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user