1
Fork 0

Lowering field access for anonymous adts

This commit is contained in:
Frank King 2024-01-04 21:45:06 +08:00
parent 36d7e7fd3f
commit 0c0df4efe0
18 changed files with 391 additions and 71 deletions

View file

@ -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);
}

View file

@ -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),
}
}

View file

@ -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
};