diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 107779ec3fa15..cb7f1221c7d58 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -758,7 +758,14 @@ 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) => { + def_id.hash_stable(hcx, hasher); + } + 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 63bf52a9bdf78..6480deb35cb84 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,25 @@ 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), + ///`<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 + 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> { @@ -65,7 +81,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{ clone: def_id, ..} => def_id } } @@ -131,7 +149,11 @@ impl<'tcx> fmt::Display for Instance<'tcx> { InstanceDef::DropGlue(_, ty) => { write!(f, " - shim({:?})", ty) } - InstanceDef::CloneShim(_, ty) => { + InstanceDef::CloneCopyShim(def) | + InstanceDef::CloneNominalShim { ty: def, ..} => { + write!(f, " - shim({:?})", def) + } + InstanceDef::CloneStructuralShim(_, ty) => { write!(f, " - shim({:?})", ty) } } @@ -289,9 +311,31 @@ 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(); + match self_ty.sty { + _ if !self_ty.moves_by_default(tcx, param_env, DUMMY_SP) => { + ty::InstanceDef::CloneCopyShim(def_id) + } + ty::TyArray(..) => ty::InstanceDef::CloneStructuralShim(def_id, self_ty), + ty::TyTuple(..) => ty::InstanceDef::CloneStructuralShim(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 { + ty::InstanceDef::Item(def_id) + }; Some(Instance { - def: ty::InstanceDef::CloneShim(def_id, trait_ref.self_ty()), - substs: rcvr_substs + def, + substs }) } else { None diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index f52f2ea0f9fc8..e29fa4a4d8e90 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..932e4c5e3a9e3 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..37c407c14265d 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..a53325172901d 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 42ffcc194ca8c..e77d9479f6809 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -99,16 +99,19 @@ 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) => { - 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) - } + 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 { 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) } ty::InstanceDef::Intrinsic(_) => { bug!("creating shims from intrinsics ({:?}) is unsupported", instance) @@ -295,13 +298,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)