Skip to content

Commit c188486

Browse files
authored
Rollup merge of rust-lang#117688 - celinval:smir-kani-reach, r=compiler-errors
Misc changes to StableMIR required to Kani use case. First, I wanted to say that I can split this review into multiple if it makes reviewing easier. I bundled them up, since I've been testing them together (See rust-lang/project-stable-mir#51 for the set of more thorough checks). So far, this review includes 3 commits: 1. Add more APIs and fix `Instance::body` - Add more APIs to retrieve information about types. - Add a few more instance resolution options. For the drop shim, we return None if the drop body is empty. Not sure it will be enough. - Make `Instance::body()` return an Option<Body>, since not every instance might have an available body. For example, foreign instances, virtual instances, dependencies. 2. Fix a bug on MIRVisitor - We were not iterating over all local variables due to a typo. 3. Add more SMIR internal impl and callback return value - In cases like Kani, we will invoke the rustc_internal run command directly for now. It would be handly to be able to have a callback that can return a value. - We also need extra methods to convert stable constructs into internal ones, so we can break down the transition into finer grain commits. - For the internal implementation of Region, we're always returning `ReErased` for now.
2 parents 1cabedc + 8e81fc0 commit c188486

File tree

12 files changed

+583
-72
lines changed

12 files changed

+583
-72
lines changed

compiler/rustc_smir/src/rustc_internal/internal.rs

+132-4
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,23 @@
66
// Prefer importing stable_mir over internal rustc constructs to make this file more readable.
77
use crate::rustc_smir::Tables;
88
use rustc_middle::ty::{self as rustc_ty, Ty as InternalTy};
9-
use stable_mir::ty::{Const, GenericArgKind, GenericArgs, Region, Ty};
10-
use stable_mir::DefId;
9+
use rustc_span::Symbol;
10+
use stable_mir::mir::mono::{Instance, MonoItem, StaticDef};
11+
use stable_mir::ty::{
12+
Binder, BoundRegionKind, BoundTyKind, BoundVariableKind, ClosureKind, Const, GenericArgKind,
13+
GenericArgs, Region, TraitRef, Ty,
14+
};
15+
use stable_mir::{AllocId, CrateItem, DefId};
1116

1217
use super::RustcInternal;
1318

19+
impl<'tcx> RustcInternal<'tcx> for CrateItem {
20+
type T = rustc_span::def_id::DefId;
21+
fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
22+
self.0.internal(tables)
23+
}
24+
}
25+
1426
impl<'tcx> RustcInternal<'tcx> for DefId {
1527
type T = rustc_span::def_id::DefId;
1628
fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
@@ -38,8 +50,9 @@ impl<'tcx> RustcInternal<'tcx> for GenericArgKind {
3850

3951
impl<'tcx> RustcInternal<'tcx> for Region {
4052
type T = rustc_ty::Region<'tcx>;
41-
fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T {
42-
todo!()
53+
fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
54+
// Cannot recover region. Use erased instead.
55+
tables.tcx.lifetimes.re_erased
4356
}
4457
}
4558

@@ -65,3 +78,118 @@ impl<'tcx> RustcInternal<'tcx> for Const {
6578
tables.constants[self.id]
6679
}
6780
}
81+
82+
impl<'tcx> RustcInternal<'tcx> for MonoItem {
83+
type T = rustc_middle::mir::mono::MonoItem<'tcx>;
84+
85+
fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
86+
use rustc_middle::mir::mono as rustc_mono;
87+
match self {
88+
MonoItem::Fn(instance) => rustc_mono::MonoItem::Fn(instance.internal(tables)),
89+
MonoItem::Static(def) => rustc_mono::MonoItem::Static(def.internal(tables)),
90+
MonoItem::GlobalAsm(_) => {
91+
unimplemented!()
92+
}
93+
}
94+
}
95+
}
96+
97+
impl<'tcx> RustcInternal<'tcx> for Instance {
98+
type T = rustc_ty::Instance<'tcx>;
99+
100+
fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
101+
tables.instances[self.def]
102+
}
103+
}
104+
105+
impl<'tcx> RustcInternal<'tcx> for StaticDef {
106+
type T = rustc_span::def_id::DefId;
107+
108+
fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
109+
self.0.internal(tables)
110+
}
111+
}
112+
113+
#[allow(rustc::usage_of_qualified_ty)]
114+
impl<'tcx, T> RustcInternal<'tcx> for Binder<T>
115+
where
116+
T: RustcInternal<'tcx>,
117+
T::T: rustc_ty::TypeVisitable<rustc_ty::TyCtxt<'tcx>>,
118+
{
119+
type T = rustc_ty::Binder<'tcx, T::T>;
120+
121+
fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
122+
rustc_ty::Binder::bind_with_vars(
123+
self.value.internal(tables),
124+
tables.tcx.mk_bound_variable_kinds_from_iter(
125+
self.bound_vars.iter().map(|bound| bound.internal(tables)),
126+
),
127+
)
128+
}
129+
}
130+
131+
impl<'tcx> RustcInternal<'tcx> for BoundVariableKind {
132+
type T = rustc_ty::BoundVariableKind;
133+
134+
fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
135+
match self {
136+
BoundVariableKind::Ty(kind) => rustc_ty::BoundVariableKind::Ty(match kind {
137+
BoundTyKind::Anon => rustc_ty::BoundTyKind::Anon,
138+
BoundTyKind::Param(def, symbol) => {
139+
rustc_ty::BoundTyKind::Param(def.0.internal(tables), Symbol::intern(&symbol))
140+
}
141+
}),
142+
BoundVariableKind::Region(kind) => rustc_ty::BoundVariableKind::Region(match kind {
143+
BoundRegionKind::BrAnon => rustc_ty::BoundRegionKind::BrAnon,
144+
BoundRegionKind::BrNamed(def, symbol) => rustc_ty::BoundRegionKind::BrNamed(
145+
def.0.internal(tables),
146+
Symbol::intern(&symbol),
147+
),
148+
BoundRegionKind::BrEnv => rustc_ty::BoundRegionKind::BrEnv,
149+
}),
150+
BoundVariableKind::Const => rustc_ty::BoundVariableKind::Const,
151+
}
152+
}
153+
}
154+
155+
impl<'tcx> RustcInternal<'tcx> for TraitRef {
156+
type T = rustc_ty::TraitRef<'tcx>;
157+
158+
fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
159+
rustc_ty::TraitRef::new(
160+
tables.tcx,
161+
self.def_id.0.internal(tables),
162+
self.args().internal(tables),
163+
)
164+
}
165+
}
166+
167+
impl<'tcx> RustcInternal<'tcx> for AllocId {
168+
type T = rustc_middle::mir::interpret::AllocId;
169+
fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
170+
tables.alloc_ids[*self]
171+
}
172+
}
173+
174+
impl<'tcx> RustcInternal<'tcx> for ClosureKind {
175+
type T = rustc_ty::ClosureKind;
176+
177+
fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T {
178+
match self {
179+
ClosureKind::Fn => rustc_ty::ClosureKind::Fn,
180+
ClosureKind::FnMut => rustc_ty::ClosureKind::FnMut,
181+
ClosureKind::FnOnce => rustc_ty::ClosureKind::FnOnce,
182+
}
183+
}
184+
}
185+
186+
impl<'tcx, T> RustcInternal<'tcx> for &T
187+
where
188+
T: RustcInternal<'tcx>,
189+
{
190+
type T = T::T;
191+
192+
fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
193+
(*self).internal(tables)
194+
}
195+
}

compiler/rustc_smir/src/rustc_internal/mod.rs

+15-9
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use rustc_span::def_id::{CrateNum, DefId};
1313
use rustc_span::Span;
1414
use scoped_tls::scoped_thread_local;
1515
use stable_mir::ty::IndexedVal;
16+
use stable_mir::Error;
1617
use std::cell::Cell;
1718
use std::cell::RefCell;
1819
use std::fmt::Debug;
@@ -21,11 +22,11 @@ use std::ops::Index;
2122

2223
mod internal;
2324

