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

+1-1
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

+14-12
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

+2-2
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

+2-2
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

+1-1
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

+1-1
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

+1-1
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

+4
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

+3
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

+57-1
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+
}

compiler/rustc_hir_analysis/src/check/check.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1323,8 +1323,8 @@ fn detect_discriminant_duplicate<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
13231323
idx.as_u32().checked_sub(distance_to_explicit).map(VariantIdx::from_u32)
13241324
{
13251325
let explicit_variant = adt.variant(explicit_idx);
1326-
let ve_ident = var.name;
1327-
let ex_ident = explicit_variant.name;
1326+
let ve_ident = var.name();
1327+
let ex_ident = explicit_variant.name();
13281328
let sp = if distance_to_explicit > 1 { "variants" } else { "variant" };
13291329

13301330
err.span_label(

compiler/rustc_hir_analysis/src/collect.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -776,7 +776,7 @@ fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
776776
}
777777
}
778778

779-
fn convert_variant(
779+
pub(crate) fn convert_variant(
780780
tcx: TyCtxt<'_>,
781781
variant_did: Option<LocalDefId>,
782782
ident: Ident,

compiler/rustc_hir_pretty/src/lib.rs

+27-15
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,14 @@ impl<'a> State<'a> {
367367
hir::TyKind::Infer => {
368368
self.word("_");
369369
}
370+
hir::TyKind::AnonStruct(fields, _hir_id) => {
371+
self.word("struct");
372+
self.print_variant_struct(ty.span, fields);
373+
}
374+
hir::TyKind::AnonUnion(fields, _hir_id) => {
375+
self.word("union");
376+
self.print_variant_struct(ty.span, fields);
377+
}
370378
}
371379
self.end()
372380
}
@@ -788,25 +796,29 @@ impl<'a> State<'a> {
788796
}
789797
hir::VariantData::Struct(..) => {
790798
self.print_where_clause(generics);
791-
self.nbsp();
792-
self.bopen();
793-
self.hardbreak_if_not_bol();
794-
795-
for field in struct_def.fields() {
796-
self.hardbreak_if_not_bol();
797-
self.maybe_print_comment(field.span.lo());
798-
self.print_outer_attributes(self.attrs(field.hir_id));
799-
self.print_ident(field.ident);
800-
self.word_nbsp(":");
801-
self.print_type(field.ty);
802-
self.word(",");
803-
}
804-
805-
self.bclose(span)
799+
self.print_variant_struct(span, struct_def.fields())
806800
}
807801
}
808802
}
809803

804+
fn print_variant_struct(&mut self, span: rustc_span::Span, fields: &[hir::FieldDef<'_>]) {
805+
self.nbsp();
806+
self.bopen();
807+
self.hardbreak_if_not_bol();
808+
809+
for field in fields {
810+
self.hardbreak_if_not_bol();
811+
self.maybe_print_comment(field.span.lo());
812+
self.print_outer_attributes(self.attrs(field.hir_id));
813+
self.print_ident(field.ident);
814+
self.word_nbsp(":");
815+
self.print_type(field.ty);
816+
self.word(",");
817+
}
818+
819+
self.bclose(span)
820+
}
821+
810822
pub fn print_variant(&mut self, v: &hir::Variant<'_>) {
811823
self.head("");
812824
let generics = hir::Generics::empty();

compiler/rustc_hir_typeck/src/expr.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -1740,7 +1740,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17401740
&cause,
17411741
target_ty,
17421742
fru_ty,
1743-
FieldMisMatch(variant.name, ident.name),
1743+
FieldMisMatch(variant.name(), ident.name),
17441744
)
17451745
.emit();
17461746
}
@@ -2060,7 +2060,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
20602060
"{} `{}::{}` has no field named `{}`",
20612061
kind_name,
20622062
actual,
2063-
variant.name,
2063+
variant.name(),
20642064
field.ident
20652065
),
20662066
_ => struct_span_err!(
@@ -2085,7 +2085,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
20852085
format!(
20862086
"`{adt}::{variant}` defined here",
20872087
adt = ty,
2088-
variant = variant.name,
2088+
variant = variant.name(),
20892089
),
20902090
);
20912091
err.span_label(field.ident.span, "field does not exist");
@@ -2094,12 +2094,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
20942094
format!(
20952095
"`{adt}::{variant}` is a tuple {kind_name}, use the appropriate syntax",
20962096
adt = ty,
2097-
variant = variant.name,
2097+
variant = variant.name(),
20982098
),
20992099
format!(
21002100
"{adt}::{variant}(/* fields */)",
21012101
adt = ty,
2102-
variant = variant.name,
2102+
variant = variant.name(),
21032103
),
21042104
Applicability::HasPlaceholders,
21052105
);
@@ -2133,7 +2133,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21332133
if adt.is_enum() {
21342134
err.span_label(
21352135
field.ident.span,
2136-
format!("`{}::{}` does not have this field", ty, variant.name),
2136+
format!("`{}::{}` does not have this field", ty, variant.name()),
21372137
);
21382138
} else {
21392139
err.span_label(

compiler/rustc_hir_typeck/src/method/suggest.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1174,7 +1174,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11741174
if unsatisfied_predicates.is_empty() && rcvr_ty.is_enum() {
11751175
let adt_def = rcvr_ty.ty_adt_def().expect("enum is not an ADT");
11761176
if let Some(suggestion) = edit_distance::find_best_match_for_name(
1177-
&adt_def.variants().iter().map(|s| s.name).collect::<Vec<_>>(),
1177+
&adt_def.variants().iter().map(|s| s.name()).collect::<Vec<_>>(),
11781178
item_name.name,
11791179
None,
11801180
) {

compiler/rustc_middle/src/hir/map/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -853,6 +853,13 @@ impl<'hir> Map<'hir> {
853853
}
854854
}
855855

856+
pub fn expect_field(self, id: HirId) -> &'hir FieldDef<'hir> {
857+
match self.find(id) {
858+
Some(Node::Field(field)) => field,
859+
_ => bug!("expected field, found {}", self.node_to_string(id)),
860+
}
861+
}
862+
856863
pub fn expect_foreign_item(self, id: OwnerId) -> &'hir ForeignItem<'hir> {
857864
match self.tcx.hir_owner(id) {
858865
Some(Owner { node: OwnerNode::ForeignItem(item), .. }) => item,

compiler/rustc_middle/src/mir/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2737,7 +2737,7 @@ impl UserTypeProjection {
27372737
field_index: FieldIdx,
27382738
) -> Self {
27392739
self.projs.push(ProjectionElem::Downcast(
2740-
Some(adt_def.variant(variant_index).name),
2740+
Some(adt_def.variant(variant_index).name()),
27412741
variant_index,
27422742
));
27432743
self.projs.push(ProjectionElem::Field(field_index, ()));

compiler/rustc_middle/src/thir.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -815,9 +815,9 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
815815
let name = if tcx.get_diagnostic_item(sym::Option) == Some(adt_did)
816816
|| tcx.get_diagnostic_item(sym::Result) == Some(adt_did)
817817
{
818-
variant.name.to_string()
818+
variant.name().to_string()
819819
} else {
820-
format!("{}::{}", tcx.def_path_str(adt_def.did()), variant.name)
820+
format!("{}::{}", tcx.def_path_str(adt_def.did()), variant.name())
821821
};
822822
Some((variant, name))
823823
}),

compiler/rustc_middle/src/ty/context.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1673,7 +1673,7 @@ impl<'tcx> TyCtxt<'tcx> {
16731673
) -> Place<'tcx> {
16741674
self.mk_place_elem(
16751675
place,
1676-
PlaceElem::Downcast(Some(adt_def.variant(variant_index).name), variant_index),
1676+
PlaceElem::Downcast(Some(adt_def.variant(variant_index).name()), variant_index),
16771677
)
16781678
}
16791679

0 commit comments

Comments
 (0)