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