24-
pub fn stable<'tcx, S: Stable<'tcx>>(item: &S) -> S::T {
25+
pub fn stable<'tcx, S: Stable<'tcx>>(item: S) -> S::T {
2526
with_tables(|tables| item.stable(tables))
2627
}
2728

28-
pub fn internal<'tcx, S: RustcInternal<'tcx>>(item: &S) -> S::T {
29+
pub fn internal<'tcx, S: RustcInternal<'tcx>>(item: S) -> S::T {
2930
with_tables(|tables| item.internal(tables))
3031
}
3132

@@ -144,12 +145,13 @@ pub fn crate_num(item: &stable_mir::Crate) -> CrateNum {
144145
// datastructures and stable MIR datastructures
145146
scoped_thread_local! (static TLV: Cell<*const ()>);
146147

147-
pub(crate) fn init<'tcx>(tables: &TablesWrapper<'tcx>, f: impl FnOnce()) {
148+
pub(crate) fn init<'tcx, F, T>(tables: &TablesWrapper<'tcx>, f: F) -> T
149+
where
150+
F: FnOnce() -> T,
151+
{
148152
assert!(!TLV.is_set());
149153
let ptr = tables as *const _ as *const ();
150-
TLV.set(&Cell::new(ptr), || {
151-
f();
152-
});
154+
TLV.set(&Cell::new(ptr), || f())
153155
}
154156

155157
/// Loads the current context and calls a function with it.
@@ -165,7 +167,10 @@ pub(crate) fn with_tables<'tcx, R>(f: impl FnOnce(&mut Tables<'tcx>) -> R) -> R
165167
})
166168
}
167169

168-
pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) {
170+
pub fn run<F, T>(tcx: TyCtxt<'_>, f: F) -> Result<T, Error>
171+
where
172+
F: FnOnce() -> T,
173+
{
169174
let tables = TablesWrapper(RefCell::new(Tables {
170175
tcx,
171176
def_ids: IndexMap::default(),
@@ -175,7 +180,7 @@ pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) {
175180
instances: IndexMap::default(),
176181
constants: IndexMap::default(),
177182
}));
178-
stable_mir::run(&tables, || init(&tables, f));
183+
stable_mir::run(&tables, || init(&tables, f))
179184
}
180185

181186
#[macro_export]
@@ -241,7 +246,8 @@ macro_rules! run {
241246
queries.global_ctxt().unwrap().enter(|tcx| {
242247
rustc_internal::run(tcx, || {
243248
self.result = Some((self.callback)(tcx));
244-
});
249+
})
250+
.unwrap();
245251
if self.result.as_ref().is_some_and(|val| val.is_continue()) {
246252
Compilation::Continue
247253
} else {

compiler/rustc_smir/src/rustc_smir/builder.rs

+21-2
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,15 @@ impl<'tcx> BodyBuilder<'tcx> {
1919
BodyBuilder { tcx, instance }
2020
}
2121

22+
/// Build a stable monomorphic body for a given instance based on the MIR body.
23+
///
24+
/// Note that we skip instantiation for static and constants. Trying to do so can cause ICE.
25+
///
26+
/// We do monomorphize non-generic functions to eval unevaluated constants.
2227
pub fn build(mut self, tables: &mut Tables<'tcx>) -> stable_mir::mir::Body {
2328
let mut body = self.tcx.instance_mir(self.instance.def).clone();
24-
let generics = self.tcx.generics_of(self.instance.def_id());
25-
if generics.requires_monomorphization(self.tcx) {
29+
if self.tcx.def_kind(self.instance.def_id()).is_fn_like() || !self.instance.args.is_empty()
30+
{
2631
self.visit_body(&mut body);
2732
}
2833
body.stable(tables)
@@ -49,6 +54,20 @@ impl<'tcx> MutVisitor<'tcx> for BodyBuilder<'tcx> {
4954
*ty = self.monomorphize(*ty);
5055
}
5156

57+
fn visit_constant(&mut self, constant: &mut mir::ConstOperand<'tcx>, location: mir::Location) {
58+
let const_ = self.monomorphize(constant.const_);
59+
let val = match const_.eval(self.tcx, ty::ParamEnv::reveal_all(), None) {
60+
Ok(v) => v,
61+
Err(mir::interpret::ErrorHandled::Reported(..)) => return,
62+
Err(mir::interpret::ErrorHandled::TooGeneric(..)) => {
63+
unreachable!("Failed to evaluate instance constant: {:?}", const_)
64+
}
65+
};
66+
let ty = constant.ty();
67+
constant.const_ = mir::Const::Val(val, ty);
68+
self.super_constant(constant, location);
69+
}
70+
5271
fn tcx(&self) -> TyCtxt<'tcx> {
5372
self.tcx
5473
}

0 commit comments

Comments
 (0)