11# Implicit Caller Location
22
3+ <!-- toc -->
4+
35Approved in [ RFC 2091] , this feature enables the accurate reporting of caller location during panics
4- initiated from functions like ` Option::unwrap ` , ` Result::expect ` , and ` Index::index ` . This feature
5- adds the [ ` #[track_caller] ` ] [ attr-reference ] attribute for functions, the
6- [ ` caller_location ` ] [ intrinsic ] intrinsic, and the stabilization-friendly
6+ initiated from functions like ` Option::unwrap ` , ` Result::expect ` , and ` Index::index ` . This feature
7+ adds the [ ` #[track_caller] ` ] [ attr-reference ] attribute for functions, the
8+ [ ` caller_location ` ] [ intrinsic ] intrinsic, and the stabilization-friendly
79[ ` core::panic::Location::caller ` ] [ wrapper ] wrapper.
810
911## Motivating Example
@@ -28,25 +30,25 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
2830As of 1.42, we get a much more helpful message:
2931
3032```
31- $ rustc +1.42.0 example.rs; example.exe
33+ $ rustc +1.42.0 example.rs; example.exe
3234thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', example.rs:3:5
3335note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
3436```
3537
3638These error messages are achieved through a combination of changes to ` panic! ` internals to make use
37- of ` core::panic::Location::caller ` and a number of ` #[track_caller] ` annotations in the standard
39+ of ` core::panic::Location::caller ` and a number of ` #[track_caller] ` annotations in the standard
3840library which propagate caller information.
3941
4042## Reading Caller Location
4143
4244Previously, ` panic! ` made use of the ` file!() ` , ` line!() ` , and ` column!() ` macros to construct a
4345[ ` Location ` ] pointing to where the panic occurred. These macros couldn't be given an overridden
44- location, so functions which intentionally invoked ` panic! ` couldn't provide their own location,
46+ location, so functions which intentionally invoked ` panic! ` couldn't provide their own location,
4547hiding the actual source of error.
4648
47- Internally, ` panic!() ` now calls [ ` core::panic::Location::caller() ` ] [ wrapper ] to find out where it
48- was expanded. This function is itself annotated with ` #[track_caller] ` and wraps the
49- [ ` caller_location ` ] [ intrinsic ] compiler intrinsic implemented by rustc. This intrinsic is easiest
49+ Internally, ` panic!() ` now calls [ ` core::panic::Location::caller() ` ] [ wrapper ] to find out where it
50+ was expanded. This function is itself annotated with ` #[track_caller] ` and wraps the
51+ [ ` caller_location ` ] [ intrinsic ] compiler intrinsic implemented by rustc. This intrinsic is easiest
5052explained in terms of how it works in a ` const ` context.
5153
5254## Caller Location in ` const `
@@ -56,20 +58,20 @@ to find the right location and allocating a const value to return.
5658
5759### Finding the right ` Location `
5860
59- In a const context we "walk up the stack" from where the intrinsic is invoked, stopping when we
61+ In a const context we "walk up the stack" from where the intrinsic is invoked, stopping when we
6062reach the first function call in the stack which does * not* have the attribute. This walk is in
6163[ ` InterpCx::find_closest_untracked_caller_location() ` ] [ const-find-closest ] .
6264
63- Starting at the bottom, we iterate up over stack [ ` Frame ` ] [ const-frame ] s in the
65+ Starting at the bottom, we iterate up over stack [ ` Frame ` ] [ const-frame ] s in the
6466[ ` InterpCx::stack ` ] [ const-stack ] , calling
65- [ ` InstanceDef::requires_caller_location ` ] [ requires-location ] on the
67+ [ ` InstanceDef::requires_caller_location ` ] [ requires-location ] on the
6668[ ` Instance ` s from each ` Frame ` ] [ frame-instance ] . We stop once we find one that returns ` false ` and
6769return the span of the * previous* frame which was the "topmost" tracked function.
6870
6971### Allocating a static ` Location `
7072
71- Once we have a ` Span ` , we need to allocate static memory for the ` Location ` , which is performed by
72- the [ ` TyCtxt::const_caller_location() ` ] [ const-location-query ] query. Internally this calls
73+ Once we have a ` Span ` , we need to allocate static memory for the ` Location ` , which is performed by
74+ the [ ` TyCtxt::const_caller_location() ` ] [ const-location-query ] query. Internally this calls
7375[ ` InterpCx::alloc_caller_location() ` ] [ alloc-location ] and results in a unique
7476[ memory kind] [ location-memory-kind ] (` MemoryKind::CallerLocation ` ). The SSA codegen backend is able
7577to emit code for these same values, and we use this code there as well.
@@ -78,14 +80,14 @@ Once our `Location` has been allocated in static memory, our intrinsic returns a
7880
7981## Generating code for ` #[track_caller] ` callees
8082
81- To generate efficient code for a tracked function and its callers, we need to provide the same
83+ To generate efficient code for a tracked function and its callers, we need to provide the same
8284behavior from the intrinsic's point of view without having a stack to walk up at runtime. We invert
8385the approach: as we grow the stack down we pass an additional argument to calls of tracked functions
8486rather than walking up the stack when the intrinsic is called. That additional argument can be
8587returned wherever the caller location is queried.
8688
8789The argument we append is of type ` &'static core::panic::Location<'static> ` . A reference was chosen
88- to avoid unnecessary copying because a pointer is a third the size of
90+ to avoid unnecessary copying because a pointer is a third the size of
8991` std::mem::size_of::<core::panic::Location>() == 24 ` at time of writing.
9092
9193When generating a call to a function which is tracked, we pass the location argument the value of
@@ -151,12 +153,12 @@ probably the best we can do without modifying fully-stabilized type signatures.
151153
152154> * Note:* We always emit a [ ` ReifyShim ` ] when taking a pointer to a tracked function. While the
153155> constraint here is imposed by codegen contexts, we don't know during MIR construction of the shim
154- > whether we'll be called in a const context (safe to ignore shim) or in a codegen context (unsafe
156+ > whether we'll be called in a const context (safe to ignore shim) or in a codegen context (unsafe
155157> to ignore shim). Even if we did know, the results from const and codegen contexts must agree.
156158
157159## The Attribute
158160
159- The ` #[track_caller] ` attribute is checked alongside other codegen attributes to ensure the
161+ The ` #[track_caller] ` attribute is checked alongside other codegen attributes to ensure the
160162function:
161163
162164* has the ` "Rust" ` ABI (as opposed to e.g., ` "C" ` )
@@ -171,7 +173,7 @@ used in both const and codegen contexts to ensure correct propagation.
171173
172174When applied to trait method implementations, the attribute works as it does for regular functions.
173175
174- When applied to a trait method prototype, the attribute applies to all implementations of the
176+ When applied to a trait method prototype, the attribute applies to all implementations of the
175177method. When applied to a default trait method implementation, the attribute takes effect on
176178that implementation * and* any overrides.
177179
@@ -203,14 +205,14 @@ trait TrackedFourWays {
203205 assert_tracked! ();
204206 }
205207
206- /// Overrides of this implementation are tracked (it is too).
208+ /// Overrides of this implementation are tracked (it is too).
207209 #[track_caller]
208210 fn default_tracked_to_override () {
209211 assert_tracked! ();
210212 }
211213}
212214
213- /// This impl uses the default impl for `default_tracked` and provides its own for
215+ /// This impl uses the default impl for `default_tracked` and provides its own for
214216/// `default_tracked_to_override`.
215217impl TrackedFourWays for () {
216218 fn blanket_tracked () {
@@ -253,7 +255,7 @@ up on the tracking issue. During the course of implementing that, it was also di
253255implementation was possible without modifying the number of arguments in a function's MIR, which
254256would simplify later stages and unlock use in traits.
255257
256- Because the RFC's implementation strategy could not readily support traits, the semantics were not
258+ Because the RFC's implementation strategy could not readily support traits, the semantics were not
257259originally specified. They have since been implemented following the path which seemed most correct
258260to the author and reviewers.
259261
0 commit comments