]> git.lizzy.rs Git - rust.git/commit
Support `#[track_caller]` on closures and generators
authorAaron Hill <aa1ronham@gmail.com>
Sun, 27 Jun 2021 19:01:11 +0000 (14:01 -0500)
committerAaron Hill <aa1ronham@gmail.com>
Wed, 22 Sep 2021 20:19:33 +0000 (15:19 -0500)
commit94b19fac263021dc85133138079d684da547a1e0
tree52af0729fc1f779a329f8c542d633eff09d377bd
parentcfff31bc833070a00578bd6178160aeed56f28ba
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.
13 files changed:
compiler/rustc_codegen_ssa/src/mir/block.rs
compiler/rustc_codegen_ssa/src/mir/mod.rs
compiler/rustc_feature/src/active.rs
compiler/rustc_middle/src/mir/visit.rs
compiler/rustc_middle/src/ty/instance.rs
compiler/rustc_middle/src/ty/structural_impls.rs
compiler/rustc_mir_transform/src/shim.rs
compiler/rustc_span/src/symbol.rs
compiler/rustc_typeck/src/collect.rs
src/doc/unstable-book/src/language-features/closure-track-caller.md [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-closure_track_caller.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-closure_track_caller.stderr [new file with mode: 0644]
src/test/ui/rfc-2091-track-caller/tracked-closure.rs [new file with mode: 0644]