1 use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
2 use crate::middle::lang_items::DropInPlaceFnLangItem;
3 use crate::ty::print::{FmtPrinter, Printer};
4 use crate::ty::{self, SubstsRef, Ty, TyCtxt, TypeFoldable};
5 use rustc_data_structures::AtomicRef;
6 use rustc_hir::def::Namespace;
7 use rustc_hir::def_id::{CrateNum, DefId};
8 use rustc_macros::HashStable;
12 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
13 #[derive(HashStable, Lift)]
14 pub struct Instance<'tcx> {
15 pub def: InstanceDef<'tcx>,
16 pub substs: SubstsRef<'tcx>,
19 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable, HashStable)]
20 pub enum InstanceDef<'tcx> {
24 /// `<T as Trait>::method` where `method` receives unsizeable `self: Self`.
27 /// `fn()` pointer where the function itself cannot be turned into a pointer.
29 /// One example is `<dyn Trait as Trait>::fn`, where the shim contains
30 /// a virtual call, which codegen supports only via a direct call to the
31 /// `<dyn Trait as Trait>::fn` instance (an `InstanceDef::Virtual`).
33 /// Another example is functions annotated with `#[track_caller]`, which
34 /// must have their implicit caller location argument populated for a call.
35 /// Because this is a required part of the function's ABI but can't be tracked
36 /// as a property of the function pointer, we use a single "caller location"
37 /// (the definition of the function itself).
40 /// `<fn() as FnTrait>::call_*`
41 /// `DefId` is `FnTrait::call_*`.
43 /// NB: the (`fn` pointer) type must currently be monomorphic to avoid double substitution
44 /// problems with the MIR shim bodies. `Instance::resolve` enforces this.
45 // FIXME(#69925) support polymorphic MIR shim bodies properly instead.
46 FnPtrShim(DefId, Ty<'tcx>),
48 /// `<dyn Trait as Trait>::fn`, "direct calls" of which are implicitly
49 /// codegen'd as virtual calls.
51 /// NB: if this is reified to a `fn` pointer, a `ReifyShim` is used
52 /// (see `ReifyShim` above for more details on that).
53 Virtual(DefId, usize),
55 /// `<[mut closure] as FnOnce>::call_once`
60 /// `core::ptr::drop_in_place::<T>`.
61 /// The `DefId` is for `core::ptr::drop_in_place`.
62 /// The `Option<Ty<'tcx>>` is either `Some(T)`, or `None` for empty drop
65 /// NB: the type must currently be monomorphic to avoid double substitution
66 /// problems with the MIR shim bodies. `Instance::resolve` enforces this.
67 // FIXME(#69925) support polymorphic MIR shim bodies properly instead.
68 DropGlue(DefId, Option<Ty<'tcx>>),
70 ///`<T as Clone>::clone` shim.
72 /// NB: the type must currently be monomorphic to avoid double substitution
73 /// problems with the MIR shim bodies. `Instance::resolve` enforces this.
74 // FIXME(#69925) support polymorphic MIR shim bodies properly instead.
75 CloneShim(DefId, Ty<'tcx>),
78 impl<'tcx> Instance<'tcx> {
79 /// Returns the `Ty` corresponding to this `Instance`,
80 /// with generic substitutions applied and lifetimes erased.
82 /// This method can only be called when the 'substs' for this Instance
83 /// are fully monomorphic (no `ty::Param`'s are present).
84 /// This is usually the case (e.g. during codegen).
85 /// However, during constant evaluation, we may want
86 /// to try to resolve a `Instance` using generic parameters
87 /// (e.g. when we are attempting to to do const-propagation).
88 /// In this case, `Instance.ty_env` should be used to provide
89 /// the `ParamEnv` for our generic context.
90 pub fn monomorphic_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
91 let ty = tcx.type_of(self.def.def_id());
92 // There shouldn't be any params - if there are, then
93 // Instance.ty_env should have been used to provide the proper
95 if self.substs.has_param_types() {
96 bug!("Instance.ty called for type {:?} with params in substs: {:?}", ty, self.substs);
98 tcx.subst_and_normalize_erasing_regions(self.substs, ty::ParamEnv::reveal_all(), &ty)
101 /// Like `Instance.ty`, but allows a `ParamEnv` to be specified for use during
102 /// normalization. This method is only really useful during constant evaluation,
103 /// where we are dealing with potentially generic types.
104 pub fn ty_env(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> {
105 let ty = tcx.type_of(self.def.def_id());
106 tcx.subst_and_normalize_erasing_regions(self.substs, param_env, &ty)
109 /// Finds a crate that contains a monomorphization of this instance that
110 /// can be linked to from the local crate. A return value of `None` means
111 /// no upstream crate provides such an exported monomorphization.
113 /// This method already takes into account the global `-Zshare-generics`
114 /// setting, always returning `None` if `share-generics` is off.
115 pub fn upstream_monomorphization(&self, tcx: TyCtxt<'tcx>) -> Option<CrateNum> {
116 // If we are not in share generics mode, we don't link to upstream
117 // monomorphizations but always instantiate our own internal versions
119 if !tcx.sess.opts.share_generics() {
123 // If this is an item that is defined in the local crate, no upstream
124 // crate can know about it/provide a monomorphization.
125 if self.def_id().is_local() {
129 // If this a non-generic instance, it cannot be a shared monomorphization.
130 self.substs.non_erasable_generics().next()?;
133 InstanceDef::Item(def_id) => tcx
134 .upstream_monomorphizations_for(def_id)
135 .and_then(|monos| monos.get(&self.substs).cloned()),
136 InstanceDef::DropGlue(_, Some(_)) => tcx.upstream_drop_glue_for(self.substs),
142 impl<'tcx> InstanceDef<'tcx> {
144 pub fn def_id(&self) -> DefId {
146 InstanceDef::Item(def_id)
147 | InstanceDef::VtableShim(def_id)
148 | InstanceDef::ReifyShim(def_id)
149 | InstanceDef::FnPtrShim(def_id, _)
150 | InstanceDef::Virtual(def_id, _)
151 | InstanceDef::Intrinsic(def_id)
152 | InstanceDef::ClosureOnceShim { call_once: def_id }
153 | InstanceDef::DropGlue(def_id, _)
154 | InstanceDef::CloneShim(def_id, _) => def_id,
159 pub fn attrs(&self, tcx: TyCtxt<'tcx>) -> ty::Attributes<'tcx> {
160 tcx.get_attrs(self.def_id())
163 /// Returns `true` if the LLVM version of this instance is unconditionally
164 /// marked with `inline`. This implies that a copy of this instance is
165 /// generated in every codegen unit.
166 /// Note that this is only a hint. See the documentation for
167 /// `generates_cgu_internal_copy` for more information.
168 pub fn requires_inline(&self, tcx: TyCtxt<'tcx>) -> bool {
169 use crate::hir::map::DefPathData;
170 let def_id = match *self {
171 ty::InstanceDef::Item(def_id) => def_id,
172 ty::InstanceDef::DropGlue(_, Some(_)) => return false,
175 match tcx.def_key(def_id).disambiguated_data.data {
176 DefPathData::Ctor | DefPathData::ClosureExpr => true,
181 /// Returns `true` if the machine code for this instance is instantiated in
182 /// each codegen unit that references it.
183 /// Note that this is only a hint! The compiler can globally decide to *not*
184 /// do this in order to speed up compilation. CGU-internal copies are
185 /// only exist to enable inlining. If inlining is not performed (e.g. at
186 /// `-Copt-level=0`) then the time for generating them is wasted and it's
187 /// better to create a single copy with external linkage.
188 pub fn generates_cgu_internal_copy(&self, tcx: TyCtxt<'tcx>) -> bool {
189 if self.requires_inline(tcx) {
192 if let ty::InstanceDef::DropGlue(.., Some(ty)) = *self {
193 // Drop glue generally wants to be instantiated at every codegen
194 // unit, but without an #[inline] hint. We should make this
195 // available to normal end-users.
196 if tcx.sess.opts.incremental.is_none() {
199 // When compiling with incremental, we can generate a *lot* of
200 // codegen units. Including drop glue into all of them has a
201 // considerable compile time cost.
203 // We include enums without destructors to allow, say, optimizing
204 // drops of `Option::None` before LTO. We also respect the intent of
205 // `#[inline]` on `Drop::drop` implementations.
206 return ty.ty_adt_def().map_or(true, |adt_def| {
207 adt_def.destructor(tcx).map_or(adt_def.is_enum(), |dtor| {
208 tcx.codegen_fn_attrs(dtor.did).requests_inline()
212 tcx.codegen_fn_attrs(self.def_id()).requests_inline()
215 pub fn requires_caller_location(&self, tcx: TyCtxt<'_>) -> bool {
217 InstanceDef::Item(def_id) => {
218 tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER)
225 impl<'tcx> fmt::Display for Instance<'tcx> {
226 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
227 ty::tls::with(|tcx| {
228 let substs = tcx.lift(&self.substs).expect("could not lift for printing");
229 FmtPrinter::new(tcx, &mut *f, Namespace::ValueNS)
230 .print_def_path(self.def_id(), substs)?;
235 InstanceDef::Item(_) => Ok(()),
236 InstanceDef::VtableShim(_) => write!(f, " - shim(vtable)"),
237 InstanceDef::ReifyShim(_) => write!(f, " - shim(reify)"),
238 InstanceDef::Intrinsic(_) => write!(f, " - intrinsic"),
239 InstanceDef::Virtual(_, num) => write!(f, " - virtual#{}", num),
240 InstanceDef::FnPtrShim(_, ty) => write!(f, " - shim({:?})", ty),
241 InstanceDef::ClosureOnceShim { .. } => write!(f, " - shim"),
242 InstanceDef::DropGlue(_, ty) => write!(f, " - shim({:?})", ty),
243 InstanceDef::CloneShim(_, ty) => write!(f, " - shim({:?})", ty),
248 impl<'tcx> Instance<'tcx> {
249 pub fn new(def_id: DefId, substs: SubstsRef<'tcx>) -> Instance<'tcx> {
251 !substs.has_escaping_bound_vars(),
252 "substs of instance {:?} not normalized for codegen: {:?}",
256 Instance { def: InstanceDef::Item(def_id), substs }
259 pub fn mono(tcx: TyCtxt<'tcx>, def_id: DefId) -> Instance<'tcx> {
260 Instance::new(def_id, tcx.empty_substs_for_def_id(def_id))
264 pub fn def_id(&self) -> DefId {
268 /// Resolves a `(def_id, substs)` pair to an (optional) instance -- most commonly,
269 /// this is used to find the precise code that will run for a trait method invocation,
272 /// Returns `None` if we cannot resolve `Instance` to a specific instance.
273 /// For example, in a context like this,
276 /// fn foo<T: Debug>(t: T) { ... }
279 /// trying to resolve `Debug::fmt` applied to `T` will yield `None`, because we do not
280 /// know what code ought to run. (Note that this setting is also affected by the
281 /// `RevealMode` in the parameter environment.)
283 /// Presuming that coherence and type-check have succeeded, if this method is invoked
284 /// in a monomorphic context (i.e., like during codegen), then it is guaranteed to return
288 param_env: ty::ParamEnv<'tcx>,
290 substs: SubstsRef<'tcx>,
291 ) -> Option<Instance<'tcx>> {
292 (*RESOLVE_INSTANCE)(tcx, param_env, def_id, substs)
295 pub fn resolve_for_fn_ptr(
297 param_env: ty::ParamEnv<'tcx>,
299 substs: SubstsRef<'tcx>,
300 ) -> Option<Instance<'tcx>> {
301 debug!("resolve(def_id={:?}, substs={:?})", def_id, substs);
302 Instance::resolve(tcx, param_env, def_id, substs).map(|mut resolved| {
304 InstanceDef::Item(def_id) if resolved.def.requires_caller_location(tcx) => {
305 debug!(" => fn pointer created for function with #[track_caller]");
306 resolved.def = InstanceDef::ReifyShim(def_id);
308 InstanceDef::Virtual(def_id, _) => {
309 debug!(" => fn pointer created for virtual call");
310 resolved.def = InstanceDef::ReifyShim(def_id);
319 pub fn resolve_for_vtable(
321 param_env: ty::ParamEnv<'tcx>,
323 substs: SubstsRef<'tcx>,
324 ) -> Option<Instance<'tcx>> {
325 debug!("resolve(def_id={:?}, substs={:?})", def_id, substs);
326 let fn_sig = tcx.fn_sig(def_id);
327 let is_vtable_shim = !fn_sig.inputs().skip_binder().is_empty()
328 && fn_sig.input(0).skip_binder().is_param(0)
329 && tcx.generics_of(def_id).has_self;
331 debug!(" => associated item with unsizeable self: Self");
332 Some(Instance { def: InstanceDef::VtableShim(def_id), substs })
334 Instance::resolve(tcx, param_env, def_id, substs)
338 pub fn resolve_closure(
341 substs: ty::SubstsRef<'tcx>,
342 requested_kind: ty::ClosureKind,
343 ) -> Instance<'tcx> {
344 let actual_kind = substs.as_closure().kind(def_id, tcx);
346 match needs_fn_once_adapter_shim(actual_kind, requested_kind) {
347 Ok(true) => Instance::fn_once_adapter_instance(tcx, def_id, substs),
348 _ => Instance::new(def_id, substs),
352 pub fn resolve_drop_in_place(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ty::Instance<'tcx> {
353 let def_id = tcx.require_lang_item(DropInPlaceFnLangItem, None);
354 let substs = tcx.intern_substs(&[ty.into()]);
355 Instance::resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap()
358 pub fn fn_once_adapter_instance(
361 substs: ty::SubstsRef<'tcx>,
362 ) -> Instance<'tcx> {
363 debug!("fn_once_adapter_shim({:?}, {:?})", closure_did, substs);
364 let fn_once = tcx.lang_items().fn_once_trait().unwrap();
366 .associated_items(fn_once)
367 .in_definition_order()
368 .find(|it| it.kind == ty::AssocKind::Method)
371 let def = ty::InstanceDef::ClosureOnceShim { call_once };
373 let self_ty = tcx.mk_closure(closure_did, substs);
375 let sig = substs.as_closure().sig(closure_did, tcx);
376 let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
377 assert_eq!(sig.inputs().len(), 1);
378 let substs = tcx.mk_substs_trait(self_ty, &[sig.inputs()[0].into()]);
380 debug!("fn_once_adapter_shim: self_ty={:?} sig={:?}", self_ty, sig);
381 Instance { def, substs }
384 /// FIXME(#69925) Depending on the kind of `InstanceDef`, the MIR body associated with an
385 /// instance is expressed in terms of the generic parameters of `self.def_id()`, and in other
386 /// cases the MIR body is expressed in terms of the types found in the substitution array.
387 /// In the former case, we want to substitute those generic types and replace them with the
388 /// values from the substs when monomorphizing the function body. But in the latter case, we
389 /// don't want to do that substitution, since it has already been done effectively.
391 /// This function returns `Some(substs)` in the former case and None otherwise -- i.e., if
392 /// this function returns `None`, then the MIR body does not require substitution during
393 /// monomorphization.
394 pub fn substs_for_mir_body(&self) -> Option<SubstsRef<'tcx>> {
396 InstanceDef::CloneShim(..)
397 | InstanceDef::DropGlue(_, Some(_)) => None,
398 InstanceDef::ClosureOnceShim { .. }
399 | InstanceDef::DropGlue(..)
400 // FIXME(#69925): `FnPtrShim` should be in the other branch.
401 | InstanceDef::FnPtrShim(..)
402 | InstanceDef::Item(_)
403 | InstanceDef::Intrinsic(..)
404 | InstanceDef::ReifyShim(..)
405 | InstanceDef::Virtual(..)
406 | InstanceDef::VtableShim(..) => Some(self.substs),
410 pub fn is_vtable_shim(&self) -> bool {
411 if let InstanceDef::VtableShim(..) = self.def { true } else { false }
415 fn needs_fn_once_adapter_shim(
416 actual_closure_kind: ty::ClosureKind,
417 trait_closure_kind: ty::ClosureKind,
418 ) -> Result<bool, ()> {
419 match (actual_closure_kind, trait_closure_kind) {
420 (ty::ClosureKind::Fn, ty::ClosureKind::Fn)
421 | (ty::ClosureKind::FnMut, ty::ClosureKind::FnMut)
422 | (ty::ClosureKind::FnOnce, ty::ClosureKind::FnOnce) => {
423 // No adapter needed.
426 (ty::ClosureKind::Fn, ty::ClosureKind::FnMut) => {
427 // The closure fn `llfn` is a `fn(&self, ...)`. We want a
428 // `fn(&mut self, ...)`. In fact, at codegen time, these are
429 // basically the same thing, so we can just return llfn.
432 (ty::ClosureKind::Fn, ty::ClosureKind::FnOnce)
433 | (ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
434 // The closure fn `llfn` is a `fn(&self, ...)` or `fn(&mut
435 // self, ...)`. We want a `fn(self, ...)`. We can produce
436 // this by doing something like:
438 // fn call_once(self, ...) { call_mut(&self, ...) }
439 // fn call_once(mut self, ...) { call_mut(&mut self, ...) }
441 // These are both the same at codegen time.
444 (ty::ClosureKind::FnMut, _) | (ty::ClosureKind::FnOnce, _) => Err(()),
448 fn resolve_instance_default(
450 _param_env: ty::ParamEnv<'tcx>,
452 _substs: SubstsRef<'tcx>,
453 ) -> Option<Instance<'tcx>> {
457 pub static RESOLVE_INSTANCE: AtomicRef<
463 ) -> Option<Instance<'tcx>>,
464 > = AtomicRef::new(&(resolve_instance_default as _));