Skip to content

Commit 8c178ef

Browse files
jbertholdgtreptadkcumming
authored
Use a type visitor to collect type metadata, remove layout (#68)
Fixes #67 As discussed, using a type visitor to collect type information is more robust than the prior `collect_ty`. Layout information causes issues with polymorphic functions again, so we do not collect it any more for now as we aren't currently using it at all in `mir-semantics`. --------- Co-authored-by: Guy Repta <[email protected]> Co-authored-by: Daniel Cumming <[email protected]> Co-authored-by: dkcumming <[email protected]>
1 parent d9e2258 commit 8c178ef

32 files changed

+686
-2081
lines changed

.github/workflows/test.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -101,4 +101,4 @@ jobs:
101101
102102
- name: 'Run smir integration tests'
103103
run: |
104-
RUST_DIR_ROOT='rust' make test-ui
104+
RUST_DIR_ROOT='rust' VERBOSE=1 make test-ui

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,4 @@ test-ui:
6666
echo "Error: RUST_DIR_ROOT is not set. Please set it to the absolute path to rust compiler checkout."; \
6767
exit 1; \
6868
fi
69-
bash tests/ui/run_ui_tests.sh "$$RUST_DIR_ROOT"
69+
bash tests/ui/run_ui_tests.sh "$$RUST_DIR_ROOT" "$$VERBOSE"

src/printer.rs

+102-111
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
1-
use std::any::Any;
21
use std::io::Write;
3-
use std::{collections::HashMap, fs::File, io, iter::Iterator, str, vec::Vec};
2+
use std::ops::ControlFlow;
3+
use std::{
4+
collections::{HashMap, HashSet},
5+
fs::File,
6+
io,
7+
iter::Iterator,
8+
str,
9+
vec::Vec,
10+
};
411
extern crate rustc_middle;
512
extern crate rustc_monomorphize;
613
extern crate rustc_session;
@@ -13,9 +20,11 @@ extern crate stable_mir;
1320
extern crate serde;
1421
extern crate serde_json;
1522
use rustc_middle as middle;
16-
use rustc_middle::ty::{EarlyBinder, FnSig, GenericArgs, Ty, TyCtxt, TypeFoldable, TypingEnv};
23+
use rustc_middle::ty::{
24+
EarlyBinder, FnSig, GenericArgs, List, Ty, TyCtxt, TypeFoldable, TypingEnv,
25+
};
1726
use rustc_session::config::{OutFileName, OutputType};
18-
use rustc_smir::rustc_internal;
27+
use rustc_smir::rustc_internal::{self, internal};
1928
use rustc_span::{
2029
def_id::{DefId, LOCAL_CRATE},
2130
symbol,
@@ -24,10 +33,8 @@ use serde::{Serialize, Serializer};
2433
use stable_mir::{
2534
mir::mono::{Instance, InstanceKind, MonoItem},
2635
mir::{alloc::AllocId, visit::MirVisitor, Body, LocalDecl, Rvalue, Terminator, TerminatorKind},
27-
ty::{
28-
AdtDef, Allocation, ConstDef, ForeignItemKind, IndexedVal, RigidTy, TyConstKind, TyKind,
29-
VariantIdx,
30-
},
36+
ty::{AdtDef, Allocation, ConstDef, ForeignItemKind, IndexedVal, RigidTy, TyKind, VariantIdx},
37+
visitor::{Visitable, Visitor},
3138
CrateDef, CrateItem, ItemKind,
3239
};
3340

@@ -480,13 +487,93 @@ type AllocMap = HashMap<stable_mir::mir::alloc::AllocId, AllocInfo>;
480487
type TyMap =
481488
HashMap<stable_mir::ty::Ty, (stable_mir::ty::TyKind, Option<stable_mir::abi::LayoutShape>)>;
482489

490+
struct TyCollector<'tcx> {
491+
tcx: TyCtxt<'tcx>,
492+
types: TyMap,
493+
resolved: HashSet<stable_mir::ty::Ty>,
494+
}
495+
496+
impl TyCollector<'_> {
497+
fn new(tcx: TyCtxt<'_>) -> TyCollector {
498+
TyCollector {
499+
tcx,
500+
types: HashMap::new(),
501+
resolved: HashSet::new(),
502+
}
503+
}
504+
}
505+
506+
impl TyCollector<'_> {
507+
#[inline(always)]
508+
fn visit_instance(&mut self, instance: Instance) -> ControlFlow<<Self as Visitor>::Break> {
509+
let fn_abi = instance.fn_abi().unwrap();
510+
let mut inputs_outputs: Vec<stable_mir::ty::Ty> =
511+
fn_abi.args.iter().map(|arg_abi| arg_abi.ty).collect();
512+
inputs_outputs.push(fn_abi.ret.ty);
513+
inputs_outputs.super_visit(self)
514+
}
515+
}
516+
517+
impl Visitor for TyCollector<'_> {
518+
type Break = ();
519+
520+
fn visit_ty(&mut self, ty: &stable_mir::ty::Ty) -> ControlFlow<Self::Break> {
521+
if self.types.contains_key(ty) || self.resolved.contains(ty) {
522+
return ControlFlow::Continue(());
523+
}
524+
525+
match ty.kind() {
526+
TyKind::RigidTy(RigidTy::Closure(def, ref args)) => {
527+
self.resolved.insert(*ty);
528+
let instance =
529+
Instance::resolve_closure(def, args, stable_mir::ty::ClosureKind::Fn).unwrap();
530+
self.visit_instance(instance)
531+
}
532+
// Break on CoroutineWitnesses, because they aren't expected when getting the layout
533+
TyKind::RigidTy(RigidTy::CoroutineWitness(..)) => ControlFlow::Break(()),
534+
TyKind::RigidTy(RigidTy::FnDef(def, ref args)) => {
535+
self.resolved.insert(*ty);
536+
let instance = Instance::resolve(def, args).unwrap();
537+
self.visit_instance(instance)
538+
}
539+
TyKind::RigidTy(RigidTy::FnPtr(binder_stable)) => {
540+
self.resolved.insert(*ty);
541+
let binder_internal = internal(self.tcx, binder_stable);
542+
let sig_stable = rustc_internal::stable(
543+
self.tcx
544+
.fn_abi_of_fn_ptr(
545+
TypingEnv::fully_monomorphized()
546+
.as_query_input((binder_internal, List::empty())),
547+
)
548+
.unwrap(),
549+
);
550+
let mut inputs_outputs: Vec<stable_mir::ty::Ty> =
551+
sig_stable.args.iter().map(|arg_abi| arg_abi.ty).collect();
552+
inputs_outputs.push(sig_stable.ret.ty);
553+
inputs_outputs.super_visit(self)
554+
}
555+
_ => {
556+
let control = ty.super_visit(self);
557+
match control {
558+
ControlFlow::Continue(_) => {
559+
let maybe_layout_shape = ty.layout().ok().map(|layout| layout.shape());
560+
self.types.insert(*ty, (ty.kind(), maybe_layout_shape));
561+
control
562+
}
563+
_ => control,
564+
}
565+
}
566+
}
567+
}
568+
}
569+
483570
struct InternedValueCollector<'tcx, 'local> {
484571
tcx: TyCtxt<'tcx>,
485572
_sym: String,
486573
locals: &'local [LocalDecl],
487574
link_map: &'local mut LinkMap<'tcx>,
488575
visited_allocs: &'local mut AllocMap,
489-
visited_tys: &'local mut TyMap,
576+
ty_visitor: &'local mut TyCollector<'tcx>,
490577
}
491578

