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