Skip to content

Commit d9347ee

Browse files
committed
Lowering anonymous structs or unions to HIR (WIP)
1 parent 868706d commit d9347ee

File tree

28 files changed

+197
-65
lines changed

28 files changed

+197
-65
lines changed

compiler/rustc_ast_lowering/src/item.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -708,7 +708,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
708708
}
709709
}
710710

711-
fn lower_field_def(&mut self, (index, f): (usize, &FieldDef)) -> hir::FieldDef<'hir> {
711+
pub(super) fn lower_field_def(&mut self, (index, f): (usize, &FieldDef)) -> hir::FieldDef<'hir> {
712712
let ty = if let TyKind::Path(qself, path) = &f.ty.kind {
713713
let t = self.lower_path_ty(
714714
&f.ty,

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1293,18 +1293,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
12931293
TyKind::Err => {
12941294
hir::TyKind::Err(self.tcx.sess.delay_span_bug(t.span, "TyKind::Err lowered"))
12951295
}
1296-
// FIXME(unnamed_fields): IMPLEMENTATION IN PROGRESS
1297-
#[allow(rustc::untranslatable_diagnostic)]
1298-
#[allow(rustc::diagnostic_outside_of_impl)]
1299-
TyKind::AnonStruct(ref _fields) => hir::TyKind::Err(
1300-
self.tcx.sess.span_err(t.span, "anonymous structs are unimplemented"),
1301-
),
1302-
// FIXME(unnamed_fields): IMPLEMENTATION IN PROGRESS
1303-
#[allow(rustc::untranslatable_diagnostic)]
1304-
#[allow(rustc::diagnostic_outside_of_impl)]
1305-
TyKind::AnonUnion(ref _fields) => hir::TyKind::Err(
1306-
self.tcx.sess.span_err(t.span, "anonymous unions are unimplemented"),
1307-
),
1296+
TyKind::AnonStruct(fields) => {
1297+
let hir_id = self.next_id();
1298+
hir::TyKind::AnonStruct(
1299+
self.arena.alloc_from_iter(fields.iter().enumerate().map(|f| self.lower_field_def(f))),
1300+
hir_id,
1301+
)
1302+
}
1303+
TyKind::AnonUnion(fields) => {
1304+
let hir_id = self.next_id();
1305+
hir::TyKind::AnonUnion(
1306+
self.arena.alloc_from_iter(fields.iter().enumerate().map(|f| self.lower_field_def(f))),
1307+
hir_id,
1308+
)
1309+
}
13081310
TyKind::Slice(ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)),
13091311
TyKind::Ptr(mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)),
13101312
TyKind::Ref(region, mt) => {

compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ fn build_single_variant_union_fields<'ll, 'tcx>(
338338
enum_type_di_node,
339339
std::iter::once((
340340
variant_index,
341-
Cow::from(enum_adt_def.variant(variant_index).name.as_str()),
341+
Cow::from(enum_adt_def.variant(variant_index).name_ref().as_str()),
342342
)),
343343
);
344344

@@ -399,7 +399,7 @@ fn build_union_fields_for_enum<'ll, 'tcx>(
399399
cx,
400400
enum_type_di_node,
401401
variant_indices.clone().map(|variant_index| {
402-
let variant_name = Cow::from(enum_adt_def.variant(variant_index).name.as_str());
402+
let variant_name = Cow::from(enum_adt_def.variant(variant_index).name_ref().as_str());
403403
(variant_index, variant_name)
404404
}),
405405
);

compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ fn build_c_style_enum_di_node<'ll, 'tcx>(
9292
&compute_debuginfo_type_name(cx.tcx, enum_type_and_layout.ty, false),
9393
tag_base_type(cx, enum_type_and_layout),
9494
enum_adt_def.discriminants(cx.tcx).map(|(variant_index, discr)| {
95-
let name = Cow::from(enum_adt_def.variant(variant_index).name.as_str());
95+
let name = Cow::from(enum_adt_def.variant(variant_index).name_ref().as_str());
9696
(name, discr.val)
9797
}),
9898
containing_scope,
@@ -263,7 +263,7 @@ fn build_enum_variant_struct_type_di_node<'ll, 'tcx>(
263263
enum_type_and_layout.ty,
264264
variant_index,
265265
),
266-
variant_def.name.as_str(),
266+
variant_def.name().as_str(),
267267
// NOTE: We use size and align of enum_type, not from variant_layout:
268268
size_and_align_of(enum_type_and_layout),
269269
Some(enum_type_di_node),

compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
8484
.variant_range()
8585
.map(|variant_index| VariantMemberInfo {
8686
variant_index,
87-
variant_name: Cow::from(enum_adt_def.variant(variant_index).name.as_str()),
87+
variant_name: Cow::from(enum_adt_def.variant(variant_index).name_ref().as_str()),
8888
variant_struct_type_di_node: super::build_enum_variant_struct_type_di_node(
8989
cx,
9090
enum_type_and_layout,

compiler/rustc_codegen_llvm/src/type_of.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ fn uncached_llvm_type<'a, 'tcx>(
5151
(layout.ty.kind(), &layout.variants)
5252
{
5353
if def.is_enum() && !def.variants().is_empty() {
54-
write!(&mut name, "::{}", def.variant(index).name).unwrap();
54+
write!(&mut name, "::{}", def.variant(index).name()).unwrap();
5555
}
5656
}
5757
if let (&ty::Generator(_, _, _), &Variants::Single { index }) =

compiler/rustc_const_eval/src/interpret/validity.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -686,7 +686,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
686686
new_op: &OpTy<'tcx, M::Provenance>,
687687
) -> InterpResult<'tcx> {
688688
let name = match old_op.layout.ty.kind() {
689-
ty::Adt(adt, _) => PathElem::Variant(adt.variant(variant_id).name),
689+
ty::Adt(adt, _) => PathElem::Variant(adt.variant(variant_id).name()),
690690
// Generators also have variants
691691
ty::Generator(..) => PathElem::GeneratorState(variant_id),
692692
_ => bug!("Unexpected type with variant: {:?}", old_op.layout.ty),

compiler/rustc_hir/src/hir.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2713,6 +2713,10 @@ pub enum TyKind<'hir> {
27132713
Never,
27142714
/// A tuple (`(A, B, C, D, ...)`).
27152715
Tup(&'hir [Ty<'hir>]),
2716+
/// An anonymous struct type i.e. `struct { foo: Type }`
2717+
AnonStruct(&'hir [FieldDef<'hir>], HirId),
2718+
/// An anonymous union type i.e. `union { bar: Type }`
2719+
AnonUnion(&'hir [FieldDef<'hir>], HirId),
27162720
/// A path to a type definition (`module::module::...::Type`), or an
27172721
/// associated type (e.g., `<Vec<T> as Trait>::Type` or `<T>::Target`).
27182722
///

compiler/rustc_hir/src/intravisit.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -862,6 +862,9 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) {
862862
}
863863
TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression),
864864
TyKind::Infer | TyKind::Err(_) => {}
865+
TyKind::AnonStruct(fields, _hir_id) | TyKind::AnonUnion(fields, _hir_id) => {
866+
walk_list!(visitor, visit_field_def, fields);
867+
}
865868
}
866869
}
867870

