Skip to main content

rustc_public_bridge/context/
impls.rs

1//! Implementation of CompilerCtxt.
2
3#![allow(rustc::usage_of_qualified_ty)]
4
5use std::iter;
6
7use rustc_abi::{Endian, Layout, ReprOptions};
8use rustc_hir::def::DefKind;
9use rustc_hir::{Attribute, LangItem};
10use rustc_middle::mir::interpret::{AllocId, ConstAllocation, ErrorHandled, GlobalAlloc, Scalar};
11use rustc_middle::mir::{BinOp, Body, Const as MirConst, ConstValue, UnOp};
12use rustc_middle::ty::layout::{FnAbiOf, LayoutOf};
13use rustc_middle::ty::print::{
14    with_forced_trimmed_paths, with_no_trimmed_paths, with_resolve_crate_name,
15};
16use rustc_middle::ty::util::Discr;
17use rustc_middle::ty::{
18    AdtDef, AdtKind, AssocItem, Binder, ClosureKind, CoroutineArgsExt, EarlyBinder,
19    ExistentialTraitRef, FnSig, GenericArgsRef, Instance, InstanceKind, IntrinsicDef, List,
20    PolyFnSig, ScalarInt, TraitDef, TraitRef, Ty, TyCtxt, TyKind, TypeVisitableExt, UintTy,
21    ValTree, VariantDef, VtblEntry,
22};
23use rustc_middle::{mir, ty};
24use rustc_session::cstore::ForeignModule;
25use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
26use rustc_span::{Span, Symbol};
27use rustc_target::callconv::FnAbi;
28
29use super::{AllocRangeHelpers, CompilerCtxt, TyHelpers, TypingEnvHelpers};
30use crate::builder::BodyBuilder;
31use crate::{Bridge, Error, Tables, filter_def_ids};
32
33impl<'tcx, B: Bridge> TyHelpers<'tcx> for CompilerCtxt<'tcx, B> {
34    fn new_foreign(&self, def_id: DefId) -> ty::Ty<'tcx> {
35        ty::Ty::new_foreign(self.tcx, def_id)
36    }
37}
38
39impl<'tcx, B: Bridge> TypingEnvHelpers<'tcx> for CompilerCtxt<'tcx, B> {
40    fn fully_monomorphized(&self) -> ty::TypingEnv<'tcx> {
41        ty::TypingEnv::fully_monomorphized()
42    }
43}
44
45impl<'tcx, B: Bridge> AllocRangeHelpers<'tcx> for CompilerCtxt<'tcx, B> {
46    fn alloc_range(
47        &self,
48        offset: rustc_abi::Size,
49        size: rustc_abi::Size,
50    ) -> mir::interpret::AllocRange {
51        rustc_middle::mir::interpret::alloc_range(offset, size)
52    }
53}
54
55impl<'tcx, B: Bridge> CompilerCtxt<'tcx, B> {
56    pub fn lift<T: ty::Lift<TyCtxt<'tcx>>>(&self, value: T) -> T::Lifted {
57        self.tcx.lift(value)
58    }
59
60    pub fn adt_def(&self, def_id: DefId) -> AdtDef<'tcx> {
61        self.tcx.adt_def(def_id)
62    }
63
64    pub fn coroutine_movability(&self, def_id: DefId) -> ty::Movability {
65        self.tcx.coroutine_movability(def_id)
66    }
67
68    pub fn valtree_to_const_val(&self, key: ty::Value<'tcx>) -> ConstValue {
69        self.tcx.valtree_to_const_val(key)
70    }
71
72    /// Return whether the instance as a body available.
73    ///
74    /// Items and intrinsics may have a body available from its definition.
75    /// Shims body may be generated depending on their type.
76    pub(crate) fn instance_has_body(&self, instance: Instance<'tcx>) -> bool {
77        let def_id = instance.def_id();
78        self.item_has_body(def_id)
79            || !#[allow(non_exhaustive_omitted_patterns)] match instance.def {
    ty::InstanceKind::Virtual(..) | ty::InstanceKind::Intrinsic(..) |
        ty::InstanceKind::Item(..) => true,
    _ => false,
}matches!(
80                instance.def,
81                ty::InstanceKind::Virtual(..)
82                    | ty::InstanceKind::Intrinsic(..)
83                    | ty::InstanceKind::Item(..)
84            )
85    }
86
87    /// Return whether the item has a body defined by the user.
88    ///
89    /// Note that intrinsics may have a placeholder body that shouldn't be used in practice.
90    /// In rustc_public, we handle this case as if the body is not available.
91    pub(crate) fn item_has_body(&self, def_id: DefId) -> bool {
92        let must_override = if let Some(intrinsic) = self.tcx.intrinsic(def_id) {
93            intrinsic.must_be_overridden
94        } else {
95            false
96        };
97        // FIXME: A good reason to make is_mir_available or mir_keys change behavior
98        !must_override && self.tcx.is_mir_available(def_id) && !self.tcx.is_trivial_const(def_id)
99    }
100
101    fn filter_fn_def(&self, def_id: DefId) -> Option<DefId> {
102        if #[allow(non_exhaustive_omitted_patterns)] match self.tcx.def_kind(def_id) {
    DefKind::Fn | DefKind::AssocFn => true,
    _ => false,
}matches!(self.tcx.def_kind(def_id), DefKind::Fn | DefKind::AssocFn) {
103            Some(def_id)
104        } else {
105            None
106        }
107    }
108
109    fn filter_static_def(&self, def_id: DefId) -> Option<DefId> {
110        #[allow(non_exhaustive_omitted_patterns)] match self.tcx.def_kind(def_id) {
    DefKind::Static { .. } => true,
    _ => false,
}matches!(self.tcx.def_kind(def_id), DefKind::Static { .. }).then(|| def_id)
111    }
112
113    fn filter_adt_def(&self, def_id: DefId) -> Option<DefId> {
114        #[allow(non_exhaustive_omitted_patterns)] match self.tcx.def_kind(def_id) {
    DefKind::Struct | DefKind::Enum | DefKind::Union => true,
    _ => false,
}matches!(self.tcx.def_kind(def_id), DefKind::Struct | DefKind::Enum | DefKind::Union)
115            .then(|| def_id)
116    }
117
118    pub fn target_endian(&self) -> Endian {
119        self.tcx.data_layout.endian
120    }
121
122    pub fn target_pointer_size(&self) -> usize {
123        self.tcx.data_layout.pointer_size().bits().try_into().unwrap()
124    }
125
126    pub fn entry_fn(&self) -> Option<DefId> {
127        Some(self.tcx.entry_fn(())?.0)
128    }
129
130    /// Retrieve all items of the local crate that have a MIR associated with them.
131    pub fn all_local_items(&self) -> Vec<DefId> {
132        self.tcx.mir_keys(()).iter().map(|item| item.to_def_id()).collect()
133    }
134
135    /// Retrieve the body of a function.
136    /// This function will panic if the body is not available.
137    pub fn mir_body(&self, item: DefId) -> &'tcx Body<'tcx> {
138        self.tcx.instance_mir(InstanceKind::Item(item))
139    }
140
141    /// Check whether the body of a function is available.
142    pub fn has_body(&self, def: DefId) -> bool {
143        self.item_has_body(def)
144    }
145
146    pub fn foreign_modules(&self, crate_num: CrateNum) -> Vec<DefId> {
147        self.tcx.foreign_modules(crate_num).keys().map(|mod_def_id| *mod_def_id).collect()
148    }
149
150    /// Retrieve all functions defined in this crate.
151    pub fn crate_functions(&self, crate_num: CrateNum) -> Vec<DefId> {
152        filter_def_ids(self.tcx, crate_num, |def_id| self.filter_fn_def(def_id))
153    }
154
155    /// Retrieve all static items defined in this crate.
156    pub fn crate_statics(&self, crate_num: CrateNum) -> Vec<DefId> {
157        filter_def_ids(self.tcx, crate_num, |def_id| self.filter_static_def(def_id))
158    }
159
160    /// Retrieve all ADTs defined in this crate.
161    pub fn crate_adts(&self, crate_num: CrateNum) -> Vec<DefId> {
162        filter_def_ids(self.tcx, crate_num, |def_id| self.filter_adt_def(def_id))
163    }
164
165    pub fn foreign_module(&self, mod_def: DefId) -> &ForeignModule {
166        self.tcx.foreign_modules(mod_def.krate).get(&mod_def).unwrap()
167    }
168
169    pub fn foreign_items(&self, mod_def: DefId) -> Vec<DefId> {
170        self.tcx
171            .foreign_modules(mod_def.krate)
172            .get(&mod_def)
173            .unwrap()
174            .foreign_items
175            .iter()
176            .map(|item_def| *item_def)
177            .collect()
178    }
179
180    pub fn all_trait_decls(&self) -> impl Iterator<Item = DefId> {
181        self.tcx.all_traits_including_private()
182    }
183
184    pub fn trait_decls(&self, crate_num: CrateNum) -> Vec<DefId> {
185        self.tcx.traits(crate_num).iter().map(|trait_def_id| *trait_def_id).collect()
186    }
187
188    pub fn trait_decl(&self, trait_def: DefId) -> &'tcx TraitDef {
189        self.tcx.trait_def(trait_def)
190    }
191
192    pub fn all_trait_impls(&self) -> Vec<DefId> {
193        iter::once(LOCAL_CRATE)
194            .chain(self.tcx.crates(()).iter().copied())
195            .flat_map(|cnum| self.tcx.trait_impls_in_crate(cnum).iter())
196            .map(|impl_def_id| *impl_def_id)
197            .collect()
198    }
199
200    pub fn trait_impls(&self, crate_num: CrateNum) -> Vec<DefId> {
201        self.tcx.trait_impls_in_crate(crate_num).iter().map(|impl_def_id| *impl_def_id).collect()
202    }
203
204    pub fn trait_impl(&self, impl_def: DefId) -> EarlyBinder<'tcx, TraitRef<'tcx>> {
205        self.tcx.impl_trait_ref(impl_def)
206    }
207
208    pub fn generics_of(&self, def_id: DefId) -> &'tcx ty::Generics {
209        self.tcx.generics_of(def_id)
210    }
211
212    pub fn predicates_of(
213        &self,
214        def_id: DefId,
215    ) -> (Option<DefId>, Vec<(ty::PredicateKind<'tcx>, Span)>) {
216        let ty::GenericPredicates { parent, predicates } = self.tcx.predicates_of(def_id);
217        (
218            parent,
219            predicates
220                .iter()
221                .map(|(clause, span)| (clause.as_predicate().kind().skip_binder(), *span))
222                .collect(),
223        )
224    }
225
226    pub fn explicit_predicates_of(
227        &self,
228        def_id: DefId,
229    ) -> (Option<DefId>, Vec<(ty::PredicateKind<'tcx>, Span)>) {
230        let ty::GenericPredicates { parent, predicates } = self.tcx.explicit_predicates_of(def_id);
231        (
232            parent,
233            predicates
234                .iter()
235                .map(|(clause, span)| (clause.as_predicate().kind().skip_binder(), *span))
236                .collect(),
237        )
238    }
239
240    pub fn crate_name(&self, crate_num: CrateNum) -> String {
241        self.tcx.crate_name(crate_num).to_string()
242    }
243
244    pub fn crate_is_local(&self, crate_num: CrateNum) -> bool {
245        crate_num == LOCAL_CRATE
246    }
247
248    pub fn crate_num_id(&self, crate_num: CrateNum) -> usize {
249        crate_num.into()
250    }
251
252    pub fn local_crate_num(&self) -> CrateNum {
253        LOCAL_CRATE
254    }
255
256    /// Retrieve a list of all external crates.
257    pub fn external_crates(&self) -> Vec<CrateNum> {
258        self.tcx.crates(()).iter().map(|crate_num| *crate_num).collect()
259    }
260
261    /// Find a crate with the given name.
262    pub fn find_crates(&self, name: &str) -> Vec<CrateNum> {
263        let crates: Vec<CrateNum> = [LOCAL_CRATE]
264            .iter()
265            .chain(self.tcx.crates(()).iter())
266            .filter_map(|crate_num| {
267                let crate_name = self.tcx.crate_name(*crate_num).to_string();
268                (name == crate_name).then(|| *crate_num)
269            })
270            .collect();
271        crates
272    }
273
274    /// Returns the name of given `DefId`.
275    pub fn def_name(&self, def_id: DefId, trimmed: bool) -> String {
276        if trimmed {
277            { let _guard = ForceTrimmedGuard::new(); self.tcx.def_path_str(def_id) }with_forced_trimmed_paths!(self.tcx.def_path_str(def_id))
278        } else {
279            // For local definitions, we need to prepend with crate name.
280            {
    let _guard = CrateNamePrefixGuard::new();
    { let _guard = NoTrimmedGuard::new(); self.tcx.def_path_str(def_id) }
}with_resolve_crate_name!(with_no_trimmed_paths!(self.tcx.def_path_str(def_id)))
281        }
282    }
283
284    /// Returns the parent of the given `DefId`.
285    pub fn def_parent(&self, def_id: DefId) -> Option<DefId> {
286        self.tcx.opt_parent(def_id)
287    }
288
289    /// Return registered tool attributes with the given attribute name.
290    ///
291    /// FIXME(jdonszelmann): may panic on non-tool attributes. After more attribute work, non-tool
292    /// attributes will simply return an empty list.
293    ///
294    /// Single segmented name like `#[clippy]` is specified as `&["clippy".to_string()]`.
295    /// Multi-segmented name like `#[rustfmt::skip]` is specified as `&["rustfmt".to_string(), "skip".to_string()]`.
296    pub fn tool_attrs(&self, def_id: DefId, attr: &[String]) -> Vec<(String, Span)> {
297        let attr_name: Vec<_> = attr.iter().map(|seg| Symbol::intern(&seg)).collect();
298        self.tcx
299            .get_attrs_by_path(def_id, &attr_name)
300            .filter_map(|attribute| {
301                if let Attribute::Unparsed(u) = attribute {
302                    let attr_str = rustc_hir_pretty::attribute_to_string(&self.tcx, attribute);
303                    Some((attr_str, u.span))
304                } else {
305                    None
306                }
307            })
308            .collect()
309    }
310
311    /// Get all tool attributes of a definition.
312    pub fn all_tool_attrs(&self, did: DefId) -> Vec<(String, Span)> {
313        let attrs_iter = if let Some(did) = did.as_local() {
314            self.tcx.hir_attrs(self.tcx.local_def_id_to_hir_id(did)).iter()
315        } else {
316            self.tcx.attrs_for_def(did).iter()
317        };
318        attrs_iter
319            .filter_map(|attribute| {
320                if let Attribute::Unparsed(u) = attribute {
321                    let attr_str = rustc_hir_pretty::attribute_to_string(&self.tcx, attribute);
322                    Some((attr_str, u.span))
323                } else {
324                    None
325                }
326            })
327            .collect()
328    }
329
330    /// Returns printable, human readable form of `Span`.
331    pub fn span_to_string(&self, span: Span) -> String {
332        self.tcx.sess.source_map().span_to_diagnostic_string(span)
333    }
334
335    /// Return filename from given `Span`, for diagnostic purposes.
336    pub fn get_filename(&self, span: Span) -> String {
337        self.tcx.sess.source_map().span_to_filename(span).prefer_local_unconditionally().to_string()
338    }
339
340    /// Return lines corresponding to this `Span`.
341    pub fn get_lines(&self, span: Span) -> (usize, usize, usize, usize) {
342        let lines = &self.tcx.sess.source_map().span_to_location_info(span);
343        (lines.1, lines.2, lines.3, lines.4)
344    }
345
346    /// Returns the `kind` of given `DefId`.
347    pub fn def_kind(&self, item: DefId) -> DefKind {
348        self.tcx.def_kind(item)
349    }
350
351    /// Returns whether this is a foreign item.
352    pub fn is_foreign_item(&self, item: DefId) -> bool {
353        self.tcx.is_foreign_item(item)
354    }
355
356    /// Returns the kind of a given foreign item.
357    pub fn foreign_item_kind(&self, def_id: DefId) -> DefKind {
358        self.tcx.def_kind(def_id)
359    }
360
361    /// Returns the kind of a given algebraic data type.
362    pub fn adt_kind(&self, def: AdtDef<'tcx>) -> AdtKind {
363        def.adt_kind()
364    }
365
366    /// Returns if the ADT is a box.
367    pub fn adt_is_box(&self, def: AdtDef<'tcx>) -> bool {
368        def.is_box()
369    }
370
371    /// Returns whether this ADT is simd.
372    pub fn adt_is_simd(&self, def: AdtDef<'tcx>) -> bool {
373        def.repr().simd()
374    }
375
376    /// Returns whether this definition is a C string.
377    pub fn adt_is_cstr(&self, def_id: DefId) -> bool {
378        self.tcx.is_lang_item(def_id, LangItem::CStr)
379    }
380
381    /// Returns the representation options for this ADT.
382    pub fn adt_repr(&self, def: AdtDef<'tcx>) -> ReprOptions {
383        def.repr()
384    }
385
386    /// Retrieve the function signature for the given generic arguments.
387    pub fn fn_sig(
388        &self,
389        def_id: DefId,
390        args_ref: GenericArgsRef<'tcx>,
391    ) -> Binder<'tcx, FnSig<'tcx>> {
392        let sig = self.tcx.fn_sig(def_id).instantiate(self.tcx, args_ref).skip_norm_wip();
393        sig
394    }
395
396    /// Retrieve the constness for the given function definition.
397    pub fn constness(&self, def_id: DefId) -> rustc_hir::Constness {
398        self.tcx.constness(def_id)
399    }
400
401    /// Retrieve the asyncness for the given function definition.
402    pub fn asyncness(&self, def_id: DefId) -> ty::Asyncness {
403        self.tcx.asyncness(def_id)
404    }
405
406    /// Retrieve the intrinsic definition if the item corresponds one.
407    pub fn intrinsic(&self, def_id: DefId) -> Option<IntrinsicDef> {
408        let intrinsic = self.tcx.intrinsic_raw(def_id);
409        intrinsic
410    }
411
412    /// Retrieve the plain function name of an intrinsic.
413    pub fn intrinsic_name(&self, def_id: DefId) -> String {
414        self.tcx.intrinsic(def_id).unwrap().name.to_string()
415    }
416
417    /// Retrieve the closure signature for the given generic arguments.
418    pub fn closure_sig(&self, args_ref: GenericArgsRef<'tcx>) -> Binder<'tcx, FnSig<'tcx>> {
419        args_ref.as_closure().sig()
420    }
421
422    /// The number of variants in this ADT.
423    pub fn adt_variants_len(&self, def: AdtDef<'tcx>) -> usize {
424        def.variants().len()
425    }
426
427    /// Discriminant for a given variant index of AdtDef.
428    pub fn adt_discr_for_variant(
429        &self,
430        adt: AdtDef<'tcx>,
431        variant: rustc_abi::VariantIdx,
432    ) -> Discr<'tcx> {
433        adt.discriminant_for_variant(self.tcx, variant)
434    }
435
436    /// Discriminant for a given variand index and args of a coroutine.
437    pub fn coroutine_discr_for_variant(
438        &self,
439        coroutine: DefId,
440        args: GenericArgsRef<'tcx>,
441        variant: rustc_abi::VariantIdx,
442    ) -> Discr<'tcx> {
443        args.as_coroutine().discriminant_for_variant(coroutine, self.tcx, variant)
444    }
445
446    /// The name of a variant.
447    pub fn variant_name(&self, def: &'tcx VariantDef) -> String {
448        def.name.to_string()
449    }
450
451    /// Evaluate constant as a target usize.
452    pub fn eval_target_usize(&self, cnst: MirConst<'tcx>) -> Result<u64, B::Error> {
453        use crate::context::TypingEnvHelpers;
454        cnst.try_eval_target_usize(self.tcx, self.fully_monomorphized())
455            .ok_or_else(|| B::Error::new(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("Const `{0:?}` cannot be encoded as u64",
                cnst))
    })format!("Const `{cnst:?}` cannot be encoded as u64")))
