about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFrank King <frankking1729@gmail.com>2024-01-04 21:56:45 +0800
committerFrank King <frankking1729@gmail.com>2024-02-12 12:47:29 +0800
commit36d7e7fd3fee2a2e3e19f103d9595329093ab68e (patch)
tree4096dd21728135f7ed53e0ff2ae4c767e4270f2c
parent879a1e571305a0fb35ef6cc4297f9230fca95be5 (diff)
downloadrust-36d7e7fd3fee2a2e3e19f103d9595329093ab68e.tar.gz
rust-36d7e7fd3fee2a2e3e19f103d9595329093ab68e.zip
check uniqueness of nested fields
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs2
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl19
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs202
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs53
-rw-r--r--compiler/rustc_middle/src/ty/adt.rs2
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs5
-rw-r--r--tests/ui/union/unnamed-fields/field_uniqueness_check.rs328
-rw-r--r--tests/ui/union/unnamed-fields/field_uniqueness_check.stderr1284
-rw-r--r--tests/ui/union/unnamed-fields/restrict_anonymous_structs.rs8
-rw-r--r--tests/ui/union/unnamed-fields/restrict_anonymous_structs.stderr12
-rw-r--r--tests/ui/union/unnamed-fields/restrict_anonymous_unions.rs8
-rw-r--r--tests/ui/union/unnamed-fields/restrict_anonymous_unions.stderr12
12 files changed, 1840 insertions, 95 deletions
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 86597d20c19..d24dc44d2c5 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -220,7 +220,7 @@ impl<'a> AstValidator<'a> {
                 }
             }
             TyKind::AnonStruct(_, ref fields) | TyKind::AnonUnion(_, ref fields) => {
-                walk_list!(self, visit_field_def, fields)
+                walk_list!(self, visit_struct_field_def, fields)
             }
             _ => visit::walk_ty(self, t),
         }
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index d6f604c180b..662d859e993 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -123,6 +123,25 @@ hir_analysis_field_already_declared =
     .label = field already declared
     .previous_decl_label = `{$field_name}` first declared here
 
+hir_analysis_field_already_declared_both_nested =
+    field `{$field_name}` is already declared
+    .label = field `{$field_name}` declared in this unnamed field
+    .nested_field_decl_note = field `{$field_name}` declared here
+    .previous_decl_label = `{$field_name}` first declared here in this unnamed field
+    .previous_nested_field_decl_note = field `{$field_name}` first declared here
+
+hir_analysis_field_already_declared_current_nested =
+    field `{$field_name}` is already declared
+    .label = field `{$field_name}` declared in this unnamed field
+    .nested_field_decl_note = field `{$field_name}` declared here
+    .previous_decl_label = `{$field_name}` first declared here
+
+hir_analysis_field_already_declared_previous_nested =
+    field `{$field_name}` is already declared
+    .label = field already declared
+    .previous_decl_label = `{$field_name}` first declared here in this unnamed field
+    .previous_nested_field_decl_note = field `{$field_name}` first declared here
+
 hir_analysis_function_not_found_in_trait = function not found in this trait
 
 hir_analysis_function_not_have_default_implementation = function doesn't have a default implementation
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 768b07069c8..12e7b5dbfce 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -789,64 +789,100 @@ fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
     }
 }
 
