rustc_smir/rustc_smir/
context.rs

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