[RFC 2091] Add #[track_caller] attribute.
- The attribute is behind a feature gate. - Error if both #[naked] and #[track_caller] are applied to the same function. - Error if #[track_caller] is applied to a non-function item. - Error if ABI is not "rust" - Error if #[track_caller] is applied to a trait function. Error codes and descriptions are pending.
This commit is contained in:
parent
e3cb9ea15a
commit
543449d4fd
22 changed files with 199 additions and 1 deletions
|
@ -0,0 +1,5 @@
|
||||||
|
# `track_caller`
|
||||||
|
|
||||||
|
The tracking issue for this feature is: [#47809](https://github.com/rust-lang/rust/issues/47809).
|
||||||
|
|
||||||
|
------------------------
|
|
@ -1640,6 +1640,16 @@ each method; it is not possible to annotate the entire impl with an `#[inline]`
|
||||||
attribute.
|
attribute.
|
||||||
"##,
|
"##,
|
||||||
|
|
||||||
|
E0900: r##"
|
||||||
|
TODO: change error number
|
||||||
|
TODO: track_caller: invalid syntax
|
||||||
|
"##,
|
||||||
|
|
||||||
|
E0901: r##"
|
||||||
|
TODO: change error number
|
||||||
|
TODO: track_caller: no naked functions
|
||||||
|
"##,
|
||||||
|
|
||||||
E0522: r##"
|
E0522: r##"
|
||||||
The lang attribute is intended for marking special items that are built-in to
|
The lang attribute is intended for marking special items that are built-in to
|
||||||
Rust itself. This includes special traits (like `Copy` and `Sized`) that affect
|
Rust itself. This includes special traits (like `Copy` and `Sized`) that affect
|
||||||
|
|
|
@ -94,6 +94,7 @@ impl CheckAttrVisitor<'tcx> {
|
||||||
/// Checks any attribute.
|
/// Checks any attribute.
|
||||||
fn check_attributes(&self, item: &hir::Item, target: Target) {
|
fn check_attributes(&self, item: &hir::Item, target: Target) {
|
||||||
let mut is_valid = true;
|
let mut is_valid = true;
|
||||||
|
let mut track_caller_span = None;
|
||||||
for attr in &item.attrs {
|
for attr in &item.attrs {
|
||||||
is_valid &= if attr.check_name(sym::inline) {
|
is_valid &= if attr.check_name(sym::inline) {
|
||||||
self.check_inline(attr, &item.span, target)
|
self.check_inline(attr, &item.span, target)
|
||||||
|
@ -103,6 +104,9 @@ impl CheckAttrVisitor<'tcx> {
|
||||||
self.check_marker(attr, item, target)
|
self.check_marker(attr, item, target)
|
||||||
} else if attr.check_name(sym::target_feature) {
|
} else if attr.check_name(sym::target_feature) {
|
||||||
self.check_target_feature(attr, item, target)
|
self.check_target_feature(attr, item, target)
|
||||||
|
} else if attr.check_name(sym::track_caller) {
|
||||||
|
track_caller_span = Some(attr.span);
|
||||||
|
self.check_track_caller(attr, &item, target)
|
||||||
} else {
|
} else {
|
||||||
true
|
true
|
||||||
};
|
};
|
||||||
|
@ -118,6 +122,19 @@ impl CheckAttrVisitor<'tcx> {
|
||||||
|
|
||||||
self.check_repr(item, target);
|
self.check_repr(item, target);
|
||||||
self.check_used(item, target);
|
self.check_used(item, target);
|
||||||
|
|
||||||
|
// Checks if `#[track_caller]` and `#[naked]` are both used.
|
||||||
|
if let Some(span) = track_caller_span {
|
||||||
|
if item.attrs.iter().any(|attr| attr.check_name(sym::naked)) {
|
||||||
|
struct_span_err!(
|
||||||
|
self.tcx.sess,
|
||||||
|
span,
|
||||||
|
E0901,
|
||||||
|
"cannot use `#[track_caller]` with `#[naked]`",
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks if an `#[inline]` is applied to a function or a closure. Returns `true` if valid.
|
/// Checks if an `#[inline]` is applied to a function or a closure. Returns `true` if valid.
|
||||||
|
@ -135,6 +152,23 @@ impl CheckAttrVisitor<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks if a `#[target_feature]` can be applied.
|
||||||
|
fn check_track_caller(&self, attr: &hir::Attribute, item: &hir::Item, target: Target) -> bool {
|
||||||
|
if target != Target::Fn {
|
||||||
|
struct_span_err!(
|
||||||
|
self.tcx.sess,
|
||||||
|
attr.span,
|
||||||
|
E0900,
|
||||||
|
"attribute should be applied to function"
|
||||||
|
)
|
||||||
|
.span_label(item.span, "not a function")
|
||||||
|
.emit();
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Checks if the `#[non_exhaustive]` attribute on an `item` is valid. Returns `true` if valid.
|
/// Checks if the `#[non_exhaustive]` attribute on an `item` is valid. Returns `true` if valid.
|
||||||
fn check_non_exhaustive(
|
fn check_non_exhaustive(
|
||||||
&self,
|
&self,
|
||||||
|
|
|
@ -2721,7 +2721,9 @@ bitflags! {
|
||||||
const USED = 1 << 9;
|
const USED = 1 << 9;
|
||||||
/// #[ffi_returns_twice], indicates that an extern function can return
|
/// #[ffi_returns_twice], indicates that an extern function can return
|
||||||
/// multiple times
|
/// multiple times
|
||||||
const FFI_RETURNS_TWICE = 1 << 10;
|
const FFI_RETURNS_TWICE = 1 << 10;
|
||||||
|
/// #[track_caller]: allow access to the caller location
|
||||||
|
const TRACK_CALLER = 1 << 11;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -172,6 +172,18 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: DefId) {
|
||||||
_ => None
|
_ => None
|
||||||
};
|
};
|
||||||
check_associated_item(tcx, trait_item.hir_id, trait_item.span, method_sig);
|
check_associated_item(tcx, trait_item.hir_id, trait_item.span, method_sig);
|
||||||
|
|
||||||
|
// Prohibits applying `#[track_caller]` to trait methods
|
||||||
|
for attr in &trait_item.attrs {
|
||||||
|
if attr.check_name(sym::track_caller) {
|
||||||
|
struct_span_err!(
|
||||||
|
tcx.sess,
|
||||||
|
attr.span,
|
||||||
|
E0903,
|
||||||
|
"`#[track_caller]` is not supported for trait items yet."
|
||||||
|
).emit();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: DefId) {
|
pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: DefId) {
|
||||||
|
|
|
@ -2594,6 +2594,16 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
|
||||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED;
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED;
|
||||||
} else if attr.check_name(sym::thread_local) {
|
} else if attr.check_name(sym::thread_local) {
|
||||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL;
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL;
|
||||||
|
} else if attr.check_name(sym::track_caller) {
|
||||||
|
if tcx.fn_sig(id).abi() != abi::Abi::Rust {
|
||||||
|
struct_span_err!(
|
||||||
|
tcx.sess,
|
||||||
|
attr.span,
|
||||||
|
E0902,
|
||||||
|
"rust ABI is required to use `#[track_caller]`"
|
||||||
|
).emit();
|
||||||
|
}
|
||||||
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
|
||||||
} else if attr.check_name(sym::export_name) {
|
} else if attr.check_name(sym::export_name) {
|
||||||
if let Some(s) = attr.value_str() {
|
if let Some(s) = attr.value_str() {
|
||||||
if s.as_str().contains("\0") {
|
if s.as_str().contains("\0") {
|
||||||
|
|
|
@ -4907,6 +4907,17 @@ fn foo_recursive(n: usize) -> Pin<Box<dyn Future<Output = ()>>> {
|
||||||
The `Box<...>` ensures that the result is of known size,
|
The `Box<...>` ensures that the result is of known size,
|
||||||
and the pin is required to keep it in the same place in memory.
|
and the pin is required to keep it in the same place in memory.
|
||||||
"##,
|
"##,
|
||||||
|
|
||||||
|
E0902: r##"
|
||||||
|
TODO: change error number
|
||||||
|
TODO: track_caller: require Rust ABI to use track_caller
|
||||||
|
"##,
|
||||||
|
|
||||||
|
E0903: r##"
|
||||||
|
TODO: change error number
|
||||||
|
TODO: track_caller: can't apply in traits
|
||||||
|
"##,
|
||||||
|
|
||||||
;
|
;
|
||||||
// E0035, merged into E0087/E0089
|
// E0035, merged into E0087/E0089
|
||||||
// E0036, merged into E0087/E0089
|
// E0036, merged into E0087/E0089
|
||||||
|
|
|
@ -525,6 +525,9 @@ declare_features! (
|
||||||
// Allows the use of raw-dylibs (RFC 2627).
|
// Allows the use of raw-dylibs (RFC 2627).
|
||||||
(active, raw_dylib, "1.40.0", Some(58713), None),
|
(active, raw_dylib, "1.40.0", Some(58713), None),
|
||||||
|
|
||||||
|
/// Enable accurate caller location reporting during panic (RFC 2091).
|
||||||
|
(active, track_caller, "1.37.0", Some(47809), None),
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// feature-group-end: actual feature gates
|
// feature-group-end: actual feature gates
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
|
|
|
@ -499,6 +499,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||||
cfg_fn!(no_debug)
|
cfg_fn!(no_debug)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
gated!(
|
||||||
|
track_caller, Whitelisted, template!(Word),
|
||||||
|
"the `#[track_caller]` attribute is an experimental feature",
|
||||||
|
),
|
||||||
gated!(
|
gated!(
|
||||||
// Used in resolve:
|
// Used in resolve:
|
||||||
prelude_import, Whitelisted, template!(Word),
|
prelude_import, Whitelisted, template!(Word),
|
||||||
|
|
|
@ -674,6 +674,7 @@ symbols! {
|
||||||
tool_attributes,
|
tool_attributes,
|
||||||
tool_lints,
|
tool_lints,
|
||||||
trace_macros,
|
trace_macros,
|
||||||
|
track_caller,
|
||||||
trait_alias,
|
trait_alias,
|
||||||
transmute,
|
transmute,
|
||||||
transparent,
|
transparent,
|
||||||
|
|
6
src/test/ui/feature-gates/feature-gate-track_caller.rs
Normal file
6
src/test/ui/feature-gates/feature-gate-track_caller.rs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
|
fn f() {}
|
||||||
|
//~^^ ERROR the `#[track_caller]` attribute is an experimental feature
|
||||||
|
|
||||||
|
fn main() {}
|
12
src/test/ui/feature-gates/feature-gate-track_caller.stderr
Normal file
12
src/test/ui/feature-gates/feature-gate-track_caller.stderr
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
error[E0658]: the `#[track_caller]` attribute is an experimental feature
|
||||||
|
--> $DIR/feature-gate-track_caller.rs:2:1
|
||||||
|
|
|
||||||
|
LL | #[track_caller]
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: for more information, see https://github.com/rust-lang/rust/issues/47809
|
||||||
|
= help: add `#![feature(track_caller)]` to the crate attributes to enable
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0658`.
|
7
src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs
Normal file
7
src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#![feature(track_caller)]
|
||||||
|
|
||||||
|
#[track_caller(1)]
|
||||||
|
fn f() {}
|
||||||
|
//~^^ ERROR malformed `track_caller` attribute input
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,8 @@
|
||||||
|
error: malformed `track_caller` attribute input
|
||||||
|
--> $DIR/error-odd-syntax.rs:3:1
|
||||||
|
|
|
||||||
|
LL | #[track_caller(1)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[track_caller]`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
#![feature(track_caller)]
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
|
extern "C" fn f() {}
|
||||||
|
//~^^ ERROR rust ABI is required to use `#[track_caller]`
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,9 @@
|
||||||
|
error[E0902]: rust ABI is required to use `#[track_caller]`
|
||||||
|
--> $DIR/error-with-invalid-abi.rs:3:1
|
||||||
|
|
|
||||||
|
LL | #[track_caller]
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0902`.
|
8
src/test/ui/rfc-2091-track-caller/error-with-naked.rs
Normal file
8
src/test/ui/rfc-2091-track-caller/error-with-naked.rs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#![feature(naked_functions, track_caller)]
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
|
#[naked]
|
||||||
|
fn f() {}
|
||||||
|
//~^^^ ERROR cannot use `#[track_caller]` with `#[naked]`
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,9 @@
|
||||||
|
error[E0901]: cannot use `#[track_caller]` with `#[naked]`
|
||||||
|
--> $DIR/error-with-naked.rs:3:1
|
||||||
|
|
|
||||||
|
LL | #[track_caller]
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0901`.
|
13
src/test/ui/rfc-2091-track-caller/error-with-trait-fns.rs
Normal file
13
src/test/ui/rfc-2091-track-caller/error-with-trait-fns.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#![feature(track_caller)]
|
||||||
|
|
||||||
|
trait Trait {
|
||||||
|
#[track_caller]
|
||||||
|
fn unwrap(&self);
|
||||||
|
//~^^ ERROR: `#[track_caller]` is not supported for trait items yet.
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Trait for u64 {
|
||||||
|
fn unwrap(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,9 @@
|
||||||
|
error[E0903]: `#[track_caller]` is not supported for trait items yet.
|
||||||
|
--> $DIR/error-with-trait-fns.rs:4:5
|
||||||
|
|
|
||||||
|
LL | #[track_caller]
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0903`.
|
7
src/test/ui/rfc-2091-track-caller/only-for-fns.rs
Normal file
7
src/test/ui/rfc-2091-track-caller/only-for-fns.rs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#![feature(track_caller)]
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
|
struct S;
|
||||||
|
//~^^ ERROR attribute should be applied to function
|
||||||
|
|
||||||
|
fn main() {}
|
11
src/test/ui/rfc-2091-track-caller/only-for-fns.stderr
Normal file
11
src/test/ui/rfc-2091-track-caller/only-for-fns.stderr
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
error[E0900]: attribute should be applied to function
|
||||||
|
--> $DIR/only-for-fns.rs:3:1
|
||||||
|
|
|
||||||
|
LL | #[track_caller]
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
LL | struct S;
|
||||||
|
| --------- not a function
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0900`.
|
Loading…
Add table
Add a link
Reference in a new issue