456    }
457
458    pub fn eval_target_usize_ty(&self, cnst: ty::Const<'tcx>) -> Result<u64, B::Error> {
459        cnst.try_to_target_usize(self.tcx)
460            .ok_or_else(|| B::Error::new(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("Const `{0:?}` cannot be encoded as u64",
                cnst))
    })format!("Const `{cnst:?}` cannot be encoded as u64")))
461    }
462
463    pub fn try_new_const_zst(&self, ty_internal: Ty<'tcx>) -> Result<MirConst<'tcx>, B::Error> {
464        let size = self
465            .tcx
466            .layout_of(self.fully_monomorphized().as_query_input(ty_internal))
467            .map_err(|err| {
468                B::Error::new(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("Cannot create a zero-sized constant for type `{0}`: {1}",
                ty_internal, err))
    })format!(
469                    "Cannot create a zero-sized constant for type `{ty_internal}`: {err}"
470                ))
471            })?
472            .size;
473        if size.bytes() != 0 {
474            return Err(B::Error::new(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("Cannot create a zero-sized constant for type `{1}`: Type `{1}` has {0} bytes",
                size.bytes(), ty_internal))
    })format!(
475                "Cannot create a zero-sized constant for type `{ty_internal}`: \
476                Type `{ty_internal}` has {} bytes",
477                size.bytes()
478            )));
479        }
480
481        Ok(MirConst::Ty(ty_internal, self.const_zero_sized(ty_internal)))
482    }
483
484    pub fn const_zero_sized(&self, ty_internal: Ty<'tcx>) -> ty::Const<'tcx> {
485        ty::Const::zero_sized(self.tcx, ty_internal)
486    }
487
488    /// Create a new constant that represents the given string value.
489    pub fn new_const_str(&self, value: &str) -> MirConst<'tcx> {
490        let ty = Ty::new_static_str(self.tcx);
491        let bytes = value.as_bytes();
492        let valtree = ValTree::from_raw_bytes(self.tcx, bytes);
493        let cv = ty::Value { ty, valtree };
494        let val = self.tcx.valtree_to_const_val(cv);
495        MirConst::from_value(val, ty)
496    }
497
498    /// Create a new constant that represents the given boolean value.
499    pub fn new_const_bool(&self, value: bool) -> MirConst<'tcx> {
500        MirConst::from_bool(self.tcx, value)
501    }
502
503    pub fn try_new_const_uint(
504        &self,
505        value: u128,
506        ty_internal: Ty<'tcx>,
507    ) -> Result<MirConst<'tcx>, B::Error> {
508        let size = self
509            .tcx
510            .layout_of(self.fully_monomorphized().as_query_input(ty_internal))
511            .unwrap()
512            .size;
513        let scalar = ScalarInt::try_from_uint(value, size).ok_or_else(|| {
514            B::Error::new(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("Value overflow: cannot convert `{0}` to `{1}`.",
                value, ty_internal))
    })format!("Value overflow: cannot convert `{value}` to `{ty_internal}`."))
