Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tracking issue for RFC 2091: Implicit caller location #47809

Closed
2 of 3 tasks
aturon opened this issue Jan 27, 2018 · 89 comments
Closed
2 of 3 tasks

Tracking issue for RFC 2091: Implicit caller location #47809

aturon opened this issue Jan 27, 2018 · 89 comments
Assignees
Labels
B-RFC-approved Blocker: Approved by a merged RFC but not yet implemented. B-unstable Blocker: Implemented in the nightly compiler and unstable. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. F-track_caller `#![feature(track_caller)]` T-lang Relevant to the language team, which will review and decide on the PR/issue. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@aturon
Copy link
Member

aturon commented Jan 27, 2018

This is a tracking issue for the RFC "Implicit caller location" (rust-lang/rfcs#2091).

Steps:

Unresolved questions:

  • If we want to support adding #[track_caller] to trait methods, the redirection
    pass/query/whatever should be placed after monomorphization, not before. Currently the RFC
    simply prohibits applying #[track_caller] to trait methods as a future-proofing measure.

  • Diverging functions should be supported.

  • The closure foo::{{closure}} should inherit most attributes applied to the function foo, in
    particular #[inline], #[cold], #[naked] and also the ABI. Currently a procedural macro
    won't see any of these, nor would there be anyway to apply these attributes to a closure.
    Therefore, #[rustc_implicit_caller_location] currently will reject #[naked] and ABI, and
    leaving #[inline] and #[cold] mean no-op. There is no semantic reason why these cannot be
    used though.

@aturon aturon added B-RFC-approved Blocker: Approved by a merged RFC but not yet implemented. T-lang Relevant to the language team, which will review and decide on the PR/issue. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. labels Jan 27, 2018
@eddyb
Copy link
Member

eddyb commented Jan 27, 2018

If we want to support adding #[track_caller] to trait methods,

This refers to impl of a trait, not the declarations within the trait, right?

IMO the easiest way to implement this involves no procedural macros or MIR passes.
We'd just pass extra arguments on direct calls, and require a shim to get function pointers of the function. That would also surely work with trait methods, since it'd be post-monomorphization.

To explain, the shim (which we may already have some variation of) would "just" do the direct call to the function, which would pass the location of the shim, the same as the original function.

@nikomatsakis
Copy link
Contributor

This refers to impl of a trait, not the declarations within the trait, right?

I can't remember. =) But I suspect so. I don't think there's anything special about "trait methods" per se -- it's really about dynamic dispatch.

@nikomatsakis
Copy link
Contributor

@kennytm had a prototype implementation:

https://github.com/kennytm/rust/tree/caller-info-4

Maybe @kennytm you can summarize the approach you took? Do you think you'll have time to rebase etc? I'd like ideally to get @eddyb to buy in to the overall approach. =)

@kennytm
Copy link
Member

kennytm commented Apr 25, 2018

The prototype implementation works like this (note that #[track_caller] was called #[implicit_caller_location] there):

  1. First there will be an AST transformation pass (implemented as an attribute proc-macro in src/libsyntax_ext/implicit_caller_location.rs) which expands:

    #[track_caller]
    #[...attributes...]
    fn foo(...) -> T {
        /* code... */
    }

    into

    #[rustc_track_caller]
    #[inline]
    #[...attributes...]
    fn foo(...) -> T {
        let __closure = |__location| { /* code... */ };
        FnOnce::call_once(__closure, intrinsics::caller_location())
    }

    The purpose of this pass is to conveniently make up a new DefId.

  2. Create a new MIR inlining pass (main implementation in src/librustc_mir/transform/inline.rs). This pass does two things:

    1. Force-inline any functions calls foo() where the attributes of the callee foo contains #[rustc_track_caller].

    2. If intrinsics::caller_location() is called :-

      • If it is used from the __closure, replace it by the argument __location. This is to propagate the caller location.
      • Otherwise, replace the call with the caller's location span.
  3. Define the caller_location() intrinsic.

    fn caller_location() -> core::panic::Location<'static>;
  4. Because Location now needs to be known by the compiler, make the Location struct a lang-item.

  5. Update the standard library to use track-caller features:

    1. Change panic! to use caller_location() (or its safe counterpart, Location::caller())
    2. Add #[track_caller] to unwrap() and expect() etc.
  6. Implement the -Z location-detail flag (search for location_detail) so that the filename/line/column can be redacted.

@eddyb
Copy link
Member

eddyb commented Apr 25, 2018

I think a syntactical transformations is unnecessary because we can instead change the "direct call ABI" (vs reifying to a fn pointer, including trait vtables via miri, which could go through a MIR shim).
MIR inlining should also not be needed.

@kennytm
Copy link
Member

kennytm commented Apr 26, 2018

@eddyb So you are suggesting to change the extern "Rust" ABI to always pass an extra argument?

@eddyb
Copy link
Member

eddyb commented Apr 26, 2018

@kennytm Only for functions declared with the attribute and called through static dispatch, everything else would use a shim when reifying (which I think we do already in some other cases).

@kennytm
Copy link
Member

kennytm commented Apr 26, 2018

@eddyb Maybe you could write down some mentoring instructions i.e. which files to look at 😊

@nikomatsakis
Copy link
Contributor

@eddyb do it! do it! I want this feature.

@Centril
Copy link
Contributor

Centril commented Dec 1, 2018

@eddyb How are the mentoring instructions coming along?

@eddyb
Copy link
Member

eddyb commented Dec 2, 2018

Oh, I don't recall exactly what happened here.

For making static calls do something different, src/librustc_codegen_ssa/mir/block.rs is the place you need to change, while for shims, src/librustc_mir/shim.rs is where their MIR is computed.

But the rest of the pieces, I don't know off the top of my head where they happen.

#54183 added a virtual-call-only shim, which is close to what this needs, so that can be used for inspiration, but here we need both reification to fn pointers and virtual calls.

We could start by disallowing reification/virtualization of such functions, and only implement the static dispatch ABI changes.

@Centril Centril added the E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. label Dec 2, 2018
@arielb1
Copy link
Contributor

arielb1 commented Dec 2, 2018

We could start by disallowing reification/virtualization of such functions, and only implement the static dispatch ABI changes.

I don't expect this attribute to be usable on "real" functions without us implementing reification.

But for implementing this, I think one good strategy would be:

Not supporting trait methods

For now, I don't think there is sufficient reason to support implicit caller location on trait methods, and supporting that is fairly complicated. So as @aturon said on the head PR, just don't do it.

Step 0: dealing with the attribute.

You should make sure that the #[blame_caller] attribute "works". This means that:

  1. It emits a feature-gate error unless the correct feature-gate is enabled (see the feature guide for more information about feature gates).
  2. It emits an error when used with odd syntax (e.g. #[blame_caller(42)]),
  3. It emits an error when used on something that is not a free fn/inherent impl fn.
  4. It does not emit an error when used "correctly'.
  5. As the RFC says: using #[naked] or extern "ABI" together with #[rustc_implicit_caller_location] should raise an error.

I'm not particularly sure what's the exact way to do this, but you can maybe find some PR that implemented an attribute for that, or ask on Discord.

Make sure to add tests.

Step 1: have reified methods and direct calls go to different LLVM functions

At this stage, I won't even add a parameter, just have the call-sites go through different paths.

So the virtual-call-only shim at #54183 is a good model for how things need to be done. You'll need to add a ReifyShim that is similar to VirtualShim in behavior (see that PR). You'll probably need to split ty::Instance::resolve to ty::Instance::resolve_direct and ty::Instance::resolve_indirect (in addition to the already-existing ty::Instance::resolve_vtable) and adjust the call-sites. Have resolve_indirect return the shim if it is needed (i.e., when calling a #[blame_caller] function).

Step 2: Add a location parameter

Step 2.0: add a location parameter to the MIR of #[blame_caller]

MIR construction is in rustc_mir::build. There's already code there handling implicit arguments, which you could work with.

You'll need to fix ty::Instance::fn_sig to also contain the new type.

Step 2.1: add an "empty" location parameter to calls from the shim.

Change the shim you added in Step 1 to pass an "empty" location parameter - some "dummy" that represents a call that uses a shim. See the other shims for how to generate things in shims. Ask @eddyb if you are fighting const eval.

Step 2.2: add a value to the location parameter to direct calls.

Find all the calls to ty::Instance::resolve_direct you added previously, and make them pass the "correct" location parameter to the function. These callsites can poobably already modify parameters because of InstanceDef::Virtual, you should be able to just follow that.

Make sure that when #[track_caller] calls are nested, you pass the location of your call-site, rather than your location. Add a test for that. Also add a test that when one of the calls in the middle is not #[track_caller], the call-site is not passed.

You should probably add a function on ty::Instance that tells you whether you need to add the caller location.

Step 3: wire up intrinsic::caller_location

See some other intrinsic for how to type-check it. Make sure it can't be called from functions that aren't #[trace_caller]!

I think it might even be the best to do the wiring in MIR construction, like the move_val_init intrinsic - that way you wouldn't even have to convince MIR optimizations not to dead-code-eliminate your new parameter or something evil like that, and to make it not be affected by "plain" MIR inlining you'll only have to change the ty::Instance::resolve_direct callsite there (you did make MIR inlining use resolve_direct, did you?).

Step 4: You have it!

Now you only need to implement the library support.

@flavius
Copy link

flavius commented Feb 11, 2019

Is anyone working on this?

@ayosec
Copy link
Contributor

ayosec commented May 7, 2019

If nobody is working on this I would like to try to implement it.

Do you think that it is feasible as a first contribution to the compiler?

Are the steps in #47809 (comment) still valid?

@cramertj
Copy link
Member

Yes, those steps still sound reasonable. This would be a difficult first contribution, but if you ask questions on https://rust-lang.zulipchat.com/# and ping @eddyb and @arielb1 I'm sure you'd be able to start making progress, and there are likely others who could help out.

@ayosec
Copy link
Contributor

ayosec commented Jul 29, 2019

I'm sorry for the delay. I couldn't have time to work on this until now =\

I have completed the step 0 described in #47809 (comment) . The progress is available in my branch, though I guess that I will have to wait until the pull-request is open to know is everything is OK.

About error codes: if I understand correctly, every error emitted by the compiler has its unique code, so I have to register a new E0### for every error. I assume that the final code is assigned only when patch is ready to be merged into master, so I'm using dummy codes (E0900, E0901, ...) for the new errors.

@anp
Copy link
Member

anp commented Sep 6, 2019

I'm interested in helping with this, are you still working on it @ayosec? If so, is there any way for me to contribute?

@ayosec
Copy link
Contributor

ayosec commented Sep 7, 2019

are you still working on it @ayosec?

Yes. I'm sorry for the lack of updates. During August I had almost no time, and I'm trying to start to continue now. At this moment I'm working with the shim to add the location parameter.

If so, is there any way for me to contribute?

Right now I spend most of the time reading and understanding how everything works, so there is not so much code to write.

Something that would be very helpful is writing the documentation for the new errors (like this or this, at the moment), since I'm not very fluent in English.

@oli-obk
Copy link
Contributor

oli-obk commented Oct 1, 2019

Ping @ayosec do you have time to address this or is it OK with you if someone else takes over?

@ayosec
Copy link
Contributor

ayosec commented Oct 2, 2019

I'm still working on it very slowly, but feel free to take it if you want. I can try to implement another issue once I get more time.

@anp
Copy link
Member

anp commented May 22, 2020

Alright! I've revised the PR to the reference and have opened a PR to stabilize the attribute and wrapper: #72445.

@ivnsch
Copy link

ivnsch commented Jun 22, 2020

Sorry, what is the name of the flag? location-detail and redact-caller-location are returning "unknown flag"

@anp
Copy link
Member

anp commented Jun 22, 2020

The flag needs implementation still: #70580.

Manishearth added a commit to Manishearth/rust that referenced this issue Jun 30, 2020
Stabilize `#[track_caller]`.

# Stabilization Report

RFC: [2091]
Tracking issue: rust-lang#47809

## Summary

From the [rustc-dev-guide chapter][dev-guide]:

> Take this example program:

```rust
fn main() {
    let foo: Option<()> = None;
    foo.unwrap(); // this should produce a useful panic message!
}
```

> Prior to Rust 1.42, panics like this `unwrap()` printed a location in libcore:

```
$ rustc +1.41.0 example.rs; example.exe
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value',...core\macros\mod.rs:15:40
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
```

> As of 1.42, we get a much more helpful message:

```
$ rustc +1.42.0 example.rs; example.exe
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', example.rs:3:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```

> These error messages are achieved through a combination of changes to `panic!` internals to make use of `core::panic::Location::caller` and a number of `#[track_caller]` annotations in the standard library which propagate caller information.

The attribute adds an implicit caller location argument to the ABI of annotated functions, but does not affect the type or MIR of the function. We implement the feature entirely in codegen and in the const evaluator.

## Bottom Line

This PR stabilizes the use of `#[track_caller]` everywhere, including traits and extern blocks. It also stabilizes `core::panic::Location::caller`, although the use of that function in a const context remains gated by `#![feature(const_caller_location)]`.

The implementation for the feature already changed the output of panic messages for a number of std functions, as described in the [1.42 release announcement]. The attribute's use in `Index` and `IndexMut` traits is visible to users since 1.44.

## Tests

All of the tests for this feature live under [src/test/ui/rfc-2091-track-caller][tests] in the repo.

Noteworthy cases:

* [use of attr in std]
  * validates user-facing benefit of the feature
* [trait attribute inheritance]
  * covers subtle behavior designed during implementation and not RFC'd
* [const/codegen equivalence]
  * this was the result of a suspected edge case and investigation
* [diverging function support]
  * covers an unresolved question from the RFC
* [fn pointers and shims]
  * covers important potential sources of unsoundness

## Documentation

The rustc-dev-guide now has a chapter on [Implicit Caller Location][dev-guide].

I have an [open PR to the reference][attr-reference-pr] documenting the attribute.

The intrinsic's [wrapper] includes some examples as well.

## Implementation History

* 2019-10-02: [`#[track_caller]` feature gate (RFC 2091 1/N) rust-lang#65037](rust-lang#65037)
  * Picked up the patch that @ayosec had started on the feature gate.
* 2019-10-13: [Add `Instance::resolve_for_fn_ptr` (RFC 2091 rust-lang#2/N) rust-lang#65182](rust-lang#65182)
* 2019-10-20: ~~[WIP Add MIR argument for #[track_caller] (RFC 2091 3/N) rust-lang#65258](rust-lang#65258
  * Abandoned approach to send location as a MIR argument.
* 2019-10-28: [`std::panic::Location` is a lang_item, add `core::intrinsics::caller_location` (RFC 2091 3/N) rust-lang#65664](rust-lang#65664)
* 2019-12-07: [Implement #[track_caller] attribute. (RFC 2091 4/N) rust-lang#65881](rust-lang#65881)
* 2020-01-04: [libstd uses `core::panic::Location` where possible. rust-lang#67137](rust-lang#67137)
* 2020-01-08: [`Option::{expect,unwrap}` and `Result::{expect, expect_err, unwrap, unwrap_err}` have `#[track_caller]` rust-lang#67887](rust-lang#67887)
* 2020-01-20: [Fix #[track_caller] and function pointers rust-lang#68302](rust-lang#68302) (fixed rust-lang#68178)
* 2020-03-23: [#[track_caller] in traits rust-lang#69251](rust-lang#69251)
* 2020-03-24: [#[track_caller] on core::ops::{Index, IndexMut}. rust-lang#70234](rust-lang#70234)
* 2020-04-08 [Support `#[track_caller]` on functions in `extern "Rust" { ... }` rust-lang#70916](rust-lang#70916)

## Unresolveds

### From the RFC

> Currently the RFC simply prohibit applying #[track_caller] to trait methods as a future-proofing
> measure.

**Resolved.** See the dev-guide documentation and the tests section above.

> Diverging functions should be supported.

**Resolved.** See the tests section above.

> The closure foo::{{closure}} should inherit most attributes applied to the function foo, ...

**Resolved.** This unknown was related to specifics of the implementation which were made irrelevant by the final implementation.

### Binary Size

I [instrumented track_caller to use custom sections][measure-size] in a local build and discovered relatively minor binary size usage for the feature overall. I'm leaving the issue open to discuss whether we want to upstream custom section support.

There's an [open issue to discuss mitigation strategies][mitigate-size]. Some decisions remain about the "right" strategies to reduce size without overly constraining the compiler implementation. I'd be excited to see someone carry that work forward but my opinion is that we shouldn't block stabilization on implementing compiler flags for redaction.

### Specialization

There's an [open issue][specialization] on the semantics of the attribute in specialization chains. I'm inclined to move forward with stabilization without an exact resolution here given that specialization is itself unstable, but I also think it should be an easy question to resolve.

### Location only points to the start of a call span

rust-lang#69977 was resolved by rust-lang#73182, and the next step should probably be to [extend `Location` with a notion of the end of a call](rust-lang#73554).

### Regression of std's panic messages

rust-lang#70963 should be resolved by serializing span hygeine to crate metadata: rust-lang#68686.

[2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md
[dev-guide]: https://rustc-dev-guide.rust-lang.org/codegen/implicit-caller-location.html
[specialization]: rust-lang#70293
[measure-size]: rust-lang#70579
[mitigate-size]: rust-lang#70580
[attr-reference-pr]: rust-lang/reference#742
[wrapper]: https://doc.rust-lang.org/nightly/core/panic/struct.Location.html#method.caller
[tests]: https://github.com/rust-lang/rust/tree/master/src/test/ui/rfc-2091-track-caller
[const/codegen equivalence]: https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs
[diverging function support]: https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2091-track-caller/diverging-caller-location.rs
[use of attr in std]: https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2091-track-caller/std-panic-locations.rs
[fn pointers and shims]: https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs
[trait attribute inheritance]: https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2091-track-caller/tracked-trait-impls.rs
[1.42 release announcement]: https://blog.rust-lang.org/2020/03/12/Rust-1.42.html#useful-line-numbers-in-option-and-result-panic-messages
Manishearth added a commit to Manishearth/rust that referenced this issue Jun 30, 2020
Stabilize `#[track_caller]`.

# Stabilization Report

RFC: [2091]
Tracking issue: rust-lang#47809

## Summary

From the [rustc-dev-guide chapter][dev-guide]:

> Take this example program:

```rust
fn main() {
    let foo: Option<()> = None;
    foo.unwrap(); // this should produce a useful panic message!
}
```

> Prior to Rust 1.42, panics like this `unwrap()` printed a location in libcore:

```
$ rustc +1.41.0 example.rs; example.exe
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value',...core\macros\mod.rs:15:40
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
```

> As of 1.42, we get a much more helpful message:

```
$ rustc +1.42.0 example.rs; example.exe
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', example.rs:3:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```

> These error messages are achieved through a combination of changes to `panic!` internals to make use of `core::panic::Location::caller` and a number of `#[track_caller]` annotations in the standard library which propagate caller information.

The attribute adds an implicit caller location argument to the ABI of annotated functions, but does not affect the type or MIR of the function. We implement the feature entirely in codegen and in the const evaluator.

## Bottom Line

This PR stabilizes the use of `#[track_caller]` everywhere, including traits and extern blocks. It also stabilizes `core::panic::Location::caller`, although the use of that function in a const context remains gated by `#![feature(const_caller_location)]`.

The implementation for the feature already changed the output of panic messages for a number of std functions, as described in the [1.42 release announcement]. The attribute's use in `Index` and `IndexMut` traits is visible to users since 1.44.

## Tests

All of the tests for this feature live under [src/test/ui/rfc-2091-track-caller][tests] in the repo.

Noteworthy cases:

* [use of attr in std]
  * validates user-facing benefit of the feature
* [trait attribute inheritance]
  * covers subtle behavior designed during implementation and not RFC'd
* [const/codegen equivalence]
  * this was the result of a suspected edge case and investigation
* [diverging function support]
  * covers an unresolved question from the RFC
* [fn pointers and shims]
  * covers important potential sources of unsoundness

## Documentation

The rustc-dev-guide now has a chapter on [Implicit Caller Location][dev-guide].

I have an [open PR to the reference][attr-reference-pr] documenting the attribute.

The intrinsic's [wrapper] includes some examples as well.

## Implementation History

* 2019-10-02: [`#[track_caller]` feature gate (RFC 2091 1/N) rust-lang#65037](rust-lang#65037)
  * Picked up the patch that @ayosec had started on the feature gate.
* 2019-10-13: [Add `Instance::resolve_for_fn_ptr` (RFC 2091 rust-lang#2/N) rust-lang#65182](rust-lang#65182)
* 2019-10-20: ~~[WIP Add MIR argument for #[track_caller] (RFC 2091 3/N) rust-lang#65258](rust-lang#65258
  * Abandoned approach to send location as a MIR argument.
* 2019-10-28: [`std::panic::Location` is a lang_item, add `core::intrinsics::caller_location` (RFC 2091 3/N) rust-lang#65664](rust-lang#65664)
* 2019-12-07: [Implement #[track_caller] attribute. (RFC 2091 4/N) rust-lang#65881](rust-lang#65881)
* 2020-01-04: [libstd uses `core::panic::Location` where possible. rust-lang#67137](rust-lang#67137)
* 2020-01-08: [`Option::{expect,unwrap}` and `Result::{expect, expect_err, unwrap, unwrap_err}` have `#[track_caller]` rust-lang#67887](rust-lang#67887)
* 2020-01-20: [Fix #[track_caller] and function pointers rust-lang#68302](rust-lang#68302) (fixed rust-lang#68178)
* 2020-03-23: [#[track_caller] in traits rust-lang#69251](rust-lang#69251)
* 2020-03-24: [#[track_caller] on core::ops::{Index, IndexMut}. rust-lang#70234](rust-lang#70234)
* 2020-04-08 [Support `#[track_caller]` on functions in `extern "Rust" { ... }` rust-lang#70916](rust-lang#70916)

## Unresolveds

### From the RFC

> Currently the RFC simply prohibit applying #[track_caller] to trait methods as a future-proofing
> measure.

**Resolved.** See the dev-guide documentation and the tests section above.

> Diverging functions should be supported.

**Resolved.** See the tests section above.

> The closure foo::{{closure}} should inherit most attributes applied to the function foo, ...

**Resolved.** This unknown was related to specifics of the implementation which were made irrelevant by the final implementation.

### Binary Size

I [instrumented track_caller to use custom sections][measure-size] in a local build and discovered relatively minor binary size usage for the feature overall. I'm leaving the issue open to discuss whether we want to upstream custom section support.

There's an [open issue to discuss mitigation strategies][mitigate-size]. Some decisions remain about the "right" strategies to reduce size without overly constraining the compiler implementation. I'd be excited to see someone carry that work forward but my opinion is that we shouldn't block stabilization on implementing compiler flags for redaction.

### Specialization

There's an [open issue][specialization] on the semantics of the attribute in specialization chains. I'm inclined to move forward with stabilization without an exact resolution here given that specialization is itself unstable, but I also think it should be an easy question to resolve.

### Location only points to the start of a call span

rust-lang#69977 was resolved by rust-lang#73182, and the next step should probably be to [extend `Location` with a notion of the end of a call](rust-lang#73554).

### Regression of std's panic messages

rust-lang#70963 should be resolved by serializing span hygeine to crate metadata: rust-lang#68686.

[2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md
[dev-guide]: https://rustc-dev-guide.rust-lang.org/codegen/implicit-caller-location.html
[specialization]: rust-lang#70293
[measure-size]: rust-lang#70579
[mitigate-size]: rust-lang#70580
[attr-reference-pr]: rust-lang/reference#742
[wrapper]: https://doc.rust-lang.org/nightly/core/panic/struct.Location.html#method.caller
[tests]: https://github.com/rust-lang/rust/tree/master/src/test/ui/rfc-2091-track-caller
[const/codegen equivalence]: https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs
[diverging function support]: https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2091-track-caller/diverging-caller-location.rs
[use of attr in std]: https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2091-track-caller/std-panic-locations.rs
[fn pointers and shims]: https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs
[trait attribute inheritance]: https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2091-track-caller/tracked-trait-impls.rs
[1.42 release announcement]: https://blog.rust-lang.org/2020/03/12/Rust-1.42.html#useful-line-numbers-in-option-and-result-panic-messages
Manishearth added a commit to Manishearth/rust that referenced this issue Jul 1, 2020
Stabilize `#[track_caller]`.

# Stabilization Report

RFC: [2091]
Tracking issue: rust-lang#47809

## Summary

From the [rustc-dev-guide chapter][dev-guide]:

> Take this example program:

```rust
fn main() {
    let foo: Option<()> = None;
    foo.unwrap(); // this should produce a useful panic message!
}
```

> Prior to Rust 1.42, panics like this `unwrap()` printed a location in libcore:

```
$ rustc +1.41.0 example.rs; example.exe
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value',...core\macros\mod.rs:15:40
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
```

> As of 1.42, we get a much more helpful message:

```
$ rustc +1.42.0 example.rs; example.exe
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', example.rs:3:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```

> These error messages are achieved through a combination of changes to `panic!` internals to make use of `core::panic::Location::caller` and a number of `#[track_caller]` annotations in the standard library which propagate caller information.

The attribute adds an implicit caller location argument to the ABI of annotated functions, but does not affect the type or MIR of the function. We implement the feature entirely in codegen and in the const evaluator.

## Bottom Line

This PR stabilizes the use of `#[track_caller]` everywhere, including traits and extern blocks. It also stabilizes `core::panic::Location::caller`, although the use of that function in a const context remains gated by `#![feature(const_caller_location)]`.

The implementation for the feature already changed the output of panic messages for a number of std functions, as described in the [1.42 release announcement]. The attribute's use in `Index` and `IndexMut` traits is visible to users since 1.44.

## Tests

All of the tests for this feature live under [src/test/ui/rfc-2091-track-caller][tests] in the repo.

Noteworthy cases:

* [use of attr in std]
  * validates user-facing benefit of the feature
* [trait attribute inheritance]
  * covers subtle behavior designed during implementation and not RFC'd
* [const/codegen equivalence]
  * this was the result of a suspected edge case and investigation
* [diverging function support]
  * covers an unresolved question from the RFC
* [fn pointers and shims]
  * covers important potential sources of unsoundness

## Documentation

The rustc-dev-guide now has a chapter on [Implicit Caller Location][dev-guide].

I have an [open PR to the reference][attr-reference-pr] documenting the attribute.

The intrinsic's [wrapper] includes some examples as well.

## Implementation History

* 2019-10-02: [`#[track_caller]` feature gate (RFC 2091 1/N) rust-lang#65037](rust-lang#65037)
  * Picked up the patch that @ayosec had started on the feature gate.
* 2019-10-13: [Add `Instance::resolve_for_fn_ptr` (RFC 2091 rust-lang#2/N) rust-lang#65182](rust-lang#65182)
* 2019-10-20: ~~[WIP Add MIR argument for #[track_caller] (RFC 2091 3/N) rust-lang#65258](rust-lang#65258
  * Abandoned approach to send location as a MIR argument.
* 2019-10-28: [`std::panic::Location` is a lang_item, add `core::intrinsics::caller_location` (RFC 2091 3/N) rust-lang#65664](rust-lang#65664)
* 2019-12-07: [Implement #[track_caller] attribute. (RFC 2091 4/N) rust-lang#65881](rust-lang#65881)
* 2020-01-04: [libstd uses `core::panic::Location` where possible. rust-lang#67137](rust-lang#67137)
* 2020-01-08: [`Option::{expect,unwrap}` and `Result::{expect, expect_err, unwrap, unwrap_err}` have `#[track_caller]` rust-lang#67887](rust-lang#67887)
* 2020-01-20: [Fix #[track_caller] and function pointers rust-lang#68302](rust-lang#68302) (fixed rust-lang#68178)
* 2020-03-23: [#[track_caller] in traits rust-lang#69251](rust-lang#69251)
* 2020-03-24: [#[track_caller] on core::ops::{Index, IndexMut}. rust-lang#70234](rust-lang#70234)
* 2020-04-08 [Support `#[track_caller]` on functions in `extern "Rust" { ... }` rust-lang#70916](rust-lang#70916)

## Unresolveds

### From the RFC

> Currently the RFC simply prohibit applying #[track_caller] to trait methods as a future-proofing
> measure.

**Resolved.** See the dev-guide documentation and the tests section above.

> Diverging functions should be supported.

**Resolved.** See the tests section above.

> The closure foo::{{closure}} should inherit most attributes applied to the function foo, ...

**Resolved.** This unknown was related to specifics of the implementation which were made irrelevant by the final implementation.

### Binary Size

I [instrumented track_caller to use custom sections][measure-size] in a local build and discovered relatively minor binary size usage for the feature overall. I'm leaving the issue open to discuss whether we want to upstream custom section support.

There's an [open issue to discuss mitigation strategies][mitigate-size]. Some decisions remain about the "right" strategies to reduce size without overly constraining the compiler implementation. I'd be excited to see someone carry that work forward but my opinion is that we shouldn't block stabilization on implementing compiler flags for redaction.

### Specialization

There's an [open issue][specialization] on the semantics of the attribute in specialization chains. I'm inclined to move forward with stabilization without an exact resolution here given that specialization is itself unstable, but I also think it should be an easy question to resolve.

### Location only points to the start of a call span

rust-lang#69977 was resolved by rust-lang#73182, and the next step should probably be to [extend `Location` with a notion of the end of a call](rust-lang#73554).

### Regression of std's panic messages

rust-lang#70963 should be resolved by serializing span hygeine to crate metadata: rust-lang#68686.

[2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md
[dev-guide]: https://rustc-dev-guide.rust-lang.org/codegen/implicit-caller-location.html
[specialization]: rust-lang#70293
[measure-size]: rust-lang#70579
[mitigate-size]: rust-lang#70580
[attr-reference-pr]: rust-lang/reference#742
[wrapper]: https://doc.rust-lang.org/nightly/core/panic/struct.Location.html#method.caller
[tests]: https://github.com/rust-lang/rust/tree/master/src/test/ui/rfc-2091-track-caller
[const/codegen equivalence]: https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs
[diverging function support]: https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2091-track-caller/diverging-caller-location.rs
[use of attr in std]: https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2091-track-caller/std-panic-locations.rs
[fn pointers and shims]: https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs
[trait attribute inheritance]: https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2091-track-caller/tracked-trait-impls.rs
[1.42 release announcement]: https://blog.rust-lang.org/2020/03/12/Rust-1.42.html#useful-line-numbers-in-option-and-result-panic-messages
Manishearth added a commit to Manishearth/rust that referenced this issue Jul 1, 2020
Stabilize `#[track_caller]`.

# Stabilization Report

RFC: [2091]
Tracking issue: rust-lang#47809

## Summary

From the [rustc-dev-guide chapter][dev-guide]:

> Take this example program:

```rust
fn main() {
    let foo: Option<()> = None;
    foo.unwrap(); // this should produce a useful panic message!
}
```

> Prior to Rust 1.42, panics like this `unwrap()` printed a location in libcore:

```
$ rustc +1.41.0 example.rs; example.exe
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value',...core\macros\mod.rs:15:40
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
```

> As of 1.42, we get a much more helpful message:

```
$ rustc +1.42.0 example.rs; example.exe
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', example.rs:3:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```

> These error messages are achieved through a combination of changes to `panic!` internals to make use of `core::panic::Location::caller` and a number of `#[track_caller]` annotations in the standard library which propagate caller information.

The attribute adds an implicit caller location argument to the ABI of annotated functions, but does not affect the type or MIR of the function. We implement the feature entirely in codegen and in the const evaluator.

## Bottom Line

This PR stabilizes the use of `#[track_caller]` everywhere, including traits and extern blocks. It also stabilizes `core::panic::Location::caller`, although the use of that function in a const context remains gated by `#![feature(const_caller_location)]`.

The implementation for the feature already changed the output of panic messages for a number of std functions, as described in the [1.42 release announcement]. The attribute's use in `Index` and `IndexMut` traits is visible to users since 1.44.

## Tests

All of the tests for this feature live under [src/test/ui/rfc-2091-track-caller][tests] in the repo.

Noteworthy cases:

* [use of attr in std]
  * validates user-facing benefit of the feature
* [trait attribute inheritance]
  * covers subtle behavior designed during implementation and not RFC'd
* [const/codegen equivalence]
  * this was the result of a suspected edge case and investigation
* [diverging function support]
  * covers an unresolved question from the RFC
* [fn pointers and shims]
  * covers important potential sources of unsoundness

## Documentation

The rustc-dev-guide now has a chapter on [Implicit Caller Location][dev-guide].

I have an [open PR to the reference][attr-reference-pr] documenting the attribute.

The intrinsic's [wrapper] includes some examples as well.

## Implementation History

* 2019-10-02: [`#[track_caller]` feature gate (RFC 2091 1/N) rust-lang#65037](rust-lang#65037)
  * Picked up the patch that @ayosec had started on the feature gate.
* 2019-10-13: [Add `Instance::resolve_for_fn_ptr` (RFC 2091 rust-lang#2/N) rust-lang#65182](rust-lang#65182)
* 2019-10-20: ~~[WIP Add MIR argument for #[track_caller] (RFC 2091 3/N) rust-lang#65258](rust-lang#65258
  * Abandoned approach to send location as a MIR argument.
* 2019-10-28: [`std::panic::Location` is a lang_item, add `core::intrinsics::caller_location` (RFC 2091 3/N) rust-lang#65664](rust-lang#65664)
* 2019-12-07: [Implement #[track_caller] attribute. (RFC 2091 4/N) rust-lang#65881](rust-lang#65881)
* 2020-01-04: [libstd uses `core::panic::Location` where possible. rust-lang#67137](rust-lang#67137)
* 2020-01-08: [`Option::{expect,unwrap}` and `Result::{expect, expect_err, unwrap, unwrap_err}` have `#[track_caller]` rust-lang#67887](rust-lang#67887)
* 2020-01-20: [Fix #[track_caller] and function pointers rust-lang#68302](rust-lang#68302) (fixed rust-lang#68178)
* 2020-03-23: [#[track_caller] in traits rust-lang#69251](rust-lang#69251)
* 2020-03-24: [#[track_caller] on core::ops::{Index, IndexMut}. rust-lang#70234](rust-lang#70234)
* 2020-04-08 [Support `#[track_caller]` on functions in `extern "Rust" { ... }` rust-lang#70916](rust-lang#70916)

## Unresolveds

### From the RFC

> Currently the RFC simply prohibit applying #[track_caller] to trait methods as a future-proofing
> measure.

**Resolved.** See the dev-guide documentation and the tests section above.

> Diverging functions should be supported.

**Resolved.** See the tests section above.

> The closure foo::{{closure}} should inherit most attributes applied to the function foo, ...

**Resolved.** This unknown was related to specifics of the implementation which were made irrelevant by the final implementation.

### Binary Size

I [instrumented track_caller to use custom sections][measure-size] in a local build and discovered relatively minor binary size usage for the feature overall. I'm leaving the issue open to discuss whether we want to upstream custom section support.

There's an [open issue to discuss mitigation strategies][mitigate-size]. Some decisions remain about the "right" strategies to reduce size without overly constraining the compiler implementation. I'd be excited to see someone carry that work forward but my opinion is that we shouldn't block stabilization on implementing compiler flags for redaction.

### Specialization

There's an [open issue][specialization] on the semantics of the attribute in specialization chains. I'm inclined to move forward with stabilization without an exact resolution here given that specialization is itself unstable, but I also think it should be an easy question to resolve.

### Location only points to the start of a call span

rust-lang#69977 was resolved by rust-lang#73182, and the next step should probably be to [extend `Location` with a notion of the end of a call](rust-lang#73554).

### Regression of std's panic messages

rust-lang#70963 should be resolved by serializing span hygeine to crate metadata: rust-lang#68686.

[2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md
[dev-guide]: https://rustc-dev-guide.rust-lang.org/codegen/implicit-caller-location.html
[specialization]: rust-lang#70293
[measure-size]: rust-lang#70579
[mitigate-size]: rust-lang#70580
[attr-reference-pr]: rust-lang/reference#742
[wrapper]: https://doc.rust-lang.org/nightly/core/panic/struct.Location.html#method.caller
[tests]: https://github.com/rust-lang/rust/tree/master/src/test/ui/rfc-2091-track-caller
[const/codegen equivalence]: https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs
[diverging function support]: https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2091-track-caller/diverging-caller-location.rs
[use of attr in std]: https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2091-track-caller/std-panic-locations.rs
[fn pointers and shims]: https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs
[trait attribute inheritance]: https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2091-track-caller/tracked-trait-impls.rs
[1.42 release announcement]: https://blog.rust-lang.org/2020/03/12/Rust-1.42.html#useful-line-numbers-in-option-and-result-panic-messages
Manishearth added a commit to Manishearth/rust that referenced this issue Jul 1, 2020
Stabilize `#[track_caller]`.

# Stabilization Report

RFC: [2091]
Tracking issue: rust-lang#47809

## Summary

From the [rustc-dev-guide chapter][dev-guide]:

> Take this example program:

```rust
fn main() {
    let foo: Option<()> = None;
    foo.unwrap(); // this should produce a useful panic message!
}
```

> Prior to Rust 1.42, panics like this `unwrap()` printed a location in libcore:

```
$ rustc +1.41.0 example.rs; example.exe
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value',...core\macros\mod.rs:15:40
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
```

> As of 1.42, we get a much more helpful message:

```
$ rustc +1.42.0 example.rs; example.exe
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', example.rs:3:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```

> These error messages are achieved through a combination of changes to `panic!` internals to make use of `core::panic::Location::caller` and a number of `#[track_caller]` annotations in the standard library which propagate caller information.

The attribute adds an implicit caller location argument to the ABI of annotated functions, but does not affect the type or MIR of the function. We implement the feature entirely in codegen and in the const evaluator.

## Bottom Line

This PR stabilizes the use of `#[track_caller]` everywhere, including traits and extern blocks. It also stabilizes `core::panic::Location::caller`, although the use of that function in a const context remains gated by `#![feature(const_caller_location)]`.

The implementation for the feature already changed the output of panic messages for a number of std functions, as described in the [1.42 release announcement]. The attribute's use in `Index` and `IndexMut` traits is visible to users since 1.44.

## Tests

All of the tests for this feature live under [src/test/ui/rfc-2091-track-caller][tests] in the repo.

Noteworthy cases:

* [use of attr in std]
  * validates user-facing benefit of the feature
* [trait attribute inheritance]
  * covers subtle behavior designed during implementation and not RFC'd
* [const/codegen equivalence]
  * this was the result of a suspected edge case and investigation
* [diverging function support]
  * covers an unresolved question from the RFC
* [fn pointers and shims]
  * covers important potential sources of unsoundness

## Documentation

The rustc-dev-guide now has a chapter on [Implicit Caller Location][dev-guide].

I have an [open PR to the reference][attr-reference-pr] documenting the attribute.

The intrinsic's [wrapper] includes some examples as well.

## Implementation History

* 2019-10-02: [`#[track_caller]` feature gate (RFC 2091 1/N) rust-lang#65037](rust-lang#65037)
  * Picked up the patch that @ayosec had started on the feature gate.
* 2019-10-13: [Add `Instance::resolve_for_fn_ptr` (RFC 2091 rust-lang#2/N) rust-lang#65182](rust-lang#65182)
* 2019-10-20: ~~[WIP Add MIR argument for #[track_caller] (RFC 2091 3/N) rust-lang#65258](rust-lang#65258
  * Abandoned approach to send location as a MIR argument.
* 2019-10-28: [`std::panic::Location` is a lang_item, add `core::intrinsics::caller_location` (RFC 2091 3/N) rust-lang#65664](rust-lang#65664)
* 2019-12-07: [Implement #[track_caller] attribute. (RFC 2091 4/N) rust-lang#65881](rust-lang#65881)
* 2020-01-04: [libstd uses `core::panic::Location` where possible. rust-lang#67137](rust-lang#67137)
* 2020-01-08: [`Option::{expect,unwrap}` and `Result::{expect, expect_err, unwrap, unwrap_err}` have `#[track_caller]` rust-lang#67887](rust-lang#67887)
* 2020-01-20: [Fix #[track_caller] and function pointers rust-lang#68302](rust-lang#68302) (fixed rust-lang#68178)
* 2020-03-23: [#[track_caller] in traits rust-lang#69251](rust-lang#69251)
* 2020-03-24: [#[track_caller] on core::ops::{Index, IndexMut}. rust-lang#70234](rust-lang#70234)
* 2020-04-08 [Support `#[track_caller]` on functions in `extern "Rust" { ... }` rust-lang#70916](rust-lang#70916)

## Unresolveds

### From the RFC

> Currently the RFC simply prohibit applying #[track_caller] to trait methods as a future-proofing
> measure.

**Resolved.** See the dev-guide documentation and the tests section above.

> Diverging functions should be supported.

**Resolved.** See the tests section above.

> The closure foo::{{closure}} should inherit most attributes applied to the function foo, ...

**Resolved.** This unknown was related to specifics of the implementation which were made irrelevant by the final implementation.

### Binary Size

I [instrumented track_caller to use custom sections][measure-size] in a local build and discovered relatively minor binary size usage for the feature overall. I'm leaving the issue open to discuss whether we want to upstream custom section support.

There's an [open issue to discuss mitigation strategies][mitigate-size]. Some decisions remain about the "right" strategies to reduce size without overly constraining the compiler implementation. I'd be excited to see someone carry that work forward but my opinion is that we shouldn't block stabilization on implementing compiler flags for redaction.

### Specialization

There's an [open issue][specialization] on the semantics of the attribute in specialization chains. I'm inclined to move forward with stabilization without an exact resolution here given that specialization is itself unstable, but I also think it should be an easy question to resolve.

### Location only points to the start of a call span

rust-lang#69977 was resolved by rust-lang#73182, and the next step should probably be to [extend `Location` with a notion of the end of a call](rust-lang#73554).

### Regression of std's panic messages

rust-lang#70963 should be resolved by serializing span hygeine to crate metadata: rust-lang#68686.

[2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md
[dev-guide]: https://rustc-dev-guide.rust-lang.org/codegen/implicit-caller-location.html
[specialization]: rust-lang#70293
[measure-size]: rust-lang#70579
[mitigate-size]: rust-lang#70580
[attr-reference-pr]: rust-lang/reference#742
[wrapper]: https://doc.rust-lang.org/nightly/core/panic/struct.Location.html#method.caller
[tests]: https://github.com/rust-lang/rust/tree/master/src/test/ui/rfc-2091-track-caller
[const/codegen equivalence]: https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs
[diverging function support]: https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2091-track-caller/diverging-caller-location.rs
[use of attr in std]: https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2091-track-caller/std-panic-locations.rs
[fn pointers and shims]: https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs
[trait attribute inheritance]: https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2091-track-caller/tracked-trait-impls.rs
[1.42 release announcement]: https://blog.rust-lang.org/2020/03/12/Rust-1.42.html#useful-line-numbers-in-option-and-result-panic-messages
@anp
Copy link
Member

anp commented Jul 1, 2020

The stabilization PR just landed! The PR to the reference should be ready to go as well, after which I think we can close this tracking issue (at least those are the only checkboxes remaining in the top message).

@nikomatsakis
Copy link
Contributor

Amazing work, @anp!

@elichai
Copy link
Contributor

elichai commented Jul 4, 2020

This is awesome!
One problem I have is that it's not possible to put #[track_caller] on closures, this is really useful when thread_local is involved because then there's a lot of logic in closures that you might want to propagate
ie

thread_local! {static DONE: bool = false;}

#[track_caller]
fn assert_done() {
    DONE.with(
        #[track_caller]
        |b| assert!(b),
    );
}

fn main() {
    assert_done();
}

@anp
Copy link
Member

anp commented Jul 4, 2020

The restriction on closures were in the original RFC, I think as a result of the implementation proposed then. Right now, I can't think of a reason the current implementation couldn't support this but I could easily be missing something. I opened #74042 to discuss/track.

@xd009642
Copy link
Contributor

Apologies if this has been raised before, but I've been playing around with trying to track where allocations happen with something like so:

use libc_print::libc_println;
use std::alloc::{GlobalAlloc, Layout};
use std::panic::Location;

pub struct TracedAlloc<T: GlobalAlloc> {
    pub allocator: T,
}

unsafe impl<T> GlobalAlloc for TracedAlloc<T>
where
    T: GlobalAlloc,
{
    #[track_caller]
    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
        libc_println!("Alloc {:?} at {:?}", layout, Location::caller());
        self.allocator.alloc(layout)
    }

    #[track_caller]
    unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
        libc_println!("Dealloc {:?} at {:?}", layout, Location::caller());
        self.allocator.dealloc(ptr, layout)
    }
}

However the caller location is always the line I've put #[global_allocator] which makes #[track_caller] useless in this context.

@KodrAus
Copy link
Contributor

KodrAus commented Jul 29, 2020

Are we happy to close this tracking issue now that #74042 has spun off work to support the attribute on closures?

@nikomatsakis
Copy link
Contributor

Sure, I guess so. Thanks again @anp for seeing this through!

@schreter
Copy link

Hi. I know this is a bit off-topic and this particular issue is already closed, but I suppose, the right people are involved here :-), so someone might help.

I implemented for our project a version of Result which uses Try trait in such a way as to track the error handling locations, so we get a "call stack" of the error at the end. This works in conjunction with #[track_caller] very well and we see the locations the error handling took.

However, there is one major deficiency in Location - it only gives us the source name and line. Yes, with that, it's possible to manually look up the function where it happened, but it would be significantly simpler to evaluate bug reports by looking at the call trace with function names (we have practiced this in a large C++ project, where basically the dev support standardized on initially evaluating everything by function names call trace, ignoring line numbers). So it would come extremely handy if the Location could be extended with another &str containing the function name (ideally with generics). It can be also a mangled name, I don't care much, but the function name is important.

Before you should "backtrace!" - yes, but... We are using heavy asynchronous processing handling errors across awaits, where the backtrace has about zero value. Similar for tracing, we can't just always trace due to performance reasons. So the error handling "call stack" is a perfect compromise - cheap and sufficiently valuable (except that it's missing the function name).

Any suggestion where/how to address this issue (Location extension by file name)? According to my code study of the Rust compiler code, it should basically boil down to getting the function name from the current Span and adding it in addition to the file name to the generated const Location here:

let const_loc = self.tcx.const_caller_location((

Thanks & regards,

Ivan

@jplatte
Copy link
Contributor

jplatte commented Mar 31, 2022

I remember asking about this quite a while ago and getting a response along the lines of "unlikely to happen for perf or code size reasons". Unfortunately I can't find an issue about it, so I guess it must have been on Zulip.

I think creating a separate issue would be more useful than continuing this conversation here, in any case.

@schreter
Copy link

schreter commented Mar 31, 2022

I remember asking about this quite a while ago and getting a response along the lines of "unlikely to happen for perf or code size reasons". Unfortunately I can't find an issue about it, so I guess it must have been on Zulip.

Well, it's clear that this will increase generated constants segment by potentially quite a bit, because instead of a single string per file we'll need to store many strings per file. So it could be made optional at compilation time. But I personally don't think it'll be significantly slower (during compilation; runtime is obviously unaffected).

I think creating a separate issue would be more useful than continuing this conversation here, in any case.

Sure. Simply a new top-level issue w/o any special tags? The question is how to get it to the attention of relevant people who could do something about it.

@est31
Copy link
Member

est31 commented Mar 31, 2022

If you have the source code, it should be quite easy to build a tool that translates the Location to the name of the function. Location contains the file name, as well as line and column, so all you need to do is go to that specific line and column, and then parse the next ident. Done easily with syn where you can write a custom visitor with a visit_ident function, like this. Then you just compare the line/col number with the line/col number of the Location, done. Maybe if the source code is not public you can export the Location via e.g. json and import it via the tool.

@schreter
Copy link

If you have the source code, it should be quite easy to build a tool that translates the Location to the name of the function.

Of course it could be translated. But that's another step, which makes it quite cumbersome. The compiler already knows it at compile time and aside from costing more space in the generated executable (string section), there should be no adverse effects of having the function name in the Location. It would in general allow building various tools which use the location for debugging purposes, which in turn would help the community in general.

Let me move this to a new issue, for further discussion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
B-RFC-approved Blocker: Approved by a merged RFC but not yet implemented. B-unstable Blocker: Implemented in the nightly compiler and unstable. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. F-track_caller `#![feature(track_caller)]` T-lang Relevant to the language team, which will review and decide on the PR/issue. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests