Skip to content

Commit 543449d

Browse files
ayosecanp
authored andcommitted
[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.
1 parent e3cb9ea commit 543449d

22 files changed

+199
-1
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# `track_caller`
2+
3+
The tracking issue for this feature is: [#47809](https://github.com/rust-lang/rust/issues/47809).
4+
5+
------------------------

src/librustc/error_codes.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1640,6 +1640,16 @@ each method; it is not possible to annotate the entire impl with an `#[inline]`
16401640
attribute.
16411641
"##,
16421642

1643+
E0900: r##"
1644+
TODO: change error number
1645+
TODO: track_caller: invalid syntax
1646+
"##,
1647+
1648+
E0901: r##"
1649+
TODO: change error number
1650+
TODO: track_caller: no naked functions
1651+
"##,
1652+
16431653
E0522: r##"
16441654
The lang attribute is intended for marking special items that are built-in to
16451655
Rust itself. This includes special traits (like `Copy` and `Sized`) that affect

src/librustc/hir/check_attr.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ impl CheckAttrVisitor<'tcx> {
9494
/// Checks any attribute.
9595
fn check_attributes(&self, item: &hir::Item, target: Target) {
9696
let mut is_valid = true;
97+
let mut track_caller_span = None;
9798
for attr in &item.attrs {
9899
is_valid &= if attr.check_name(sym::inline) {
99100
self.check_inline(attr, &item.span, target)
@@ -103,6 +104,9 @@ impl CheckAttrVisitor<'tcx> {
103104
self.check_marker(attr, item, target)
104105
} else if attr.check_name(sym::target_feature) {
105106
self.check_target_feature(attr, item, target)
107+
} else if attr.check_name(sym::track_caller) {
108+
track_caller_span = Some(attr.span);
109+
self.check_track_caller(attr, &item, target)
106110
} else {
107111
true
108112
};
@@ -118,6 +122,19 @@ impl CheckAttrVisitor<'tcx> {
118122

119123
self.check_repr(item, target);
120124
self.check_used(item, target);
125+
126+
// Checks if `#[track_caller]` and `#[naked]` are both used.
127+
if let Some(span) = track_caller_span {
128+
if item.attrs.iter().any(|attr| attr.check_name(sym::naked)) {
129+
struct_span_err!(
130+
self.tcx.sess,
131+
span,
132+
E0901,
133+
"cannot use `#[track_caller]` with `#[naked]`",
134+
)
135+
.emit();
136+
}
137+
}
121138
}
122139

123140
/// Checks if an `#[inline]` is applied to a function or a closure. Returns `true` if valid.
@@ -135,6 +152,23 @@ impl CheckAttrVisitor<'tcx> {
135152
}
136153
}
137154

155+
/// Checks if a `#[target_feature]` can be applied.
156+
fn check_track_caller(&self, attr: &hir::Attribute, item: &hir::Item, target: Target) -> bool {
157+
if target != Target::Fn {
158+
struct_span_err!(
159+
self.tcx.sess,
160+
attr.span,
161+
E0900,
162+
"attribute should be applied to function"
163+
)
164+
.span_label(item.span, "not a function")
165+
.emit();
166+
false
167+
} else {
168+
true
169+
}
170+
}
171+
138172
/// Checks if the `#[non_exhaustive]` attribute on an `item` is valid. Returns `true` if valid.
139173
fn check_non_exhaustive(
140174
&self,

src/librustc/hir/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2721,7 +2721,9 @@ bitflags! {
27212721
const USED = 1 << 9;
27222722
/// #[ffi_returns_twice], indicates that an extern function can return
27232723
/// multiple times
2724-
const FFI_RETURNS_TWICE = 1 << 10;
2724+
const FFI_RETURNS_TWICE = 1 << 10;
2725+
/// #[track_caller]: allow access to the caller location
2726+
const TRACK_CALLER = 1 << 11;
27252727
}
27262728
}
27272729

src/librustc_typeck/check/wfcheck.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,18 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: DefId) {
172172
_ => None
173173
};
174174
check_associated_item(tcx, trait_item.hir_id, trait_item.span, method_sig);
175+
176+
// Prohibits applying `#[track_caller]` to trait methods
177+
for attr in &trait_item.attrs {
178+
if attr.check_name(sym::track_caller) {
179+
struct_span_err!(
180+
tcx.sess,
181+
attr.span,
182+
E0903,
183+
"`#[track_caller]` is not supported for trait items yet."
184+
).emit();
185+
}
186+
}
175187
}
176188

