Skip to content

Commit b7cb84b

Browse files
committed
Document #[track_caller].
1 parent 0ea7bc4 commit b7cb84b

File tree

2 files changed

+96
-0
lines changed

2 files changed

+96
-0
lines changed

src/attributes.md

+2
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ The following is an index of all built-in attributes.
221221
- [`cold`] — Hint that a function is unlikely to be called.
222222
- [`no_builtins`] — Disables use of certain built-in functions.
223223
- [`target_feature`] — Configure platform-specific code generation.
224+
- [`track_caller`] - Pass the parent call location to `std::panic::Location::caller()`.
224225
- Documentation
225226
- `doc` — Specifies documentation. See [The Rustdoc Book] for more
226227
information. [Doc comments] are transformed into `doc` attributes.
@@ -294,6 +295,7 @@ The following is an index of all built-in attributes.
294295
[`should_panic`]: attributes/testing.md#the-should_panic-attribute
295296
[`target_feature`]: attributes/codegen.md#the-target_feature-attribute
296297
[`test`]: attributes/testing.md#the-test-attribute
298+
[`track_caller`]: attributes/codegen.md#the-track_caller-attribute
297299
[`type_length_limit`]: attributes/limits.md#the-type_length_limit-attribute
298300
[`used`]: abi.md#the-used-attribute
299301
[`warn`]: attributes/diagnostics.md#lint-check-attributes

src/attributes/codegen.md

+94
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,96 @@ feature detection on the x86 platforms.
143143
> may be enabled or disabled for an entire crate with the
144144
> [`-C target-feature`] flag.
145145
146+
## The `track_caller` attribute
147+
148+
The `track_caller` attribute may be applied to any function with [`"Rust"` ABI][rust-abi]. When
149+
applied to functions and methods in trait declarations, the attribute applies to all
150+
implementations. If the trait provides a default implementation with the attribute, then the
151+
attribute also applies to override implementations.
152+
153+
When applied to a function in an `extern` block the attribute must also be applied to any linked
154+
implementations, otherwise undefined behavior results. When applied to a function which is made
155+
available to an `extern` block, the declaration in the `extern` block must also have the attribute,
156+
otherwise undefined behavior results.
157+
158+
### Behavior
159+
160+
Applying the attribute to a function `f` allows code within `f` to get a hint of the [`Location`] of
161+
the "topmost" tracked call that led to `f`'s invocation. At the point of observation, an
162+
implementation behaves as if it walks up the stack from `f`'s frame to find the nearest frame of an
163+
*unattributed* function `outer`, and it returns the [`Location`] of the tracked call in `outer`.
164+
165+
```rust
166+
#[track_caller]
167+
fn f() {
168+
println!("{}", std::panic::Location::caller());
169+
}
170+
```
171+
172+
> Note: `core` provides [`core::panic::Location::caller`] for observing caller locations. It wraps
173+
> the [`core::intrinsics::caller_location`] intrinsic implemented by `rustc`.
174+
175+
> Note: because the resulting `Location` is a hint, an implementation may halt its walk up the stack
176+
> early. See [Limitations](#limitations) for important caveats.
177+
178+
#### Examples
179+
180+
When `f` is called directly by `calls_f`, code in `f` observes its callsite within `calls_f`:
181+
182+
```rust
183+
fn calls_f() {
184+
f(); // <-- f() prints this location
185+
}
186+
```
187+
188+
When `f` is called by another attributed function `g` which is in turn called by `calls_g`, code in
189+
both `f` and `g` observes `g`'s callsite within `calls_g`:
190+
191+
```rust
192+
#[track_caller]
193+
fn g() {
194+
println!("{}", std::panic::Location::caller());
195+
f();
196+
}
197+
198+
fn calls_g() {
199+
g(); // <-- g() prints this location twice, once itself and once from f()
200+
}
201+
```
202+
203+
When `g` is called by another attributed function `h` which is in turn called by `calls_h`, all code
204+
in `f`, `g`, and `h` observes `h`'s callsite within `calls_h`:
205+
206+
```rust
207+
#[track_caller]
208+
fn h() {
209+
println!("{}", std::panic::Location::caller());
210+
g();
211+
}
212+
213+
fn calls_h() {
214+
h(); // <-- prints this location three times, once itself, once from g(), once from f()
215+
}
216+
```
217+
218+
And so on.
219+
220+
### Limitations
221+
222+
This information is a hint and implementations are not required to preserve it.
223+
224+
In particular, coercing a function with `#[track_caller]` to a function pointer creates a shim which
225+
appears to observers to have been called at the attributed function's definition site, losing actual
226+
caller information across virtual calls. A common example of this coercion is the creation of a
227+
trait object whose methods are attributed.
228+
229+
> Note: The aforementioned shim for function pointers is necessary because `rustc` implements
230+
> `track_caller` in a codegen context by appending an implicit parameter to the function ABI, but
231+
> this would be unsound for an indirect call because the parameter is not a part of the function's
232+
> type and a given function pointer type may or may not refer to a function with the attribute. The
233+
> creation of a shim hides the implicit parameter from callers of the function pointer, preserving
234+
> soundness.
235+
146236
[_MetaListNameValueStr_]: ../attributes.md#meta-item-attribute-syntax
147237
[`-C target-cpu`]: ../../rustc/codegen-options/index.html#target-cpu
148238
[`-C target-feature`]: ../../rustc/codegen-options/index.html#target-feature
@@ -155,3 +245,7 @@ feature detection on the x86 platforms.
155245
[trait]: ../items/traits.md
156246
[undefined behavior]: ../behavior-considered-undefined.md
157247
[unsafe function]: ../unsafe-functions.md
248+
[rust-abi]: ../items/external-blocks.md#abi
249+
[`core::intrinsics::caller_location`]: ../../core/intrinsics/fn.caller_location.html
250+
[`core::panic::Location::caller`]: ../../core/panic/struct.Location.html#method.caller
251+
[`Location`]: ../../core/panic/struct.Location.html

0 commit comments

Comments
 (0)