Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More clone shim cleanups #48063

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/librustc/ich/impls_ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
56 changes: 50 additions & 6 deletions src/librustc/ty/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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> {
Expand All @@ -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
}
}

Expand Down Expand Up @@ -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)
}
}
Expand Down Expand Up @@ -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
Expand Down
4 changes: 3 additions & 1 deletion src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/librustc_mir/interpret/terminator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)? {
Expand Down
8 changes: 6 additions & 2 deletions src/librustc_mir/monomorphize/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
}
Expand All @@ -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(..)) => {
Expand Down
12 changes: 9 additions & 3 deletions src/librustc_mir/monomorphize/partitioning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,9 @@ pub trait CodegenUnitExt<'tcx> {
InstanceDef::Virtual(..) |
InstanceDef::ClosureOnceShim { .. } |
InstanceDef::DropGlue(..) |
InstanceDef::CloneShim(..) => {
InstanceDef::CloneCopyShim(..) |
InstanceDef::CloneStructuralShim(..) |
InstanceDef::CloneNominalShim { .. } => {
None
}
}
Expand Down Expand Up @@ -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
}
};
Expand Down Expand Up @@ -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
Expand Down
25 changes: 13 additions & 12 deletions src/librustc_mir/shim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I..don't understand this. How can we have just one shim for all monomorphizations? Don't their sizes depend on the specific types in use?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And what does this DefId refer to anyhow?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shims are not per-monomorphization, they're pretty generic (look at some of the other ones). CloneShim (and now the CloneStructuralShim) was incorrectly too monomorphic (but the array/tuple cases are harder to fix).

What's happening now is that there's only one MIR body forreturn *self; and one per closure definition, which you monomorphize just like you'd monomorphize a generic closure definition.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"One shim for all monomorphizations" is the reason behind this PR. As for how it works, ask @eddyb

}
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)
Expand Down Expand Up @@ -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)
Expand Down