-/*
-/// In a type definition, we check that unnamed field names are distinct.
-fn check_unnamed_fields_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>) {
-    let mut seen_fields: FxHashMap<Ident, Option<Span>> = Default::default();
-    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,
-            _ => return,
-        };
-        for field in fields.fields() {
-            if field.ident.name == kw::Underscore {
-                if let hir::TyKind::AnonAdt(item_id) = field.ty.kind() {
-                    let item = tcx.hir().item(item_id);
-                    check_fields_anon_adt_defn(tcx, item, &mut *seen_fields);
-                } else {
-                    let field_ty = match tcx.type_of(field.def_id).instantiate_identity().ty_adt_def() {
-                        Some(adt_ty) => adt_ty,
-                        None => {
-                            tcx.sess.emit_err(err);
-                            return;
-                        }
-                    };
-                    if let Some(def_id) = field_ty.did().as_local() {
-                        let item = tcx.hir().item(hir::ItemId { owner_id: hir::OwnerId { def_id }});
-                        check_fields_anon_adt_defn(tcx, item, &mut *seen_fields);
-                    }
+#[derive(Clone, Copy)]
+struct NestedSpan {
+    span: Span,
+    nested_field_span: Span,
+}
+
+#[derive(Clone, Copy)]
+enum FieldDeclSpan {
+    NotNested(Span),
+    Nested(NestedSpan),
+}
+
+impl From<Span> for FieldDeclSpan {
+    fn from(span: Span) -> Self {
+        Self::NotNested(span)
+    }
+}
+
+impl From<NestedSpan> for FieldDeclSpan {
+    fn from(span: NestedSpan) -> Self {
+        Self::Nested(span)
+    }
+}
+
+/// Check the uniqueness of fields across adt where there are
+/// nested fields imported from an unnamed field.
+fn check_field_uniqueness_in_nested_adt(
+    tcx: TyCtxt<'_>,
+    adt_def: ty::AdtDef<'_>,
+    check: &mut impl FnMut(Ident, /* nested_field_span */ Span),
+) {
+    for field in adt_def.all_fields() {
+        if field.is_unnamed() {
+            // Here we don't care about the generic parameters, so `instantiate_identity` is enough.
+            match tcx.type_of(field.did).instantiate_identity().kind() {
+                ty::Adt(adt_def, _) => {
+                    check_field_uniqueness_in_nested_adt(tcx, *adt_def, &mut *check);
                 }
-                field_ty.flags()
-                let inner_adt_def = field_ty.ty_adt_def().expect("expect an adt");
-                check_fields_anon_adt_defn(tcx, adt_def, &mut *seen_fields);
-            } else {
-                let span = field.did.as_local().map(|did| {
-                    let hir_id = tcx.hir().local_def_id_to_hir_id(did);
-                    tcx.hir().span(hir_id)
-                });
-                match seen_fields.get(&ident.normalize_to_macros_2_0()).cloned() {
-                    Some(Some(prev_span)) => {
-                        tcx.sess.emit_err(errors::FieldAlreadyDeclared {
-                            field_name: ident,
-                            span: f.span,
-                            prev_span,
-                        });
-                    }
-                    Some(None) => {
-                        tcx.sess.emit_err(errors::FieldAlreadyDeclared {
-                            field_name: f.ident,
-                            span: f.span,
-                            prev_span,
-                        });
+                ty_kind => bug!(
+                    "Unexpected ty kind in check_field_uniqueness_in_nested_adt(): {ty_kind:?}"
+                ),
+            }
+        } else {
+            check(field.ident(tcx), tcx.def_span(field.did));
+        }
+    }
+}
+
+/// Check the uniqueness of fields in a struct variant, and recursively
+/// check the nested fields if it is an unnamed field with type of an
+/// annoymous adt.
+fn check_field_uniqueness(
+    tcx: TyCtxt<'_>,
+    field: &hir::FieldDef<'_>,
+    check: &mut impl FnMut(Ident, FieldDeclSpan),
+) {
+    if field.ident.name == kw::Underscore {
+        let ty_span = field.ty.span;
+        match &field.ty.kind {
+            hir::TyKind::AnonAdt(item_id) => {
+                match &tcx.hir_node(item_id.hir_id()).expect_item().kind {
+                    hir::ItemKind::Struct(variant_data, ..)
+                    | hir::ItemKind::Union(variant_data, ..) => {
+                        variant_data
+                            .fields()
+                            .iter()
+                            .for_each(|f| check_field_uniqueness(tcx, f, &mut *check));
                     }
-                    None =>
-                        seen_fields.insert(f.ident.normalize_to_macros_2_0(), f.span);
+                    item_kind => span_bug!(
+                        ty_span,
+                        "Unexpected item kind in check_field_uniqueness(): {item_kind:?}"
+                    ),
                 }
             }
+            hir::TyKind::Path(hir::QPath::Resolved(_, hir::Path { res, .. })) => {
+                check_field_uniqueness_in_nested_adt(
+                    tcx,
+                    tcx.adt_def(res.def_id()),
+                    &mut |ident, nested_field_span| {
+                        check(ident, NestedSpan { span: field.span, nested_field_span }.into())
+                    },
+                );
+            }
+            // Abort due to errors (there must be an error if an unnamed field
+            //  has any type kind other than an anonymous adt or a named adt)
+            _ => {
+                debug_assert!(tcx.sess.has_errors().is_some());
+                tcx.sess.abort_if_errors()
+            }
         }
+        return;
     }
+    check(field.ident, field.span.into());
 }
- */
 
 fn convert_variant(
     tcx: TyCtxt<'_>,
@@ -856,27 +892,61 @@ fn convert_variant(
     def: &hir::VariantData<'_>,
     adt_kind: ty::AdtKind,
     parent_did: LocalDefId,
+    is_anonymous: bool,
 ) -> ty::VariantDef {
     let mut has_unnamed_fields = false;
-    let mut seen_fields: FxHashMap<Ident, Span> = Default::default();
+    let mut seen_fields: FxHashMap<Ident, FieldDeclSpan> = Default::default();
     let fields = def
         .fields()
         .iter()
         .inspect(|f| {
-            // Skip the unnamed field here, we will check it later.
-            if f.ident.name == kw::Underscore {
-                has_unnamed_fields = true;
-                return;
-            }
-            let dup_span = seen_fields.get(&f.ident.normalize_to_macros_2_0()).cloned();
-            if let Some(prev_span) = dup_span {
-                tcx.dcx().emit_err(errors::FieldAlreadyDeclared {
-                    field_name: f.ident,
-                    span: f.span,
-                    prev_span,
+            has_unnamed_fields |= f.ident.name == kw::Underscore;
+            if !is_anonymous {
+                check_field_uniqueness(tcx, f, &mut |ident, field_decl| {
+                    use FieldDeclSpan::*;
+                    let field_name = ident.name;
+                    let ident = ident.normalize_to_macros_2_0();
+                    match (field_decl, seen_fields.get(&ident).copied()) {
+                        (NotNested(span), Some(NotNested(prev_span))) => {
+                            tcx.sess.emit_err(errors::FieldAlreadyDeclared::NotNested {
+                                field_name,
+                                span,
+                                prev_span,
+                            });
+                        }
+                        (NotNested(span), Some(Nested(prev))) => {
+                            tcx.sess.emit_err(errors::FieldAlreadyDeclared::PreviousNested {
+                                field_name,
+                                span,
+                                prev_span: prev.span,
+                                prev_nested_field_span: prev.nested_field_span,
+                            });
+                        }
+                        (
+                            Nested(NestedSpan { span, nested_field_span }),
+                            Some(NotNested(prev_span)),
+                        ) => {
+                            tcx.sess.emit_err(errors::FieldAlreadyDeclared::CurrentNested {
+                                field_name,
+                                span,
+                                nested_field_span,
+                                prev_span,
+                            });
+                        }
+                        (Nested(NestedSpan { span, nested_field_span }), Some(Nested(prev))) => {
+                            tcx.sess.emit_err(errors::FieldAlreadyDeclared::BothNested {
+                                field_name,
+                                span,
+                                nested_field_span,
+                                prev_span: prev.span,
+                                prev_nested_field_span: prev.nested_field_span,
+                            });
+                        }
+                        (field_decl, None) => {
+                            seen_fields.insert(ident, field_decl);
+                        }
+                    }
                 });
-            } else {
-                seen_fields.insert(f.ident.normalize_to_macros_2_0(), f.span);
             }
         })
         .map(|f| ty::FieldDef {
@@ -937,6 +1007,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
                         &v.data,
                         AdtKind::Enum,
                         def_id,
+                        is_anonymous,
                     )
                 })
                 .collect();
@@ -956,6 +1027,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
                 def,
                 adt_kind,
                 def_id,
+                is_anonymous,
             ))
             .collect();
 
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index bec53693d6c..1e172f1d9f0 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -175,14 +175,51 @@ pub struct DropImplOnWrongItem {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_field_already_declared, code = E0124)]
-pub struct FieldAlreadyDeclared {
-    pub field_name: Ident,
-    #[primary_span]
-    #[label]
-    pub span: Span,
-    #[label(hir_analysis_previous_decl_label)]
-    pub prev_span: Span,
+pub enum FieldAlreadyDeclared {
+    #[diag(hir_analysis_field_already_declared, code = E0124)]
+    NotNested {
+        field_name: Symbol,
+        #[primary_span]
+        #[label]
+        span: Span,
+        #[label(hir_analysis_previous_decl_label)]
+        prev_span: Span,
+    },
+    #[diag(hir_analysis_field_already_declared_current_nested)]
+    CurrentNested {
+        field_name: Symbol,
+        #[primary_span]
+        #[label]
+        span: Span,
+        #[note(hir_analysis_nested_field_decl_note)]
+        nested_field_span: Span,
+        #[label(hir_analysis_previous_decl_label)]
+        prev_span: Span,
+    },
+    #[diag(hir_analysis_field_already_declared_previous_nested)]
+    PreviousNested {
+        field_name: Symbol,
+        #[primary_span]
+        #[label]
+        span: Span,
+        #[label(hir_analysis_previous_decl_label)]
+        prev_span: Span,
+        #[note(hir_analysis_previous_nested_field_decl_note)]
+        prev_nested_field_span: Span,
+    },
+    #[diag(hir_analysis_field_already_declared_both_nested)]
+    BothNested {
+        field_name: Symbol,
+        #[primary_span]
+        #[label]
+        span: Span,
+        #[note(hir_analysis_nested_field_decl_note)]
+        nested_field_span: Span,
+        #[label(hir_analysis_previous_decl_label)]
+        prev_span: Span,
+        #[note(hir_analysis_previous_nested_field_decl_note)]
+        prev_nested_field_span: Span,
+    },
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs
index 854046c9ceb..d07a53ee679 100644
--- a/compiler/rustc_middle/src/ty/adt.rs
+++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -401,7 +401,7 @@ impl<'tcx> AdtDef<'tcx> {
     }
 
     /// Returns an iterator over all fields contained
-    /// by this ADT.
+    /// by this ADT (nested unnamed fields are not expanded).
     #[inline]
     pub fn all_fields(self) -> impl Iterator<Item = &'tcx FieldDef> + Clone {
         self.variants().iter().flat_map(|v| v.fields.iter())
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 3cbe8f287e1..e73b9836174 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -1387,6 +1387,11 @@ impl<'tcx> FieldDef {
     pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident {
         Ident::new(self.name, tcx.def_ident_span(self.did).unwrap())
     }
+
+    /// Returns whether the field is unnamed
+    pub fn is_unnamed(&self) -> bool {
+        self.name == rustc_span::symbol::kw::Underscore
+    }
 }
 
 #[derive(Debug, PartialEq, Eq)]
diff --git a/tests/ui/union/unnamed-fields/field_uniqueness_check.rs b/tests/ui/union/unnamed-fields/field_uniqueness_check.rs
new file mode 100644
index 00000000000..3cc36211875
--- /dev/null
+++ b/tests/ui/union/unnamed-fields/field_uniqueness_check.rs
@@ -0,0 +1,328 @@
+#![allow(incomplete_features)]
+#![feature(unnamed_fields)]
+
+#[repr(C)]
+struct Foo {
+    a: u8,
+}
+
+#[repr(C)]
+struct Bar {
+    _: union {
+        a: u8,
+    },
+}
+
+
+// duplicated with a normal field
+#[repr(C)]
+union A {
+    // referent field
+    a: u8,
+
+    // normal field
+    a: u8, //~ ERROR field `a` is already declared [E0124]
+    // nested field
+    _: struct {
+        a: u8, //~ ERROR field `a` is already declared [E0124]
+        a: u8, //~ ERROR field `a` is already declared [E0124]
+    },
+    // more nested field
+    _: union {
+        _: struct {
+            a: u8, //~ ERROR field `a` is already declared [E0124]
+        },
+    },
+    // nested field in a named adt
+    _: Foo, //~ ERROR field `a` is already declared
+    _: Bar, //~ ERROR field `a` is already declared
+    // nested field in a named adt in an anoymous adt
+    _: struct {
+        _: Foo, //~ ERROR field `a` is already declared
+        _: Bar, //~ ERROR field `a` is already declared
+    },
+}
+
+// duplicated with a nested field
+#[repr(C)]
+struct B {
+    _: union {
+        // referent field
+        a: u8,
+
+        // normal field (within the same anonymous adt)
+        a: u8, //~ ERROR field `a` is already declared [E0124]
+        // nested field (within the same anonymous adt)
+        _: struct {
+            a: u8, //~ ERROR field `a` is already declared [E0124]
+        },
+        // more nested field (within the same anonymous adt)
+        _: union {
+            _: struct {
+                a: u8, //~ ERROR field `a` is already declared [E0124]
+            },
+        },
+        // nested field in a named adt (within the same anonymous adt)
+        _: Foo, //~ ERROR field `a` is already declared
+        _: Bar, //~ ERROR field `a` is already declared
+        // nested field in a named adt in an anoymous adt (within the same anonymous adt)
+        _: struct {
+            _: Foo, //~ ERROR field `a` is already declared
+            _: Bar, //~ ERROR field `a` is already declared
+        },
+    },
+
+    // normal field
+    a: u8, //~ ERROR field `a` is already declared [E0124]
+    // nested field
+    _: struct {
+        a: u8, //~ ERROR field `a` is already declared [E0124]
+    },
+    // more nested field
+    _: union {
+        _: struct {
+            a: u8, //~ ERROR field `a` is already declared [E0124]
+        },
+    },
+    // nested field in a named adt
+    _: Foo, //~ ERROR field `a` is already declared
+    _: Bar, //~ ERROR field `a` is already declared
+    // nested field in a named adt in an anoymous adt
+    _: struct {
+        _: Foo, //~ ERROR field `a` is already declared
+        _: Bar, //~ ERROR field `a` is already declared
+    },
+}
+
+// duplicated with a more nested field
+#[repr(C)]
+union C {
+    _: struct {
+        _: union {
+            // referent field
+            a: u8,
+
+            // normal field (within the same anonymous adt)
+            a: u8, //~ ERROR field `a` is already declared [E0124]
+            // nested field (within the same anonymous adt)
+            _: struct {
+                a: u8, //~ ERROR field `a` is already declared [E0124]
+            },
+            // more nested field (within the same anonymous adt)
+            _: union {
+                _: struct {
+                    a: u8, //~ ERROR field `a` is already declared [E0124]
+                },
+            },
+            // nested field in a named adt (within the same anonymous adt)
+            _: Foo, //~ ERROR field `a` is already declared
+            _: Bar, //~ ERROR field `a` is already declared
+            // nested field in a named adt in an anoymous adt (within the same anonymous adt)
+            _: struct {
+                _: Foo, //~ ERROR field `a` is already declared
+                _: Bar, //~ ERROR field `a` is already declared
+            },
+        },
+
+        // normal field (within the direct outer anonymous adt)
+        a: u8, //~ ERROR field `a` is already declared [E0124]
+        // nested field (within the direct outer anonymous adt)
+        _: struct {
+            a: u8, //~ ERROR field `a` is already declared [E0124]
+        },
+        // more nested field (within the direct outer anonymous adt)
+        _: union {
+            _: struct {
+                a: u8, //~ ERROR field `a` is already declared [E0124]
+            },
+        },
+        // nested field in a named adt (within the direct outer anonymous adt)
+        _: Foo, //~ ERROR field `a` is already declared
+        _: Bar, //~ ERROR field `a` is already declared
+        // nested field in a named adt in an anoymous adt (within the direct outer anonymous adt)
+        _: struct {
+            _: Foo, //~ ERROR field `a` is already declared
+            _: Bar, //~ ERROR field `a` is already declared
+        },
+    },
+    // normal field
+    a: u8, //~ ERROR field `a` is already declared [E0124]
+    // nested field
+    _: union {
+        a: u8, //~ ERROR field `a` is already declared [E0124]
+    },
+    // more nested field
+    _: struct {
+        _: union {
+            a: u8, //~ ERROR field `a` is already declared [E0124]
+        },
+    },
+    // nested field in a named adt
+    _: Foo, //~ ERROR field `a` is already declared
+    _: Bar, //~ ERROR field `a` is already declared
+    // nested field in a named adt in an anoymous adt
+    _: union {
+        _: Foo, //~ ERROR field `a` is already declared
+        _: Bar, //~ ERROR field `a` is already declared
+    },
+}
+
+// duplicated with a nested field in a named adt
+#[repr(C)]
+struct D {
+    // referent field `a`
+    _: Foo,
+
+    // normal field
+    a: u8, //~ ERROR field `a` is already declared
+    // nested field
+    _: union {
+        a: u8, //~ ERROR field `a` is already declared
+    },
+    // more nested field
+    _: struct {
+        _: union {
+            a: u8, //~ ERROR field `a` is already declared
+        },
+    },
+    // nested field in another named adt
+    _: Foo, //~ ERROR field `a` is already declared
+    _: Bar, //~ ERROR field `a` is already declared
+    // nested field in a named adt in an anoymous adt
+    _: union {
+        _: Foo, //~ ERROR field `a` is already declared
+        _: Bar, //~ ERROR field `a` is already declared
+    },
+}
+
+// duplicated with a nested field in a nested field of a named adt
+#[repr(C)]
+union D2 {
+    // referent field `a`
+    _: Bar,
+
+    // normal field
+    a: u8, //~ ERROR field `a` is already declared
+    // nested field
+    _: union {
+        a: u8, //~ ERROR field `a` is already declared
+    },
+    // more nested field
+    _: struct {
+        _: union {
+            a: u8, //~ ERROR field `a` is already declared
+        },
+    },
+    // nested field in another named adt
+    _: Foo, //~ ERROR field `a` is already declared
+    _: Bar, //~ ERROR field `a` is already declared
+    // nested field in a named adt in an anoymous adt
+    _: union {
+        _: Foo, //~ ERROR field `a` is already declared
+        _: Bar, //~ ERROR field `a` is already declared
+    },
+}
+
+// duplicated with a nested field in a named adt in an anonymous adt
+#[repr(C)]
+struct E {
+    _: struct {
+        // referent field `a`
+        _: Foo,
+
+        // normal field (within the same anonymous adt)
+        a: u8, //~ ERROR field `a` is already declared
+        // nested field (within the same anonymous adt)
+        _: struct {
+            a: u8, //~ ERROR field `a` is already declared
+        },
+        // more nested field (within the same anonymous adt)
+        _: union {
+            _: struct {
+                a: u8, //~ ERROR field `a` is already declared
+            },
+        },
+        // nested field in a named adt (within the same anonymous adt)
+        _: Foo, //~ ERROR field `a` is already declared
+        _: Bar, //~ ERROR field `a` is already declared
+        // nested field in a named adt in an anoymous adt (within the same anonymous adt)
+        _: struct {
+            _: Foo, //~ ERROR field `a` is already declared
+            _: Bar, //~ ERROR field `a` is already declared
+        },
+    },
+
+    // normal field
+    a: u8, //~ ERROR field `a` is already declared
+    // nested field
+    _: union {
+        a: u8, //~ ERROR field `a` is already declared
+    },
+    // more nested field
+    _: struct {
+        _: union {
+            a: u8, //~ ERROR field `a` is already declared
+        },
+    },
+    // nested field in another named adt
+    _: Foo, //~ ERROR field `a` is already declared
+    _: Bar, //~ ERROR field `a` is already declared
+    // nested field in a named adt in an anoymous adt
+    _: union {
+        _: Foo, //~ ERROR field `a` is already declared
+        _: Bar, //~ ERROR field `a` is already declared
+    },
+}
+
+// duplicated with a nested field in a named adt in an anonymous adt
+#[repr(C)]
+union E2 {
+    _: struct {
+        // referent field `a`
+        _: Bar,
+
+        // normal field (within the same anonymous adt)
+        a: u8, //~ ERROR field `a` is already declared
+        // nested field (within the same anonymous adt)
+        _: struct {
+            a: u8, //~ ERROR field `a` is already declared
+        },
+        // more nested field (within the same anonymous adt)
+        _: union {
+            _: struct {
+                a: u8, //~ ERROR field `a` is already declared
+            },
+        },
+        // nested field in a named adt (within the same anonymous adt)
+        _: Foo, //~ ERROR field `a` is already declared
+        _: Bar, //~ ERROR field `a` is already declared
+        // nested field in a named adt in an anoymous adt (within the same anonymous adt)
+        _: struct {
+            _: Foo, //~ ERROR field `a` is already declared
+            _: Bar, //~ ERROR field `a` is already declared
+        },
+    },
+
+    // normal field
+    a: u8, //~ ERROR field `a` is already declared
+    // nested field
+    _: union {
+        a: u8, //~ ERROR field `a` is already declared
+    },
+    // more nested field
+    _: struct {
+        _: union {
+            a: u8, //~ ERROR field `a` is already declared
+        },
+    },
+    // nested field in another named adt
+    _: Foo, //~ ERROR field `a` is already declared
+    _: Bar, //~ ERROR field `a` is already declared
+    // nested field in a named adt in an anoymous adt
+    _: union {
+        _: Foo, //~ ERROR field `a` is already declared
+        _: Bar, //~ ERROR field `a` is already declared
+    },
+}
+
+fn main() {}
diff --git a/tests/ui/union/unnamed-fields/field_uniqueness_check.stderr b/tests/ui/union/unnamed-fields/field_uniqueness_check.stderr
new file mode 100644
index 00000000000..4dea0aa4233
--- /dev/null
+++ b/tests/ui/union/unnamed-fields/field_uniqueness_check.stderr
@@ -0,0 +1,1284 @@
+error[E0124]: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:24:5
+   |
+LL |     a: u8,
+   |     ----- `a` first declared here
+...
+LL |     a: u8,
+   |     ^^^^^ field already declared
+
+error[E0124]: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:27:9
+   |
+LL |     a: u8,
+   |     ----- `a` first declared here
+...
+LL |         a: u8,
+   |         ^^^^^ field already declared
+
+error[E0124]: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:28:9
+   |
+LL |     a: u8,
+   |     ----- `a` first declared here
+...
+LL |         a: u8,
+   |         ^^^^^ field already declared
+
+error[E0124]: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:33:13
+   |
+LL |     a: u8,
+   |     ----- `a` first declared here
+...
+LL |             a: u8,
+   |             ^^^^^ field already declared
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:37:5
+   |
+LL |     a: u8,
+   |     ----- `a` first declared here
+...
+LL |     _: Foo,
+   |     ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:38:5
+   |
+LL |     a: u8,
+   |     ----- `a` first declared here
+...
+LL |     _: Bar,
+   |     ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:41:9
+   |
+LL |     a: u8,
+   |     ----- `a` first declared here
+...
+LL |         _: Foo,
+   |         ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:42:9
+   |
+LL |     a: u8,
+   |     ----- `a` first declared here
+...
+LL |         _: Bar,
+   |         ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+
+error[E0124]: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:54:9
+   |
+LL |         a: u8,
+   |         ----- `a` first declared here
+...
+LL |         a: u8,
+   |         ^^^^^ field already declared
+
+error[E0124]: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:57:13
+   |
+LL |         a: u8,
+   |         ----- `a` first declared here
+...
+LL |             a: u8,
+   |             ^^^^^ field already declared
+
+error[E0124]: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:62:17
+   |
+LL |         a: u8,
+   |         ----- `a` first declared here
+...
+LL |                 a: u8,
+   |                 ^^^^^ field already declared
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:66:9
+   |
+LL |         a: u8,
+   |         ----- `a` first declared here
+...
+LL |         _: Foo,
+   |         ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:67:9
+   |
+LL |         a: u8,
+   |         ----- `a` first declared here
+...
+LL |         _: Bar,
+   |         ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:70:13
+   |
+LL |         a: u8,
+   |         ----- `a` first declared here
+...
+LL |             _: Foo,
+   |             ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:71:13
+   |
+LL |         a: u8,
+   |         ----- `a` first declared here
+...
+LL |             _: Bar,
+   |             ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+
+error[E0124]: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:76:5
+   |
+LL |         a: u8,
+   |         ----- `a` first declared here
+...
+LL |     a: u8,
+   |     ^^^^^ field already declared
+
+error[E0124]: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:79:9
+   |
+LL |         a: u8,
+   |         ----- `a` first declared here
+...
+LL |         a: u8,
+   |         ^^^^^ field already declared
+
+error[E0124]: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:84:13
+   |
+LL |         a: u8,
+   |         ----- `a` first declared here
+...
+LL |             a: u8,
+   |             ^^^^^ field already declared
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:88:5
+   |
+LL |         a: u8,
+   |         ----- `a` first declared here
+...
+LL |     _: Foo,
+   |     ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:89:5
+   |
+LL |         a: u8,
+   |         ----- `a` first declared here
+...
+LL |     _: Bar,
+   |     ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:92:9
+   |
+LL |         a: u8,
+   |         ----- `a` first declared here
+...
+LL |         _: Foo,
+   |         ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:93:9
+   |
+LL |         a: u8,
+   |         ----- `a` first declared here
+...
+LL |         _: Bar,
+   |         ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+
+error[E0124]: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:106:13
+   |
+LL |             a: u8,
+   |             ----- `a` first declared here
+...
+LL |             a: u8,
+   |             ^^^^^ field already declared
+
+error[E0124]: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:109:17
+   |
+LL |             a: u8,
+   |             ----- `a` first declared here
+...
+LL |                 a: u8,
+   |                 ^^^^^ field already declared
+
+error[E0124]: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:114:21
+   |
+LL |             a: u8,
+   |             ----- `a` first declared here
+...
+LL |                     a: u8,
+   |                     ^^^^^ field already declared
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:118:13
+   |
+LL |             a: u8,
+   |             ----- `a` first declared here
+...
+LL |             _: Foo,
+   |             ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:119:13
+   |
+LL |             a: u8,
+   |             ----- `a` first declared here
+...
+LL |             _: Bar,
+   |             ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:122:17
+   |
+LL |             a: u8,
+   |             ----- `a` first declared here
+...
+LL |                 _: Foo,
+   |                 ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:123:17
+   |
+LL |             a: u8,
+   |             ----- `a` first declared here
+...
+LL |                 _: Bar,
+   |                 ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+
+error[E0124]: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:128:9
+   |
+LL |             a: u8,
+   |             ----- `a` first declared here
+...
+LL |         a: u8,
+   |         ^^^^^ field already declared
+
+error[E0124]: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:131:13
+   |
+LL |             a: u8,
+   |             ----- `a` first declared here
+...
+LL |             a: u8,
+   |             ^^^^^ field already declared
+
+error[E0124]: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:136:17
+   |
+LL |             a: u8,
+   |             ----- `a` first declared here
+...
+LL |                 a: u8,
+   |                 ^^^^^ field already declared
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:140:9
+   |
+LL |             a: u8,
+   |             ----- `a` first declared here
+...
+LL |         _: Foo,
+   |         ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:141:9
+   |
+LL |             a: u8,
+   |             ----- `a` first declared here
+...
+LL |         _: Bar,
+   |         ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:144:13
+   |
+LL |             a: u8,
+   |             ----- `a` first declared here
+...
+LL |             _: Foo,
+   |             ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:145:13
+   |
+LL |             a: u8,
+   |             ----- `a` first declared here
+...
+LL |             _: Bar,
+   |             ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+
+error[E0124]: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:149:5
+   |
+LL |             a: u8,
+   |             ----- `a` first declared here
+...
+LL |     a: u8,
+   |     ^^^^^ field already declared
+
+error[E0124]: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:152:9
+   |
+LL |             a: u8,
+   |             ----- `a` first declared here
+...
+LL |         a: u8,
+   |         ^^^^^ field already declared
+
+error[E0124]: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:157:13
+   |
+LL |             a: u8,
+   |             ----- `a` first declared here
+...
+LL |             a: u8,
+   |             ^^^^^ field already declared
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:161:5
+   |
+LL |             a: u8,
+   |             ----- `a` first declared here
+...
+LL |     _: Foo,
+   |     ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:162:5
+   |
+LL |             a: u8,
+   |             ----- `a` first declared here
+...
+LL |     _: Bar,
+   |     ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:165:9
+   |
+LL |             a: u8,
+   |             ----- `a` first declared here
+...
+LL |         _: Foo,
+   |         ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:166:9
+   |
+LL |             a: u8,
+   |             ----- `a` first declared here
+...
+LL |         _: Bar,
+   |         ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:177:5
+   |
+LL |     _: Foo,
+   |     ------ `a` first declared here in this unnamed field
+...
+LL |     a: u8,
+   |     ^^^^^ field already declared
+   |
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:180:9
+   |
+LL |     _: Foo,
+   |     ------ `a` first declared here in this unnamed field
+...
+LL |         a: u8,
+   |         ^^^^^ field already declared
+   |
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:185:13
+   |
+LL |     _: Foo,
+   |     ------ `a` first declared here in this unnamed field
+...
+LL |             a: u8,
+   |             ^^^^^ field already declared
+   |
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:189:5
+   |
+LL |     _: Foo,
+   |     ------ `a` first declared here in this unnamed field
+...
+LL |     _: Foo,
+   |     ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:190:5
+   |
+LL |     _: Foo,
+   |     ------ `a` first declared here in this unnamed field
+...
+LL |     _: Bar,
+   |     ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:193:9
+   |
+LL |     _: Foo,
+   |     ------ `a` first declared here in this unnamed field
+...
+LL |         _: Foo,
+   |         ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:194:9
+   |
+LL |     _: Foo,
+   |     ------ `a` first declared here in this unnamed field
+...
+LL |         _: Bar,
+   |         ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:205:5
+   |
+LL |     _: Bar,
+   |     ------ `a` first declared here in this unnamed field
+...
+LL |     a: u8,
+   |     ^^^^^ field already declared
+   |
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:208:9
+   |
+LL |     _: Bar,
+   |     ------ `a` first declared here in this unnamed field
+...
+LL |         a: u8,
+   |         ^^^^^ field already declared
+   |
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:213:13
+   |
+LL |     _: Bar,
+   |     ------ `a` first declared here in this unnamed field
+...
+LL |             a: u8,
+   |             ^^^^^ field already declared
+   |
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:217:5
+   |
+LL |     _: Bar,
+   |     ------ `a` first declared here in this unnamed field
+...
+LL |     _: Foo,
+   |     ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:218:5
+   |
+LL |     _: Bar,
+   |     ------ `a` first declared here in this unnamed field
+...
+LL |     _: Bar,
+   |     ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:221:9
+   |
+LL |     _: Bar,
+   |     ------ `a` first declared here in this unnamed field
+...
+LL |         _: Foo,
+   |         ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:222:9
+   |
+LL |     _: Bar,
+   |     ------ `a` first declared here in this unnamed field
+...
+LL |         _: Bar,
+   |         ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:234:9
+   |
+LL |         _: Foo,
+   |         ------ `a` first declared here in this unnamed field
+...
+LL |         a: u8,
+   |         ^^^^^ field already declared
+   |
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:237:13
+   |
+LL |         _: Foo,
+   |         ------ `a` first declared here in this unnamed field
+...
+LL |             a: u8,
+   |             ^^^^^ field already declared
+   |
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:242:17
+   |
+LL |         _: Foo,
+   |         ------ `a` first declared here in this unnamed field
+...
+LL |                 a: u8,
+   |                 ^^^^^ field already declared
+   |
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:246:9
+   |
+LL |         _: Foo,
+   |         ------ `a` first declared here in this unnamed field
+...
+LL |         _: Foo,
+   |         ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:247:9
+   |
+LL |         _: Foo,
+   |         ------ `a` first declared here in this unnamed field
+...
+LL |         _: Bar,
+   |         ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:250:13
+   |
+LL |         _: Foo,
+   |         ------ `a` first declared here in this unnamed field
+...
+LL |             _: Foo,
+   |             ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:251:13
+   |
+LL |         _: Foo,
+   |         ------ `a` first declared here in this unnamed field
+...
+LL |             _: Bar,
+   |             ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:256:5
+   |
+LL |         _: Foo,
+   |         ------ `a` first declared here in this unnamed field
+...
+LL |     a: u8,
+   |     ^^^^^ field already declared
+   |
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:259:9
+   |
+LL |         _: Foo,
+   |         ------ `a` first declared here in this unnamed field
+...
+LL |         a: u8,
+   |         ^^^^^ field already declared
+   |
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:264:13
+   |
+LL |         _: Foo,
+   |         ------ `a` first declared here in this unnamed field
+...
+LL |             a: u8,
+   |             ^^^^^ field already declared
+   |
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:268:5
+   |
+LL |         _: Foo,
+   |         ------ `a` first declared here in this unnamed field
+...
+LL |     _: Foo,
+   |     ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:269:5
+   |
+LL |         _: Foo,
+   |         ------ `a` first declared here in this unnamed field
+...
+LL |     _: Bar,
+   |     ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:272:9
+   |
+LL |         _: Foo,
+   |         ------ `a` first declared here in this unnamed field
+...
+LL |         _: Foo,
+   |         ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:273:9
+   |
+LL |         _: Foo,
+   |         ------ `a` first declared here in this unnamed field
+...
+LL |         _: Bar,
+   |         ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:285:9
+   |
+LL |         _: Bar,
+   |         ------ `a` first declared here in this unnamed field
+...
+LL |         a: u8,
+   |         ^^^^^ field already declared
+   |
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:288:13
+   |
+LL |         _: Bar,
+   |         ------ `a` first declared here in this unnamed field
+...
+LL |             a: u8,
+   |             ^^^^^ field already declared
+   |
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:293:17
+   |
+LL |         _: Bar,
+   |         ------ `a` first declared here in this unnamed field
+...
+LL |                 a: u8,
+   |                 ^^^^^ field already declared
+   |
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:297:9
+   |
+LL |         _: Bar,
+   |         ------ `a` first declared here in this unnamed field
+...
+LL |         _: Foo,
+   |         ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:298:9
+   |
+LL |         _: Bar,
+   |         ------ `a` first declared here in this unnamed field
+...
+LL |         _: Bar,
+   |         ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:301:13
+   |
+LL |         _: Bar,
+   |         ------ `a` first declared here in this unnamed field
+...
+LL |             _: Foo,
+   |             ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:302:13
+   |
+LL |         _: Bar,
+   |         ------ `a` first declared here in this unnamed field
+...
+LL |             _: Bar,
+   |             ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:307:5
+   |
+LL |         _: Bar,
+   |         ------ `a` first declared here in this unnamed field
+...
+LL |     a: u8,
+   |     ^^^^^ field already declared
+   |
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:310:9
+   |
+LL |         _: Bar,
+   |         ------ `a` first declared here in this unnamed field
+...
+LL |         a: u8,
+   |         ^^^^^ field already declared
+   |
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:315:13
+   |
+LL |         _: Bar,
+   |         ------ `a` first declared here in this unnamed field
+...
+LL |             a: u8,
+   |             ^^^^^ field already declared
+   |
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:319:5
+   |
+LL |         _: Bar,
+   |         ------ `a` first declared here in this unnamed field
+...
+LL |     _: Foo,
+   |     ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:320:5
+   |
+LL |         _: Bar,
+   |         ------ `a` first declared here in this unnamed field
+...
+LL |     _: Bar,
+   |     ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:323:9
+   |
+LL |         _: Bar,
+   |         ------ `a` first declared here in this unnamed field
+...
+LL |         _: Foo,
+   |         ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:6:5
+   |
+LL |     a: u8,
+   |     ^^^^^
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+
+error: field `a` is already declared
+  --> $DIR/field_uniqueness_check.rs:324:9
+   |
+LL |         _: Bar,
+   |         ------ `a` first declared here in this unnamed field
+...
+LL |         _: Bar,
+   |         ^^^^^^ field `a` declared in this unnamed field
+   |
+note: field `a` declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+note: field `a` first declared here
+  --> $DIR/field_uniqueness_check.rs:12:9
+   |
+LL |         a: u8,
+   |         ^^^^^
+
+error: aborting due to 85 previous errors
+
+For more information about this error, try `rustc --explain E0124`.
diff --git a/tests/ui/union/unnamed-fields/restrict_anonymous_structs.rs b/tests/ui/union/unnamed-fields/restrict_anonymous_structs.rs
index 76525ec0bb1..03545ed7b18 100644
--- a/tests/ui/union/unnamed-fields/restrict_anonymous_structs.rs
+++ b/tests/ui/union/unnamed-fields/restrict_anonymous_structs.rs
@@ -2,8 +2,8 @@
 #![feature(unnamed_fields)]
 
 struct F {
-    field: struct { field: u8 }, //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
-    _: struct { field: u8 },
+    field1: struct { field2: u8 }, //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
+    _: struct { field3: u8 },
 }
 
 struct G {
@@ -11,8 +11,8 @@ struct G {
 }
 
 union H {
-    field: struct { field: u8 }, //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
-    _: struct { field: u8 },
+    field1: struct { field2: u8 }, //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
+    _: struct { field3: u8 },
 }
 
 union I {
diff --git a/tests/ui/union/unnamed-fields/restrict_anonymous_structs.stderr b/tests/ui/union/unnamed-fields/restrict_anonymous_structs.stderr
index 846e3451a71..3b3890af771 100644
--- a/tests/ui/union/unnamed-fields/restrict_anonymous_structs.stderr
+++ b/tests/ui/union/unnamed-fields/restrict_anonymous_structs.stderr
@@ -1,8 +1,8 @@
 error: anonymous structs are not allowed outside of unnamed struct or union fields
-  --> $DIR/restrict_anonymous_structs.rs:5:12
+  --> $DIR/restrict_anonymous_structs.rs:5:13
    |
-LL |     field: struct { field: u8 },
-   |            ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
+LL |     field1: struct { field2: u8 },
+   |             ^^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
 
 error: unnamed fields can only have struct or union types
   --> $DIR/restrict_anonymous_structs.rs:10:5
@@ -11,10 +11,10 @@ LL |     _: (u8, u8),
    |     ^  -------- not a struct or union
 
 error: anonymous structs are not allowed outside of unnamed struct or union fields
-  --> $DIR/restrict_anonymous_structs.rs:14:12
+  --> $DIR/restrict_anonymous_structs.rs:14:13
    |
-LL |     field: struct { field: u8 },
-   |            ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
+LL |     field1: struct { field2: u8 },
+   |             ^^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
 
 error: unnamed fields can only have struct or union types
   --> $DIR/restrict_anonymous_structs.rs:19:5
diff --git a/tests/ui/union/unnamed-fields/restrict_anonymous_unions.rs b/tests/ui/union/unnamed-fields/restrict_anonymous_unions.rs
index c049ba92ed2..9ffe71b28c2 100644
--- a/tests/ui/union/unnamed-fields/restrict_anonymous_unions.rs
+++ b/tests/ui/union/unnamed-fields/restrict_anonymous_unions.rs
@@ -2,8 +2,8 @@
 #![feature(unnamed_fields)]
 
 struct F {
-    field: union { field: u8 }, //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields
-    _: union { field: u8 },
+    field1: union { field2: u8 }, //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields
+    _: union { field3: u8 },
 }
 
 struct G {
@@ -11,8 +11,8 @@ struct G {
 }
 
 union H {
-    field: union { field: u8 }, //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields
-    _: union { field: u8 },
+    field1: union { field2: u8 }, //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields
+    _: union { field3: u8 },
 }
 
 union I {
diff --git a/tests/ui/union/unnamed-fields/restrict_anonymous_unions.stderr b/tests/ui/union/unnamed-fields/restrict_anonymous_unions.stderr
index c916e37a3e9..f8679aad2d7 100644
--- a/tests/ui/union/unnamed-fields/restrict_anonymous_unions.stderr
+++ b/tests/ui/union/unnamed-fields/restrict_anonymous_unions.stderr
@@ -1,8 +1,8 @@
 error: anonymous unions are not allowed outside of unnamed struct or union fields
-  --> $DIR/restrict_anonymous_unions.rs:5:12
+  --> $DIR/restrict_anonymous_unions.rs:5:13
    |
-LL |     field: union { field: u8 },
-   |            ^^^^^^^^^^^^^^^^^^^ anonymous union declared here
+LL |     field1: union { field2: u8 },
+   |             ^^^^^^^^^^^^^^^^^^^^ anonymous union declared here
 
 error: unnamed fields can only have struct or union types
   --> $DIR/restrict_anonymous_unions.rs:10:5
@@ -11,10 +11,10 @@ LL |     _: (u8, u8),
    |     ^  -------- not a struct or union
 
 error: anonymous unions are not allowed outside of unnamed struct or union fields
-  --> $DIR/restrict_anonymous_unions.rs:14:12
+  --> $DIR/restrict_anonymous_unions.rs:14:13
    |
-LL |     field: union { field: u8 },
-   |            ^^^^^^^^^^^^^^^^^^^ anonymous union declared here
+LL |     field1: union { field2: u8 },
+   |             ^^^^^^^^^^^^^^^^^^^^ anonymous union declared here
 
 error: unnamed fields can only have struct or union types
   --> $DIR/restrict_anonymous_unions.rs:19:5