about summary refs log tree commit diff
path: root/compiler/rustc_resolve
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_resolve')
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs88
-rw-r--r--compiler/rustc_resolve/src/def_collector.rs20
-rw-r--r--compiler/rustc_resolve/src/lib.rs6
3 files changed, 93 insertions, 21 deletions
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 7eb7c8c2bca..469d15e4214 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -313,18 +313,17 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
         }
     }
 
-    fn insert_field_def_ids(&mut self, def_id: LocalDefId, vdata: &ast::VariantData) {
-        if vdata.fields().iter().any(|field| field.is_placeholder) {
+    fn insert_field_def_ids(&mut self, def_id: LocalDefId, fields: &[ast::FieldDef]) {
+        if fields.iter().any(|field| field.is_placeholder) {
             // The fields are not expanded yet.
             return;
         }
-        let def_ids = vdata.fields().iter().map(|field| self.r.local_def_id(field.id).to_def_id());
+        let def_ids = fields.iter().map(|field| self.r.local_def_id(field.id).to_def_id());
         self.r.field_def_ids.insert(def_id, self.r.tcx.arena.alloc_from_iter(def_ids));
     }
 
-    fn insert_field_visibilities_local(&mut self, def_id: DefId, vdata: &ast::VariantData) {
-        let field_vis = vdata
-            .fields()
+    fn insert_field_visibilities_local(&mut self, def_id: DefId, fields: &[ast::FieldDef]) {
+        let field_vis = fields
             .iter()
             .map(|field| field.vis.span.until(field.ident.map_or(field.ty.span, |i| i.span)))
             .collect();
@@ -629,6 +628,50 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
         }
     }
 
+    fn build_reduced_graph_for_struct_variant(
+        &mut self,
+        fields: &[ast::FieldDef],
+        ident: Ident,
+        def_id: LocalDefId,
+        adt_res: Res,
+        adt_vis: ty::Visibility,
+        adt_span: Span,
+    ) {
+        let parent_scope = &self.parent_scope;
+        let parent = parent_scope.module;
+        let expansion = parent_scope.expansion;
+
+        // Define a name in the type namespace if it is not anonymous.
+        self.r.define(parent, ident, TypeNS, (adt_res, adt_vis, adt_span, expansion));
+        self.r.feed_visibility(def_id, adt_vis);
+
+        // Record field names for error reporting.
+        self.insert_field_def_ids(def_id, fields);
+        self.insert_field_visibilities_local(def_id.to_def_id(), fields);
+
+        for field in fields {
+            match &field.ty.kind {
+                ast::TyKind::AnonStruct(id, nested_fields)
+                | ast::TyKind::AnonUnion(id, nested_fields) => {
+                    let local_def_id = self.r.local_def_id(*id);
+                    let def_id = local_def_id.to_def_id();
+                    let def_kind = self.r.tcx.def_kind(local_def_id);
+                    let res = Res::Def(def_kind, def_id);
+                    self.build_reduced_graph_for_struct_variant(
+                        &nested_fields,
+                        Ident::empty(),
+                        local_def_id,
+                        res,
+                        // Anonymous adts inherit visibility from their parent adts.
+                        adt_vis,
+                        field.ty.span,
+                    );
+                }
+                _ => {}
+            }
+        }
+    }
+
     /// Constructs the reduced graph for one item.
     fn build_reduced_graph_for_item(&mut self, item: &'b Item) {
         let parent_scope = &self.parent_scope;
@@ -716,12 +759,14 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
 
             // These items live in both the type and value namespaces.
             ItemKind::Struct(ref vdata, _) => {
-                // Define a name in the type namespace.
-                self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion));
-
-                // Record field names for error reporting.
-                self.insert_field_def_ids(local_def_id, vdata);
-                self.insert_field_visibilities_local(def_id, vdata);
+                self.build_reduced_graph_for_struct_variant(
+                    vdata.fields(),
+                    ident,
+                    local_def_id,
+                    res,
+                    vis,
+                    sp,
+                );
 
                 // If this is a tuple or unit struct, define a name
                 // in the value namespace as well.
@@ -755,7 +800,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
                     self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, sp, expansion));
                     self.r.feed_visibility(ctor_def_id, ctor_vis);
                     // We need the field visibility spans also for the constructor for E0603.