compiler/rustc_hir_analysis/src/astconv/mod.rs

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1427,7 +1427,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
14271427
&adt_def
14281428
.variants()
14291429
.iter()
1430-
.map(|variant| variant.name)
1430+
.map(|variant| variant.name())
14311431
.collect::<Vec<Symbol>>(),
14321432
assoc_ident.name,
14331433
None,
@@ -2524,6 +2524,27 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
25242524
self.ty_infer(None, ast_ty.span)
25252525
}
25262526
hir::TyKind::Err(guar) => Ty::new_error(tcx, *guar),
2527+
&hir::TyKind::AnonStruct(fields, hir_id) | &hir::TyKind::AnonUnion(fields, hir_id) => {
2528+
let repr = tcx.repr_options_of_def(hir_id.owner.to_def_id());
2529+
if !repr.c() {
2530+
// tcx.sess.emit_err(todo!());
2531+
}
2532+
let adt_kind = match ast_ty.kind {
2533+
hir::TyKind::AnonStruct(..) => ty::AdtKind::Struct,
2534+
_ => ty::AdtKind::Union,
2535+
};
2536+
let field_def = tcx.hir().expect_field(tcx.hir().parent_id(hir_id));
2537+
let did = field_def.def_id;
2538+
let variants = std::iter::once(convert_variant(
2539+
tcx,
2540+
did,
2541+
fields,
2542+
adt_kind,
2543+
))
2544+
.collect();
2545+
let adt_def = tcx.mk_adt_def(did.to_def_id(), adt_kind, variants, repr);
2546+
Ty::new_adt(tcx, adt_def, tcx.mk_args(&[]))
2547+
}
25272548
};
25282549

25292550
self.record_ty(ast_ty.hir_id, result_ty, ast_ty.span);
@@ -2813,3 +2834,38 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
28132834
Some(r)
28142835
}
28152836
}
2837+
2838+
fn convert_variant(
2839+
tcx: TyCtxt<'_>,
2840+
did: LocalDefId,
2841+
fields: &[hir::FieldDef<'_>],
2842+
adt_kind: ty::AdtKind,
2843+
) -> ty::VariantDef {
2844+
let mut seen_fields: FxHashMap<Ident, Span> = Default::default();
2845+
let fields = fields
2846+
.iter()
2847+
.map(|f| {
2848+
let dup_span = seen_fields.get(&f.ident.normalize_to_macros_2_0()).cloned();
2849+
if let Some(prev_span) = dup_span {
2850+
tcx.sess.emit_err(crate::errors::FieldAlreadyDeclared {
2851+
field_name: f.ident,
2852+
span: f.span,
2853+
prev_span,
2854+
});
2855+
} else {
2856+
seen_fields.insert(f.ident.normalize_to_macros_2_0(), f.span);
2857+
}
2858+
2859+
ty::FieldDef {
2860+
did: f.def_id.to_def_id(),
2861+
name: f.ident.name,
2862+
vis: tcx.visibility(f.def_id),
2863+
}
2864+
})
2865+
.collect();
2866+
ty::VariantDef::new_anon(
2867+
did.to_def_id(),
2868+
fields,
2869+
adt_kind,
2870+
)
2871+
}

0 commit comments

Comments
 (0)