-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Support forwarding caller location through trait object method call #81360
Conversation
r? @lcnr (rust-highfive has picked a reviewer for you, use r? to override) |
cc @rust-lang/lang @anp |
This comment has been minimized.
This comment has been minimized.
// (e.g. `trait Foo { #[track_caller] my_fn() { /* impl */ } }`), | ||
// then we don't need to generate a shim. This check is needed because | ||
// `should_inherit_track_caller` returns `false` if our method | ||
// implementation comes from the trait block, and not an impl block |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// implementation comes from the trait block, and not an impl block | |
// implementation comes from the trait block, and not an impl block. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, cc @eddyb who reviewed most of the original query code.
If this lands, make sure to update the reference's language too?
☔ The latest upstream changes (presumably #81660) made this pull request unmergeable. Please resolve the merge conflicts. |
We discussed this in the most recent language team meeting and everyone was generally favorable to offering this behavior. However, we would like a write-up explaining the feature, its interaction with user-written ABI annotations, and the changes to the Rust reference. Additionally, several of us felt that the annotation should come with a warning in the case that the annotation is present on the trait but not on a specific implementation. Personally, I might prefer this to be an error, but I understand that there may be traits which would want to add this attribute after-the-fact in a backwards compatible way. |
Removing nominated label. Please re-nominate when there's a write-up! Thanks. |
@Aaron1011 Ping from triage! would you want to write such a writeup, or do you want some help on this? |
I think being able to add this backwards-compatibly is very important - otherwise, adding this annotation to a trait would require updating every downstream crate. |
We've already done this to e.g. There's no reason to require the |
InstanceDef::Item(def) => { | ||
tcx.codegen_fn_attrs(def.did).flags.contains(CodegenFnAttrFlags::TRACK_CALLER) | ||
InstanceDef::Item(ty::WithOptConstParam { did: def_id, .. }) | ||
| InstanceDef::Virtual(def_id, _) => { | ||
tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Heh, nice, I like that this is all it takes for virtual calls to start taking panic::Location
.
I assume the rest of the changes is there "just" to handle edge cases.
Ping from triage: |
I am not able to review any PRs in the near future. r? @nagisa |
// We have `#[track_caller]` on the implementation of the method, | ||
// but not on the definition of the method in the trait. Therefore, | ||
// caller location information will *not* work through a method call | ||
// on a trait object. Instead, we will get the location of this method | ||
#[track_caller] | ||
fn track_caller_not_on_trait_method(&self) { | ||
let location = std::panic::Location::caller(); | ||
assert_eq!(location.file(), file!()); | ||
assert_eq!(location.line(), line!() - 3); | ||
assert_eq!(location.column(), 5); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any reason why the file!
/line!
don't fall-back to their usual behaviour of providing precisely the line/column they are on, rather than that of where the method definition item begins? As implemented right now, this seems like a 3rd new behaviour for these macros.
(Though with the behaviour as it is, I'm sure that the bikeshed could go on ad infinitum here)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the current behavior whenever we need to generate a shim:
trait Foo {
#[track_caller] fn bar(&self);
}
impl Foo for () {
fn bar(&self) {
panic!("Where does this end up?")
}
}
fn foo(val: &dyn Foo) {
val.bar();
}
fn main() {
foo(&());
}
On the latest nightly, this prints thread 'main' panicked at 'Where does this end up?', src/main.rs:6:5
I agree that it would probably be good to change this, but I think that could be done separately.
The final comment period, with a disposition to merge, as per the review above, is now complete. As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed. The RFC will be merged soon. |
We are okay with merging this, correct? I gave my consent to r=me this previously on the implementation side of things. |
Yes, FCP passed. |
@bors r=nagisa |
@bors r=nagisa |
📌 Commit 6fd6624 has been approved by |
☀️ Test successful - checks-actions |
Tested on commit rust-lang/rust@3982eb3. Direct link to PR: <rust-lang/rust#81360> 💔 miri on windows: test-pass → test-fail (cc @RalfJung @eddyb @oli-obk). 💔 miri on linux: test-pass → test-fail (cc @RalfJung @eddyb @oli-obk).
This change led to moderate performance regressions. It would probably be good to run perf on ~all changes adding a query -- it looks like that may have been the primary cause of the regressions in this PR (though is hard to tell when the querification is combined with other changes). As part of the performance triage process, I'm marking this as a performance regression, and as "triaged". I don't think this merits further investigation; performance regression is focused on smaller crates and is not particularly large. @rustbot label +perf-regression perf-regression-triaged |
Since PR #69251, the
#[track_caller]
attribute has been supported ontraits. However, it only has an effect on direct (monomorphized) method
calls. Calling a
#[track_caller]
method on a trait object will notpropagate caller location information - instead,
Location::caller()
willreturn the location of the method definition.
This PR forwards caller location information when
#[track_caller]
ispresent on the method definition in the trait. This is possible because
#[track_caller]
in this position is 'inherited' by any impls of thattrait, so all implementations will have the same ABI.
This PR does not change the behavior in the case where
#[track_caller]
is present only on the impl of a trait.While all implementations of the method might have an explicit
#[track_caller]
, we cannot know this at codegen time, since othercrates may have impls of the trait. Therefore, we keep the current
behavior of not forwarding the caller location, ensuring that all
implementations of the trait will have the correct ABI.
See the modified test for examples of how this works