Auto merge of #65881 - anp:implicit-caller-location, r=eddyb,oli-obk
Implement #[track_caller] attribute. (RFC 2091 4/N) Implements the `#[track_caller]` attribute in both const and codegen contexts. The const implementation walks up the stack to find the nearest untracked callsite. The codegen implementation adds an implicit argument to tracked function calls, and populates it with either a call to the previously-landed intrinsic or if the caller has `#[track_caller]` with a copy of the location passed to the current function. Also includes a little cleanup and a few comments in the other caller location areas. [Depends on: 65664](https://github.com/rust-lang/rust/pull/65664) [RFC 2091 text](https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md) [Tracking issue](https://github.com/rust-lang/rust/issues/47809) [Tracking doc](https://paper.dropbox.com/doc/track_rfc_2091_impl-notes--Anf1NwnIb0xcRv31YLIadyj0Ag-rwCdRc2fi2yvRZ7syGZ9q#:uid=863513134494965680023183&h2=TODO-actually-pass-location-to)
This commit is contained in:
commit
de17464b14
35 changed files with 286 additions and 141 deletions
|
|
@ -1,23 +0,0 @@
|
|||
// run-pass
|
||||
|
||||
#![feature(const_fn, core_intrinsics)]
|
||||
|
||||
use std::{intrinsics::caller_location, panic::Location};
|
||||
|
||||
const LOCATION: &Location = caller_location();
|
||||
const NESTED: &Location = {
|
||||
const fn nested_location() -> &'static Location<'static> {
|
||||
caller_location()
|
||||
};
|
||||
nested_location()
|
||||
};
|
||||
|
||||
fn main() {
|
||||
assert_eq!(LOCATION.file(), file!());
|
||||
assert_eq!(LOCATION.line(), 7);
|
||||
assert_eq!(LOCATION.column(), 29);
|
||||
|
||||
assert_eq!(NESTED.file(), file!());
|
||||
assert_eq!(NESTED.line(), 10);
|
||||
assert_eq!(NESTED.column(), 9);
|
||||
}
|
||||
|
|
@ -1,21 +1,27 @@
|
|||
// run-pass
|
||||
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(track_caller)]
|
||||
|
||||
#[inline(never)]
|
||||
#[track_caller]
|
||||
fn defeat_const_prop() -> &'static core::panic::Location<'static> {
|
||||
core::panic::Location::caller()
|
||||
}
|
||||
|
||||
macro_rules! caller_location_from_macro {
|
||||
() => (core::intrinsics::caller_location());
|
||||
() => (defeat_const_prop());
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let loc = core::intrinsics::caller_location();
|
||||
let loc = defeat_const_prop();
|
||||
assert_eq!(loc.file(), file!());
|
||||
assert_eq!(loc.line(), 10);
|
||||
assert_eq!(loc.line(), 16);
|
||||
assert_eq!(loc.column(), 15);
|
||||
|
||||
// `caller_location()` in a macro should behave similarly to `file!` and `line!`,
|
||||
// `Location::caller()` in a macro should behave similarly to `file!` and `line!`,
|
||||
// i.e. point to where the macro was invoked, instead of the macro itself.
|
||||
let loc2 = caller_location_from_macro!();
|
||||
assert_eq!(loc2.file(), file!());
|
||||
assert_eq!(loc2.line(), 17);
|
||||
assert_eq!(loc2.line(), 23);
|
||||
assert_eq!(loc2.column(), 16);
|
||||
}
|
||||
|
|
|
|||
41
src/test/ui/rfc-2091-track-caller/const-caller-location.rs
Normal file
41
src/test/ui/rfc-2091-track-caller/const-caller-location.rs
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
// run-pass
|
||||
|
||||
#![feature(const_fn, track_caller)]
|
||||
|
||||
use std::panic::Location;
|
||||
|
||||
const LOCATION: &Location = Location::caller();
|
||||
|
||||
const TRACKED: &Location = tracked();
|
||||
#[track_caller]
|
||||
const fn tracked() -> &'static Location <'static> {
|
||||
Location::caller()
|
||||
}
|
||||
|
||||
const NESTED: &Location = nested_location();
|
||||
const fn nested_location() -> &'static Location<'static> {
|
||||
Location::caller()
|
||||
}
|
||||
|
||||
const CONTAINED: &Location = contained();
|
||||
const fn contained() -> &'static Location<'static> {
|
||||
tracked()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert_eq!(LOCATION.file(), file!());
|
||||
assert_eq!(LOCATION.line(), 7);
|
||||
assert_eq!(LOCATION.column(), 29);
|
||||
|
||||
assert_eq!(TRACKED.file(), file!());
|
||||
assert_eq!(TRACKED.line(), 9);
|
||||
assert_eq!(TRACKED.column(), 28);
|
||||
|
||||
assert_eq!(NESTED.file(), file!());
|
||||
assert_eq!(NESTED.line(), 17);
|
||||
assert_eq!(NESTED.column(), 5);
|
||||
|
||||
assert_eq!(CONTAINED.file(), file!());
|
||||
assert_eq!(CONTAINED.line(), 22);
|
||||
assert_eq!(CONTAINED.column(), 5);
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete
|
||||
#![feature(track_caller)]
|
||||
|
||||
#[track_caller(1)]
|
||||
fn f() {}
|
||||
|
|
|
|||
|
|
@ -4,13 +4,5 @@ error: malformed `track_caller` attribute input
|
|||
LL | #[track_caller(1)]
|
||||
| ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[track_caller]`
|
||||
|
||||
warning: the feature `track_caller` is incomplete and may cause the compiler to crash
|
||||
--> $DIR/error-odd-syntax.rs:1:12
|
||||
|
|
||||
LL | #![feature(track_caller)]
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete
|
||||
#![feature(track_caller)]
|
||||
|
||||
#[track_caller] //~ ERROR Rust ABI is required to use `#[track_caller]`
|
||||
#[track_caller]
|
||||
extern "C" fn f() {}
|
||||
//~^^ ERROR `#[track_caller]` requires Rust ABI
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,4 @@
|
|||
warning: the feature `track_caller` is incomplete and may cause the compiler to crash
|
||||
--> $DIR/error-with-invalid-abi.rs:1:12
|
||||
|
|
||||
LL | #![feature(track_caller)]
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error[E0737]: Rust ABI is required to use `#[track_caller]`
|
||||
error[E0737]: `#[track_caller]` requires Rust ABI
|
||||
--> $DIR/error-with-invalid-abi.rs:3:1
|
||||
|
|
||||
LL | #[track_caller]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#![feature(naked_functions, track_caller)] //~ WARN the feature `track_caller` is incomplete
|
||||
#![feature(naked_functions, track_caller)]
|
||||
|
||||
#[track_caller]
|
||||
#[naked]
|
||||
|
|
|
|||
|
|
@ -1,11 +1,3 @@
|
|||
warning: the feature `track_caller` is incomplete and may cause the compiler to crash
|
||||
--> $DIR/error-with-naked.rs:1:29
|
||||
|
|
||||
LL | #![feature(naked_functions, track_caller)]
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error[E0736]: cannot use `#[track_caller]` with `#[naked]`
|
||||
--> $DIR/error-with-naked.rs:3:1
|
||||
|
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete
|
||||
#![feature(track_caller)]
|
||||
|
||||
trait Trait {
|
||||
#[track_caller] //~ ERROR: `#[track_caller]` may not be used on trait methods
|
||||
|
|
|
|||
|
|
@ -1,11 +1,3 @@
|
|||
warning: the feature `track_caller` is incomplete and may cause the compiler to crash
|
||||
--> $DIR/error-with-trait-decl.rs:1:12
|
||||
|
|
||||
LL | #![feature(track_caller)]
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error[E0738]: `#[track_caller]` may not be used on trait methods
|
||||
--> $DIR/error-with-trait-decl.rs:4:5
|
||||
|
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete
|
||||
#![feature(track_caller)]
|
||||
|
||||
trait Trait {
|
||||
#[track_caller] //~ ERROR: `#[track_caller]` may not be used on trait methods
|
||||
|
|
|
|||
|
|
@ -1,11 +1,3 @@
|
|||
warning: the feature `track_caller` is incomplete and may cause the compiler to crash
|
||||
--> $DIR/error-with-trait-default-impl.rs:1:12
|
||||
|
|
||||
LL | #![feature(track_caller)]
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error[E0738]: `#[track_caller]` may not be used on trait methods
|
||||
--> $DIR/error-with-trait-default-impl.rs:4:5
|
||||
|
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// check-fail
|
||||
|
||||
#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete
|
||||
#![feature(track_caller)]
|
||||
|
||||
trait Trait {
|
||||
fn unwrap(&self);
|
||||
|
|
|
|||
|
|
@ -1,11 +1,3 @@
|
|||
warning: the feature `track_caller` is incomplete and may cause the compiler to crash
|
||||
--> $DIR/error-with-trait-fn-impl.rs:3:12
|
||||
|
|
||||
LL | #![feature(track_caller)]
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error[E0738]: `#[track_caller]` may not be used on trait methods
|
||||
--> $DIR/error-with-trait-fn-impl.rs:10:5
|
||||
|
|
||||
|
|
|
|||
21
src/test/ui/rfc-2091-track-caller/intrinsic-wrapper.rs
Normal file
21
src/test/ui/rfc-2091-track-caller/intrinsic-wrapper.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
// run-pass
|
||||
|
||||
#![feature(track_caller)]
|
||||
|
||||
macro_rules! caller_location_from_macro {
|
||||
() => (core::panic::Location::caller());
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let loc = core::panic::Location::caller();
|
||||
assert_eq!(loc.file(), file!());
|
||||
assert_eq!(loc.line(), 10);
|
||||
assert_eq!(loc.column(), 15);
|
||||
|
||||
// `Location::caller()` in a macro should behave similarly to `file!` and `line!`,
|
||||
// i.e. point to where the macro was invoked, instead of the macro itself.
|
||||
let loc2 = caller_location_from_macro!();
|
||||
assert_eq!(loc2.file(), file!());
|
||||
assert_eq!(loc2.line(), 17);
|
||||
assert_eq!(loc2.column(), 16);
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete
|
||||
#![feature(track_caller)]
|
||||
|
||||
#[track_caller]
|
||||
struct S;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,3 @@
|
|||
warning: the feature `track_caller` is incomplete and may cause the compiler to crash
|
||||
--> $DIR/only-for-fns.rs:1:12
|
||||
|
|
||||
LL | #![feature(track_caller)]
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error[E0739]: attribute should be applied to function
|
||||
--> $DIR/only-for-fns.rs:3:1
|
||||
|
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// run-pass
|
||||
#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete
|
||||
#![feature(track_caller)]
|
||||
|
||||
#[track_caller]
|
||||
fn f() {}
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
warning: the feature `track_caller` is incomplete and may cause the compiler to crash
|
||||
--> $DIR/pass.rs:2:12
|
||||
|
|
||||
LL | #![feature(track_caller)]
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
40
src/test/ui/rfc-2091-track-caller/track-caller-attribute.rs
Normal file
40
src/test/ui/rfc-2091-track-caller/track-caller-attribute.rs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
// run-pass
|
||||
|
||||
#![feature(const_fn, track_caller)]
|
||||
|
||||
use std::panic::Location;
|
||||
|
||||
#[track_caller]
|
||||
fn tracked() -> &'static Location<'static> {
|
||||
Location::caller()
|
||||
}
|
||||
|
||||
fn nested_intrinsic() -> &'static Location<'static> {
|
||||
Location::caller()
|
||||
}
|
||||
|
||||
fn nested_tracked() -> &'static Location<'static> {
|
||||
tracked()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let location = Location::caller();
|
||||
assert_eq!(location.file(), file!());
|
||||
assert_eq!(location.line(), 21);
|
||||
assert_eq!(location.column(), 20);
|
||||
|
||||
let tracked = tracked();
|
||||
assert_eq!(tracked.file(), file!());
|
||||
assert_eq!(tracked.line(), 26);
|
||||
assert_eq!(tracked.column(), 19);
|
||||
|
||||
let nested = nested_intrinsic();
|
||||
assert_eq!(nested.file(), file!());
|
||||
assert_eq!(nested.line(), 13);
|
||||
assert_eq!(nested.column(), 5);
|
||||
|
||||
let contained = nested_tracked();
|
||||
assert_eq!(contained.file(), file!());
|
||||
assert_eq!(contained.line(), 17);
|
||||
assert_eq!(contained.column(), 5);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue