about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2019-10-29 20:56:21 +0200
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2019-12-03 15:41:56 +0200
commit39e50e2f289a58a46f46044d8e9d296b9e7ac7e6 (patch)
tree0d38df30866d8949cc5d84a3a466abad6ee28284
parent4b68afe257603a61aa2eb8b8eaa394c5e7a246fe (diff)
downloadrust-39e50e2f289a58a46f46044d8e9d296b9e7ac7e6.tar.gz
rust-39e50e2f289a58a46f46044d8e9d296b9e7ac7e6.zip
rustc: use ReifyShim for reifying Virtual call instances.
-rw-r--r--src/librustc/ty/instance.rs32
-rw-r--r--src/librustc_mir/monomorphize/collector.rs16
-rw-r--r--src/librustc_mir/shim.rs11
3 files changed, 34 insertions, 25 deletions
diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs
index 856be6f3c77..06fc168bd57 100644
--- a/src/librustc/ty/instance.rs
+++ b/src/librustc/ty/instance.rs
@@ -29,10 +29,15 @@ pub enum InstanceDef<'tcx> {
 
     /// `fn()` pointer where the function itself cannot be turned into a pointer.
     ///
-    /// One example in the compiler today is functions annotated with `#[track_caller]`, which
-    /// must have their implicit caller location argument populated for a call. Because this is a
-    /// required part of the function's ABI but can't be tracked as a property of the function
-    /// pointer, we create a single "caller location" at the site where the function is reified.
+    /// One example is `<dyn Trait as Trait>::fn`, where the shim contains
+    /// a virtual call, which codegen supports only via a direct call to the
+    /// `<dyn Trait as Trait>::fn` instance (an `InstanceDef::Virtual`).
+    ///
+    /// Another example is functions annotated with `#[track_caller]`, which
+    /// must have their implicit caller location argument populated for a call.
+    /// Because this is a required part of the function's ABI but can't be tracked
+    /// as a property of the function pointer, we use a single "caller location"
+    /// (the definition of the function itself).
     ReifyShim(DefId),
 
     /// `<fn() as FnTrait>::call_*`
@@ -194,7 +199,7 @@ impl<'tcx> fmt::Display for Instance<'tcx> {
                 write!(f, " - intrinsic")
             }
             InstanceDef::Virtual(_, num) => {
-                write!(f, " - shim(#{})", num)
+                write!(f, " - virtual#{}", num)
             }
             InstanceDef::FnPtrShim(_, ty) => {
                 write!(f, " - shim({:?})", ty)
@@ -309,20 +314,23 @@ impl<'tcx> Instance<'tcx> {
         substs: SubstsRef<'tcx>,
     ) -> Option<Instance<'tcx>> {
         debug!("resolve(def_id={:?}, substs={:?})", def_id, substs);
-        Instance::resolve(tcx, param_env, def_id, substs).map(|resolved| {
+        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) => {
                     debug!(" => fn pointer created for function with #[track_caller]");
-                    Instance {
-                        def: InstanceDef::ReifyShim(def_id),
-                        substs,
-                    }
-                },
-                _ => resolved,
+                    resolved.def = InstanceDef::ReifyShim(def_id);
+                }
+                InstanceDef::Virtual(def_id, _) => {
+                    debug!(" => fn pointer created for virtual call");
+                    resolved.def = InstanceDef::ReifyShim(def_id);
+                }
+                _ => {}
             }
+
+            resolved
         })
     }
 
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index 4fe53cf35e5..93a76712b28 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -741,23 +741,21 @@ fn visit_instance_use<'tcx>(
     }
 
     match instance.def {
-        ty::InstanceDef::Intrinsic(def_id) => {
+        ty::InstanceDef::Virtual(..) |
+        ty::InstanceDef::Intrinsic(_) => {
             if !is_direct_call {
-                bug!("intrinsic {:?} being reified", def_id);
+                bug!("{:?} being reified", instance);
             }
         }
-        ty::InstanceDef::VtableShim(..) |
-        ty::InstanceDef::ReifyShim(..) |
-        ty::InstanceDef::Virtual(..) |
         ty::InstanceDef::DropGlue(_, None) => {
-            // Don't need to emit shim if we are calling directly.
+            // Don't need to emit noop drop glue if we are calling directly.
             if !is_direct_call {
                 output.push(create_fn_mono_item(instance));
             }
         }
-        ty::InstanceDef::DropGlue(_, Some(_)) => {
-            output.push(create_fn_mono_item(instance));
-        }
+        ty::InstanceDef::DropGlue(_, Some(_)) |
+        ty::InstanceDef::VtableShim(..) |
+        ty::InstanceDef::ReifyShim(..) |
         ty::InstanceDef::ClosureOnceShim { .. } |
         ty::InstanceDef::Item(..) |
         ty::InstanceDef::FnPtrShim(..) |
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index fc606db98be..5b208dd8587 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -67,10 +67,10 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx
             )
         }
         // We are generating a call back to our def-id, which the
-        // codegen backend knows to turn to an actual virtual call.
-        ty::InstanceDef::Virtual(def_id, _) |
-        // ...or we are generating a direct call to a function for which indirect calls must be
-        // codegen'd differently than direct ones (example: #[track_caller])
+        // codegen backend knows to turn to an actual call, be it
+        // a virtual call, or a direct call to a function for which
+        // indirect calls must be codegen'd differently than direct ones
+        // (such as `#[track_caller]`).
         ty::InstanceDef::ReifyShim(def_id) => {
             build_call_shim(
                 tcx,
@@ -109,6 +109,9 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx
                 bug!("builtin clone shim {:?} not supported", instance)
             }
         }
+        ty::InstanceDef::Virtual(..) => {
+            bug!("InstanceDef::Virtual ({:?}) is for direct calls only", instance)
+        }
         ty::InstanceDef::Intrinsic(_) => {
             bug!("creating shims from intrinsics ({:?}) is unsupported", instance)
         }