Rollup merge of #65037 - anp:track-caller, r=oli-obk
`#[track_caller]` feature gate (RFC 2091 1/N) RFC text: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md Tracking issue: https://github.com/rust-lang/rust/issues/47809 I started with @ayosec's commit to add the feature gate with tests and rebased it onto current master. I fixed up some tidy lints and added a test.
This commit is contained in:
commit
ae5bb7e289
@ -0,0 +1,5 @@
|
||||
# `track_caller`
|
||||
|
||||
The tracking issue for this feature is: [#47809](https://github.com/rust-lang/rust/issues/47809).
|
||||
|
||||
------------------------
|
@ -2120,6 +2120,25 @@ These attributes are meant to only be used by the standard library and are
|
||||
rejected in your own crates.
|
||||
"##,
|
||||
|
||||
E0736: r##"
|
||||
#[track_caller] and #[naked] cannot be applied to the same function.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0736
|
||||
#![feature(track_caller)]
|
||||
|
||||
#[naked]
|
||||
#[track_caller]
|
||||
fn foo() {}
|
||||
```
|
||||
|
||||
This is primarily due to ABI incompatibilities between the two attributes.
|
||||
See [RFC 2091] for details on this and other limitations.
|
||||
|
||||
[RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md
|
||||
"##,
|
||||
|
||||
;
|
||||
// E0006, // merged with E0005
|
||||
// E0101, // replaced with E0282
|
||||
@ -2179,4 +2198,5 @@ rejected in your own crates.
|
||||
E0726, // non-explicit (not `'_`) elided lifetime in unsupported position
|
||||
E0727, // `async` generators are not yet supported
|
||||
E0728, // `await` must be in an `async` function or block
|
||||
E0739, // invalid track_caller application/syntax
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ use crate::ty::TyCtxt;
|
||||
use crate::ty::query::Providers;
|
||||
|
||||
use std::fmt::{self, Display};
|
||||
use syntax::symbol::sym;
|
||||
use syntax::{attr, symbol::sym};
|
||||
use syntax_pos::Span;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
@ -103,6 +103,8 @@ impl CheckAttrVisitor<'tcx> {
|
||||
self.check_marker(attr, item, target)
|
||||
} else if attr.check_name(sym::target_feature) {
|
||||
self.check_target_feature(attr, item, target)
|
||||
} else if attr.check_name(sym::track_caller) {
|
||||
self.check_track_caller(attr, &item, target)
|
||||
} else {
|
||||
true
|
||||
};
|
||||
@ -135,6 +137,32 @@ impl CheckAttrVisitor<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if a `#[track_caller]` is applied to a non-naked function. Returns `true` if valid.
|
||||
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,
|
||||
E0739,
|
||||
"attribute should be applied to function"
|
||||
)
|
||||
.span_label(item.span, "not a function")
|
||||
.emit();
|
||||
false
|
||||
} else if attr::contains_name(&item.attrs, sym::naked) {
|
||||
struct_span_err!(
|
||||
self.tcx.sess,
|
||||
attr.span,
|
||||
E0736,
|
||||
"cannot use `#[track_caller]` with `#[naked]`",
|
||||
)
|
||||
.emit();
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if the `#[non_exhaustive]` attribute on an `item` is valid. Returns `true` if valid.
|
||||
fn check_non_exhaustive(
|
||||
&self,
|
||||
|
@ -2734,7 +2734,9 @@ bitflags! {
|
||||
const USED = 1 << 9;
|
||||
/// #[ffi_returns_twice], indicates that an extern function can return
|
||||
/// 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
|
||||
};
|
||||
check_associated_item(tcx, trait_item.hir_id, trait_item.span, method_sig);
|
||||
|
||||
// Prohibits applying `#[track_caller]` to trait decls
|
||||
for attr in &trait_item.attrs {
|
||||
if attr.check_name(sym::track_caller) {
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
attr.span,
|
||||
E0738,
|
||||
"`#[track_caller]` is not supported in trait declarations."
|
||||
).emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: DefId) {
|
||||
@ -182,6 +194,30 @@ pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: DefId) {
|
||||
hir::ImplItemKind::Method(ref sig, _) => Some(sig),
|
||||
_ => None
|
||||
};
|
||||
|
||||
// Prohibits applying `#[track_caller]` to trait impls
|
||||
if method_sig.is_some() {
|
||||
let track_caller_attr = impl_item.attrs.iter()
|
||||
.find(|a| a.check_name(sym::track_caller));
|
||||
if let Some(tc_attr) = track_caller_attr {
|
||||
let parent_hir_id = tcx.hir().get_parent_item(hir_id);
|
||||
let containing_item = tcx.hir().expect_item(parent_hir_id);
|
||||
let containing_impl_is_for_trait = match &containing_item.kind {
|
||||
hir::ItemKind::Impl(_, _, _, _, tr, _, _) => tr.is_some(),
|
||||
_ => bug!("parent of an ImplItem must be an Impl"),
|
||||
};
|
||||
|
||||
if containing_impl_is_for_trait {
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
tc_attr.span,
|
||||
E0738,
|
||||
"`#[track_caller]` is not supported in traits yet."
|
||||
).emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
check_associated_item(tcx, impl_item.hir_id, impl_item.span, method_sig);
|
||||
}
|
||||
|
||||
|
@ -2594,6 +2594,16 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED;
|
||||
} else if attr.check_name(sym::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,
|
||||
E0737,
|
||||
"rust ABI is required to use `#[track_caller]`"
|
||||
).emit();
|
||||
}
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
|
||||
} else if attr.check_name(sym::export_name) {
|
||||
if let Some(s) = attr.value_str() {
|
||||
if s.as_str().contains("\0") {
|
||||
|
@ -4905,6 +4905,75 @@ fn foo_recursive(n: usize) -> Pin<Box<dyn Future<Output = ()>>> {
|
||||
The `Box<...>` ensures that the result is of known size,
|
||||
and the pin is required to keep it in the same place in memory.
|
||||
"##,
|
||||
|
||||
E0737: r##"
|
||||
#[track_caller] requires functions to have the "Rust" ABI for implicitly
|
||||
receiving caller location. See [RFC 2091] for details on this and other
|
||||
restrictions.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0737
|
||||
#![feature(track_caller)]
|
||||
|
||||
#[track_caller]
|
||||
extern "C" fn foo() {}
|
||||
```
|
||||
|
||||
[RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md
|
||||
"##,
|
||||
|
||||
E0738: r##"
|
||||
#[track_caller] cannot be used in traits yet. This is due to limitations in the
|
||||
compiler which are likely to be temporary. See [RFC 2091] for details on this
|
||||
and other restrictions.
|
||||
|
||||
Erroneous example with a trait method implementation:
|
||||
|
||||
```compile_fail,E0738
|
||||
#![feature(track_caller)]
|
||||
|
||||
trait Foo {
|
||||
fn bar(&self);
|
||||
}
|
||||
|
||||
impl Foo for u64 {
|
||||
#[track_caller]
|
||||
fn bar(&self) {}
|
||||
}
|
||||
```
|
||||
|
||||
Erroneous example with a blanket trait method implementation:
|
||||
|
||||
```compile_fail,E0738
|
||||
#![feature(track_caller)]
|
||||
|
||||
trait Foo {
|
||||
#[track_caller]
|
||||
fn bar(&self) {}
|
||||
fn baz(&self);
|
||||
}
|
||||
```
|
||||
|
||||
Erroneous example with a trait method declaration:
|
||||
|
||||
```compile_fail,E0738
|
||||
#![feature(track_caller)]
|
||||
|
||||
trait Foo {
|
||||
fn bar(&self) {}
|
||||
|
||||
#[track_caller]
|
||||
fn baz(&self);
|
||||
}
|
||||
```
|
||||
|
||||
Note that while the compiler may be able to support the attribute in traits in
|
||||
the future, [RFC 2091] prohibits their implementation without a follow-up RFC.
|
||||
|
||||
[RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md
|
||||
"##,
|
||||
|
||||
;
|
||||
// E0035, merged into E0087/E0089
|
||||
// E0036, merged into E0087/E0089
|
||||
|
@ -525,6 +525,9 @@ declare_features! (
|
||||
// Allows the use of raw-dylibs (RFC 2627).
|
||||
(active, raw_dylib, "1.40.0", Some(58713), None),
|
||||
|
||||
/// Enable accurate caller location reporting during panic (RFC 2091).
|
||||
(active, track_caller, "1.40.0", Some(47809), None),
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// feature-group-end: actual feature gates
|
||||
// -------------------------------------------------------------------------
|
||||
@ -540,4 +543,5 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[
|
||||
sym::or_patterns,
|
||||
sym::let_chains,
|
||||
sym::raw_dylib,
|
||||
sym::track_caller,
|
||||
];
|
||||
|
@ -324,6 +324,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||
),
|
||||
|
||||
gated!(ffi_returns_twice, Whitelisted, template!(Word), experimental!(ffi_returns_twice)),
|
||||
gated!(track_caller, Whitelisted, template!(Word), experimental!(track_caller)),
|
||||
|
||||
// ==========================================================================
|
||||
// Internal attributes: Stability, deprecation, and unsafe:
|
||||
|
@ -674,6 +674,7 @@ symbols! {
|
||||
tool_attributes,
|
||||
tool_lints,
|
||||
trace_macros,
|
||||
track_caller,
|
||||
trait_alias,
|
||||
transmute,
|
||||
transparent,
|
||||
|
5
src/test/ui/feature-gates/feature-gate-track_caller.rs
Normal file
5
src/test/ui/feature-gates/feature-gate-track_caller.rs
Normal file
@ -0,0 +1,5 @@
|
||||
#[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:1: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)] //~ WARN the feature `track_caller` is incomplete
|
||||
|
||||
#[track_caller(1)]
|
||||
fn f() {}
|
||||
//~^^ ERROR malformed `track_caller` attribute input
|
||||
|
||||
fn main() {}
|
16
src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr
Normal file
16
src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr
Normal file
@ -0,0 +1,16 @@
|
||||
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]`
|
||||
|
||||
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
|
||||
|
@ -0,0 +1,7 @@
|
||||
#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete
|
||||
|
||||
#[track_caller]
|
||||
extern "C" fn f() {}
|
||||
//~^^ ERROR rust ABI is required to use `#[track_caller]`
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,17 @@
|
||||
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]`
|
||||
--> $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 E0737`.
|
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)] //~ WARN the feature `track_caller` is incomplete
|
||||
|
||||
#[track_caller]
|
||||
#[naked]
|
||||
fn f() {}
|
||||
//~^^^ ERROR cannot use `#[track_caller]` with `#[naked]`
|
||||
|
||||
fn main() {}
|
17
src/test/ui/rfc-2091-track-caller/error-with-naked.stderr
Normal file
17
src/test/ui/rfc-2091-track-caller/error-with-naked.stderr
Normal file
@ -0,0 +1,17 @@
|
||||
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
|
||||
|
|
||||
LL | #[track_caller]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0736`.
|
13
src/test/ui/rfc-2091-track-caller/error-with-trait-decl.rs
Normal file
13
src/test/ui/rfc-2091-track-caller/error-with-trait-decl.rs
Normal file
@ -0,0 +1,13 @@
|
||||
#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete
|
||||
|
||||
trait Trait {
|
||||
#[track_caller]
|
||||
fn unwrap(&self);
|
||||
//~^^ ERROR: `#[track_caller]` is not supported in trait declarations.
|
||||
}
|
||||
|
||||
impl Trait for u64 {
|
||||
fn unwrap(&self) {}
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,17 @@
|
||||
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]` is not supported in trait declarations.
|
||||
--> $DIR/error-with-trait-decl.rs:4:5
|
||||
|
|
||||
LL | #[track_caller]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0738`.
|
@ -0,0 +1,9 @@
|
||||
#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete
|
||||
|
||||
trait Trait {
|
||||
#[track_caller]
|
||||
fn unwrap(&self) {}
|
||||
//~^^ ERROR: `#[track_caller]` is not supported in trait declarations.
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,17 @@
|
||||
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]` is not supported in trait declarations.
|
||||
--> $DIR/error-with-trait-default-impl.rs:4:5
|
||||
|
|
||||
LL | #[track_caller]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0738`.
|
@ -0,0 +1,13 @@
|
||||
#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete
|
||||
|
||||
trait Trait {
|
||||
fn unwrap(&self);
|
||||
}
|
||||
|
||||
impl Trait for u64 {
|
||||
#[track_caller]
|
||||
fn unwrap(&self) {}
|
||||
//~^^ ERROR: `#[track_caller]` is not supported in traits yet.
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,17 @@
|
||||
warning: the feature `track_caller` is incomplete and may cause the compiler to crash
|
||||
--> $DIR/error-with-trait-fn-impl.rs:1:12
|
||||
|
|
||||
LL | #![feature(track_caller)]
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error[E0738]: `#[track_caller]` is not supported in traits yet.
|
||||
--> $DIR/error-with-trait-fn-impl.rs:8:5
|
||||
|
|
||||
LL | #[track_caller]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0738`.
|
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)] //~ WARN the feature `track_caller` is incomplete
|
||||
|
||||
#[track_caller]
|
||||
struct S;
|
||||
//~^^ ERROR attribute should be applied to function
|
||||
|
||||
fn main() {}
|
18
src/test/ui/rfc-2091-track-caller/only-for-fns.stderr
Normal file
18
src/test/ui/rfc-2091-track-caller/only-for-fns.stderr
Normal file
@ -0,0 +1,18 @@
|
||||
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
|
||||
|
|
||||
LL | #[track_caller]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
LL | struct S;
|
||||
| --------- not a function
|
||||
|
||||
error: aborting due to previous error
|
||||
|
9
src/test/ui/rfc-2091-track-caller/pass.rs
Normal file
9
src/test/ui/rfc-2091-track-caller/pass.rs
Normal file
@ -0,0 +1,9 @@
|
||||
// run-pass
|
||||
#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete
|
||||
|
||||
#[track_caller]
|
||||
fn f() {}
|
||||
|
||||
fn main() {
|
||||
f();
|
||||
}
|
8
src/test/ui/rfc-2091-track-caller/pass.stderr
Normal file
8
src/test/ui/rfc-2091-track-caller/pass.stderr
Normal file
@ -0,0 +1,8 @@
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user