515        })?;
516        Ok(self.mir_const_from_scalar(Scalar::Int(scalar), ty_internal))
517    }
518
519    pub fn try_new_ty_const_uint(
520        &self,
521        value: u128,
522        ty_internal: Ty<'tcx>,
523    ) -> Result<ty::Const<'tcx>, B::Error> {
524        let size = self
525            .tcx
526            .layout_of(self.fully_monomorphized().as_query_input(ty_internal))
527            .unwrap()
528            .size;
529        let scalar = ScalarInt::try_from_uint(value, size).ok_or_else(|| {
530            B::Error::new(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("Value overflow: cannot convert `{0}` to `{1}`.",
                value, ty_internal))
    })format!("Value overflow: cannot convert `{value}` to `{ty_internal}`."))
531        })?;
532
533        Ok(self.ty_const_new_value(ValTree::from_scalar_int(self.tcx, scalar), ty_internal))
534    }
535
536    pub fn ty_new_uint(&self, ty: UintTy) -> Ty<'tcx> {
537        Ty::new_uint(self.tcx, ty)
538    }
539
540    pub fn mir_const_from_scalar(&self, s: Scalar, ty: Ty<'tcx>) -> MirConst<'tcx> {
541        MirConst::from_scalar(self.tcx, s, ty)
542    }
543
544    pub fn ty_const_new_value(&self, valtree: ValTree<'tcx>, ty: Ty<'tcx>) -> ty::Const<'tcx> {
545        ty::Const::new_value(self.tcx, valtree, ty)
546    }
547
548    pub fn ty_valtree_from_scalar_int(&self, i: ScalarInt) -> ValTree<'tcx> {
549        ValTree::from_scalar_int(self.tcx, i)
550    }
551
552    /// Create a new type from the given kind.
553    pub fn new_rigid_ty(&self, internal_kind: TyKind<'tcx>) -> Ty<'tcx> {
554        self.tcx.mk_ty_from_kind(internal_kind)
555    }
556
557    /// Create a new box type, `Box<T>`, for the given inner type `T`.
558    pub fn new_box_ty(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
559        ty::Ty::new_box(self.tcx, ty)
560    }
561
562    /// Returns the type of given crate item.
563    pub fn def_ty(&self, item: DefId) -> Ty<'tcx> {
564        self.tcx.type_of(item).instantiate_identity().skip_norm_wip()
565    }
566
567    /// Returns the type of given definition instantiated with the given arguments.
568    pub fn def_ty_with_args(&self, item: DefId, args_ref: GenericArgsRef<'tcx>) -> Ty<'tcx> {
569        let def_ty = self.tcx.type_of(item);
570        self.tcx.instantiate_and_normalize_erasing_regions(
571            args_ref,
572            self.fully_monomorphized(),
573            def_ty,
574        )
575    }
576
577    /// `Span` of a `DefId`.
578    pub fn span_of_a_def(&self, def_id: DefId) -> Span {
579        self.tcx.def_span(def_id)
580    }
581
582    pub fn ty_const_pretty(&self, ct: ty::Const<'tcx>) -> String {
583        ct.to_string()
584    }
585
586    /// Obtain the representation of a type.
587    pub fn ty_pretty(&self, ty: Ty<'tcx>) -> String {
588        ty.to_string()
589    }
590
591    /// Obtain the kind of a type.
592    pub fn ty_kind(&self, ty: Ty<'tcx>) -> &'tcx TyKind<'tcx> {
593        ty.kind()
594    }
595
596    /// Get the discriminant Ty for this Ty if there's one.
597    pub fn rigid_ty_discriminant_ty(&self, internal_kind: TyKind<'tcx>) -> Ty<'tcx> {
598        let internal_ty = self.tcx.mk_ty_from_kind(internal_kind);
599        internal_ty.discriminant_ty(self.tcx)
600    }
601
602    /// Get the body of an Instance which is already monomorphized.
603    pub fn instance_body(&self, instance: ty::Instance<'tcx>) -> Option<Body<'tcx>> {
604        self.instance_has_body(instance).then(|| BodyBuilder::new(self.tcx, instance).build())
605    }
606
607    /// Get the instance type with generic instantiations applied and lifetimes erased.
608    pub fn instance_ty(&self, instance: ty::Instance<'tcx>) -> Ty<'tcx> {
609        if !!instance.has_non_region_param() {
    {
        ::core::panicking::panic_fmt(format_args!("{0:?} needs further instantiation",
                instance));
    }
};assert!(!instance.has_non_region_param(), "{instance:?} needs further instantiation");
610        instance.ty(self.tcx, self.fully_monomorphized())
611    }
612
613    /// Get the instantiation types.
614    pub fn instance_args(&self, instance: ty::Instance<'tcx>) -> GenericArgsRef<'tcx> {
615        instance.args
616    }
617
618    /// Get an instance ABI.
619    pub fn instance_abi(
620        &self,
621        instance: ty::Instance<'tcx>,
622    ) -> Result<&FnAbi<'tcx, Ty<'tcx>>, B::Error> {
623        Ok(self.fn_abi_of_instance(instance, List::empty())?)
624    }
625
626    /// Get the ABI of a function pointer.
627    pub fn fn_ptr_abi(&self, sig: PolyFnSig<'tcx>) -> Result<&FnAbi<'tcx, Ty<'tcx>>, B::Error> {
628        Ok(self.fn_abi_of_fn_ptr(sig, List::empty())?)
629    }
630
631    /// Get the instance.
632    pub fn instance_def_id(
633        &self,
634        instances: ty::Instance<'tcx>,
635        tables: &mut Tables<'_, B>,
636    ) -> B::DefId {
637        let def_id = instances.def_id();
638        tables.create_def_id(def_id)
639    }
640
641    /// Get the instance mangled name.
642    pub fn instance_mangled_name(&self, instance: ty::Instance<'tcx>) -> String {
643        self.tcx.symbol_name(instance).name.to_string()
644    }
645
646    /// Check if this is an empty DropGlue shim.
647    pub fn is_empty_drop_shim(&self, instance: ty::Instance<'tcx>) -> bool {
648        #[allow(non_exhaustive_omitted_patterns)] match instance.def {
    ty::InstanceKind::DropGlue(_, None) => true,
    _ => false,
}matches!(instance.def, ty::InstanceKind::DropGlue(_, None))
649    }
650
651    /// Convert a non-generic crate item into an instance.
652    /// This function will panic if the item is generic.
653    pub fn mono_instance(&self, def_id: DefId) -> Instance<'tcx> {
654        Instance::mono(self.tcx, def_id)
655    }
656
657    /// Item requires monomorphization.
658    pub fn requires_monomorphization(&self, def_id: DefId) -> bool {
659        let generics = self.tcx.generics_of(def_id);
660        let result = generics.requires_monomorphization(self.tcx);
661        result
662    }
663
664    /// Resolve an instance from the given function definition and generic arguments.
665    pub fn resolve_instance(
666        &self,
667        def_id: DefId,
668        args_ref: GenericArgsRef<'tcx>,
669    ) -> Option<Instance<'tcx>> {
670        match Instance::try_resolve(self.tcx, self.fully_monomorphized(), def_id, args_ref) {
671            Ok(Some(instance)) => Some(instance),
672            Ok(None) | Err(_) => None,
673        }
674    }
675
676    /// Resolve an instance for drop_in_place for the given type.
677    pub fn resolve_drop_in_place(&self, internal_ty: Ty<'tcx>) -> Instance<'tcx> {
678        let instance = Instance::resolve_drop_glue(self.tcx, internal_ty);
679        instance
680    }
681
682    /// Resolve instance for a function pointer.
683    pub fn resolve_for_fn_ptr(
684        &self,
685        def_id: DefId,
686        args_ref: GenericArgsRef<'tcx>,
687    ) -> Option<Instance<'tcx>> {
688        Instance::resolve_for_fn_ptr(self.tcx, self.fully_monomorphized(), def_id, args_ref)
689    }
690
691    /// Resolve instance for a closure with the requested type.
692    pub fn resolve_closure(
693        &self,
694        def_id: DefId,
695        args_ref: GenericArgsRef<'tcx>,
696        closure_kind: ClosureKind,
697    ) -> Option<Instance<'tcx>> {
698        Some(Instance::resolve_closure(self.tcx, def_id, args_ref, closure_kind))
699    }
700
701    /// Try to evaluate an instance into a constant.
702    pub fn eval_instance(&self, instance: ty::Instance<'tcx>) -> Result<ConstValue, ErrorHandled> {
703        self.tcx.const_eval_instance(
704            self.fully_monomorphized(),
705            instance,
706            self.tcx.def_span(instance.def_id()),
707        )
708    }
709
710    /// Evaluate a static's initializer.
711    pub fn eval_static_initializer(
712        &self,
713        def_id: DefId,
714    ) -> Result<ConstAllocation<'tcx>, ErrorHandled> {
715        self.tcx.eval_static_initializer(def_id)
716    }
717
718    /// Retrieve global allocation for the given allocation ID.
719    pub fn global_alloc(&self, alloc_id: AllocId) -> GlobalAlloc<'tcx> {
720        self.tcx.global_alloc(alloc_id)
721    }
722
723    /// Retrieve the id for the virtual table.
724    pub fn vtable_allocation(
725        &self,
726        ty: Ty<'tcx>,
727        trait_ref: Option<Binder<'tcx, ExistentialTraitRef<'tcx>>>,
728    ) -> AllocId {
729        let alloc_id = self.tcx.vtable_allocation((
730            ty,
731            trait_ref.map(|principal| self.tcx.instantiate_bound_regions_with_erased(principal)),
732        ));
733        alloc_id
734    }
735
736    /// Retrieve the instance name for diagnostic messages.
737    ///
738    /// This will return the specialized name, e.g., `Vec<char>::new`.
739    pub fn instance_name(&self, instance: ty::Instance<'tcx>, trimmed: bool) -> String {
740        if trimmed {
741            {
    let _guard = ForceTrimmedGuard::new();
    self.tcx.def_path_str_with_args(instance.def_id(), instance.args)
}with_forced_trimmed_paths!(
742                self.tcx.def_path_str_with_args(instance.def_id(), instance.args)
743            )
744        } else {
745            {
    let _guard = CrateNamePrefixGuard::new();
    {
        let _guard = NoTrimmedGuard::new();
        self.tcx.def_path_str_with_args(instance.def_id(), instance.args)
    }
}with_resolve_crate_name!(with_no_trimmed_paths!(
746                self.tcx.def_path_str_with_args(instance.def_id(), instance.args)
747            ))
748        }
749    }
750
751    /// Get the layout of a type.
752    pub fn ty_layout(&self, ty: Ty<'tcx>) -> Result<Layout<'tcx>, B::Error> {
753        let layout = self.layout_of(ty)?.layout;
754        Ok(layout)
755    }
756
757    /// Get the resulting type of binary operation.
758    pub fn binop_ty(&self, bin_op: BinOp, rhs: Ty<'tcx>, lhs: Ty<'tcx>) -> Ty<'tcx> {
759        bin_op.ty(self.tcx, rhs, lhs)
760    }
761
762    /// Get the resulting type of unary operation.
763    pub fn unop_ty(&self, un_op: UnOp, arg: Ty<'tcx>) -> Ty<'tcx> {
764        un_op.ty(self.tcx, arg)
765    }
766
767    /// Get all associated items of a definition.
768    pub fn associated_items(&self, def_id: DefId) -> Vec<AssocItem> {
769        let assoc_items = if self.tcx.is_trait_alias(def_id) {
770            Vec::new()
771        } else {
772            self.tcx
773                .associated_item_def_ids(def_id)
774                .iter()
775                .map(|did| self.tcx.associated_item(*did))
776                .collect()
777        };
778        assoc_items
779    }
780
781    /// Get all vtable entries of a trait.
782    pub fn vtable_entries(&self, trait_ref: TraitRef<'tcx>) -> Vec<VtblEntry<'tcx>> {
783        self.tcx.vtable_entries(trait_ref).to_vec()
784    }
785
786    /// Returns the vtable entry at the given index.
787    ///
788    /// Returns `None` if the index is out of bounds.
789    pub fn vtable_entry(&self, trait_ref: TraitRef<'tcx>, idx: usize) -> Option<VtblEntry<'tcx>> {
790        self.vtable_entries(trait_ref).get(idx).copied()
791    }
792}