1
Fork 0

Support #[track_caller] on closures and generators

This PR allows applying a `#[track_caller]` attribute to a
closure/generator expression. The attribute as interpreted as applying
to the compiler-generated implementation of the corresponding trait
method (`FnOnce::call_once`, `FnMut::call_mut`, `Fn::call`, or
`Generator::resume`).

This feature does not have its own feature gate - however, it requires
`#![feature(stmt_expr_attributes)]` in order to actually apply
an attribute to a closure or generator.

This is implemented in the same way as for functions - an extra
location argument is appended to the end of the ABI. For closures,
this argument is *not* part of the 'tupled' argument storing the
parameters - the final closure argument for `#[track_caller]` closures
is no longer a tuple.

For direct (monomorphized) calls, the necessary support was already
implemented - we just needeed to adjust some assertions around checking
the ABI and argument count to take closures into account.

For calls through a trait object, more work was needed.
When creating a `ReifyShim`, we need to create a shim
for the trait method (e.g. `FnOnce::call_mut`) - unlike normal
functions, closures are never invoked directly, and always go through a
trait method.

Additional handling was needed for `InstanceDef::ClosureOnceShim`. In
order to pass location information throgh a direct (monomorphized) call
to `FnOnce::call_once` on an `FnMut` closure, we need to make
`ClosureOnceShim` aware of `#[tracked_caller]`. A new field
`track_caller` is added to `ClosureOnceShim` - this is used by
`InstanceDef::requires_caller` location, allowing codegen to
pass through the extra location argument.

Since `ClosureOnceShim.track_caller` is only used by codegen,
we end up generating two identical MIR shims - one for
`track_caller == true`, and one for `track_caller == false`. However,
these two shims are used by the entire crate (i.e. it's two shims total,
not two shims per unique closure), so this shouldn't a big deal.
This commit is contained in:
Aaron Hill 2021-06-27 14:01:11 -05:00
parent cfff31bc83
commit 94b19fac26
No known key found for this signature in database
GPG key ID: B4087E510E98B164
13 changed files with 267 additions and 23 deletions

View file

@ -638,8 +638,8 @@ impl<'a, 'tcx> Lift<'tcx> for ty::InstanceDef<'a> {
Some(ty::InstanceDef::FnPtrShim(def_id, tcx.lift(ty)?))
}
ty::InstanceDef::Virtual(def_id, n) => Some(ty::InstanceDef::Virtual(def_id, n)),
ty::InstanceDef::ClosureOnceShim { call_once } => {
Some(ty::InstanceDef::ClosureOnceShim { call_once })
ty::InstanceDef::ClosureOnceShim { call_once, track_caller } => {
Some(ty::InstanceDef::ClosureOnceShim { call_once, track_caller })
}
ty::InstanceDef::DropGlue(def_id, ty) => {
Some(ty::InstanceDef::DropGlue(def_id, tcx.lift(ty)?))
@ -824,8 +824,8 @@ impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> {
Intrinsic(did) => Intrinsic(did.fold_with(folder)),
FnPtrShim(did, ty) => FnPtrShim(did.fold_with(folder), ty.fold_with(folder)),
Virtual(did, i) => Virtual(did.fold_with(folder), i),
ClosureOnceShim { call_once } => {
ClosureOnceShim { call_once: call_once.fold_with(folder) }
ClosureOnceShim { call_once, track_caller } => {
ClosureOnceShim { call_once: call_once.fold_with(folder), track_caller }
}
DropGlue(did, ty) => DropGlue(did.fold_with(folder), ty.fold_with(folder)),
CloneShim(did, ty) => CloneShim(did.fold_with(folder), ty.fold_with(folder)),
@ -849,7 +849,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> {
did.visit_with(visitor)?;
ty.visit_with(visitor)
}
ClosureOnceShim { call_once } => call_once.visit_with(visitor),
ClosureOnceShim { call_once, track_caller: _ } => call_once.visit_with(visitor),
}
}
}