Skip to content

Commit b2da370

Browse files
committed
WIP: anonymous adt recognized as recursive types
1 parent d9347ee commit b2da370

File tree

12 files changed

+77
-34
lines changed

12 files changed

+77
-34
lines changed

compiler/rustc_ast_lowering/src/lib.rs

-4
Original file line numberDiff line numberDiff line change
@@ -1294,17 +1294,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
12941294
hir::TyKind::Err(self.tcx.sess.delay_span_bug(t.span, "TyKind::Err lowered"))
12951295
}
12961296
TyKind::AnonStruct(fields) => {
1297-
let hir_id = self.next_id();
12981297
hir::TyKind::AnonStruct(
12991298
self.arena.alloc_from_iter(fields.iter().enumerate().map(|f| self.lower_field_def(f))),
1300-
hir_id,
13011299
)
13021300
}
13031301
TyKind::AnonUnion(fields) => {
1304-
let hir_id = self.next_id();
13051302
hir::TyKind::AnonUnion(
13061303
self.arena.alloc_from_iter(fields.iter().enumerate().map(|f| self.lower_field_def(f))),
1307-
hir_id,
13081304
)
13091305
}
13101306
TyKind::Slice(ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)),

compiler/rustc_hir/src/hir.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2714,9 +2714,9 @@ pub enum TyKind<'hir> {
27142714
/// A tuple (`(A, B, C, D, ...)`).
27152715
Tup(&'hir [Ty<'hir>]),
27162716
/// An anonymous struct type i.e. `struct { foo: Type }`
2717-
AnonStruct(&'hir [FieldDef<'hir>], HirId),
2717+
AnonStruct(&'hir [FieldDef<'hir>]),
27182718
/// An anonymous union type i.e. `union { bar: Type }`
2719-
AnonUnion(&'hir [FieldDef<'hir>], HirId),
2719+
AnonUnion(&'hir [FieldDef<'hir>]),
27202720
/// A path to a type definition (`module::module::...::Type`), or an
27212721
/// associated type (e.g., `<Vec<T> as Trait>::Type` or `<T>::Target`).
27222722
///

compiler/rustc_hir/src/intravisit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -862,7 +862,7 @@ 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) => {
865+
TyKind::AnonStruct(fields) | TyKind::AnonUnion(fields) => {
866866
walk_list!(visitor, visit_field_def, fields);
867867
}
868868
}

