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

#[track_caller] feature gate (RFC 2091 1/N) #65037

Merged
merged 13 commits into from
Oct 9, 2019
5 changes: 5 additions & 0 deletions src/doc/unstable-book/src/language-features/track-caller.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# `track_caller`

The tracking issue for this feature is: [#47809](https://github.com/rust-lang/rust/issues/47809).

------------------------
20 changes: 20 additions & 0 deletions src/librustc/error_codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2075,6 +2075,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
Expand Down Expand Up @@ -2136,4 +2155,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
}
30 changes: 29 additions & 1 deletion src/librustc/hir/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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
};
Expand Down Expand Up @@ -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,
Expand Down
4 changes: 3 additions & 1 deletion src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2721,7 +2721,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;
}
}

Expand Down
36 changes: 36 additions & 0 deletions src/librustc_typeck/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Centril marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why isn't this in check_attr.rs instead?

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) {
Expand All @@ -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);
}

Expand Down
10 changes: 10 additions & 0 deletions src/librustc_typeck/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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") {
Expand Down
69 changes: 69 additions & 0 deletions src/librustc_typeck/error_codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4907,6 +4907,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
Expand Down
4 changes: 4 additions & 0 deletions src/libsyntax/feature_gate/active.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
// -------------------------------------------------------------------------
Expand All @@ -540,4 +543,5 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[
sym::or_patterns,
sym::let_chains,
sym::raw_dylib,
sym::track_caller,
];
1 change: 1 addition & 0 deletions src/libsyntax/feature_gate/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
1 change: 1 addition & 0 deletions src/libsyntax_pos/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,7 @@ symbols! {
tool_attributes,
tool_lints,
trace_macros,
track_caller,
trait_alias,
transmute,
transparent,
Expand Down
5 changes: 5 additions & 0 deletions src/test/ui/feature-gates/feature-gate-track_caller.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#[track_caller]
fn f() {}
//~^^ ERROR the `#[track_caller]` attribute is an experimental feature

fn main() {}
12 changes: 12 additions & 0 deletions src/test/ui/feature-gates/feature-gate-track_caller.stderr
Original file line number Diff line number Diff line change
@@ -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 changes: 7 additions & 0 deletions src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 16 additions & 0 deletions src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr
Original file line number Diff line number Diff line change
@@ -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

7 changes: 7 additions & 0 deletions src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs
Original file line number Diff line number Diff line change
@@ -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() {}
17 changes: 17 additions & 0 deletions src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr
Original file line number Diff line number Diff line change
@@ -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 changes: 8 additions & 0 deletions src/test/ui/rfc-2091-track-caller/error-with-naked.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 17 additions & 0 deletions src/test/ui/rfc-2091-track-caller/error-with-naked.stderr
Original file line number Diff line number Diff line change
@@ -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 changes: 13 additions & 0 deletions src/test/ui/rfc-2091-track-caller/error-with-trait-decl.rs
Original file line number Diff line number Diff line change
@@ -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() {}
Loading