about summary refs log tree commit diff
path: root/src/librustc/ty
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-12-07 21:14:39 +0000
committerbors <bors@rust-lang.org>2019-12-07 21:14:39 +0000
commitde17464b14e503edca6625daa9cd4c338ffafee2 (patch)
tree88969c0d7bbddc53c7fa798ae477efad19f2147c /src/librustc/ty
parent5c5c8eb864e56ce905742b8e97df5506bba6aeef (diff)
parent15d1f7cffdc0b111123a6d34a356eae95af04676 (diff)
downloadrust-de17464b14e503edca6625daa9cd4c338ffafee2.tar.gz
rust-de17464b14e503edca6625daa9cd4c338ffafee2.zip
Auto merge of #65881 - anp:implicit-caller-location, r=eddyb,oli-obk
Implement #[track_caller] attribute. (RFC 2091 4/N)

Implements the `#[track_caller]` attribute in both const and codegen contexts.

The const implementation walks up the stack to find the nearest untracked callsite.

The codegen implementation adds an implicit argument to tracked function calls, and populates it with either a call to the previously-landed intrinsic or if the caller has `#[track_caller]` with a copy of the location passed to the current function.

Also includes a little cleanup and a few comments in the other caller location areas.

[Depends on: 65664](https://github.com/rust-lang/rust/pull/65664)
[RFC 2091 text](https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md)
[Tracking issue](https://github.com/rust-lang/rust/issues/47809)
[Tracking doc](https://paper.dropbox.com/doc/track_rfc_2091_impl-notes--Anf1NwnIb0xcRv31YLIadyj0Ag-rwCdRc2fi2yvRZ7syGZ9q#:uid=863513134494965680023183&h2=TODO-actually-pass-location-to)
Diffstat (limited to 'src/librustc/ty')
-rw-r--r--src/librustc/ty/context.rs10
-rw-r--r--src/librustc/ty/instance.rs9
-rw-r--r--src/librustc/ty/layout.rs13
3 files changed, 26 insertions, 6 deletions
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 6a0002cd80f..bf6c10dd3c9 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -8,6 +8,7 @@ use crate::session::Session;
 use crate::session::config::{BorrowckMode, OutputFilenames};
 use crate::session::config::CrateType;
 use crate::middle;
+use crate::middle::lang_items::PanicLocationLangItem;
 use crate::hir::{self, TraitCandidate, HirId, ItemKind, ItemLocalId, Node};
 use crate::hir::def::{Res, DefKind, Export};
 use crate::hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
@@ -1588,6 +1589,15 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn has_strict_asm_symbol_naming(&self) -> bool {
         self.sess.target.target.arch.contains("nvptx")
     }
+
+    /// Returns `&'static core::panic::Location<'static>`.
+    pub fn caller_location_ty(&self) -> Ty<'tcx> {
+        self.mk_imm_ref(
+            self.lifetimes.re_static,
+            self.type_of(self.require_lang_item(PanicLocationLangItem, None))
+                .subst(*self, self.mk_substs([self.lifetimes.re_static.into()].iter())),
+        )
+    }
 }
 
 impl<'tcx> GlobalCtxt<'tcx> {
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/ty/layout.rs b/src/librustc/ty/layout.rs
index 7f93e8c91e9..6c921134ab8 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -2434,6 +2434,7 @@ where
         cx: &C,
         sig: ty::PolyFnSig<'tcx>,
         extra_args: &[Ty<'tcx>],
+        caller_location: Option<Ty<'tcx>>,
         mk_arg_type: impl Fn(Ty<'tcx>, Option<usize>) -> ArgAbi<'tcx, Ty<'tcx>>,
     ) -> Self;
     fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi);
@@ -2448,13 +2449,19 @@ where
         + HasParamEnv<'tcx>,
 {
     fn of_fn_ptr(cx: &C, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self {
-        call::FnAbi::new_internal(cx, sig, extra_args, |ty, _| ArgAbi::new(cx.layout_of(ty)))
+        call::FnAbi::new_internal(cx, sig, extra_args, None, |ty, _| ArgAbi::new(cx.layout_of(ty)))
     }
 
     fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> Self {
         let sig = instance.fn_sig_for_fn_abi(cx.tcx());
 
-        call::FnAbi::new_internal(cx, sig, extra_args, |ty, arg_idx| {
+        let caller_location = if instance.def.requires_caller_location(cx.tcx()) {
+            Some(cx.tcx().caller_location_ty())
+        } else {
+            None
+        };
+
+        call::FnAbi::new_internal(cx, sig, extra_args, caller_location, |ty, arg_idx| {
             let mut layout = cx.layout_of(ty);
             // Don't pass the vtable, it's not an argument of the virtual fn.
             // Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait`
@@ -2512,6 +2519,7 @@ where
         cx: &C,
         sig: ty::PolyFnSig<'tcx>,
         extra_args: &[Ty<'tcx>],
+        caller_location: Option<Ty<'tcx>>,
         mk_arg_type: impl Fn(Ty<'tcx>, Option<usize>) -> ArgAbi<'tcx, Ty<'tcx>>,
     ) -> Self {
         debug!("FnAbi::new_internal({:?}, {:?})", sig, extra_args);
@@ -2684,6 +2692,7 @@ where
                 .iter()
                 .cloned()
                 .chain(extra_args)
+                .chain(caller_location)
                 .enumerate()
                 .map(|(i, ty)| arg_of(ty, Some(i)))
                 .collect(),