rustc_smir/
lib.rs

1//! Crate that implements what will become the rustc side of Stable MIR.
2//!
3//! This crate is responsible for building Stable MIR components from internal components.
4//!
5//! This crate is not intended to be invoked directly by users.
6//! This crate is the public API of rustc that will be invoked by the `stable_mir` crate.
7//!
8//! For more information see <https://github.com/rust-lang/project-stable-mir>
9//!
10//! # Note
11//!
12//! This API is still completely unstable and subject to change.
13
14// tidy-alphabetical-start
15#![allow(internal_features)]
16#![allow(rustc::usage_of_ty_tykind)]
17#![doc(
18    html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
19    test(attr(allow(unused_variables), deny(warnings)))
20)]
21#![doc(rust_logo)]
22#![feature(rustdoc_internals)]
23#![feature(sized_hierarchy)]
24// tidy-alphabetical-end
25
26use std::cell::RefCell;
27use std::fmt::Debug;
28use std::hash::Hash;
29use std::ops::Index;
30
31use bridge::*;
32use context::SmirCtxt;
33use rustc_data_structures::fx::{self, FxIndexMap};
34use rustc_middle::mir;
35use rustc_middle::mir::interpret::AllocId;
36use rustc_middle::ty::{self, Ty, TyCtxt};
37use rustc_span::Span;
38use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
39
40pub mod alloc;
41pub mod bridge;
42mod builder;
43pub mod context;
44
45#[deprecated(note = "please use `stable_mir::rustc_internal` instead")]
46pub mod rustc_internal {}
47
48/// A container which is used for TLS.
49pub struct SmirContainer<'tcx, B: Bridge> {
50    pub tables: RefCell<Tables<'tcx, B>>,
51    pub cx: RefCell<SmirCtxt<'tcx, B>>,
52}
53
54pub struct Tables<'tcx, B: Bridge> {
55    pub def_ids: IndexMap<DefId, B::DefId>,
56    pub alloc_ids: IndexMap<AllocId, B::AllocId>,
57    pub spans: IndexMap<rustc_span::Span, B::Span>,
58    pub types: IndexMap<Ty<'tcx>, B::Ty>,
59    pub instances: IndexMap<ty::Instance<'tcx>, B::InstanceDef>,
60    pub ty_consts: IndexMap<ty::Const<'tcx>, B::TyConstId>,
61    pub mir_consts: IndexMap<mir::Const<'tcx>, B::MirConstId>,
62    pub layouts: IndexMap<rustc_abi::Layout<'tcx>, B::Layout>,
63}
64
65impl<'tcx, B: Bridge> Default for Tables<'tcx, B> {
66    fn default() -> Self {
67        Self {
68            def_ids: IndexMap::default(),
69            alloc_ids: IndexMap::default(),
70            spans: IndexMap::default(),
71            types: IndexMap::default(),
72            instances: IndexMap::default(),
73            ty_consts: IndexMap::default(),
74            mir_consts: IndexMap::default(),
75            layouts: IndexMap::default(),
76        }
77    }
78}
79
80impl<'tcx, B: Bridge> Index<B::DefId> for Tables<'tcx, B> {
81    type Output = DefId;
82
83    #[inline(always)]
84    fn index(&self, index: B::DefId) -> &Self::Output {
85        &self.def_ids[index]
86    }
87}
88
89impl<'tcx, B: Bridge> Tables<'tcx, B> {
90    pub fn intern_ty(&mut self, ty: Ty<'tcx>) -> B::Ty {
91        self.types.create_or_fetch(ty)
92    }
93
94    pub fn intern_ty_const(&mut self, ct: ty::Const<'tcx>) -> B::TyConstId {
95        self.ty_consts.create_or_fetch(ct)
96    }
97
98    pub fn intern_mir_const(&mut self, constant: mir::Const<'tcx>) -> B::MirConstId {
99        self.mir_consts.create_or_fetch(constant)
100    }
101
102    pub fn create_def_id(&mut self, did: DefId) -> B::DefId {
103        self.def_ids.create_or_fetch(did)
104    }
105
106    pub fn create_alloc_id(&mut self, aid: AllocId) -> B::AllocId {
107        self.alloc_ids.create_or_fetch(aid)
108    }
109
110    pub fn create_span(&mut self, span: Span) -> B::Span {
111        self.spans.create_or_fetch(span)
112    }
113
114    pub fn instance_def(&mut self, instance: ty::Instance<'tcx>) -> B::InstanceDef {
115        self.instances.create_or_fetch(instance)
116    }
117
118    pub fn layout_id(&mut self, layout: rustc_abi::Layout<'tcx>) -> B::Layout {
119        self.layouts.create_or_fetch(layout)
120    }
121
122    pub fn crate_item(&mut self, did: rustc_span::def_id::DefId) -> B::CrateItem {
123        B::CrateItem::new(self.create_def_id(did))
124    }
125
126    pub fn adt_def(&mut self, did: rustc_span::def_id::DefId) -> B::AdtDef {
127        B::AdtDef::new(self.create_def_id(did))
128    }
129
130    pub fn foreign_module_def(&mut self, did: rustc_span::def_id::DefId) -> B::ForeignModuleDef {
131        B::ForeignModuleDef::new(self.create_def_id(did))
132    }
133
134    pub fn foreign_def(&mut self, did: rustc_span::def_id::DefId) -> B::ForeignDef {
135        B::ForeignDef::new(self.create_def_id(did))
136    }
137
138    pub fn fn_def(&mut self, did: rustc_span::def_id::DefId) -> B::FnDef {
139        B::FnDef::new(self.create_def_id(did))
140    }
141
142    pub fn closure_def(&mut self, did: rustc_span::def_id::DefId) -> B::ClosureDef {
143        B::ClosureDef::new(self.create_def_id(did))
144    }
145
146    pub fn coroutine_def(&mut self, did: rustc_span::def_id::DefId) -> B::CoroutineDef {
147        B::CoroutineDef::new(self.create_def_id(did))
148    }
149
150    pub fn coroutine_closure_def(
151        &mut self,
152        did: rustc_span::def_id::DefId,
153    ) -> B::CoroutineClosureDef {
154        B::CoroutineClosureDef::new(self.create_def_id(did))
155    }
156
157    pub fn alias_def(&mut self, did: rustc_span::def_id::DefId) -> B::AliasDef {
158        B::AliasDef::new(self.create_def_id(did))
159    }
160
161    pub fn param_def(&mut self, did: rustc_span::def_id::DefId) -> B::ParamDef {
162        B::ParamDef::new(self.create_def_id(did))
163    }
164
165    pub fn br_named_def(&mut self, did: rustc_span::def_id::DefId) -> B::BrNamedDef {
166        B::BrNamedDef::new(self.create_def_id(did))
167    }
168
169    pub fn trait_def(&mut self, did: rustc_span::def_id::DefId) -> B::TraitDef {
170        B::TraitDef::new(self.create_def_id(did))
171    }
172
173    pub fn generic_def(&mut self, did: rustc_span::def_id::DefId) -> B::GenericDef {
174        B::GenericDef::new(self.create_def_id(did))
175    }
176
177    pub fn const_def(&mut self, did: rustc_span::def_id::DefId) -> B::ConstDef {
178        B::ConstDef::new(self.create_def_id(did))
179    }
180
181    pub fn impl_def(&mut self, did: rustc_span::def_id::DefId) -> B::ImplDef {
182        B::ImplDef::new(self.create_def_id(did))
183    }
184
185    pub fn region_def(&mut self, did: rustc_span::def_id::DefId) -> B::RegionDef {
186        B::RegionDef::new(self.create_def_id(did))
187    }
188
189    pub fn coroutine_witness_def(
190        &mut self,
191        did: rustc_span::def_id::DefId,
192    ) -> B::CoroutineWitnessDef {
193        B::CoroutineWitnessDef::new(self.create_def_id(did))
194    }
195
196    pub fn assoc_def(&mut self, did: rustc_span::def_id::DefId) -> B::AssocDef {
197        B::AssocDef::new(self.create_def_id(did))
198    }
199
200    pub fn opaque_def(&mut self, did: rustc_span::def_id::DefId) -> B::OpaqueDef {
201        B::OpaqueDef::new(self.create_def_id(did))
202    }
203
204    pub fn prov(&mut self, aid: rustc_middle::mir::interpret::AllocId) -> B::Prov {
205        B::Prov::new(self.create_alloc_id(aid))
206    }
207
208    pub fn static_def(&mut self, did: rustc_span::def_id::DefId) -> B::StaticDef {
209        B::StaticDef::new(self.create_def_id(did))
210    }
211}
212
213/// A trait defining types that are used to emulate StableMIR components, which is really
214/// useful when programming in stable_mir-agnostic settings.
215pub trait Bridge: Sized {
216    type DefId: Copy + Debug + PartialEq + IndexedVal;
217    type AllocId: Copy + Debug + PartialEq + IndexedVal;
218    type Span: Copy + Debug + PartialEq + IndexedVal;
219    type Ty: Copy + Debug + PartialEq + IndexedVal;
220    type InstanceDef: Copy + Debug + PartialEq + IndexedVal;
221    type TyConstId: Copy + Debug + PartialEq + IndexedVal;
222    type MirConstId: Copy + Debug + PartialEq + IndexedVal;
223    type Layout: Copy + Debug + PartialEq + IndexedVal;
224
225    type Error: SmirError;
226    type CrateItem: CrateItem<Self>;
227    type AdtDef: AdtDef<Self>;
228    type ForeignModuleDef: ForeignModuleDef<Self>;
229    type ForeignDef: ForeignDef<Self>;
230    type FnDef: FnDef<Self>;
231    type ClosureDef: ClosureDef<Self>;
232    type CoroutineDef: CoroutineDef<Self>;
233    type CoroutineClosureDef: CoroutineClosureDef<Self>;
234    type AliasDef: AliasDef<Self>;
235    type ParamDef: ParamDef<Self>;
236    type BrNamedDef: BrNamedDef<Self>;
237    type TraitDef: TraitDef<Self>;
238    type GenericDef: GenericDef<Self>;
239    type ConstDef: ConstDef<Self>;
240    type ImplDef: ImplDef<Self>;
241    type RegionDef: RegionDef<Self>;
242    type CoroutineWitnessDef: CoroutineWitnessDef<Self>;
243    type AssocDef: AssocDef<Self>;
244    type OpaqueDef: OpaqueDef<Self>;
245    type Prov: Prov<Self>;
246    type StaticDef: StaticDef<Self>;
247
248    type Allocation: Allocation<Self>;
249}
250
251pub trait IndexedVal {
252    fn to_val(index: usize) -> Self;
253
254    fn to_index(&self) -> usize;
255}
256
257/// Similar to rustc's `FxIndexMap`, `IndexMap` with extra
258/// safety features added.
259pub struct IndexMap<K, V> {
260    index_map: fx::FxIndexMap<K, V>,
261}
262
263impl<K, V> Default for IndexMap<K, V> {
264    fn default() -> Self {
265        Self { index_map: FxIndexMap::default() }
266    }
267}
268
269impl<K: PartialEq + Hash + Eq, V: Copy + Debug + PartialEq + IndexedVal> IndexMap<K, V> {
270    pub fn create_or_fetch(&mut self, key: K) -> V {
271        let len = self.index_map.len();
272        let v = self.index_map.entry(key).or_insert(V::to_val(len));
273        *v
274    }
275}
276
277impl<K: PartialEq + Hash + Eq, V: Copy + Debug + PartialEq + IndexedVal> Index<V>
278    for IndexMap<K, V>
279{
280    type Output = K;
281
282    fn index(&self, index: V) -> &Self::Output {
283        let (k, v) = self.index_map.get_index(index.to_index()).unwrap();
284        assert_eq!(*v, index, "Provided value doesn't match with indexed value");
285        k
286    }
287}
288
289/// Iterate over the definitions of the given crate.
290pub(crate) fn filter_def_ids<F, T>(tcx: TyCtxt<'_>, krate: CrateNum, mut func: F) -> Vec<T>
291where
292    F: FnMut(DefId) -> Option<T>,
293{
294    if krate == LOCAL_CRATE {
295        tcx.iter_local_def_id().filter_map(|did| func(did.to_def_id())).collect()
296    } else {
297        let num_definitions = tcx.num_extern_def_ids(krate);
298        (0..num_definitions)
299            .filter_map(move |i| {
300                let def_id = DefId { krate, index: rustc_span::def_id::DefIndex::from_usize(i) };
301                func(def_id)
302            })
303            .collect()
304    }
305}