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