compiler/rustc_hir_analysis/src/astconv/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -2524,16 +2524,16 @@ 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());
2527+
hir::TyKind::AnonStruct(fields,) | hir::TyKind::AnonUnion(fields) => {
2528+
let repr = tcx.repr_options_of_def(ast_ty.hir_id.owner.to_def_id());
25292529
if !repr.c() {
25302530
// tcx.sess.emit_err(todo!());
25312531
}
25322532
let adt_kind = match ast_ty.kind {
25332533
hir::TyKind::AnonStruct(..) => ty::AdtKind::Struct,
25342534
_ => ty::AdtKind::Union,
25352535
};
2536-
let field_def = tcx.hir().expect_field(tcx.hir().parent_id(hir_id));
2536+
let field_def = tcx.hir().expect_field(tcx.hir().parent_id(ast_ty.hir_id));
25372537
let did = field_def.def_id;
25382538
let variants = std::iter::once(convert_variant(
25392539
tcx,

compiler/rustc_hir_pretty/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -367,11 +367,11 @@ impl<'a> State<'a> {
367367
hir::TyKind::Infer => {
368368
self.word("_");
369369
}
370-
hir::TyKind::AnonStruct(fields, _hir_id) => {
370+
hir::TyKind::AnonStruct(fields) => {
371371
self.word("struct");
372372
self.print_variant_struct(ty.span, fields);
373373
}
374-
hir::TyKind::AnonUnion(fields, _hir_id) => {
374+
hir::TyKind::AnonUnion(fields) => {
375375
self.word("union");
376376
self.print_variant_struct(ty.span, fields);
377377
}

compiler/rustc_middle/src/ty/mod.rs

+12
Original file line numberDiff line numberDiff line change
@@ -2113,6 +2113,18 @@ impl<'tcx> FieldDef {
21132113
pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident {
21142114
Ident::new(self.name, tcx.def_ident_span(self.did).unwrap())
21152115
}
2116+
2117+
/// Returns the inner adt if it is an unnamed field.
2118+
pub fn inner_adt(&self, tcx: TyCtxt<'tcx>, arg: GenericArgsRef<'tcx>) -> Option<(AdtDef<'tcx>, GenericArgsRef<'tcx>)> {
2119+
if self.name == kw::Underscore {
2120+
let ty = self.ty(tcx, arg);
2121+
let &TyKind::Adt(adt_def, generic_args) = ty.kind() else {
2122+
bug!("Unammed fields must be adt type")
2123+
};
2124+
return Some((adt_def, generic_args));
2125+
}
2126+
None
2127+
}
21162128
}
21172129

21182130
#[derive(Debug, PartialEq, Eq)]

compiler/rustc_mir_dataflow/src/value_analysis.rs

+25-12
Original file line numberDiff line numberDiff line change
@@ -999,20 +999,33 @@ pub fn iter_fields<'tcx>(
999999
f(None, field.into(), ty);
10001000
}
10011001
}
1002-
ty::Adt(def, args) => {
1003-
if def.is_union() {
1004-
return;
1005-
}
1006-
for (v_index, v_def) in def.variants().iter_enumerated() {
1007-
let variant = if def.is_struct() { None } else { Some(v_index) };
1008-
for (f_index, f_def) in v_def.fields.iter().enumerate() {
1009-
let field_ty = f_def.ty(tcx, args);
1010-
let field_ty = tcx
1011-
.try_normalize_erasing_regions(param_env, field_ty)
1012-
.unwrap_or_else(|_| tcx.erase_regions(field_ty));
1013-
f(variant, f_index.into(), field_ty);
1002+
&ty::Adt(def, args) => {
1003+
fn iter_adt_fields<'tcx>(
1004+
def: ty::AdtDef<'tcx>,
1005+
args: ty::GenericArgsRef<'tcx>,
1006+
tcx: TyCtxt<'tcx>,
1007+
param_env: ty::ParamEnv<'tcx>,
1008+
f: &mut impl FnMut(Option<VariantIdx>, FieldIdx, Ty<'tcx>),
1009+
) {
1010+
if def.is_union() {
1011+
return;
1012+
}
1013+
for (v_index, v_def) in def.variants().iter_enumerated() {
1014+
let variant = if def.is_struct() { None } else { Some(v_index) };
1015+
for (f_index, f_def) in v_def.fields.iter().enumerate() {
1016+
if let Some((def, args)) = f_def.inner_adt(tcx, args) {
1017+
iter_adt_fields(def, args, tcx, param_env, &mut *f);
1018+
} else {
1019+
let field_ty = f_def.ty(tcx, args);
1020+
let field_ty = tcx
1021+
.try_normalize_erasing_regions(param_env, field_ty)
1022+
.unwrap_or_else(|_| tcx.erase_regions(field_ty));
1023+
f(variant, f_index.into(), field_ty);
1024+
}
1025+
}
10141026
}
10151027
}
1028+
iter_adt_fields(def, args, tcx, param_env, &mut f);
10161029
}
10171030
ty::Closure(_, args) => {
10181031
iter_fields(args.as_closure().tupled_upvars_ty(), tcx, param_env, f);

compiler/rustc_ty_utils/src/representability.rs

+14-5
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,22 @@ macro_rules! rtry {
2323
fn representability(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Representability {
2424
match tcx.def_kind(def_id) {
2525
DefKind::Struct | DefKind::Union | DefKind::Enum => {
26-
let adt_def = tcx.adt_def(def_id);
27-
for variant in adt_def.variants() {
28-
for field in variant.fields.iter() {
29-
rtry!(tcx.representability(field.did.expect_local()));
26+
fn representability_rec<'tcx>(tcx: TyCtxt<'tcx>, adt_def: ty::AdtDef<'tcx>) -> Representability {
27+
for variant in adt_def.variants() {
28+
for field in variant.fields.iter() {
29+
// info!(?field);
30+
// info!(ty = ?tcx.type_of(field.did.expect_local()));
31+
if let Some((adt_def, _args)) = field.inner_adt(tcx, ty::GenericArgs::empty()) {
32+
// info!(variants = ?adt_def.variants());
33+
rtry!(representability_rec(tcx, adt_def));
34+
} else {
35+
rtry!(tcx.representability(field.did.expect_local()));
36+
}
37+
}
3038
}
39+
Representability::Representable
3140
}
32-
Representability::Representable
41+
representability_rec(tcx, tcx.adt_def(def_id))
3342
}
3443
DefKind::Field => representability_ty(tcx, tcx.type_of(def_id).instantiate_identity()),
3544
def_kind => bug!("unexpected {def_kind:?}"),

src/librustdoc/clean/mod.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -1842,6 +1842,14 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
18421842
TyKind::BareFn(barefn) => BareFunction(Box::new(clean_bare_fn_ty(barefn, cx))),
18431843
// Rustdoc handles `TyKind::Err`s by turning them into `Type::Infer`s.
18441844
TyKind::Infer | TyKind::Err(_) | TyKind::Typeof(..) => Infer,
1845+
TyKind::AnonStruct(..) | TyKind::AnonUnion(..) =>
1846+
span_bug!(ty.span, "Anonymous structs or unions are not fully implemented"),
1847+
// TyKind::AnonStruct(fields) => Type::AnonStruct(VariantStruct {
1848+
// fields: variant.fields().iter().map(|x| clean_field(x, cx)).collect(),
1849+
// }),
1850+
// TyKind::AnonUnion(fields) => Type::AnonUnion(VariantStruct {
1851+
// fields: variant.fields().iter().map(|x| clean_field(x, cx)).collect(),
1852+
// }),
18451853
}
18461854
}
18471855

@@ -2344,7 +2352,7 @@ pub(crate) fn clean_variant_def<'tcx>(variant: &ty::VariantDef, cx: &mut DocCont
23442352

23452353
Item::from_def_id_and_parts(
23462354
variant.def_id,
2347-
Some(variant.name),
2355+
Some(variant.name()),
23482356
VariantItem(Variant { kind, discriminant }),
23492357
cx,
23502358
)

src/librustdoc/clean/types.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1509,6 +1509,11 @@ pub(crate) enum Type {
15091509

15101510
/// An `impl Trait`: `impl TraitA + TraitB + ...`
15111511
ImplTrait(Vec<GenericBound>),
1512+
1513+
// /// An anonymous struct type i.e. `struct { foo: Type }`
1514+
// AnonStruct(VariantStruct),
1515+
// /// An anonymous union type i.e. `union { bar: Type }`
1516+
// AnonUnion(VariantStruct),
15121517
}
15131518

15141519
impl Type {

src/librustdoc/html/render/type_layout.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ pub(crate) fn document_type_layout<'a, 'cx: 'a>(
6262
let Adt(adt, _) = type_layout.ty.kind() else {
6363
span_bug!(tcx.def_span(ty_def_id), "not an adt")
6464
};
65-
let name = adt.variant(variant_idx).name;
65+
let name = adt.variant(variant_idx).name();
6666
let is_unsized = variant_layout.abi.is_unsized();
6767
let is_uninhabited = variant_layout.abi.is_uninhabited();
6868
let size = variant_layout.size.bytes() - tag_size;

src/librustdoc/passes/collect_intra_doc_links.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
300300
match ty_res {
301301
Res::Def(DefKind::Enum, did) => match tcx.type_of(did).instantiate_identity().kind() {
302302
ty::Adt(def, _) if def.is_enum() => {
303-
if let Some(variant) = def.variants().iter().find(|v| v.name == variant_name)
303+
if let Some(variant) = def.variants().iter().find(|v| v.name() == variant_name)
304304
&& let Some(field) = variant.fields.iter().find(|f| f.name == variant_field_name) {
305305
Ok((ty_res, field.did))
306306
} else {
@@ -609,7 +609,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
609609
match tcx.type_of(did).instantiate_identity().kind() {
610610
ty::Adt(adt_def, _) => {
611611
for variant in adt_def.variants() {
612-
if variant.name == item_name {
612+
if variant.name() == item_name {
613613
return vec![(root_res, variant.def_id)];
614614
}
615615
}
@@ -1818,7 +1818,7 @@ fn resolution_failure(
18181818
let is_struct_variant = |did| {
18191819
if let ty::Adt(def, _) = tcx.type_of(did).instantiate_identity().kind()
18201820
&& def.is_enum()
1821-
&& let Some(variant) = def.variants().iter().find(|v| v.name == res.name(tcx)) {
1821+
&& let Some(variant) = def.variants().iter().find(|v| v.name() == res.name(tcx)) {
18221822
// ctor is `None` if variant is a struct
18231823
variant.ctor.is_none()
18241824
} else {

0 commit comments

Comments
 (0)