Skip to content

Commit a8b2fe0

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 2daa404 commit a8b2fe0

22 files changed

+199
-1
lines changed
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

+10
Original file line numberDiff line numberDiff line change
@@ -1727,6 +1727,16 @@ each method; it is not possible to annotate the entire impl with an `#[inline]`
17271727
attribute.
17281728
"##,
17291729

1730+
E0900: r##"
1731+
TODO: change error number
1732+
TODO: track_caller: invalid syntax
1733+
"##,
1734+
1735+
E0901: r##"
1736+
TODO: change error number
1737+
TODO: track_caller: no naked functions
1738+
"##,
1739+
17301740
E0522: r##"
17311741
The lang attribute is intended for marking special items that are built-in to
17321742
Rust itself. This includes special traits (like `Copy` and `Sized`) that affect

src/librustc/hir/check_attr.rs

+34
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

+3-1
Original file line numberDiff line numberDiff line change
@@ -2687,7 +2687,9 @@ bitflags! {
26872687
const USED = 1 << 9;
26882688
/// #[ffi_returns_twice], indicates that an extern function can return
26892689
/// multiple times
2690-
const FFI_RETURNS_TWICE = 1 << 10;
2690+
const FFI_RETURNS_TWICE = 1 << 10;
2691+
/// #[track_caller]: allow access to the caller location
2692+
const TRACK_CALLER = 1 << 11;
26912693
}
26922694
}
26932695

src/librustc_typeck/check/wfcheck.rs

+12
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

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

src/librustc_typeck/error_codes.rs

+11
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

+3
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,9 @@ declare_features! (
519519
/// Allows the use of or-patterns (e.g., `0 | 1`).
520520
(active, or_patterns, "1.38.0", Some(54883), None),
521521

522+
/// Enable accurate caller location reporting during panic (RFC 2091).
523+
(active, track_caller, "1.37.0", Some(47809), None),
524+
522525
// -------------------------------------------------------------------------
523526
// feature-group-end: actual feature gates
524527
// -------------------------------------------------------------------------

src/libsyntax/feature_gate/builtin_attrs.rs

+4
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
482482
cfg_fn!(no_debug)
483483
)
484484
),
485+
gated!(
486+
track_caller, Whitelisted, template!(Word),
487+
"the `#[track_caller]` attribute is an experimental feature",
488+
),
485489
gated!(
486490
// Used in resolve:
487491
prelude_import, Whitelisted, template!(Word),

src/libsyntax_pos/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,7 @@ symbols! {
671671
tool_attributes,
672672
tool_lints,
673673
trace_macros,
674+
track_caller,
674675
trait_alias,
675676
transmute,
676677
transparent,
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() {}
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`.
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() {}
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+
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() {}
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`.
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() {}
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`.
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() {}
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`.
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() {}
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)