]> git.lizzy.rs Git - rust.git/blob - src/librustc/ty/instance.rs
Rollup merge of #70038 - DutchGhost:const-forget-tests, r=RalfJung
[rust.git] / src / librustc / ty / instance.rs
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;
9
10 use std::fmt;
11
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>,
17 }
18
19 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable, HashStable)]
20 pub enum InstanceDef<'tcx> {
21     Item(DefId),
22     Intrinsic(DefId),
23
24     /// `<T as Trait>::method` where `method` receives unsizeable `self: Self`.
25     VtableShim(DefId),
26
27     /// `fn()` pointer where the function itself cannot be turned into a pointer.
28     ///
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`).
32     ///
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).
38     ReifyShim(DefId),
39
40     /// `<fn() as FnTrait>::call_*`
41     /// `DefId` is `FnTrait::call_*`.
42     ///
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>),
47
48     /// `<dyn Trait as Trait>::fn`, "direct calls" of which are implicitly
49     /// codegen'd as virtual calls.
50     ///
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),
54
55     /// `<[mut closure] as FnOnce>::call_once`
56     ClosureOnceShim {
57         call_once: DefId,
58     },
59
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
63     /// glue.
64     ///
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>>),
69
70     ///`<T as Clone>::clone` shim.
71     ///
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>),
76 }
77
78 impl<'tcx> Instance<'tcx> {
79     /// Returns the `Ty` corresponding to this `Instance`,
80     /// with generic substitutions applied and lifetimes erased.
81     ///
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
94         // ParamEnv
95         if self.substs.has_param_types() {
96             bug!("Instance.ty called for type {:?} with params in substs: {:?}", ty, self.substs);
97         }
98         tcx.subst_and_normalize_erasing_regions(self.substs, ty::ParamEnv::reveal_all(), &ty)
99     }
100
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)
107     }
108
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.
112     ///
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
118         // instead.
119         if !tcx.sess.opts.share_generics() {
120             return None;
121         }
122
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() {
126             return None;
127         }
128
129         // If this a non-generic instance, it cannot be a shared monomorphization.
130         self.substs.non_erasable_generics().next()?;
131
132         match self.def {
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),
137             _ => None,
138         }
139     }
140 }
141
142 impl<'tcx> InstanceDef<'tcx> {
143     #[inline]
144     pub fn def_id(&self) -> DefId {
145         match *self {
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,
155         }
156     }
157
158     #[inline]
159     pub fn attrs(&self, tcx: TyCtxt<'tcx>) -> ty::Attributes<'tcx> {
160         tcx.get_attrs(self.def_id())
161     }
162
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,
173             _ => return true,
174         };
175         match tcx.def_key(def_id).disambiguated_data.data {
176             DefPathData::Ctor | DefPathData::ClosureExpr => true,
177             _ => false,
178         }
179     }
180
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) {
190             return true;
191         }
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() {
197                 return true;
198             }
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.
202             //
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()
209                 })
210             });
211         }
212         tcx.codegen_fn_attrs(self.def_id()).requests_inline()
213     }
214
215     pub fn requires_caller_location(&self, tcx: TyCtxt<'_>) -> bool {
216         match *self {
217             InstanceDef::Item(def_id) => {
218                 tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER)
219             }
220             _ => false,
221         }
222     }
223 }
224
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)?;
231             Ok(())
232         })?;
233
234         match self.def {
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),
244         }
245     }
246 }
247
248 impl<'tcx> Instance<'tcx> {
249     pub fn new(def_id: DefId, substs: SubstsRef<'tcx>) -> Instance<'tcx> {
250         assert!(
251             !substs.has_escaping_bound_vars(),
252             "substs of instance {:?} not normalized for codegen: {:?}",
253             def_id,
254             substs
255         );
256         Instance { def: InstanceDef::Item(def_id), substs }
257     }
258
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))
261     }
262
263     #[inline]
264     pub fn def_id(&self) -> DefId {
265         self.def.def_id()
266     }
267
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,
270     /// if known.
271     ///
272     /// Returns `None` if we cannot resolve `Instance` to a specific instance.
273     /// For example, in a context like this,
274     ///
275     /// ```
276     /// fn foo<T: Debug>(t: T) { ... }
277     /// ```
278     ///
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.)
282     ///
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
285     /// `Some`.
286     pub fn resolve(
287         tcx: TyCtxt<'tcx>,
288         param_env: ty::ParamEnv<'tcx>,
289         def_id: DefId,
290         substs: SubstsRef<'tcx>,
291     ) -> Option<Instance<'tcx>> {
292         (*RESOLVE_INSTANCE)(tcx, param_env, def_id, substs)
293     }
294
295     pub fn resolve_for_fn_ptr(
296         tcx: TyCtxt<'tcx>,
297         param_env: ty::ParamEnv<'tcx>,
298         def_id: DefId,
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| {
303             match resolved.def {
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);
307                 }
308                 InstanceDef::Virtual(def_id, _) => {
309                     debug!(" => fn pointer created for virtual call");
310                     resolved.def = InstanceDef::ReifyShim(def_id);
311                 }
312                 _ => {}
313             }
314
315             resolved
316         })
317     }
318
319     pub fn resolve_for_vtable(
320         tcx: TyCtxt<'tcx>,
321         param_env: ty::ParamEnv<'tcx>,
322         def_id: DefId,
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;
330         if is_vtable_shim {
331             debug!(" => associated item with unsizeable self: Self");
332             Some(Instance { def: InstanceDef::VtableShim(def_id), substs })
333         } else {
334             Instance::resolve(tcx, param_env, def_id, substs)
335         }
336     }
337
338     pub fn resolve_closure(
339         tcx: TyCtxt<'tcx>,
340         def_id: DefId,
341         substs: ty::SubstsRef<'tcx>,
342         requested_kind: ty::ClosureKind,
343     ) -> Instance<'tcx> {
344         let actual_kind = substs.as_closure().kind(def_id, tcx);
345
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),
349         }
350     }
351
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()
356     }
357
358     pub fn fn_once_adapter_instance(
359         tcx: TyCtxt<'tcx>,
360         closure_did: DefId,
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();
365         let call_once = tcx
366             .associated_items(fn_once)
367             .in_definition_order()
368             .find(|it| it.kind == ty::AssocKind::Method)
369             .unwrap()
370             .def_id;
371         let def = ty::InstanceDef::ClosureOnceShim { call_once };
372
373         let self_ty = tcx.mk_closure(closure_did, substs);
374
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()]);
379
380         debug!("fn_once_adapter_shim: self_ty={:?} sig={:?}", self_ty, sig);
381         Instance { def, substs }
382     }
383
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.
390     ///
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>> {
395         match self.def {
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),
407         }
408     }
409
410     pub fn is_vtable_shim(&self) -> bool {
411         if let InstanceDef::VtableShim(..) = self.def { true } else { false }
412     }
413 }
414
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.
424             Ok(false)
425         }
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.
430             Ok(false)
431         }
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:
437             //
438             //     fn call_once(self, ...) { call_mut(&self, ...) }
439             //     fn call_once(mut self, ...) { call_mut(&mut self, ...) }
440             //
441             // These are both the same at codegen time.
442             Ok(true)
443         }
444         (ty::ClosureKind::FnMut, _) | (ty::ClosureKind::FnOnce, _) => Err(()),
445     }
446 }
447
448 fn resolve_instance_default(
449     _tcx: TyCtxt<'tcx>,
450     _param_env: ty::ParamEnv<'tcx>,
451     _def_id: DefId,
452     _substs: SubstsRef<'tcx>,
453 ) -> Option<Instance<'tcx>> {
454     unimplemented!()
455 }
456
457 pub static RESOLVE_INSTANCE: AtomicRef<
458     for<'tcx> fn(
459         TyCtxt<'tcx>,
460         ty::ParamEnv<'tcx>,
461         DefId,
462         SubstsRef<'tcx>,
463     ) -> Option<Instance<'tcx>>,
464 > = AtomicRef::new(&(resolve_instance_default as _));