diff options
Diffstat (limited to 'compiler/rustc_resolve')
| -rw-r--r-- | compiler/rustc_resolve/src/build_reduced_graph.rs | 88 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/def_collector.rs | 20 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/lib.rs | 6 | 
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 }; | 
