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