From 8bdb10d2e3102b8eb65c0af4d79e15ce50b8bc66 Mon Sep 17 00:00:00 2001
From: Manish Goregaokar <manishsmail@gmail.com>
Date: Wed, 7 Feb 2018 15:58:02 -0800
Subject: [PATCH 1/4] Use InstanceDef::Item for clone_from shims

---
 src/librustc/ty/instance.rs |  8 +++++++-
 src/librustc_mir/shim.rs    | 10 +---------
 2 files changed, 8 insertions(+), 10 deletions(-)

diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs
index 63bf52a9bdf78..66c935c4da3d1 100644
--- a/src/librustc/ty/instance.rs
+++ b/src/librustc/ty/instance.rs
@@ -289,8 +289,14 @@ fn resolve_associated_item<'a, 'tcx>(
         }
         traits::VtableBuiltin(..) => {
             if let Some(_) = tcx.lang_items().clone_trait() {
+                let name = tcx.item_name(def_id);
+                let def = if name == "clone" {
+                    ty::InstanceDef::CloneShim(def_id, trait_ref.self_ty())
+                } else {
+                    ty::InstanceDef::Item(def_id)
+                };
                 Some(Instance {
-                    def: ty::InstanceDef::CloneShim(def_id, trait_ref.self_ty()),
+                    def,
                     substs: rcvr_substs
                 })
             } else {
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index 42ffcc194ca8c..0995324b4f98a 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -100,15 +100,7 @@ fn make_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             build_drop_shim(tcx, def_id, ty)
         }
         ty::InstanceDef::CloneShim(def_id, ty) => {
-            let name = tcx.item_name(def_id);
-            if name == "clone" {
-                build_clone_shim(tcx, def_id, ty)
-            } else if name == "clone_from" {
-                debug!("make_shim({:?}: using default trait implementation", instance);
-                return tcx.optimized_mir(def_id);
-            } else {
-                bug!("builtin clone shim {:?} not supported", instance)
-            }
+            build_clone_shim(tcx, def_id, ty)
         }
         ty::InstanceDef::Intrinsic(_) => {
             bug!("creating shims from intrinsics ({:?}) is unsupported", instance)

From d45a70cfed751971240da422a7e1d1c35435cff5 Mon Sep 17 00:00:00 2001
From: Manish Goregaokar <manishsmail@gmail.com>
Date: Wed, 7 Feb 2018 15:32:02 -0800
Subject: [PATCH 2/4] Split CloneShim into CloneCopyShim, CloneStructuralShim,
 CloneNominalShim

---
 src/librustc/ich/impls_ty.rs                  |  4 ++-
 src/librustc/ty/instance.rs                   | 36 ++++++++++++++++---
 src/librustc/ty/mod.rs                        |  4 ++-
 src/librustc_mir/interpret/terminator/mod.rs  |  4 ++-
 src/librustc_mir/monomorphize/collector.rs    |  8 +++--
 src/librustc_mir/monomorphize/partitioning.rs | 12 +++++--
 src/librustc_mir/shim.rs                      |  4 ++-
 7 files changed, 58 insertions(+), 14 deletions(-)

diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index 107779ec3fa15..b8e71f2caf65a 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -758,7 +758,9 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::InstanceDef<'gcx> {
                 def_id.hash_stable(hcx, hasher);
                 t.hash_stable(hcx, hasher);
             }
-            ty::InstanceDef::CloneShim(def_id, t) => {
+            ty::InstanceDef::CloneCopyShim(def_id, t) |
+            ty::InstanceDef::CloneStructuralShim(def_id, t) |
+            ty::InstanceDef::CloneNominalShim(def_id, t) => {
                 def_id.hash_stable(hcx, hasher);
                 t.hash_stable(hcx, hasher);
             }
diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs
index 66c935c4da3d1..6fa58800af50c 100644
--- a/src/librustc/ty/instance.rs
+++ b/src/librustc/ty/instance.rs
@@ -13,6 +13,7 @@ use ty::{self, Ty, TypeFoldable, Substs, TyCtxt};
 use ty::subst::Kind;
 use traits;
 use syntax::abi::Abi;
+use syntax::codemap::DUMMY_SP;
 use util::ppaux;
 
 use std::fmt;
@@ -39,10 +40,22 @@ pub enum InstanceDef<'tcx> {
     ClosureOnceShim { call_once: DefId },
 
     /// drop_in_place::<T>; None for empty drop glue.
+    ///
+    /// The DefId is the DefId of drop_in_place
     DropGlue(DefId, Option<Ty<'tcx>>),
 
-    ///`<T as Clone>::clone` shim.
-    CloneShim(DefId, Ty<'tcx>),
+    ///`<T as Clone>::clone` shim for Copy types
+    ///
+    /// The DefId is the DefId of the Clone::clone function
+    CloneCopyShim(DefId, Ty<'tcx>),
+    ///`<T as Clone>::clone` shim for arrays and tuples
+    ///
+    /// The DefId is the DefId of the Clone::clone function
+    CloneStructuralShim(DefId, Ty<'tcx>),
+    ///`<T as Clone>::clone` shim for closures
+    ///
+    /// The DefId is the DefId of the Clone::clone function
+    CloneNominalShim(DefId, Ty<'tcx>),
 }
 
 impl<'a, 'tcx> Instance<'tcx> {
@@ -65,7 +78,9 @@ impl<'tcx> InstanceDef<'tcx> {
             InstanceDef::Intrinsic(def_id, ) |
             InstanceDef::ClosureOnceShim { call_once: def_id } |
             InstanceDef::DropGlue(def_id, _) |
-            InstanceDef::CloneShim(def_id, _) => def_id
+            InstanceDef::CloneCopyShim(def_id, _) |
+            InstanceDef::CloneStructuralShim(def_id, _) |
+            InstanceDef::CloneNominalShim(def_id, _) => def_id
         }
     }
 
@@ -131,7 +146,9 @@ impl<'tcx> fmt::Display for Instance<'tcx> {
             InstanceDef::DropGlue(_, ty) => {
                 write!(f, " - shim({:?})", ty)
             }
-            InstanceDef::CloneShim(_, ty) => {
+            InstanceDef::CloneCopyShim(_, ty) |
+            InstanceDef::CloneStructuralShim(_, ty) |
+            InstanceDef::CloneNominalShim(_, ty) => {
                 write!(f, " - shim({:?})", ty)
             }
         }
@@ -291,7 +308,16 @@ fn resolve_associated_item<'a, 'tcx>(
             if let Some(_) = tcx.lang_items().clone_trait() {
                 let name = tcx.item_name(def_id);
                 let def = if name == "clone" {
-                    ty::InstanceDef::CloneShim(def_id, trait_ref.self_ty())
+                    let self_ty = trait_ref.self_ty();
+                    match self_ty.sty {
+                        _ if !self_ty.moves_by_default(tcx, param_env, DUMMY_SP) => {
+                            ty::InstanceDef::CloneCopyShim(def_id, self_ty)
+                        }
+                        ty::TyArray(..) => ty::InstanceDef::CloneStructuralShim(def_id, self_ty),
+                        ty::TyTuple(..) => ty::InstanceDef::CloneStructuralShim(def_id, self_ty),
+                        ty::TyClosure(..) => ty::InstanceDef::CloneNominalShim(def_id, self_ty),
+                        _ => unreachable!("Type {:?} does not have clone shims", self_ty)
+                    }
                 } else {
                     ty::InstanceDef::Item(def_id)
                 };
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index f52f2ea0f9fc8..4037df26b5535 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -2351,7 +2351,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             ty::InstanceDef::Virtual(..) |
             ty::InstanceDef::ClosureOnceShim { .. } |
             ty::InstanceDef::DropGlue(..) |
-            ty::InstanceDef::CloneShim(..) => {
+            ty::InstanceDef::CloneCopyShim(..) |
+            ty::InstanceDef::CloneStructuralShim(..) |
+            ty::InstanceDef::CloneNominalShim(..) => {
                 self.mir_shims(instance)
             }
         }
diff --git a/src/librustc_mir/interpret/terminator/mod.rs b/src/librustc_mir/interpret/terminator/mod.rs
index c8a0dbdd90308..da664acc6f195 100644
--- a/src/librustc_mir/interpret/terminator/mod.rs
+++ b/src/librustc_mir/interpret/terminator/mod.rs
@@ -295,7 +295,9 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
             }
             ty::InstanceDef::FnPtrShim(..) |
             ty::InstanceDef::DropGlue(..) |
-            ty::InstanceDef::CloneShim(..) |
+            ty::InstanceDef::CloneCopyShim(..) |
+            ty::InstanceDef::CloneStructuralShim(..) |
+            ty::InstanceDef::CloneNominalShim(..) |
             ty::InstanceDef::Item(_) => {
                 // Push the stack frame, and potentially be entirely done if the call got hooked
                 if M::eval_fn_call(self, instance, destination, args, span, sig)? {
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index f16187797d4e5..52739420dfb51 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -711,7 +711,9 @@ fn visit_instance_use<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         ty::InstanceDef::ClosureOnceShim { .. } |
         ty::InstanceDef::Item(..) |
         ty::InstanceDef::FnPtrShim(..) |
-        ty::InstanceDef::CloneShim(..) => {
+        ty::InstanceDef::CloneCopyShim(..) |
+        ty::InstanceDef::CloneStructuralShim(..) |
+        ty::InstanceDef::CloneNominalShim(..) => {
             output.push(create_fn_mono_item(instance));
         }
     }
@@ -729,7 +731,9 @@ fn should_monomorphize_locally<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance:
         ty::InstanceDef::FnPtrShim(..) |
         ty::InstanceDef::DropGlue(..) |
         ty::InstanceDef::Intrinsic(_) |
-        ty::InstanceDef::CloneShim(..) => return true
+        ty::InstanceDef::CloneCopyShim(..) |
+        ty::InstanceDef::CloneStructuralShim(..) |
+        ty::InstanceDef::CloneNominalShim(..) => return true
     };
     match tcx.hir.get_if_local(def_id) {
         Some(hir_map::NodeForeignItem(..)) => {
diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs
index e9471cdb4f949..a73ec0deeb817 100644
--- a/src/librustc_mir/monomorphize/partitioning.rs
+++ b/src/librustc_mir/monomorphize/partitioning.rs
@@ -175,7 +175,9 @@ pub trait CodegenUnitExt<'tcx> {
                         InstanceDef::Virtual(..) |
                         InstanceDef::ClosureOnceShim { .. } |
                         InstanceDef::DropGlue(..) |
-                        InstanceDef::CloneShim(..) => {
+                        InstanceDef::CloneCopyShim(..) |
+                        InstanceDef::CloneStructuralShim(..) |
+                        InstanceDef::CloneNominalShim(..) => {
                             None
                         }
                     }
@@ -376,7 +378,9 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                             InstanceDef::Intrinsic(..) |
                             InstanceDef::ClosureOnceShim { .. } |
                             InstanceDef::DropGlue(..) |
-                            InstanceDef::CloneShim(..) => {
+                            InstanceDef::CloneCopyShim(..) |
+                            InstanceDef::CloneStructuralShim(..) |
+                            InstanceDef::CloneNominalShim(..) => {
                                 Visibility::Hidden
                             }
                         };
@@ -619,7 +623,9 @@ fn characteristic_def_id_of_trans_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 ty::InstanceDef::Intrinsic(..) |
                 ty::InstanceDef::DropGlue(..) |
                 ty::InstanceDef::Virtual(..) |
-                ty::InstanceDef::CloneShim(..) => return None
+                ty::InstanceDef::CloneCopyShim(..) |
+                ty::InstanceDef::CloneStructuralShim(..) |
+                ty::InstanceDef::CloneNominalShim(..) => return None
             };
 
             // If this is a method, we want to put it into the same module as
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index 0995324b4f98a..46481a5c11e74 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -99,7 +99,9 @@ fn make_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         ty::InstanceDef::DropGlue(def_id, ty) => {
             build_drop_shim(tcx, def_id, ty)
         }
-        ty::InstanceDef::CloneShim(def_id, ty) => {
+        ty::InstanceDef::CloneCopyShim(def_id, ty) |
+        ty::InstanceDef::CloneNominalShim(def_id, ty) |
+        ty::InstanceDef::CloneStructuralShim(def_id, ty) => {
             build_clone_shim(tcx, def_id, ty)
         }
         ty::InstanceDef::Intrinsic(_) => {

From 9898cff64065a95365ad2962041bd90b97d72de7 Mon Sep 17 00:00:00 2001
From: Manish Goregaokar <manishsmail@gmail.com>
Date: Wed, 7 Feb 2018 10:28:31 -0800
Subject: [PATCH 3/4] Remove ty from CloneCopyShim so that it creates a single
 shim for all monomorphizations

---
 src/librustc/ich/impls_ty.rs |  4 +++-
 src/librustc/ty/instance.rs  | 10 ++++++----
 src/librustc_mir/shim.rs     | 10 +++++++---
 3 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index b8e71f2caf65a..8f33dde422950 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -758,7 +758,9 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::InstanceDef<'gcx> {
                 def_id.hash_stable(hcx, hasher);
                 t.hash_stable(hcx, hasher);
             }
-            ty::InstanceDef::CloneCopyShim(def_id, t) |
+            ty::InstanceDef::CloneCopyShim(def_id) => {
+                def_id.hash_stable(hcx, hasher);
+            }
             ty::InstanceDef::CloneStructuralShim(def_id, t) |
             ty::InstanceDef::CloneNominalShim(def_id, t) => {
                 def_id.hash_stable(hcx, hasher);
diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs
index 6fa58800af50c..ef6b47fd6582e 100644
--- a/src/librustc/ty/instance.rs
+++ b/src/librustc/ty/instance.rs
@@ -47,7 +47,7 @@ pub enum InstanceDef<'tcx> {
     ///`<T as Clone>::clone` shim for Copy types
     ///
     /// The DefId is the DefId of the Clone::clone function
-    CloneCopyShim(DefId, Ty<'tcx>),
+    CloneCopyShim(DefId),
     ///`<T as Clone>::clone` shim for arrays and tuples
     ///
     /// The DefId is the DefId of the Clone::clone function
@@ -78,7 +78,7 @@ impl<'tcx> InstanceDef<'tcx> {
             InstanceDef::Intrinsic(def_id, ) |
             InstanceDef::ClosureOnceShim { call_once: def_id } |
             InstanceDef::DropGlue(def_id, _) |
-            InstanceDef::CloneCopyShim(def_id, _) |
+            InstanceDef::CloneCopyShim(def_id) |
             InstanceDef::CloneStructuralShim(def_id, _) |
             InstanceDef::CloneNominalShim(def_id, _) => def_id
         }
@@ -146,7 +146,9 @@ impl<'tcx> fmt::Display for Instance<'tcx> {
             InstanceDef::DropGlue(_, ty) => {
                 write!(f, " - shim({:?})", ty)
             }
-            InstanceDef::CloneCopyShim(_, ty) |
+            InstanceDef::CloneCopyShim(def) => {
+                write!(f, " - shim({:?})", def)
+            }
             InstanceDef::CloneStructuralShim(_, ty) |
             InstanceDef::CloneNominalShim(_, ty) => {
                 write!(f, " - shim({:?})", ty)
@@ -311,7 +313,7 @@ fn resolve_associated_item<'a, 'tcx>(
                     let self_ty = trait_ref.self_ty();
                     match self_ty.sty {
                         _ if !self_ty.moves_by_default(tcx, param_env, DUMMY_SP) => {
-                            ty::InstanceDef::CloneCopyShim(def_id, self_ty)
+                            ty::InstanceDef::CloneCopyShim(def_id)
                         }
                         ty::TyArray(..) => ty::InstanceDef::CloneStructuralShim(def_id, self_ty),
                         ty::TyTuple(..) => ty::InstanceDef::CloneStructuralShim(def_id, self_ty),
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index 46481a5c11e74..98889c1047c80 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -99,7 +99,13 @@ fn make_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         ty::InstanceDef::DropGlue(def_id, ty) => {
             build_drop_shim(tcx, def_id, ty)
         }
-        ty::InstanceDef::CloneCopyShim(def_id, ty) |
+        ty::InstanceDef::CloneCopyShim(def_id) => {
+            let substs = Substs::identity_for_item(tcx, def_id);
+            let self_ty = substs.type_at(0);
+            let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty);
+            builder.copy_shim();
+            builder.into_mir()
+        }
         ty::InstanceDef::CloneNominalShim(def_id, ty) |
         ty::InstanceDef::CloneStructuralShim(def_id, ty) => {
             build_clone_shim(tcx, def_id, ty)
@@ -289,13 +295,11 @@ fn build_clone_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     debug!("build_clone_shim(def_id={:?})", def_id);
 
     let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty);
-    let is_copy = !self_ty.moves_by_default(tcx, tcx.param_env(def_id), builder.span);
 
     let dest = Place::Local(RETURN_PLACE);
     let src = Place::Local(Local::new(1+0)).deref();
 
     match self_ty.sty {
-        _ if is_copy => builder.copy_shim(),
         ty::TyArray(ty, len) => {
             let len = len.val.to_const_int().unwrap().to_u64().unwrap();
             builder.array_shim(dest, src, ty, len)

From 2c33d2f87ff44ceba998b8b3d58a99af42c8baea Mon Sep 17 00:00:00 2001
From: Manish Goregaokar <manishsmail@gmail.com>
Date: Wed, 7 Feb 2018 13:39:10 -0800
Subject: [PATCH 4/4] Pass down the self def id instead of the type

---
 src/librustc/ich/impls_ty.rs                  |  7 +++--
 src/librustc/ty/instance.rs                   | 28 +++++++++++++------
 src/librustc/ty/mod.rs                        |  2 +-
 src/librustc_mir/interpret/terminator/mod.rs  |  2 +-
 src/librustc_mir/monomorphize/collector.rs    |  4 +--
 src/librustc_mir/monomorphize/partitioning.rs |  6 ++--
 src/librustc_mir/shim.rs                      |  5 +++-
 7 files changed, 35 insertions(+), 19 deletions(-)

diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index 8f33dde422950..cb7f1221c7d58 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -761,8 +761,11 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::InstanceDef<'gcx> {
             ty::InstanceDef::CloneCopyShim(def_id) => {
                 def_id.hash_stable(hcx, hasher);
             }
-            ty::InstanceDef::CloneStructuralShim(def_id, t) |
-            ty::InstanceDef::CloneNominalShim(def_id, t) => {
+            ty::InstanceDef::CloneNominalShim { clone, ty } => {
+                clone.hash_stable(hcx, hasher);
+                ty.hash_stable(hcx, hasher);
+            }
+            ty::InstanceDef::CloneStructuralShim(def_id, t) => {
                 def_id.hash_stable(hcx, hasher);
                 t.hash_stable(hcx, hasher);
             }
diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs
index ef6b47fd6582e..6480deb35cb84 100644
--- a/src/librustc/ty/instance.rs
+++ b/src/librustc/ty/instance.rs
@@ -53,9 +53,12 @@ pub enum InstanceDef<'tcx> {
     /// The DefId is the DefId of the Clone::clone function
     CloneStructuralShim(DefId, Ty<'tcx>),
     ///`<T as Clone>::clone` shim for closures
-    ///
-    /// The DefId is the DefId of the Clone::clone function
-    CloneNominalShim(DefId, Ty<'tcx>),
+    CloneNominalShim {
+        /// The DefId of the Clone::clone trait method def
+        clone: DefId,
+        /// The DefId of the self type
+        ty: DefId
+    },
 }
 
 impl<'a, 'tcx> Instance<'tcx> {
@@ -80,7 +83,7 @@ impl<'tcx> InstanceDef<'tcx> {
             InstanceDef::DropGlue(def_id, _) |
             InstanceDef::CloneCopyShim(def_id) |
             InstanceDef::CloneStructuralShim(def_id, _) |
-            InstanceDef::CloneNominalShim(def_id, _) => def_id
+            InstanceDef::CloneNominalShim{ clone: def_id, ..} => def_id
         }
     }
 
@@ -146,11 +149,11 @@ impl<'tcx> fmt::Display for Instance<'tcx> {
             InstanceDef::DropGlue(_, ty) => {
                 write!(f, " - shim({:?})", ty)
             }
-            InstanceDef::CloneCopyShim(def) => {
+            InstanceDef::CloneCopyShim(def) |
+            InstanceDef::CloneNominalShim { ty: def, ..} => {
                 write!(f, " - shim({:?})", def)
             }
-            InstanceDef::CloneStructuralShim(_, ty) |
-            InstanceDef::CloneNominalShim(_, ty) => {
+            InstanceDef::CloneStructuralShim(_, ty) => {
                 write!(f, " - shim({:?})", ty)
             }
         }
@@ -308,6 +311,7 @@ fn resolve_associated_item<'a, 'tcx>(
         }
         traits::VtableBuiltin(..) => {
             if let Some(_) = tcx.lang_items().clone_trait() {
+                let mut substs = rcvr_substs;
                 let name = tcx.item_name(def_id);
                 let def = if name == "clone" {
                     let self_ty = trait_ref.self_ty();
@@ -317,7 +321,13 @@ fn resolve_associated_item<'a, 'tcx>(
                         }
                         ty::TyArray(..) => ty::InstanceDef::CloneStructuralShim(def_id, self_ty),
                         ty::TyTuple(..) => ty::InstanceDef::CloneStructuralShim(def_id, self_ty),
-                        ty::TyClosure(..) => ty::InstanceDef::CloneNominalShim(def_id, self_ty),
+                        ty::TyClosure(ty_did, closure_substs) => {
+                            substs = closure_substs.substs;
+                            ty::InstanceDef::CloneNominalShim {
+                                clone: def_id,
+                                ty: ty_did
+                            }
+                        }
                         _ => unreachable!("Type {:?} does not have clone shims", self_ty)
                     }
                 } else {
@@ -325,7 +335,7 @@ fn resolve_associated_item<'a, 'tcx>(
                 };
                 Some(Instance {
                     def,
-                    substs: rcvr_substs
+                    substs
                 })
             } else {
                 None
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 4037df26b5535..e29fa4a4d8e90 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -2353,7 +2353,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             ty::InstanceDef::DropGlue(..) |
             ty::InstanceDef::CloneCopyShim(..) |
             ty::InstanceDef::CloneStructuralShim(..) |
-            ty::InstanceDef::CloneNominalShim(..) => {
+            ty::InstanceDef::CloneNominalShim { .. } => {
                 self.mir_shims(instance)
             }
         }
diff --git a/src/librustc_mir/interpret/terminator/mod.rs b/src/librustc_mir/interpret/terminator/mod.rs
index da664acc6f195..932e4c5e3a9e3 100644
--- a/src/librustc_mir/interpret/terminator/mod.rs
+++ b/src/librustc_mir/interpret/terminator/mod.rs
@@ -297,7 +297,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
             ty::InstanceDef::DropGlue(..) |
             ty::InstanceDef::CloneCopyShim(..) |
             ty::InstanceDef::CloneStructuralShim(..) |
-            ty::InstanceDef::CloneNominalShim(..) |
+            ty::InstanceDef::CloneNominalShim { .. } |
             ty::InstanceDef::Item(_) => {
                 // Push the stack frame, and potentially be entirely done if the call got hooked
                 if M::eval_fn_call(self, instance, destination, args, span, sig)? {
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index 52739420dfb51..37c407c14265d 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -713,7 +713,7 @@ fn visit_instance_use<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         ty::InstanceDef::FnPtrShim(..) |
         ty::InstanceDef::CloneCopyShim(..) |
         ty::InstanceDef::CloneStructuralShim(..) |
-        ty::InstanceDef::CloneNominalShim(..) => {
+        ty::InstanceDef::CloneNominalShim { .. } => {
             output.push(create_fn_mono_item(instance));
         }
     }
@@ -733,7 +733,7 @@ fn should_monomorphize_locally<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance:
         ty::InstanceDef::Intrinsic(_) |
         ty::InstanceDef::CloneCopyShim(..) |
         ty::InstanceDef::CloneStructuralShim(..) |
-        ty::InstanceDef::CloneNominalShim(..) => return true
+        ty::InstanceDef::CloneNominalShim { .. } => return true
     };
     match tcx.hir.get_if_local(def_id) {
         Some(hir_map::NodeForeignItem(..)) => {
diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs
index a73ec0deeb817..a53325172901d 100644
--- a/src/librustc_mir/monomorphize/partitioning.rs
+++ b/src/librustc_mir/monomorphize/partitioning.rs
@@ -177,7 +177,7 @@ pub trait CodegenUnitExt<'tcx> {
                         InstanceDef::DropGlue(..) |
                         InstanceDef::CloneCopyShim(..) |
                         InstanceDef::CloneStructuralShim(..) |
-                        InstanceDef::CloneNominalShim(..) => {
+                        InstanceDef::CloneNominalShim { .. } => {
                             None
                         }
                     }
@@ -380,7 +380,7 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                             InstanceDef::DropGlue(..) |
                             InstanceDef::CloneCopyShim(..) |
                             InstanceDef::CloneStructuralShim(..) |
-                            InstanceDef::CloneNominalShim(..) => {
+                            InstanceDef::CloneNominalShim { .. } => {
                                 Visibility::Hidden
                             }
                         };
@@ -625,7 +625,7 @@ fn characteristic_def_id_of_trans_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 ty::InstanceDef::Virtual(..) |
                 ty::InstanceDef::CloneCopyShim(..) |
                 ty::InstanceDef::CloneStructuralShim(..) |
-                ty::InstanceDef::CloneNominalShim(..) => return None
+                ty::InstanceDef::CloneNominalShim { .. } => return None
             };
 
             // If this is a method, we want to put it into the same module as
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index 98889c1047c80..e77d9479f6809 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -106,7 +106,10 @@ fn make_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             builder.copy_shim();
             builder.into_mir()
         }
-        ty::InstanceDef::CloneNominalShim(def_id, ty) |
+        ty::InstanceDef::CloneNominalShim { clone, ty } => {
+            let ty = tcx.type_of(ty);
+            build_clone_shim(tcx, clone, ty)
+        }
         ty::InstanceDef::CloneStructuralShim(def_id, ty) => {
             build_clone_shim(tcx, def_id, ty)
         }