Lowering field access for anonymous adts
This commit is contained in:
parent
36d7e7fd3f
commit
0c0df4efe0
18 changed files with 391 additions and 71 deletions
|
@ -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_fields(
|
||||
&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_fields(
|
||||
&nested_fields,
|
||||
Ident::empty(),
|
||||
local_def_id,
|
||||
res,
|
||||
// Anonymous adts inherit visibility from their parent adts.
|
||||
adt_vis,
|
||||
field.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_fields(
|
||||
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_fields(
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -324,8 +324,21 @@ 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),
|
||||
TyKind::AnonStruct(node_id, fields) | TyKind::AnonUnion(node_id, fields) => {
|
||||
let def_kind = match &ty.kind {
|
||||
TyKind::AnonStruct(..) => DefKind::Struct,
|
||||
TyKind::AnonUnion(..) => DefKind::Union,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let def_id = self.create_def(*node_id, kw::Empty, def_kind, ty.span);
|
||||
self.with_parent(def_id, |this| {
|
||||
for f in fields {
|
||||
this.visit_field_def(f);
|
||||
}
|
||||
});
|
||||
}
|
||||
_ => visit::walk_ty(self, ty),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue