rustc_public_bridge/
lib.rs

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