-                    self.insert_field_visibilities_local(ctor_def_id.to_def_id(), vdata);
+                    self.insert_field_visibilities_local(ctor_def_id.to_def_id(), vdata.fields());
 
                     self.r
                         .struct_constructors
@@ -764,11 +809,14 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
             }
 
             ItemKind::Union(ref vdata, _) => {
-                self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion));
-
-                // Record field names for error reporting.
-                self.insert_field_def_ids(local_def_id, vdata);
-                self.insert_field_visibilities_local(def_id, vdata);
+                self.build_reduced_graph_for_struct_variant(
+                    vdata.fields(),
+                    ident,
+                    local_def_id,
+                    res,
+                    vis,
+                    sp,
+                );
             }
 
             // These items do not add names to modules.
@@ -1461,8 +1509,8 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
         }
 
         // Record field names for error reporting.
-        self.insert_field_def_ids(def_id, &variant.data);
-        self.insert_field_visibilities_local(def_id.to_def_id(), &variant.data);
+        self.insert_field_def_ids(def_id, variant.data.fields());
+        self.insert_field_visibilities_local(def_id.to_def_id(), variant.data.fields());
 
         visit::walk_variant(self, variant);
     }
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index 42ace9bb22f..45aea585f97 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -80,6 +80,22 @@ impl<'a, 'b, 'tcx> DefCollector<'a, 'b, 'tcx> {
             let name = field.ident.map_or_else(|| sym::integer(index(self)), |ident| ident.name);
             let def = self.create_def(field.id, name, DefKind::Field, field.span);
             self.with_parent(def, |this| visit::walk_field_def(this, field));
+            self.visit_anon_adt(&field.ty);
+        }
+    }
+
+    fn visit_anon_adt(&mut self, ty: &'a Ty) {
+        let def_kind = match &ty.kind {
+            TyKind::AnonStruct(..) => DefKind::Struct,
+            TyKind::AnonUnion(..) => DefKind::Union,
+            _ => return,
+        };
+        match &ty.kind {
+            TyKind::AnonStruct(node_id, _) | TyKind::AnonUnion(node_id, _) => {
+                let def_id = self.create_def(*node_id, kw::Empty, def_kind, ty.span);
+                self.with_parent(def_id, |this| visit::walk_ty(this, ty));
+            }
+            _ => {}
         }
     }
 
@@ -324,8 +340,10 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
     }
 
     fn visit_ty(&mut self, ty: &'a Ty) {
-        match ty.kind {
+        match &ty.kind {
             TyKind::MacCall(..) => self.visit_macro_invoc(ty.id),
+            // Anonymous structs or unions are visited later after defined.
+            TyKind::AnonStruct(..) | TyKind::AnonUnion(..) => {}
             _ => visit::walk_ty(self, ty),
         }
     }
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 6c0f2b89347..6b07bfdec67 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -1016,6 +1016,8 @@ pub struct Resolver<'a, 'tcx> {
     binding_parent_modules: FxHashMap<NameBinding<'a>, Module<'a>>,
 
     underscore_disambiguator: u32,
+    /// Disambiguator for anonymous adts.
+    empty_disambiguator: u32,
 
     /// Maps glob imports to the names of items actually imported.
     glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>,
@@ -1367,6 +1369,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             module_children: Default::default(),
             trait_map: NodeMap::default(),
             underscore_disambiguator: 0,
+            empty_disambiguator: 0,
             empty_module,
             module_map,
             block_map: Default::default(),
@@ -1734,6 +1737,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         let disambiguator = if ident.name == kw::Underscore {
             self.underscore_disambiguator += 1;
             self.underscore_disambiguator
+        } else if ident.name == kw::Empty {
+            self.empty_disambiguator += 1;
+            self.empty_disambiguator
         } else {
             0
         };