Skip to content

Commit 18f452d

Browse files
authored
92 - Improvements to type metadata (#93)
* Collect ADT field types to emit their type metadata * add field types for enum variants * emit enum discriminants as simple array (`VariantIdx` will always be 0..n for n+1 variants) * properly instantiate parameterised types with their concrete type arguments Also * remove old `tests_ui.failing` notes * add a compilation feature `debug_log` for debug messages during SMIR processing
1 parent 180bfb4 commit 18f452d

33 files changed

+8040
-567
lines changed

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ home = "0.5"
1515
name = "cargo_stable_mir_json"
1616
path = "src/bin/cargo_stable_mir_json.rs"
1717

18+
[features]
19+
debug_log = []
20+
1821
[package.metadata.rust-analyzer]
1922
# This package uses rustc crates.
2023
rustc_private=true

src/printer.rs

Lines changed: 95 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ extern crate serde;
2222
extern crate serde_json;
2323
use rustc_middle as middle;
2424
use rustc_middle::ty::{
25-
EarlyBinder, FnSig, GenericArgs, List, Ty, TyCtxt, TypeFoldable, TypingEnv,
25+
EarlyBinder, FnSig, GenericArgs, GenericArgsRef, List, Ty, TyCtxt, TypeFoldable, TypingEnv,
2626
};
2727
use rustc_session::config::{OutFileName, OutputType};
2828
use rustc_smir::rustc_internal::{self, internal};
@@ -34,7 +34,7 @@ use serde::{Serialize, Serializer};
3434
use stable_mir::{
3535
mir::mono::{Instance, InstanceKind, MonoItem},
3636
mir::{alloc::AllocId, visit::MirVisitor, Body, LocalDecl, Rvalue, Terminator, TerminatorKind},
37-
ty::{AdtDef, Allocation, ConstDef, ForeignItemKind, IndexedVal, RigidTy, TyKind, VariantIdx},
37+
ty::{AdtDef, Allocation, ConstDef, ForeignItemKind, IndexedVal, RigidTy, TyKind},
3838
visitor::{Visitable, Visitor},
3939
CrateDef, CrateItem, ItemKind,
4040
};
@@ -554,6 +554,32 @@ impl Visitor for TyCollector<'_> {
554554
inputs_outputs.push(sig_stable.ret.ty);
555555
inputs_outputs.super_visit(self)
556556
}
557+
// The visitor won't collect field types for ADTs, therefore doing it explicitly
558+
TyKind::RigidTy(RigidTy::Adt(adt_def, args)) => {
559+
let tcx = self.tcx;
560+
let adt = rustc_internal::internal(tcx, adt_def);
561+
562+
let args: GenericArgsRef = rustc_internal::internal(tcx, args);
563+
let fields: Vec<stable_mir::ty::Ty> = adt
564+
.all_fields()
565+
.map(move |field| field.ty(tcx, args))
566+
.map(rustc_internal::stable)
567+
.collect();
568+
569+
let mut control = ty.super_visit(self);
570+
if matches!(control, ControlFlow::Continue(_)) {
571+
let maybe_layout_shape = ty.layout().ok().map(|layout| layout.shape());
572+
self.types.insert(*ty, (ty.kind(), maybe_layout_shape));
573+
}
574+
575+
for f_ty in fields {
576+
control = self.visit_ty(&f_ty);
577+
if matches!(control, ControlFlow::Break(())) {
578+
break;
579+
}
580+
}
581+
control
582+
}
557583
_ => {
558584
let control = ty.super_visit(self);
559585
match control {
@@ -606,23 +632,21 @@ fn update_link_map<'tcx>(
606632
);
607633
}
608634
curr_val.0 .0 |= new_val.0 .0;
609-
if debug_enabled() {
610-
println!(
611-
"Regenerated link map entry: {:?}:{:?} -> {:?}",
612-
&key,
613-
key.0.kind().fn_def(),
614-
new_val
615-
);
616-
}
635+
#[cfg(feature = "debug_log")]
636+
println!(
637+
"Regenerated link map entry: {:?}:{:?} -> {:?}",
638+
&key,
639+
key.0.kind().fn_def(),
640+
new_val
641+
);
617642
} else {
618-
if debug_enabled() {
619-
println!(
620-
"Generated link map entry from call: {:?}:{:?} -> {:?}",
621-
&key,
622-
key.0.kind().fn_def(),
623-
new_val
624-
);
625-
}
643+
#[cfg(feature = "debug_log")]
644+
println!(
645+
"Generated link map entry from call: {:?}:{:?} -> {:?}",
646+
&key,
647+
key.0.kind().fn_def(),
648+
new_val
649+
);
626650
link_map.insert(key.clone(), new_val);
627651
}
628652
}
@@ -657,12 +681,11 @@ fn collect_alloc(
657681
match global_alloc {
658682
GlobalAlloc::Memory(ref alloc) => {
659683
let pointed_kind = get_prov_type(kind);
660-
if debug_enabled() {
661-
println!(
662-
"DEBUG: called collect_alloc: {:?}:{:?}:{:?}",
663-
val, pointed_kind, global_alloc
664-
);
665-
}
684+
#[cfg(feature = "debug_log")]
685+
println!(
686+
"DEBUG: called collect_alloc: {:?}:{:?}:{:?}",
687+
val, pointed_kind, global_alloc
688+
);
666689
entry.or_insert(AllocInfo::Memory(alloc.clone())); // TODO: include pointed_kind.clone().unwrap() ?
667690
alloc.provenance.ptrs.iter().for_each(|(_, prov)| {
668691
collect_alloc(val_collector, pointed_kind.clone(), prov.0);
@@ -763,13 +786,12 @@ impl MirVisitor for InternedValueCollector<'_, '_> {
763786
use stable_mir::ty::{ConstantKind, TyConstKind}; // TyConst
764787
match constant.kind() {
765788
ConstantKind::Allocated(alloc) => {
766-
if debug_enabled() {
767-
println!(
768-
"visited_mir_const::Allocated({:?}) as {:?}",
769-
alloc,
770-
constant.ty().kind()
771-
);
772-
}
789+
#[cfg(feature = "debug_log")]
790+
println!(
791+
"visited_mir_const::Allocated({:?}) as {:?}",
792+
alloc,
793+
constant.ty().kind()
794+
);
773795
alloc.provenance.ptrs.iter().for_each(|(_offset, prov)| {
774796
collect_alloc(self, Some(constant.ty().kind()), prov.0)
775797
});
@@ -889,9 +911,8 @@ impl MirVisitor for UnevaluatedConstCollector<'_, '_> {
889911
|| self.pending_items.contains_key(&item_name)
890912
|| self.current_item == hash(&item_name))
891913
{
892-
if debug_enabled() {
893-
println!("Adding unevaluated const body for: {}", item_name);
894-
}
914+
#[cfg(feature = "debug_log")]
915+
println!("Adding unevaluated const body for: {}", item_name);
895916
self.unevaluated_consts
896917
.insert(uconst.def, item_name.clone());
897918
self.pending_items.insert(
@@ -982,7 +1003,8 @@ pub enum TypeMetadata {
9821003
EnumType {
9831004
name: String,
9841005
adt_def: AdtDef,
985-
discriminants: Vec<(VariantIdx, u128)>,
1006+
discriminants: Vec<u128>,
1007+
fields: Vec<Vec<stable_mir::ty::Ty>>,
9861008
},
9871009
StructType {
9881010
name: String,
@@ -1000,6 +1022,7 @@ pub enum TypeMetadata {
10001022
types: Vec<stable_mir::ty::Ty>,
10011023
},
10021024
FunType(String),
1025+
VoidType,
10031026
}
10041027

10051028
fn mk_type_metadata(
@@ -1014,28 +1037,40 @@ fn mk_type_metadata(
10141037
T(prim_type) if t.is_primitive() => Some((k, PrimitiveType(prim_type))),
10151038
// for enums, we need a mapping of variantIdx to discriminant
10161039
// this requires access to the internals and is not provided as an interface function at the moment
1017-
T(Adt(adt_def, _)) if t.is_enum() => {
1040+
T(Adt(adt_def, args)) if t.is_enum() => {
10181041
let adt_internal = rustc_internal::internal(tcx, adt_def);
10191042
let discriminants = adt_internal
10201043
.discriminants(tcx)
1021-
.map(|(v_idx, discr)| (rustc_internal::stable(v_idx), discr.val))
1044+
.map(|(_, discr)| discr.val)
10221045
.collect::<Vec<_>>();
1046+
let fields = adt_internal
1047+
.variants()
1048+
.into_iter()
1049+
.map(|def| {
1050+
def.fields
1051+
.iter()
1052+
.map(|f| f.ty(tcx, rustc_internal::internal(tcx, &args)))
1053+
.map(rustc_internal::stable)
1054+
.collect::<Vec<stable_mir::ty::Ty>>()
1055+
})
1056+
.collect();
10231057
let name = adt_def.name();
10241058
Some((
10251059
k,
10261060
EnumType {
10271061
name,
10281062
adt_def,
10291063
discriminants,
1064+
fields,
10301065
},
10311066
))
10321067
}
10331068
// for structs, we record the name for information purposes and the field types
1034-
T(Adt(adt_def, _)) if t.is_struct() => {
1069+
T(Adt(adt_def, args)) if t.is_struct() => {
10351070
let name = adt_def.name();
10361071
let fields = rustc_internal::internal(tcx, adt_def)
10371072
.all_fields() // is_struct, so only one variant
1038-
.map(move |field| tcx.type_of(field.did).instantiate_identity())
1073+
.map(move |f| f.ty(tcx, rustc_internal::internal(tcx, &args)))
10391074
.map(rustc_internal::stable)
10401075
.collect();
10411076
Some((
@@ -1069,9 +1104,27 @@ fn mk_type_metadata(
10691104
| T(Pat(_, _))
10701105
| T(Coroutine(_, _, _))
10711106
| T(Dynamic(_, _, _))
1072-
| T(CoroutineWitness(_, _)) => None,
1073-
TyKind::Alias(_, _) | TyKind::Param(_) | TyKind::Bound(_, _) => None,
1074-
_ => None, // redundant because of first 4 cases, but rustc does not understand that
1107+
| T(CoroutineWitness(_, _)) => {
1108+
#[cfg(feature = "debug_log")]
1109+
println!(
1110+
"\nDEBUG: Skipping unsupported ty {}: {:?}",
1111+
k.to_index(),
1112+
k.kind()
1113+
);
1114+
None
1115+
}
1116+
T(Never) => Some((k, VoidType)),
1117+
TyKind::Alias(_, _) | TyKind::Param(_) | TyKind::Bound(_, _) => {
1118+
#[cfg(feature = "debug_log")]
1119+
println!("\nSkipping undesired ty {}: {:?}", k.to_index(), k.kind());
1120+
None
1121+
}
1122+
_ => {
1123+
// redundant because of first 4 cases, but rustc does not understand that
1124+
#[cfg(feature = "debug_log")]
1125+
println!("\nDEBUG: Funny other Ty {}: {:?}", k.to_index(), k.kind());
1126+
None
1127+
}
10751128
}
10761129
}
10771130

tests/integration/normalise-filter.jq

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,18 @@
55
| .allocs = ( [ .allocs[] ] | map(del(.[0])) )
66
| .functions = ( [ .functions[] ] | map(del(.[0])) )
77
| .types = ( [ .types[] ] | map(del(.[0])) )
8+
# remove "Never" type
9+
| .types = ( [ .types[] ] | map(select(.[0] != "VoidType")) )
810
|
911
# Apply the normalisation filter
10-
{ allocs: .allocs,
12+
{ allocs: ( .allocs | sort ),
1113
functions: .functions,
1214
items: .items,
1315
types: ( [
1416
# sort by constructors and remove unstable IDs within each
1517
( .types | map(select(.[0].PrimitiveType)) | sort ),
1618
# delete unstable adt_ref IDs and struct field Ty IDs
17-
( .types | map(select(.[0].EnumType) | del(.[0].EnumType.adt_def)) | sort ),
19+
( .types | map(select(.[0].EnumType) | del(.[0].EnumType.adt_def) | .[0].EnumType.fields = "elided") | sort ),
1820
( .types | map(select(.[0].StructType) | del(.[0].StructType.adt_def) | .[0].StructType.fields = "elided" ) | sort ),
1921
( .types | map(select(.[0].UnionType) | del(.[0].UnionType.adt_def)) | sort ),
2022
# delete unstable Ty IDs for arrays and tuples

0 commit comments

Comments
 (0)