rustc_smir/rustc_smir/
context.rs

1//! Implementation of StableMIR Context.
2
3#![allow(rustc::usage_of_qualified_ty)]
4
5use std::cell::RefCell;
6use std::iter;
7
8use rustc_abi::HasDataLayout;
9use rustc_hir::{Attribute, LangItem};
10use rustc_middle::ty::layout::{
11    FnAbiOf, FnAbiOfHelpers, HasTyCtxt, HasTypingEnv, LayoutOf, LayoutOfHelpers,
12};
13use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths};
14use rustc_middle::ty::{
15    GenericPredicates, Instance, List, ScalarInt, TyCtxt, TypeVisitableExt, ValTree,
16};
17use rustc_middle::{mir, ty};
18use rustc_span::def_id::LOCAL_CRATE;
19use stable_mir::abi::{FnAbi, Layout, LayoutShape};
20use stable_mir::mir::alloc::GlobalAlloc;
21use stable_mir::mir::mono::{InstanceDef, StaticDef};
22use stable_mir::mir::{BinOp, Body, Place, UnOp};
23use stable_mir::target::{MachineInfo, MachineSize};
24use stable_mir::ty::{
25    AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, FieldDef, FnDef, ForeignDef,
26    ForeignItemKind, GenericArgs, IntrinsicDef, LineInfo, MirConst, PolyFnSig, RigidTy, Span, Ty,
27    TyConst, TyKind, UintTy, VariantDef,
28};
29use stable_mir::{Crate, CrateDef, CrateItem, CrateNum, DefId, Error, Filename, ItemKind, Symbol};
30
31use crate::rustc_internal::RustcInternal;
32use crate::rustc_smir::builder::BodyBuilder;
33use crate::rustc_smir::{Stable, Tables, alloc, filter_def_ids, new_item_kind, smir_crate};
34use crate::stable_mir;
35
36/// Provides direct access to rustc's internal queries.
37///
38/// The [`crate::stable_mir::compiler_interface::SmirInterface`] must go through
39/// this context to obtain rustc-level information.
40pub struct SmirCtxt<'tcx>(pub RefCell<Tables<'tcx>>);
41
42impl<'tcx> SmirCtxt<'tcx> {
43    pub fn target_info(&self) -> MachineInfo {
44        let mut tables = self.0.borrow_mut();
45        MachineInfo {
46            endian: tables.tcx.data_layout.endian.stable(&mut *tables),
47            pointer_width: MachineSize::from_bits(
48                tables.tcx.data_layout.pointer_size.bits().try_into().unwrap(),
49            ),
50        }
51    }
52
53    pub fn entry_fn(&self) -> Option<stable_mir::CrateItem> {
54        let mut tables = self.0.borrow_mut();
55        let tcx = tables.tcx;
56        Some(tables.crate_item(tcx.entry_fn(())?.0))
57    }
58
59    /// Retrieve all items of the local crate that have a MIR associated with them.
60    pub fn all_local_items(&self) -> stable_mir::CrateItems {
61        let mut tables = self.0.borrow_mut();
62        tables.tcx.mir_keys(()).iter().map(|item| tables.crate_item(item.to_def_id())).collect()
63    }
64
65    /// Retrieve the body of a function.
66    /// This function will panic if the body is not available.
67    pub fn mir_body(&self, item: stable_mir::DefId) -> stable_mir::mir::Body {
68        let mut tables = self.0.borrow_mut();
69        let def_id = tables[item];
70        tables.tcx.instance_mir(rustc_middle::ty::InstanceKind::Item(def_id)).stable(&mut tables)
71    }
72
73    /// Check whether the body of a function is available.
74    pub fn has_body(&self, def: DefId) -> bool {
75        let mut tables = self.0.borrow_mut();
76        let tcx = tables.tcx;
77        let def_id = def.internal(&mut *tables, tcx);
78        tables.item_has_body(def_id)
79    }
80
81    pub fn foreign_modules(&self, crate_num: CrateNum) -> Vec<stable_mir::ty::ForeignModuleDef> {
82        let mut tables = self.0.borrow_mut();
83        let tcx = tables.tcx;
84        tcx.foreign_modules(crate_num.internal(&mut *tables, tcx))
85            .keys()
86            .map(|mod_def_id| tables.foreign_module_def(*mod_def_id))
87            .collect()
88    }
89
90    /// Retrieve all functions defined in this crate.
91    pub fn crate_functions(&self, crate_num: CrateNum) -> Vec<FnDef> {
92        let mut tables = self.0.borrow_mut();
93        let tcx = tables.tcx;
94        let krate = crate_num.internal(&mut *tables, tcx);
95        filter_def_ids(tcx, krate, |def_id| tables.to_fn_def(def_id))
96    }
97
98    /// Retrieve all static items defined in this crate.
99    pub fn crate_statics(&self, crate_num: CrateNum) -> Vec<StaticDef> {
100        let mut tables = self.0.borrow_mut();
101        let tcx = tables.tcx;
102        let krate = crate_num.internal(&mut *tables, tcx);
103        filter_def_ids(tcx, krate, |def_id| tables.to_static(def_id))
104    }
105
106    pub fn foreign_module(
107        &self,
108        mod_def: stable_mir::ty::ForeignModuleDef,
109    ) -> stable_mir::ty::ForeignModule {
110        let mut tables = self.0.borrow_mut();
111        let def_id = tables[mod_def.def_id()];
112        let mod_def = tables.tcx.foreign_modules(def_id.krate).get(&def_id).unwrap();
113        mod_def.stable(&mut *tables)
114    }
115
116    pub fn foreign_items(&self, mod_def: stable_mir::ty::ForeignModuleDef) -> Vec<ForeignDef> {
117        let mut tables = self.0.borrow_mut();
118        let def_id = tables[mod_def.def_id()];
119        tables
120            .tcx
121            .foreign_modules(def_id.krate)
122            .get(&def_id)
123            .unwrap()
124            .foreign_items
125            .iter()
126            .map(|item_def| tables.foreign_def(*item_def))
127            .collect()
128    }
129
130    pub fn all_trait_decls(&self) -> stable_mir::TraitDecls {
131        let mut tables = self.0.borrow_mut();
132        tables.tcx.all_traits().map(|trait_def_id| tables.trait_def(trait_def_id)).collect()
133    }
134
135    pub fn trait_decls(&self, crate_num: CrateNum) -> stable_mir::TraitDecls {
136        let mut tables = self.0.borrow_mut();
137        let tcx = tables.tcx;
138        tcx.traits(crate_num.internal(&mut *tables, tcx))
139            .iter()
140            .map(|trait_def_id| tables.trait_def(*trait_def_id))
141            .collect()
142    }
143
144    pub fn trait_decl(&self, trait_def: &stable_mir::ty::TraitDef) -> stable_mir::ty::TraitDecl {
145        let mut tables = self.0.borrow_mut();
146        let def_id = tables[trait_def.0];
147        let trait_def = tables.tcx.trait_def(def_id);
148        trait_def.stable(&mut *tables)
149    }
150
151    pub fn all_trait_impls(&self) -> stable_mir::ImplTraitDecls {
152        let mut tables = self.0.borrow_mut();
153        let tcx = tables.tcx;
154        iter::once(LOCAL_CRATE)
155            .chain(tables.tcx.crates(()).iter().copied())
156            .flat_map(|cnum| tcx.trait_impls_in_crate(cnum).iter())
157            .map(|impl_def_id| tables.impl_def(*impl_def_id))
158            .collect()
159    }
160
161    pub fn trait_impls(&self, crate_num: CrateNum) -> stable_mir::ImplTraitDecls {
162        let mut tables = self.0.borrow_mut();
163        let tcx = tables.tcx;
164        tcx.trait_impls_in_crate(crate_num.internal(&mut *tables, tcx))
165            .iter()
166            .map(|impl_def_id| tables.impl_def(*impl_def_id))
167            .collect()
168    }
169
170    pub fn trait_impl(&self, impl_def: &stable_mir::ty::ImplDef) -> stable_mir::ty::ImplTrait {
171        let mut tables = self.0.borrow_mut();
172        let def_id = tables[impl_def.0];
173        let impl_trait = tables.tcx.impl_trait_ref(def_id).unwrap();
174        impl_trait.stable(&mut *tables)
175    }
176
177    pub fn generics_of(&self, def_id: stable_mir::DefId) -> stable_mir::ty::Generics {
178        let mut tables = self.0.borrow_mut();
179        let def_id = tables[def_id];
180        let generics = tables.tcx.generics_of(def_id);
181        generics.stable(&mut *tables)
182    }
183
184    pub fn predicates_of(&self, def_id: stable_mir::DefId) -> stable_mir::ty::GenericPredicates {
185        let mut tables = self.0.borrow_mut();
186        let def_id = tables[def_id];
187        let GenericPredicates { parent, predicates } = tables.tcx.predicates_of(def_id);
188        stable_mir::ty::GenericPredicates {
189            parent: parent.map(|did| tables.trait_def(did)),
190            predicates: predicates
191                .iter()
192                .map(|(clause, span)| {
193                    (
194                        clause.as_predicate().kind().skip_binder().stable(&mut *tables),
195                        span.stable(&mut *tables),
196                    )
197                })
198                .collect(),
199        }
200    }
201
202    pub fn explicit_predicates_of(
203        &self,
204        def_id: stable_mir::DefId,
205    ) -> stable_mir::ty::GenericPredicates {
206        let mut tables = self.0.borrow_mut();
207        let def_id = tables[def_id];
208        let GenericPredicates { parent, predicates } = tables.tcx.explicit_predicates_of(def_id);
209        stable_mir::ty::GenericPredicates {
210            parent: parent.map(|did| tables.trait_def(did)),
211            predicates: predicates
212                .iter()
213                .map(|(clause, span)| {
214                    (
215                        clause.as_predicate().kind().skip_binder().stable(&mut *tables),
216                        span.stable(&mut *tables),
217                    )
218                })
219                .collect(),
220        }
221    }
222
223    /// Get information about the local crate.
224    pub fn local_crate(&self) -> stable_mir::Crate {
225        let tables = self.0.borrow();
226        smir_crate(tables.tcx, LOCAL_CRATE)
227    }
228
229    /// Retrieve a list of all external crates.
230    pub fn external_crates(&self) -> Vec<stable_mir::Crate> {
231        let tables = self.0.borrow();
232        tables.tcx.crates(()).iter().map(|crate_num| smir_crate(tables.tcx, *crate_num)).collect()
233    }
234
235    /// Find a crate with the given name.
236    pub fn find_crates(&self, name: &str) -> Vec<stable_mir::Crate> {
237        let tables = self.0.borrow();
238        let crates: Vec<stable_mir::Crate> = [LOCAL_CRATE]
239            .iter()
240            .chain(tables.tcx.crates(()).iter())
241            .filter_map(|crate_num| {
242                let crate_name = tables.tcx.crate_name(*crate_num).to_string();
243                (name == crate_name).then(|| smir_crate(tables.tcx, *crate_num))
244            })
245            .collect();
246        crates
247    }
248
249    /// Returns the name of given `DefId`.
250    pub fn def_name(&self, def_id: stable_mir::DefId, trimmed: bool) -> Symbol {
251        let tables = self.0.borrow();
252        if trimmed {
253            with_forced_trimmed_paths!(tables.tcx.def_path_str(tables[def_id]))
254        } else {
255            with_no_trimmed_paths!(tables.tcx.def_path_str(tables[def_id]))
256        }
257    }
258
259    /// Return registered tool attributes with the given attribute name.
260    ///
261    /// FIXME(jdonszelmann): may panic on non-tool attributes. After more attribute work, non-tool
262    /// attributes will simply return an empty list.
263    ///
264    /// Single segmented name like `#[clippy]` is specified as `&["clippy".to_string()]`.
265    /// Multi-segmented name like `#[rustfmt::skip]` is specified as `&["rustfmt".to_string(), "skip".to_string()]`.
266    pub fn tool_attrs(
267        &self,
268        def_id: stable_mir::DefId,
269        attr: &[stable_mir::Symbol],
270    ) -> Vec<stable_mir::crate_def::Attribute> {
271        let mut tables = self.0.borrow_mut();
272        let tcx = tables.tcx;
273        let did = tables[def_id];
274        let attr_name: Vec<_> = attr.iter().map(|seg| rustc_span::Symbol::intern(&seg)).collect();
275        tcx.get_attrs_by_path(did, &attr_name)
276            .filter_map(|attribute| {
277                if let Attribute::Unparsed(u) = attribute {
278                    let attr_str = rustc_hir_pretty::attribute_to_string(&tcx, attribute);
279                    Some(stable_mir::crate_def::Attribute::new(
280                        attr_str,
281                        u.span.stable(&mut *tables),
282                    ))
283                } else {
284                    None
285                }
286            })
287            .collect()
288    }
289
290    /// Get all tool attributes of a definition.
291    pub fn all_tool_attrs(
292        &self,
293        def_id: stable_mir::DefId,
294    ) -> Vec<stable_mir::crate_def::Attribute> {
295        let mut tables = self.0.borrow_mut();
296        let tcx = tables.tcx;
297        let did = tables[def_id];
298        let attrs_iter = if let Some(did) = did.as_local() {
299            tcx.hir_attrs(tcx.local_def_id_to_hir_id(did)).iter()
300        } else {
301            tcx.attrs_for_def(did).iter()
302        };
303        attrs_iter
304            .filter_map(|attribute| {
305                if let Attribute::Unparsed(u) = attribute {
306                    let attr_str = rustc_hir_pretty::attribute_to_string(&tcx, attribute);
307                    Some(stable_mir::crate_def::Attribute::new(
308                        attr_str,
309                        u.span.stable(&mut *tables),
310                    ))
311                } else {
312                    None
313                }
314            })
315            .collect()
316    }
317
318    /// Returns printable, human readable form of `Span`.
319    pub fn span_to_string(&self, span: stable_mir::ty::Span) -> String {
320        let tables = self.0.borrow();
321        tables.tcx.sess.source_map().span_to_diagnostic_string(tables[span])
322    }
323
324    /// Return filename from given `Span`, for diagnostic purposes.
325    pub fn get_filename(&self, span: &Span) -> Filename {
326        let tables = self.0.borrow();
327        tables
328            .tcx
329            .sess
330            .source_map()
331            .span_to_filename(tables[*span])
332            .display(rustc_span::FileNameDisplayPreference::Local)
333            .to_string()
334    }
335
336    /// Return lines corresponding to this `Span`.
337    pub fn get_lines(&self, span: &Span) -> LineInfo {
338        let tables = self.0.borrow();
339        let lines = &tables.tcx.sess.source_map().span_to_location_info(tables[*span]);
340        LineInfo { start_line: lines.1, start_col: lines.2, end_line: lines.3, end_col: lines.4 }
341    }
342
343    /// Returns the `kind` of given `DefId`.
344    pub fn item_kind(&self, item: CrateItem) -> ItemKind {
345        let tables = self.0.borrow();
346        new_item_kind(tables.tcx.def_kind(tables[item.0]))
347    }
348
349    /// Returns whether this is a foreign item.
350    pub fn is_foreign_item(&self, item: DefId) -> bool {
351        let tables = self.0.borrow();
352        tables.tcx.is_foreign_item(tables[item])
353    }
354
355    /// Returns the kind of a given foreign item.
356    pub fn foreign_item_kind(&self, def: ForeignDef) -> ForeignItemKind {
357        let mut tables = self.0.borrow_mut();
358        let def_id = tables[def.def_id()];
359        let tcx = tables.tcx;
360        use rustc_hir::def::DefKind;
361        match tcx.def_kind(def_id) {
362            DefKind::Fn => ForeignItemKind::Fn(tables.fn_def(def_id)),
363            DefKind::Static { .. } => ForeignItemKind::Static(tables.static_def(def_id)),
364            DefKind::ForeignTy => ForeignItemKind::Type(
365                tables.intern_ty(rustc_middle::ty::Ty::new_foreign(tcx, def_id)),
366            ),
367            def_kind => unreachable!("Unexpected kind for a foreign item: {:?}", def_kind),
368        }
369    }
370
371    /// Returns the kind of a given algebraic data type.
372    pub fn adt_kind(&self, def: AdtDef) -> AdtKind {
373        let mut tables = self.0.borrow_mut();
374        let tcx = tables.tcx;
375        def.internal(&mut *tables, tcx).adt_kind().stable(&mut *tables)
376    }
377
378    /// Returns if the ADT is a box.
379    pub fn adt_is_box(&self, def: AdtDef) -> bool {
380        let mut tables = self.0.borrow_mut();
381        let tcx = tables.tcx;
382        def.internal(&mut *tables, tcx).is_box()
383    }
384
385    /// Returns whether this ADT is simd.
386    pub fn adt_is_simd(&self, def: AdtDef) -> bool {
387        let mut tables = self.0.borrow_mut();
388        let tcx = tables.tcx;
389        def.internal(&mut *tables, tcx).repr().simd()
390    }
391
392    /// Returns whether this definition is a C string.
393    pub fn adt_is_cstr(&self, def: AdtDef) -> bool {
394        let mut tables = self.0.borrow_mut();
395        let tcx = tables.tcx;
396        let def_id = def.0.internal(&mut *tables, tcx);
397        tables.tcx.is_lang_item(def_id, LangItem::CStr)
398    }
399
400    /// Retrieve the function signature for the given generic arguments.
401    pub fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig {
402        let mut tables = self.0.borrow_mut();
403        let tcx = tables.tcx;
404        let def_id = def.0.internal(&mut *tables, tcx);
405        let sig =
406            tables.tcx.fn_sig(def_id).instantiate(tables.tcx, args.internal(&mut *tables, tcx));
407        sig.stable(&mut *tables)
408    }
409
410    /// Retrieve the intrinsic definition if the item corresponds one.
411    pub fn intrinsic(&self, def: DefId) -> Option<IntrinsicDef> {
412        let mut tables = self.0.borrow_mut();
413        let tcx = tables.tcx;
414        let def_id = def.internal(&mut *tables, tcx);
415        let intrinsic = tcx.intrinsic_raw(def_id);
416        intrinsic.map(|_| IntrinsicDef(def))
417    }
418
419    /// Retrieve the plain function name of an intrinsic.
420    pub fn intrinsic_name(&self, def: IntrinsicDef) -> Symbol {
421        let mut tables = self.0.borrow_mut();
422        let tcx = tables.tcx;
423        let def_id = def.0.internal(&mut *tables, tcx);
424        tcx.intrinsic(def_id).unwrap().name.to_string()
425    }
426
427    /// Retrieve the closure signature for the given generic arguments.
428    pub fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig {
429        let mut tables = self.0.borrow_mut();
430        let tcx = tables.tcx;
431        let args_ref = args.internal(&mut *tables, tcx);
432        let sig = args_ref.as_closure().sig();
433        sig.stable(&mut *tables)
434    }
435
436    /// The number of variants in this ADT.
437    pub fn adt_variants_len(&self, def: AdtDef) -> usize {
438        let mut tables = self.0.borrow_mut();
439        let tcx = tables.tcx;
440        def.internal(&mut *tables, tcx).variants().len()
441    }
442
443    /// The name of a variant.
444    pub fn variant_name(&self, def: VariantDef) -> Symbol {
445        let mut tables = self.0.borrow_mut();
446        let tcx = tables.tcx;
447        def.internal(&mut *tables, tcx).name.to_string()
448    }
449
450    pub fn variant_fields(&self, def: VariantDef) -> Vec<FieldDef> {
451        let mut tables = self.0.borrow_mut();
452        let tcx = tables.tcx;
453        def.internal(&mut *tables, tcx).fields.iter().map(|f| f.stable(&mut *tables)).collect()
454    }
455
456    /// Evaluate constant as a target usize.
457    pub fn eval_target_usize(&self, cnst: &MirConst) -> Result<u64, Error> {
458        let mut tables = self.0.borrow_mut();
459        let tcx = tables.tcx;
460        let mir_const = cnst.internal(&mut *tables, tcx);
461        mir_const
462            .try_eval_target_usize(tables.tcx, ty::TypingEnv::fully_monomorphized())
463            .ok_or_else(|| Error::new(format!("Const `{cnst:?}` cannot be encoded as u64")))
464    }
465    pub fn eval_target_usize_ty(&self, cnst: &TyConst) -> Result<u64, Error> {
466        let mut tables = self.0.borrow_mut();
467        let tcx = tables.tcx;
468        let mir_const = cnst.internal(&mut *tables, tcx);
469        mir_const
470            .try_to_target_usize(tables.tcx)
471            .ok_or_else(|| Error::new(format!("Const `{cnst:?}` cannot be encoded as u64")))
472    }
473
474    /// Create a new zero-sized constant.
475    pub fn try_new_const_zst(&self, ty: Ty) -> Result<MirConst, Error> {
476        let mut tables = self.0.borrow_mut();
477        let tcx = tables.tcx;
478        let ty_internal = ty.internal(&mut *tables, tcx);
479        let size = tables
480            .tcx
481            .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty_internal))
482            .map_err(|err| {
483                Error::new(format!(
484                    "Cannot create a zero-sized constant for type `{ty_internal}`: {err}"
485                ))
486            })?
487            .size;
488        if size.bytes() != 0 {
489            return Err(Error::new(format!(
490                "Cannot create a zero-sized constant for type `{ty_internal}`: \
491                 Type `{ty_internal}` has {} bytes",
492                size.bytes()
493            )));
494        }
495
496        Ok(mir::Const::Ty(ty_internal, ty::Const::zero_sized(tables.tcx, ty_internal))
497            .stable(&mut *tables))
498    }
499
500    /// Create a new constant that represents the given string value.
501    pub fn new_const_str(&self, value: &str) -> MirConst {
502        let mut tables = self.0.borrow_mut();
503        let tcx = tables.tcx;
504        let ty = ty::Ty::new_static_str(tcx);
505        let bytes = value.as_bytes();
506        let valtree = ty::ValTree::from_raw_bytes(tcx, bytes);
507        let cv = ty::Value { ty, valtree };
508        let val = tcx.valtree_to_const_val(cv);
509        mir::Const::from_value(val, ty).stable(&mut tables)
510    }
511
512    /// Create a new constant that represents the given boolean value.
513    pub fn new_const_bool(&self, value: bool) -> MirConst {
514        let mut tables = self.0.borrow_mut();
515        mir::Const::from_bool(tables.tcx, value).stable(&mut tables)
516    }
517
518    /// Create a new constant that represents the given value.
519    pub fn try_new_const_uint(&self, value: u128, uint_ty: UintTy) -> Result<MirConst, Error> {
520        let mut tables = self.0.borrow_mut();
521        let tcx = tables.tcx;
522        let ty = ty::Ty::new_uint(tcx, uint_ty.internal(&mut *tables, tcx));
523        let size = tables
524            .tcx
525            .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty))
526            .unwrap()
527            .size;
528        let scalar = ScalarInt::try_from_uint(value, size).ok_or_else(|| {
529            Error::new(format!("Value overflow: cannot convert `{value}` to `{ty}`."))
530        })?;
531        Ok(mir::Const::from_scalar(tcx, mir::interpret::Scalar::Int(scalar), ty)
532            .stable(&mut tables))
533    }
534    pub fn try_new_ty_const_uint(
535        &self,
536        value: u128,
537        uint_ty: UintTy,
538    ) -> Result<stable_mir::ty::TyConst, Error> {
539        let mut tables = self.0.borrow_mut();
540        let tcx = tables.tcx;
541        let ty = ty::Ty::new_uint(tcx, uint_ty.internal(&mut *tables, tcx));
542        let size = tables
543            .tcx
544            .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty))
545            .unwrap()
546            .size;
547
548        // We don't use Const::from_bits since it doesn't have any error checking.
549        let scalar = ScalarInt::try_from_uint(value, size).ok_or_else(|| {
550            Error::new(format!("Value overflow: cannot convert `{value}` to `{ty}`."))
551        })?;
552        Ok(ty::Const::new_value(tcx, ValTree::from_scalar_int(tcx, scalar), ty)
553            .stable(&mut *tables))
554    }
555
556    /// Create a new type from the given kind.
557    pub fn new_rigid_ty(&self, kind: RigidTy) -> stable_mir::ty::Ty {
558        let mut tables = self.0.borrow_mut();
559        let tcx = tables.tcx;
560        let internal_kind = kind.internal(&mut *tables, tcx);
561        tables.tcx.mk_ty_from_kind(internal_kind).stable(&mut *tables)
562    }
563
564    /// Create a new box type, `Box<T>`, for the given inner type `T`.
565    pub fn new_box_ty(&self, ty: stable_mir::ty::Ty) -> stable_mir::ty::Ty {
566        let mut tables = self.0.borrow_mut();
567        let tcx = tables.tcx;
568        let inner = ty.internal(&mut *tables, tcx);
569        ty::Ty::new_box(tables.tcx, inner).stable(&mut *tables)
570    }
571
572    /// Returns the type of given crate item.
573    pub fn def_ty(&self, item: stable_mir::DefId) -> stable_mir::ty::Ty {
574        let mut tables = self.0.borrow_mut();
575        let tcx = tables.tcx;
576        tcx.type_of(item.internal(&mut *tables, tcx)).instantiate_identity().stable(&mut *tables)
577    }
578
579    /// Returns the type of given definition instantiated with the given arguments.
580    pub fn def_ty_with_args(
581        &self,
582        item: stable_mir::DefId,
583        args: &GenericArgs,
584    ) -> stable_mir::ty::Ty {
585        let mut tables = self.0.borrow_mut();
586        let tcx = tables.tcx;
587        let args = args.internal(&mut *tables, tcx);
588        let def_ty = tables.tcx.type_of(item.internal(&mut *tables, tcx));
589        tables
590            .tcx
591            .instantiate_and_normalize_erasing_regions(
592                args,
593                ty::TypingEnv::fully_monomorphized(),
594                def_ty,
595            )
596            .stable(&mut *tables)
597    }
598
599    /// Returns literal value of a const as a string.
600    pub fn mir_const_pretty(&self, cnst: &stable_mir::ty::MirConst) -> String {
601        let mut tables = self.0.borrow_mut();
602        let tcx = tables.tcx;
603        cnst.internal(&mut *tables, tcx).to_string()
604    }
605
606    /// `Span` of an item.
607    pub fn span_of_an_item(&self, def_id: stable_mir::DefId) -> Span {
608        let mut tables = self.0.borrow_mut();
609        tables.tcx.def_span(tables[def_id]).stable(&mut *tables)
610    }
611
612    /// Obtain the representation of a type.
613    pub fn ty_pretty(&self, ty: stable_mir::ty::Ty) -> String {
614        let tables = self.0.borrow_mut();
615        tables.types[ty].to_string()
616    }
617
618    /// Obtain the representation of a type.
619    pub fn ty_kind(&self, ty: stable_mir::ty::Ty) -> TyKind {
620        let mut tables = self.0.borrow_mut();
621        tables.types[ty].kind().stable(&mut *tables)
622    }
623
624    pub fn ty_const_pretty(&self, ct: stable_mir::ty::TyConstId) -> String {
625        let tables = self.0.borrow_mut();
626        tables.ty_consts[ct].to_string()
627    }
628
629    /// Get the discriminant Ty for this Ty if there's one.
630    pub fn rigid_ty_discriminant_ty(&self, ty: &RigidTy) -> stable_mir::ty::Ty {
631        let mut tables = self.0.borrow_mut();
632        let tcx = tables.tcx;
633        let internal_kind = ty.internal(&mut *tables, tcx);
634        let internal_ty = tables.tcx.mk_ty_from_kind(internal_kind);
635        internal_ty.discriminant_ty(tables.tcx).stable(&mut *tables)
636    }
637
638    /// Get the body of an Instance which is already monomorphized.
639    pub fn instance_body(&self, def: InstanceDef) -> Option<Body> {
640        let mut tables = self.0.borrow_mut();
641        let instance = tables.instances[def];
642        tables
643            .instance_has_body(instance)
644            .then(|| BodyBuilder::new(tables.tcx, instance).build(&mut *tables))
645    }
646
647    /// Get the instance type with generic instantiations applied and lifetimes erased.
648    pub fn instance_ty(&self, def: InstanceDef) -> stable_mir::ty::Ty {
649        let mut tables = self.0.borrow_mut();
650        let instance = tables.instances[def];
651        assert!(!instance.has_non_region_param(), "{instance:?} needs further instantiation");
652        instance.ty(tables.tcx, ty::TypingEnv::fully_monomorphized()).stable(&mut *tables)
653    }
654
655    /// Get the instantiation types.
656    pub fn instance_args(&self, def: InstanceDef) -> GenericArgs {
657        let mut tables = self.0.borrow_mut();
658        let instance = tables.instances[def];
659        instance.args.stable(&mut *tables)
660    }
661
662    /// Get an instance ABI.
663    pub fn instance_abi(&self, def: InstanceDef) -> Result<FnAbi, Error> {
664        let mut tables = self.0.borrow_mut();
665        let instance = tables.instances[def];
666        Ok(tables.fn_abi_of_instance(instance, List::empty())?.stable(&mut *tables))
667    }
668
669    /// Get the ABI of a function pointer.
670    pub fn fn_ptr_abi(&self, fn_ptr: PolyFnSig) -> Result<FnAbi, Error> {
671        let mut tables = self.0.borrow_mut();
672        let tcx = tables.tcx;
673        let sig = fn_ptr.internal(&mut *tables, tcx);
674        Ok(tables.fn_abi_of_fn_ptr(sig, List::empty())?.stable(&mut *tables))
675    }
676
677    /// Get the instance.
678    pub fn instance_def_id(&self, def: InstanceDef) -> stable_mir::DefId {
679        let mut tables = self.0.borrow_mut();
680        let def_id = tables.instances[def].def_id();
681        tables.create_def_id(def_id)
682    }
683
684    /// Get the instance mangled name.
685    pub fn instance_mangled_name(&self, instance: InstanceDef) -> Symbol {
686        let tables = self.0.borrow_mut();
687        let instance = tables.instances[instance];
688        tables.tcx.symbol_name(instance).name.to_string()
689    }
690
691    /// Check if this is an empty DropGlue shim.
692    pub fn is_empty_drop_shim(&self, def: InstanceDef) -> bool {
693        let tables = self.0.borrow_mut();
694        let instance = tables.instances[def];
695        matches!(instance.def, ty::InstanceKind::DropGlue(_, None))
696    }
697
698    /// Convert a non-generic crate item into an instance.
699    /// This function will panic if the item is generic.
700    pub fn mono_instance(&self, def_id: stable_mir::DefId) -> stable_mir::mir::mono::Instance {
701        let mut tables = self.0.borrow_mut();
702        let def_id = tables[def_id];
703        Instance::mono(tables.tcx, def_id).stable(&mut *tables)
704    }
705
706    /// Item requires monomorphization.
707    pub fn requires_monomorphization(&self, def_id: stable_mir::DefId) -> bool {
708        let tables = self.0.borrow();
709        let def_id = tables[def_id];
710        let generics = tables.tcx.generics_of(def_id);
711        let result = generics.requires_monomorphization(tables.tcx);
712        result
713    }
714
715    /// Resolve an instance from the given function definition and generic arguments.
716    pub fn resolve_instance(
717        &self,
718        def: stable_mir::ty::FnDef,
719        args: &stable_mir::ty::GenericArgs,
720    ) -> Option<stable_mir::mir::mono::Instance> {
721        let mut tables = self.0.borrow_mut();
722        let tcx = tables.tcx;
723        let def_id = def.0.internal(&mut *tables, tcx);
724        let args_ref = args.internal(&mut *tables, tcx);
725        match Instance::try_resolve(
726            tables.tcx,
727            ty::TypingEnv::fully_monomorphized(),
728            def_id,
729            args_ref,
730        ) {
731            Ok(Some(instance)) => Some(instance.stable(&mut *tables)),
732            Ok(None) | Err(_) => None,
733        }
734    }
735
736    /// Resolve an instance for drop_in_place for the given type.
737    pub fn resolve_drop_in_place(&self, ty: stable_mir::ty::Ty) -> stable_mir::mir::mono::Instance {
738        let mut tables = self.0.borrow_mut();
739        let tcx = tables.tcx;
740        let internal_ty = ty.internal(&mut *tables, tcx);
741        let instance = Instance::resolve_drop_in_place(tables.tcx, internal_ty);
742        instance.stable(&mut *tables)
743    }
744
745    /// Resolve instance for a function pointer.
746    pub fn resolve_for_fn_ptr(
747        &self,
748        def: FnDef,
749        args: &GenericArgs,
750    ) -> Option<stable_mir::mir::mono::Instance> {
751        let mut tables = self.0.borrow_mut();
752        let tcx = tables.tcx;
753        let def_id = def.0.internal(&mut *tables, tcx);
754        let args_ref = args.internal(&mut *tables, tcx);
755        Instance::resolve_for_fn_ptr(
756            tables.tcx,
757            ty::TypingEnv::fully_monomorphized(),
758            def_id,
759            args_ref,
760        )
761        .stable(&mut *tables)
762    }
763
764    /// Resolve instance for a closure with the requested type.
765    pub fn resolve_closure(
766        &self,
767        def: ClosureDef,
768        args: &GenericArgs,
769        kind: ClosureKind,
770    ) -> Option<stable_mir::mir::mono::Instance> {
771        let mut tables = self.0.borrow_mut();
772        let tcx = tables.tcx;
773        let def_id = def.0.internal(&mut *tables, tcx);
774        let args_ref = args.internal(&mut *tables, tcx);
775        let closure_kind = kind.internal(&mut *tables, tcx);
776        Some(
777            Instance::resolve_closure(tables.tcx, def_id, args_ref, closure_kind)
778                .stable(&mut *tables),
779        )
780    }
781
782    /// Try to evaluate an instance into a constant.
783    pub fn eval_instance(&self, def: InstanceDef, const_ty: Ty) -> Result<Allocation, Error> {
784        let mut tables = self.0.borrow_mut();
785        let instance = tables.instances[def];
786        let tcx = tables.tcx;
787        let result = tcx.const_eval_instance(
788            ty::TypingEnv::fully_monomorphized(),
789            instance,
790            tcx.def_span(instance.def_id()),
791        );
792        result
793            .map(|const_val| {
794                alloc::try_new_allocation(
795                    const_ty.internal(&mut *tables, tcx),
796                    const_val,
797                    &mut *tables,
798                )
799            })
800            .map_err(|e| e.stable(&mut *tables))?
801    }
802
803    /// Evaluate a static's initializer.
804    pub fn eval_static_initializer(&self, def: StaticDef) -> Result<Allocation, Error> {
805        let mut tables = self.0.borrow_mut();
806        let tcx = tables.tcx;
807        let def_id = def.0.internal(&mut *tables, tcx);
808        tables.tcx.eval_static_initializer(def_id).stable(&mut *tables)
809    }
810
811    /// Retrieve global allocation for the given allocation ID.
812    pub fn global_alloc(&self, alloc: stable_mir::mir::alloc::AllocId) -> GlobalAlloc {
813        let mut tables = self.0.borrow_mut();
814        let tcx = tables.tcx;
815        let alloc_id = alloc.internal(&mut *tables, tcx);
816        tables.tcx.global_alloc(alloc_id).stable(&mut *tables)
817    }
818
819    /// Retrieve the id for the virtual table.
820    pub fn vtable_allocation(
821        &self,
822        global_alloc: &GlobalAlloc,
823    ) -> Option<stable_mir::mir::alloc::AllocId> {
824        let mut tables = self.0.borrow_mut();
825        let GlobalAlloc::VTable(ty, trait_ref) = global_alloc else {
826            return None;
827        };
828        let tcx = tables.tcx;
829        let alloc_id = tables.tcx.vtable_allocation((
830            ty.internal(&mut *tables, tcx),
831            trait_ref
832                .internal(&mut *tables, tcx)
833                .map(|principal| tcx.instantiate_bound_regions_with_erased(principal)),
834        ));
835        Some(alloc_id.stable(&mut *tables))
836    }
837
838    pub fn krate(&self, def_id: stable_mir::DefId) -> Crate {
839        let tables = self.0.borrow();
840        smir_crate(tables.tcx, tables[def_id].krate)
841    }
842
843    /// Retrieve the instance name for diagnostic messages.
844    ///
845    /// This will return the specialized name, e.g., `Vec<char>::new`.
846    pub fn instance_name(&self, def: InstanceDef, trimmed: bool) -> Symbol {
847        let tables = self.0.borrow_mut();
848        let instance = tables.instances[def];
849        if trimmed {
850            with_forced_trimmed_paths!(
851                tables.tcx.def_path_str_with_args(instance.def_id(), instance.args)
852            )
853        } else {
854            with_no_trimmed_paths!(
855                tables.tcx.def_path_str_with_args(instance.def_id(), instance.args)
856            )
857        }
858    }
859
860    /// Get the layout of a type.
861    pub fn ty_layout(&self, ty: Ty) -> Result<Layout, Error> {
862        let mut tables = self.0.borrow_mut();
863        let tcx = tables.tcx;
864        let ty = ty.internal(&mut *tables, tcx);
865        let layout = tables.layout_of(ty)?.layout;
866        Ok(layout.stable(&mut *tables))
867    }
868
869    /// Get the layout shape.
870    pub fn layout_shape(&self, id: Layout) -> LayoutShape {
871        let mut tables = self.0.borrow_mut();
872        let tcx = tables.tcx;
873        id.internal(&mut *tables, tcx).0.stable(&mut *tables)
874    }
875
876    /// Get a debug string representation of a place.
877    pub fn place_pretty(&self, place: &Place) -> String {
878        let mut tables = self.0.borrow_mut();
879        let tcx = tables.tcx;
880        format!("{:?}", place.internal(&mut *tables, tcx))
881    }
882
883    /// Get the resulting type of binary operation.
884    pub fn binop_ty(&self, bin_op: BinOp, rhs: Ty, lhs: Ty) -> Ty {
885        let mut tables = self.0.borrow_mut();
886        let tcx = tables.tcx;
887        let rhs_internal = rhs.internal(&mut *tables, tcx);
888        let lhs_internal = lhs.internal(&mut *tables, tcx);
889        let ty = bin_op.internal(&mut *tables, tcx).ty(tcx, rhs_internal, lhs_internal);
890        ty.stable(&mut *tables)
891    }
892
893    /// Get the resulting type of unary operation.
894    pub fn unop_ty(&self, un_op: UnOp, arg: Ty) -> Ty {
895        let mut tables = self.0.borrow_mut();
896        let tcx = tables.tcx;
897        let arg_internal = arg.internal(&mut *tables, tcx);
898        let ty = un_op.internal(&mut *tables, tcx).ty(tcx, arg_internal);
899        ty.stable(&mut *tables)
900    }
901
902    /// Get all associated items of a definition.
903    pub fn associated_items(&self, def_id: stable_mir::DefId) -> stable_mir::AssocItems {
904        let mut tables = self.0.borrow_mut();
905        let tcx = tables.tcx;
906        let def_id = tables[def_id];
907        let assoc_items = if tcx.is_trait_alias(def_id) {
908            Vec::new()
909        } else {
910            tcx.associated_item_def_ids(def_id)
911                .iter()
912                .map(|did| tcx.associated_item(*did).stable(&mut *tables))
913                .collect()
914        };
915        assoc_items
916    }
917}
918
919/// Implement error handling for extracting function ABI information.
920impl<'tcx> FnAbiOfHelpers<'tcx> for Tables<'tcx> {
921    type FnAbiOfResult = Result<&'tcx rustc_target::callconv::FnAbi<'tcx, ty::Ty<'tcx>>, Error>;
922
923    #[inline]
924    fn handle_fn_abi_err(
925        &self,
926        err: ty::layout::FnAbiError<'tcx>,
927        _span: rustc_span::Span,
928        fn_abi_request: ty::layout::FnAbiRequest<'tcx>,
929    ) -> Error {
930        Error::new(format!("Failed to get ABI for `{fn_abi_request:?}`: {err:?}"))
931    }
932}
933
934impl<'tcx> LayoutOfHelpers<'tcx> for Tables<'tcx> {
935    type LayoutOfResult = Result<ty::layout::TyAndLayout<'tcx>, Error>;
936
937    #[inline]
938    fn handle_layout_err(
939        &self,
940        err: ty::layout::LayoutError<'tcx>,
941        _span: rustc_span::Span,
942        ty: ty::Ty<'tcx>,
943    ) -> Error {
944        Error::new(format!("Failed to get layout for `{ty}`: {err}"))
945    }
946}
947
948impl<'tcx> HasTypingEnv<'tcx> for Tables<'tcx> {
949    fn typing_env(&self) -> ty::TypingEnv<'tcx> {
950        ty::TypingEnv::fully_monomorphized()
951    }
952}
953
954impl<'tcx> HasTyCtxt<'tcx> for Tables<'tcx> {
955    fn tcx(&self) -> TyCtxt<'tcx> {
956        self.tcx
957    }
958}
959
960impl<'tcx> HasDataLayout for Tables<'tcx> {
961    fn data_layout(&self) -> &rustc_abi::TargetDataLayout {
962        self.tcx.data_layout()
963    }
964}