|
| 1 | +use crate::hir::CodegenFnAttrFlags; |
1 | 2 | use crate::hir::Unsafety;
|
2 | 3 | use crate::hir::def::Namespace;
|
3 | 4 | use crate::hir::def_id::DefId;
|
@@ -25,6 +26,14 @@ pub enum InstanceDef<'tcx> {
|
25 | 26 | /// `<T as Trait>::method` where `method` receives unsizeable `self: Self`.
|
26 | 27 | VtableShim(DefId),
|
27 | 28 |
|
| 29 | + /// `fn()` pointer where the function itself cannot be turned into a pointer. |
| 30 | + /// |
| 31 | + /// One example in the compiler today is functions annotated with `#[track_caller]`, which |
| 32 | + /// must have their implicit caller location argument populated for a call. Because this is a |
| 33 | + /// required part of the function's ABI but can't be tracked as a property of the function |
| 34 | + /// pointer, we create a single "caller location" at the site where the function is reified. |
| 35 | + ReifyShim(DefId), |
| 36 | + |
28 | 37 | /// `<fn() as FnTrait>::call_*`
|
29 | 38 | /// `DefId` is `FnTrait::call_*`
|
30 | 39 | FnPtrShim(DefId, Ty<'tcx>),
|
@@ -123,6 +132,7 @@ impl<'tcx> InstanceDef<'tcx> {
|
123 | 132 | match *self {
|
124 | 133 | InstanceDef::Item(def_id) |
|
125 | 134 | InstanceDef::VtableShim(def_id) |
|
| 135 | + InstanceDef::ReifyShim(def_id) | |
126 | 136 | InstanceDef::FnPtrShim(def_id, _) |
|
127 | 137 | InstanceDef::Virtual(def_id, _) |
|
128 | 138 | InstanceDef::Intrinsic(def_id, ) |
|
@@ -178,6 +188,9 @@ impl<'tcx> fmt::Display for Instance<'tcx> {
|
178 | 188 | InstanceDef::VtableShim(_) => {
|
179 | 189 | write!(f, " - shim(vtable)")
|
180 | 190 | }
|
| 191 | + InstanceDef::ReifyShim(_) => { |
| 192 | + write!(f, " - shim(reify)") |
| 193 | + } |
181 | 194 | InstanceDef::Intrinsic(_) => {
|
182 | 195 | write!(f, " - intrinsic")
|
183 | 196 | }
|
@@ -290,6 +303,30 @@ impl<'tcx> Instance<'tcx> {
|
290 | 303 | result
|
291 | 304 | }
|
292 | 305 |
|
| 306 | + pub fn resolve_for_fn_ptr( |
| 307 | + tcx: TyCtxt<'tcx>, |
| 308 | + param_env: ty::ParamEnv<'tcx>, |
| 309 | + def_id: DefId, |
| 310 | + substs: SubstsRef<'tcx>, |
| 311 | + ) -> Option<Instance<'tcx>> { |
| 312 | + debug!("resolve(def_id={:?}, substs={:?})", def_id, substs); |
| 313 | + Instance::resolve(tcx, param_env, def_id, substs).map(|resolved| { |
| 314 | + let has_track_caller = |def| tcx.codegen_fn_attrs(def).flags |
| 315 | + .contains(CodegenFnAttrFlags::TRACK_CALLER); |
| 316 | + |
| 317 | + match resolved.def { |
| 318 | + InstanceDef::Item(def_id) if has_track_caller(def_id) => { |
| 319 | + debug!(" => fn pointer created for function with #[track_caller]"); |
| 320 | + Instance { |
| 321 | + def: InstanceDef::ReifyShim(def_id), |
| 322 | + substs, |
| 323 | + } |
| 324 | + }, |
| 325 | + _ => resolved, |
| 326 | + } |
| 327 | + }) |
| 328 | + } |
| 329 | + |
293 | 330 | pub fn resolve_for_vtable(
|
294 | 331 | tcx: TyCtxt<'tcx>,
|
295 | 332 | param_env: ty::ParamEnv<'tcx>,
|
|
0 commit comments