about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorAyose <ayosec@gmail.com>2019-07-20 00:55:58 +0000
committerAdam Perry <adam.n.perry@gmail.com>2019-10-07 08:05:21 -0700
commit543449d4fdf7bb7fd4a12c2fea96dafbe26eea90 (patch)
tree3f1550e764c244fd3908871db551aed213ed29d7 /src
parente3cb9ea15a2082f39d4d4f10a22e779701dd0d64 (diff)
downloadrust-543449d4fdf7bb7fd4a12c2fea96dafbe26eea90.tar.gz
rust-543449d4fdf7bb7fd4a12c2fea96dafbe26eea90.zip
[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.
Diffstat (limited to 'src')
-rw-r--r--src/doc/unstable-book/src/language-features/track-caller.md5
-rw-r--r--src/librustc/error_codes.rs10
-rw-r--r--src/librustc/hir/check_attr.rs34
-rw-r--r--src/librustc/hir/mod.rs4
-rw-r--r--src/librustc_typeck/check/wfcheck.rs12
-rw-r--r--src/librustc_typeck/collect.rs10
-rw-r--r--src/librustc_typeck/error_codes.rs11
-rw-r--r--src/libsyntax/feature_gate/active.rs3
-rw-r--r--src/libsyntax/feature_gate/builtin_attrs.rs4
-rw-r--r--src/libsyntax_pos/symbol.rs1
-rw-r--r--src/test/ui/feature-gates/feature-gate-track_caller.rs6
-rw-r--r--src/test/ui/feature-gates/feature-gate-track_caller.stderr12
-rw-r--r--src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs7
-rw-r--r--src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr8
-rw-r--r--src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs7
-rw-r--r--src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr9
-rw-r--r--src/test/ui/rfc-2091-track-caller/error-with-naked.rs8
-rw-r--r--src/test/ui/rfc-2091-track-caller/error-with-naked.stderr9
-rw-r--r--src/test/ui/rfc-2091-track-caller/error-with-trait-fns.rs13
-rw-r--r--src/test/ui/rfc-2091-track-caller/error-with-trait-fns.stderr9
-rw-r--r--src/test/ui/rfc-2091-track-caller/only-for-fns.rs7
-rw-r--r--src/test/ui/rfc-2091-track-caller/only-for-fns.stderr11
22 files changed, 199 insertions, 1 deletions
diff --git a/src/doc/unstable-book/src/language-features/track-caller.md b/src/doc/unstable-book/src/language-features/track-caller.md
new file mode 100644
index 00000000000..afc11a2b949
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/track-caller.md
@@ -0,0 +1,5 @@
+# `track_caller`
+
+The tracking issue for this feature is: [#47809](https://github.com/rust-lang/rust/issues/47809).
+
+------------------------
diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs
index 502172db91c..959a06c2e32 100644
--- a/src/librustc/error_codes.rs
+++ b/src/librustc/error_codes.rs
@@ -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
diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs
index d5e956555bd..31a09645d16 100644
--- a/src/librustc/hir/check_attr.rs
+++ b/src/librustc/hir/check_attr.rs
@@ -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,
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 30b05036688..f7240d6bf82 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -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;
     }
 }
 
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index e736a55a5f5..3c9010de5cb 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -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 methods
+    for attr in &trait_item.attrs {
+        if attr.check_name(sym::track_caller) {
+            struct_span_err!(
+                tcx.sess,
+                attr.span,
+                E0903,
+                "`#[track_caller]` is not supported for trait items yet."
+            ).emit();
+        }
+    }
 }
 
 pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: DefId) {
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 64eca137144..0b98e4b781d 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -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,
+                    E0902,
+                    "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") {
diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs
index 3a07171b12f..f698427c78a 100644
--- a/src/librustc_typeck/error_codes.rs
+++ b/src/librustc_typeck/error_codes.rs
@@ -4907,6 +4907,17 @@ 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.
 "##,
+
+E0902: r##"
+TODO: change error number
+TODO: track_caller: require Rust ABI to use track_caller
+"##,
+
+E0903: r##"
+TODO: change error number
+TODO: track_caller: can't apply in traits
+"##,
+
 ;
 //  E0035, merged into E0087/E0089
 //  E0036, merged into E0087/E0089
diff --git a/src/libsyntax/feature_gate/active.rs b/src/libsyntax/feature_gate/active.rs
index 19ef430318d..312a9bf6e75 100644
--- a/src/libsyntax/feature_gate/active.rs
+++ b/src/libsyntax/feature_gate/active.rs
@@ -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.37.0", Some(47809), None),
+
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
     // -------------------------------------------------------------------------
diff --git a/src/libsyntax/feature_gate/builtin_attrs.rs b/src/libsyntax/feature_gate/builtin_attrs.rs
index c12d0ce06ff..d6a6450e471 100644
--- a/src/libsyntax/feature_gate/builtin_attrs.rs
+++ b/src/libsyntax/feature_gate/builtin_attrs.rs
@@ -500,6 +500,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         )
     ),
     gated!(
+        track_caller, Whitelisted, template!(Word),
+        "the `#[track_caller]` attribute is an experimental feature",
+    ),
+    gated!(
         // Used in resolve:
         prelude_import, Whitelisted, template!(Word),
         "`#[prelude_import]` is for use by rustc only",
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index c7230d5ca15..2b005c3fc42 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -674,6 +674,7 @@ symbols! {
         tool_attributes,
         tool_lints,
         trace_macros,
+        track_caller,
         trait_alias,
         transmute,
         transparent,
diff --git a/src/test/ui/feature-gates/feature-gate-track_caller.rs b/src/test/ui/feature-gates/feature-gate-track_caller.rs
new file mode 100644
index 00000000000..458df0b2b02
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-track_caller.rs
@@ -0,0 +1,6 @@
+
+#[track_caller]
+fn f() {}
+//~^^ ERROR the `#[track_caller]` attribute is an experimental feature
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-track_caller.stderr b/src/test/ui/feature-gates/feature-gate-track_caller.stderr
new file mode 100644
index 00000000000..9a058736e50
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-track_caller.stderr
@@ -0,0 +1,12 @@
+error[E0658]: the `#[track_caller]` attribute is an experimental feature
+  --> $DIR/feature-gate-track_caller.rs:2: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`.
diff --git a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs
new file mode 100644
index 00000000000..d6560231871
--- /dev/null
+++ b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs
@@ -0,0 +1,7 @@
+#![feature(track_caller)]
+
+#[track_caller(1)]
+fn f() {}
+//~^^ ERROR malformed `track_caller` attribute input
+
+fn main() {}
diff --git a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr
new file mode 100644
index 00000000000..8906fa59506
--- /dev/null
+++ b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr
@@ -0,0 +1,8 @@
+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]`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs
new file mode 100644
index 00000000000..5c42a1b3faa
--- /dev/null
+++ b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs
@@ -0,0 +1,7 @@
+#![feature(track_caller)]
+
+#[track_caller]
+extern "C" fn f() {}
+//~^^ ERROR rust ABI is required to use `#[track_caller]`
+
+fn main() {}
diff --git a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr
new file mode 100644
index 00000000000..fc6f4d17dcc
--- /dev/null
+++ b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr
@@ -0,0 +1,9 @@
+error[E0902]: 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 E0902`.
diff --git a/src/test/ui/rfc-2091-track-caller/error-with-naked.rs b/src/test/ui/rfc-2091-track-caller/error-with-naked.rs
new file mode 100644
index 00000000000..dd9e5d04135
--- /dev/null
+++ b/src/test/ui/rfc-2091-track-caller/error-with-naked.rs
@@ -0,0 +1,8 @@
+#![feature(naked_functions, track_caller)]
+
+#[track_caller]
+#[naked]
+fn f() {}
+//~^^^ ERROR cannot use `#[track_caller]` with `#[naked]`
+
+fn main() {}
diff --git a/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr b/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr
new file mode 100644
index 00000000000..3566d288ed1
--- /dev/null
+++ b/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr
@@ -0,0 +1,9 @@
+error[E0901]: 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 E0901`.
diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.rs b/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.rs
new file mode 100644
index 00000000000..c00cf7367ce
--- /dev/null
+++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.rs
@@ -0,0 +1,13 @@
+#![feature(track_caller)]
+
+trait Trait {
+    #[track_caller]
+    fn unwrap(&self);
+    //~^^ ERROR: `#[track_caller]` is not supported for trait items yet.
+}
+
+impl Trait for u64 {
+    fn unwrap(&self) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.stderr b/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.stderr
new file mode 100644
index 00000000000..bd3d4043a64
--- /dev/null
+++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.stderr
@@ -0,0 +1,9 @@
+error[E0903]: `#[track_caller]` is not supported for trait items yet.
+  --> $DIR/error-with-trait-fns.rs:4:5
+   |
+LL |     #[track_caller]
+   |     ^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0903`.
diff --git a/src/test/ui/rfc-2091-track-caller/only-for-fns.rs b/src/test/ui/rfc-2091-track-caller/only-for-fns.rs
new file mode 100644
index 00000000000..0fd59b4bf49
--- /dev/null
+++ b/src/test/ui/rfc-2091-track-caller/only-for-fns.rs
@@ -0,0 +1,7 @@
+#![feature(track_caller)]
+
+#[track_caller]
+struct S;
+//~^^ ERROR attribute should be applied to function
+
+fn main() {}
diff --git a/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr b/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr
new file mode 100644
index 00000000000..9ddc99c02bf
--- /dev/null
+++ b/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr
@@ -0,0 +1,11 @@
+error[E0900]: 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
+
+For more information about this error, try `rustc --explain E0900`.