177189
pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: DefId) {

src/librustc_typeck/collect.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2594,6 +2594,16 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
25942594
codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED;
25952595
} else if attr.check_name(sym::thread_local) {
25962596
codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL;
2597+
} else if attr.check_name(sym::track_caller) {
2598+
if tcx.fn_sig(id).abi() != abi::Abi::Rust {
2599+
struct_span_err!(
2600+
tcx.sess,
2601+
attr.span,
2602+
E0902,
2603+
"rust ABI is required to use `#[track_caller]`"
2604+
).emit();
2605+
}
2606+
codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
25972607
} else if attr.check_name(sym::export_name) {
25982608
if let Some(s) = attr.value_str() {
25992609
if s.as_str().contains("\0") {

src/librustc_typeck/error_codes.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4907,6 +4907,17 @@ fn foo_recursive(n: usize) -> Pin<Box<dyn Future<Output = ()>>> {
49074907
The `Box<...>` ensures that the result is of known size,
49084908
and the pin is required to keep it in the same place in memory.
49094909
"##,
4910+
4911+
E0902: r##"
4912+
TODO: change error number
4913+
TODO: track_caller: require Rust ABI to use track_caller
4914+
"##,
4915+
4916+
E0903: r##"
4917+
TODO: change error number
4918+
TODO: track_caller: can't apply in traits
4919+
"##,
4920+
49104921
;
49114922
// E0035, merged into E0087/E0089
49124923
// E0036, merged into E0087/E0089

src/libsyntax/feature_gate/active.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,9 @@ declare_features! (
525525
// Allows the use of raw-dylibs (RFC 2627).
526526
(active, raw_dylib, "1.40.0", Some(58713), None),
527527

528+
/// Enable accurate caller location reporting during panic (RFC 2091).
529+
(active, track_caller, "1.37.0", Some(47809), None),
530+
528531
// -------------------------------------------------------------------------
529532
// feature-group-end: actual feature gates
530533
// -------------------------------------------------------------------------

src/libsyntax/feature_gate/builtin_attrs.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
499499
cfg_fn!(no_debug)
500500
)
501501
),
502+
gated!(
503+
track_caller, Whitelisted, template!(Word),
504+
"the `#[track_caller]` attribute is an experimental feature",
505+
),
502506
gated!(
503507
// Used in resolve:
504508
prelude_import, Whitelisted, template!(Word),

src/libsyntax_pos/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,7 @@ symbols! {
674674
tool_attributes,
675675
tool_lints,
676676
trace_macros,
677+
track_caller,
677678
trait_alias,
678679
transmute,
679680
transparent,
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
#[track_caller]
3+
fn f() {}
4+
//~^^ ERROR the `#[track_caller]` attribute is an experimental feature
5+
6+
fn main() {}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0658]: the `#[track_caller]` attribute is an experimental feature
2+
--> $DIR/feature-gate-track_caller.rs:2:1
3+
|
4+
LL | #[track_caller]
5+
| ^^^^^^^^^^^^^^^
6+
|
7+
= note: for more information, see https://github.com/rust-lang/rust/issues/47809
8+
= help: add `#![feature(track_caller)]` to the crate attributes to enable
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0658`.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#![feature(track_caller)]
2+
3+
#[track_caller(1)]
4+
fn f() {}
5+
//~^^ ERROR malformed `track_caller` attribute input
6+
7+
fn main() {}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: malformed `track_caller` attribute input
2+
--> $DIR/error-odd-syntax.rs:3:1
3+
|
4+
LL | #[track_caller(1)]
5+
| ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[track_caller]`
6+
7+
error: aborting due to previous error
8+
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#![feature(track_caller)]
2+
3+
#[track_caller]
4+
extern "C" fn f() {}
5+
//~^^ ERROR rust ABI is required to use `#[track_caller]`
6+
7+
fn main() {}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0902]: rust ABI is required to use `#[track_caller]`
2+
--> $DIR/error-with-invalid-abi.rs:3:1
3+
|
4+
LL | #[track_caller]
5+
| ^^^^^^^^^^^^^^^
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0902`.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![feature(naked_functions, track_caller)]
2+
3+
#[track_caller]
4+
#[naked]
5+
fn f() {}
6+
//~^^^ ERROR cannot use `#[track_caller]` with `#[naked]`
7+
8+
fn main() {}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0901]: cannot use `#[track_caller]` with `#[naked]`
2+
--> $DIR/error-with-naked.rs:3:1
3+
|
4+
LL | #[track_caller]
5+
| ^^^^^^^^^^^^^^^
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0901`.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#![feature(track_caller)]
2+
3+
trait Trait {
4+
#[track_caller]
5+
fn unwrap(&self);
6+
//~^^ ERROR: `#[track_caller]` is not supported for trait items yet.
7+
}
8+
9+
impl Trait for u64 {
10+
fn unwrap(&self) {}
11+
}
12+
13+
fn main() {}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0903]: `#[track_caller]` is not supported for trait items yet.
2+
--> $DIR/error-with-trait-fns.rs:4:5
3+
|
4+
LL | #[track_caller]
5+
| ^^^^^^^^^^^^^^^
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0903`.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#![feature(track_caller)]
2+
3+
#[track_caller]
4+
struct S;
5+
//~^^ ERROR attribute should be applied to function
6+
7+
fn main() {}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0900]: attribute should be applied to function
2+
--> $DIR/only-for-fns.rs:3:1
3+
|
4+
LL | #[track_caller]
5+
| ^^^^^^^^^^^^^^^
6+
LL | struct S;
7+
| --------- not a function
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0900`.

0 commit comments

Comments
 (0)