about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/librustc/ty/instance.rs9
-rw-r--r--src/librustc_mir/interpret/intrinsics.rs1
-rw-r--r--src/librustc_mir/interpret/intrinsics/caller_location.rs22
-rw-r--r--src/test/ui/consts/const-eval/const_caller_location.rs36
-rw-r--r--src/test/ui/rfc-2091-track-caller/const_caller_location.stderr8
5 files changed, 63 insertions, 13 deletions
diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs
index 801dfa81ef1..366951bc9f4 100644
--- a/src/librustc/ty/instance.rs
+++ b/src/librustc/ty/instance.rs
@@ -116,6 +116,10 @@ impl<'tcx> InstanceDef<'tcx> {
         }
         tcx.codegen_fn_attrs(self.def_id()).requests_inline()
     }
+
+    pub fn requires_caller_location(&self, tcx: TyCtxt<'_>) -> bool {
+        tcx.codegen_fn_attrs(self.def_id()).flags.contains(CodegenFnAttrFlags::TRACK_CALLER)
+    }
 }
 
 impl<'tcx> fmt::Display for Instance<'tcx> {
@@ -255,11 +259,8 @@ impl<'tcx> Instance<'tcx> {
     ) -> Option<Instance<'tcx>> {
         debug!("resolve(def_id={:?}, substs={:?})", def_id, substs);
         Instance::resolve(tcx, param_env, def_id, substs).map(|mut resolved| {
-            let has_track_caller = |def| tcx.codegen_fn_attrs(def).flags
-                .contains(CodegenFnAttrFlags::TRACK_CALLER);
-
             match resolved.def {
-                InstanceDef::Item(def_id) if has_track_caller(def_id) => {
+                InstanceDef::Item(def_id) if resolved.def.requires_caller_location(tcx) => {
                     debug!(" => fn pointer created for function with #[track_caller]");
                     resolved.def = InstanceDef::ReifyShim(def_id);
                 }
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index ad5df5aff1a..20f1a1d7c48 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -112,6 +112,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // `src/librustc/ty/constness.rs`
         match intrinsic_name {
             sym::caller_location => {
+                let span = self.find_closest_untracked_caller_location(span);
                 let location = self.alloc_caller_location_for_span(span);
                 self.write_scalar(location.ptr, dest)?;
             }
diff --git a/src/librustc_mir/interpret/intrinsics/caller_location.rs b/src/librustc_mir/interpret/intrinsics/caller_location.rs
index ecf4b7a39b7..391c0c30bde 100644
--- a/src/librustc_mir/interpret/intrinsics/caller_location.rs
+++ b/src/librustc_mir/interpret/intrinsics/caller_location.rs
@@ -6,6 +6,28 @@ use syntax_pos::{Symbol, Span};
 use crate::interpret::{Scalar, MemoryKind, MPlaceTy, intrinsics::{InterpCx, Machine}};
 
 impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
+    /// Walks up the callstack from the intrinsic's callsite, searching for the first frame which is
+    /// not `#[track_caller]`. Returns the (passed) span of the intrinsic's callsite if the first
+    /// frame in the stack is untracked so that we can display the callsite of the intrinsic within
+    /// that function.
+    crate fn find_closest_untracked_caller_location(
+        &self,
+        intrinsic_loc: Span,
+    ) -> Span {
+        debug!("finding closest untracked caller relative to {:?}", intrinsic_loc);
+
+        let mut caller_span = intrinsic_loc;
+        for next_caller in self.stack.iter().rev() {
+            if !next_caller.instance.def.requires_caller_location(*self.tcx) {
+                return caller_span;
+            }
+            caller_span = next_caller.span;
+        }
+
+        intrinsic_loc
+    }
+
+    /// Allocate a `const core::panic::Location` with the provided filename and line/column numbers.
     crate fn alloc_caller_location(
         &mut self,
         filename: Symbol,
diff --git a/src/test/ui/consts/const-eval/const_caller_location.rs b/src/test/ui/consts/const-eval/const_caller_location.rs
index c63822f052b..e36790505e8 100644
--- a/src/test/ui/consts/const-eval/const_caller_location.rs
+++ b/src/test/ui/consts/const-eval/const_caller_location.rs
@@ -1,23 +1,41 @@
 // run-pass
 
-#![feature(const_fn, core_intrinsics)]
+#![feature(const_fn, core_intrinsics, track_caller)]
 
 use std::{intrinsics::caller_location, panic::Location};
 
 const LOCATION: &Location = caller_location();
-const NESTED: &Location = {
-    const fn nested_location() -> &'static Location<'static> {
-        caller_location()
-    };
-    nested_location()
-};
+
+const TRACKED: &Location = tracked();
+#[track_caller]
+const fn tracked() -> &'static Location <'static> {
+    caller_location()
+}
+
+const NESTED: &Location = nested_location();
+const fn nested_location() -> &'static Location<'static> {
+    caller_location()
+}
+
+const CONTAINED: &Location = contained();
+const fn contained() -> &'static Location<'static> {
+    tracked()
+}
 
 fn main() {
     assert_eq!(LOCATION.file(), file!());
     assert_eq!(LOCATION.line(), 7);
     assert_eq!(LOCATION.column(), 29);
 
+    assert_eq!(TRACKED.file(), file!());
+    assert_eq!(TRACKED.line(), 9);
+    assert_eq!(TRACKED.column(), 28);
+
     assert_eq!(NESTED.file(), file!());
-    assert_eq!(NESTED.line(), 10);
-    assert_eq!(NESTED.column(), 9);
+    assert_eq!(NESTED.line(), 17);
+    assert_eq!(NESTED.column(), 5);
+
+    assert_eq!(CONTAINED.file(), file!());
+    assert_eq!(CONTAINED.line(), 22);
+    assert_eq!(CONTAINED.column(), 5);
 }
diff --git a/src/test/ui/rfc-2091-track-caller/const_caller_location.stderr b/src/test/ui/rfc-2091-track-caller/const_caller_location.stderr
new file mode 100644
index 00000000000..01a00dd28fd
--- /dev/null
+++ b/src/test/ui/rfc-2091-track-caller/const_caller_location.stderr
@@ -0,0 +1,8 @@
+warning: the feature `track_caller` is incomplete and may cause the compiler to crash
+  --> $DIR/const_caller_location.rs:3:39
+   |
+LL | #![feature(const_fn, core_intrinsics, track_caller)]
+   |                                       ^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+