492579
type InternedValues<'tcx> = (LinkMap<'tcx>, AllocMap, TyMap);
@@ -601,103 +688,6 @@ fn collect_alloc(
601688
};
602689
}
603690

604-
fn collect_vec_tys(collector: &mut InternedValueCollector, tys: Vec<stable_mir::ty::Ty>) {
605-
tys.into_iter().for_each(|ty| collect_ty(collector, ty));
606-
}
607-
608-
fn collect_arg_tys(collector: &mut InternedValueCollector, args: &stable_mir::ty::GenericArgs) {
609-
use stable_mir::ty::{GenericArgKind::*, TyConstKind::*}; // TyConst
610-
for arg in args.0.iter() {
611-
match arg {
612-
Type(ty) => collect_ty(collector, *ty),
613-
Const(ty_const) => match ty_const.kind() {
614-
Value(ty, _) | ZSTValue(ty) => collect_ty(collector, *ty),
615-
_ => {}
616-
},
617-
_ => {}
618-
}
619-
}
620-
}
621-
622-
fn collect_ty(val_collector: &mut InternedValueCollector, val: stable_mir::ty::Ty) {
623-
use stable_mir::ty::{RigidTy::*, TyKind::RigidTy};
624-
625-
let maybe_layout_shape = val.layout().ok().map(|layout| layout.shape());
626-
627-
if val_collector
628-
.visited_tys
629-
.insert(val, (val.kind(), maybe_layout_shape))
630-
.is_some()
631-
{
632-
match val.kind() {
633-
RigidTy(Array(ty, ty_const)) => {
634-
collect_ty(val_collector, ty);
635-
match ty_const.kind() {
636-
TyConstKind::Value(ty, _) => collect_ty(val_collector, *ty),
637-
TyConstKind::ZSTValue(ty) => collect_ty(val_collector, *ty),
638-
_ => (),
639-
}
640-
}
641-
RigidTy(Pat(ty, _) | Slice(ty) | RawPtr(ty, _) | Ref(_, ty, _)) => {
642-
collect_ty(val_collector, ty)
643-
}
644-
RigidTy(Tuple(tys)) => collect_vec_tys(val_collector, tys),
645-
RigidTy(Adt(def, ref args)) => {
646-
for variant in def.variants_iter() {
647-
for field in variant.fields() {
648-
collect_ty(val_collector, field.ty());
649-
}
650-
}
651-
collect_arg_tys(val_collector, args);
652-
}
653-
// FIXME: Would be good to grab the coroutine signature
654-
RigidTy(Coroutine(_, ref args, _) | CoroutineWitness(_, ref args)) => {
655-
collect_arg_tys(val_collector, args)
656-
}
657-
RigidTy(Closure(def, ref args)) => {
658-
// Need to monomorphise again
659-
// let ty_internal = rustc_internal::internal(val_collector.tcx, val);
660-
// let closure_kind = ty_internal.to_opt_closure_kind().unwrap(); // Errors on span for some reason
661-
// Choose FnOnce, got the idea from kani reachability.rs
662-
let instance =
663-
Instance::resolve_closure(def, args, stable_mir::ty::ClosureKind::Fn).unwrap();
664-
let fn_abi = instance.fn_abi().unwrap();
665-
let mut inputs_and_outputs: Vec<stable_mir::ty::Ty> =
666-
fn_abi.args.iter().map(|arg| arg.ty).collect();
667-
if inputs_and_outputs[0].type_id() == val.type_id() {
668-
// TODO: Not sure if it always occurs, but had case where the first ArgAbi had ty same as val.
669-
// This causes an infinite loop
670-
inputs_and_outputs.remove(0);
671-
}
672-
inputs_and_outputs.push(fn_abi.ret.ty);
673-
674-
collect_vec_tys(val_collector, inputs_and_outputs);
675-
collect_arg_tys(val_collector, args); // Do I need to do this again?
676-
}
677-
ref _kind @ RigidTy(FnDef(def, ref args)) => {
678-
// Need to monomorphise again
679-
let instance = Instance::resolve(def, args).unwrap();
680-
let fn_abi = instance.fn_abi().unwrap();
681-
let mut inputs_and_outputs: Vec<stable_mir::ty::Ty> =
682-
fn_abi.args.iter().map(|arg| arg.ty).collect();
683-
inputs_and_outputs.push(fn_abi.ret.ty);
684-
685-
collect_vec_tys(val_collector, inputs_and_outputs);
686-
collect_arg_tys(val_collector, args); // Do I need to do this again?
687-
}
688-
RigidTy(Foreign(def)) => match def.kind() {
689-
ForeignItemKind::Fn(def) => {
690-
// I think this is fully monomorphised???
691-
collect_vec_tys(val_collector, def.fn_sig().value.inputs_and_output)
692-
}
693-
ForeignItemKind::Type(ty) => collect_ty(val_collector, ty),
694-
ForeignItemKind::Static(def) => collect_ty(val_collector, def.ty()),
695-
},
696-
_ => {} // TODO: I think we need to add arm for FnPtr? Maybe we should create an example that uses it first
697-
}
698-
}
699-
}
700-
701691
impl MirVisitor for InternedValueCollector<'_, '_> {
702692
fn visit_terminator(&mut self, term: &Terminator, loc: stable_mir::mir::visit::Location) {
703693
use stable_mir::mir::{ConstOperand, Operand::Constant};
@@ -772,14 +762,15 @@ impl MirVisitor for InternedValueCollector<'_, '_> {
772762
}
773763

774764
fn visit_ty(&mut self, ty: &stable_mir::ty::Ty, _location: stable_mir::mir::visit::Location) {
775-
collect_ty(self, *ty);
765+
ty.visit(self.ty_visitor);
766+
self.super_ty(ty);
776767
}
777768
}
778769

779770
fn collect_interned_values<'tcx>(tcx: TyCtxt<'tcx>, items: Vec<&MonoItem>) -> InternedValues<'tcx> {
780771
let mut calls_map = HashMap::new();
781-
let mut visited_tys = HashMap::new();
782772
let mut visited_allocs = HashMap::new();
773+
let mut ty_visitor = TyCollector::new(tcx);
783774
if link_items_enabled() {
784775
for item in items.iter() {
785776
if let MonoItem::Fn(inst) = item {
@@ -800,8 +791,8 @@ fn collect_interned_values<'tcx>(tcx: TyCtxt<'tcx>, items: Vec<&MonoItem>) -> In
800791
_sym: inst.mangled_name(),
801792
locals: body.locals(),
802793
link_map: &mut calls_map,
803-
visited_tys: &mut visited_tys,
804794
visited_allocs: &mut visited_allocs,
795+
ty_visitor: &mut ty_visitor,
805796
}
806797
.visit_body(&body)
807798
} else {
@@ -819,8 +810,8 @@ fn collect_interned_values<'tcx>(tcx: TyCtxt<'tcx>, items: Vec<&MonoItem>) -> In
819810
_sym: inst.mangled_name(),
820811
locals: &[],
821812
link_map: &mut calls_map,
822-
visited_tys: &mut visited_tys,
823813
visited_allocs: &mut visited_allocs,
814+
ty_visitor: &mut ty_visitor,
824815
}
825816
.visit_body(&body)
826817
} else {
@@ -833,7 +824,7 @@ fn collect_interned_values<'tcx>(tcx: TyCtxt<'tcx>, items: Vec<&MonoItem>) -> In
833824
MonoItem::GlobalAsm(_) => {}
834825
}
835826
}
836-
(calls_map, visited_allocs, visited_tys)
827+
(calls_map, visited_allocs, ty_visitor.types)
837828
}
838829

839830
// Collection Transitive Closure

tests/integration/normalise-filter.jq

+5-5
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@
1212
items: .items,
1313
types: ( [
1414
# sort by constructors and remove unstable IDs within each
15-
( .types | map(select(.[0].PrimitiveType)) ),
15+
( .types | map(select(.[0].PrimitiveType)) | sort ),
1616
# delete unstable adt_ref IDs
17-
( .types | map(select(.[0].EnumType) | del(.[0].EnumType.adt_def)) ),
18-
( .types | map(select(.[0].StructType) | del(.[0].StructType.adt_def)) ),
19-
( .types | map(select(.[0].UnionType) | del(.[0].UnionType.adt_def)) ),
17+
( .types | map(select(.[0].EnumType) | del(.[0].EnumType.adt_def)) | sort ),
18+
( .types | map(select(.[0].StructType) | del(.[0].StructType.adt_def)) | sort ),
19+
( .types | map(select(.[0].UnionType) | del(.[0].UnionType.adt_def)) | sort ),
2020
# delete unstable Ty IDs for arrays and tuples
21-
( .types | map(select(.[0].ArrayType) | del(.[0].ArrayType[0])) ),
21+
( .types | map(select(.[0].ArrayType) | del(.[0].ArrayType[0]) | del(.[0].ArrayType[0].id)) | sort ),
2222
( .types | map(select(.[0].TupleType) | .[0].TupleType.types = "elided") ),
2323
# replace unstable Ty IDs for references by zero
2424
( .types | map(select(.[0].PtrType) | .[0].PtrType = "elided") ),

0 commit comments

Comments
 (0)