[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
|
|
@ -1640,6 +1640,16 @@ each method; it is not possible to annotate the entire impl with an `#[inline]`
|
|||
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##"
|
||||
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
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ impl CheckAttrVisitor<'tcx> {
|
|||
/// Checks any attribute.
|
||||
fn check_attributes(&self, item: &hir::Item, target: Target) {
|
||||
let mut is_valid = true;
|
||||
let mut track_caller_span = None;
|
||||
for attr in &item.attrs {
|
||||
is_valid &= if attr.check_name(sym::inline) {
|
||||
self.check_inline(attr, &item.span, target)
|
||||
|
|
@ -103,6 +104,9 @@ 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) {
|
||||
track_caller_span = Some(attr.span);
|
||||
self.check_track_caller(attr, &item, target)
|
||||
} else {
|
||||
true
|
||||
};
|
||||
|
|
@ -118,6 +122,19 @@ impl CheckAttrVisitor<'tcx> {
|
|||
|
||||
self.check_repr(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.
|
||||
|
|
@ -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.
|
||||
fn check_non_exhaustive(
|
||||
&self,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue