Skip to content

Commit d35bc21

Browse files
committed
Collapse all Copy arms
1 parent 8594f87 commit d35bc21

File tree

1 file changed

+34
-9
lines changed

1 file changed

+34
-9
lines changed

src/librustc_mir/shim.rs

+34-9
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ fn build_clone_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
301301
let src = Place::Local(Local::new(1+0)).deref();
302302

303303
match self_ty.sty {
304-
_ if is_copy => builder.copy_shim(),
304+
_ if is_copy => { builder.copy_shim(dest, src); }
305305
ty::TyArray(ty, len) => {
306306
let len = len.val.to_const_int().unwrap().to_u64().unwrap();
307307
builder.array_shim(dest, src, ty, len)
@@ -402,15 +402,15 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
402402
}
403403
}
404404

405-
fn copy_shim(&mut self) {
406-
let rcvr = Place::Local(Local::new(1+0)).deref();
405+
fn copy_shim(&mut self, dest: Place<'tcx>, src: Place<'tcx>) -> BasicBlock {
406+
let rcvr = src;
407407
let ret_statement = self.make_statement(
408408
StatementKind::Assign(
409-
Place::Local(RETURN_PLACE),
409+
dest,
410410
Rvalue::Use(Operand::Copy(rcvr))
411411
)
412412
);
413-
self.block(vec![ret_statement], TerminatorKind::Return, false);
413+
self.block(vec![ret_statement], TerminatorKind::Return, false)
414414
}
415415

416416
fn make_place(&mut self, mutability: Mutability, ty: Ty<'tcx>) -> Place<'tcx> {
@@ -679,6 +679,18 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
679679
if !adt.is_enum() {
680680
bug!("We only make Clone shims for enum ADTs");
681681
}
682+
683+
let param_env = self.tcx.param_env(adt.did);
684+
let all_copy = adt.all_fields().all(|field| {
685+
!field.ty(self.tcx, substs)
686+
.moves_by_default(self.tcx, param_env, self.span)
687+
});
688+
689+
if all_copy {
690+
self.copy_shim(dest, src);
691+
return;
692+
}
693+
682694
// should be u128 maybe?
683695
let discr_ty = adt.repr.discr_type().to_ty(self.tcx);
684696
let discr = self.make_place(Mutability::Not, discr_ty);
@@ -691,7 +703,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
691703
);
692704
// insert dummy first block
693705
let entry_block = self.block(vec![], TerminatorKind::Abort, false);
694-
let switch = self.make_enum_match(adt, substs, discr, dest, src);
706+
let switch = self.make_enum_match(adt, substs, discr, dest, src, param_env);
695707

696708
let source_info = self.source_info();
697709
self.blocks[entry_block].statements = vec![assign_discr];
@@ -702,11 +714,24 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
702714
substs: &'tcx Substs<'tcx>,
703715
discr: Place<'tcx>,
704716
dest: Place<'tcx>,
705-
receiver: Place<'tcx>) -> TerminatorKind<'tcx> {
717+
receiver: Place<'tcx>,
718+
param_env: ty::ParamEnv<'tcx>) -> TerminatorKind<'tcx> {
706719

707720
let mut values = vec![];
708721
let mut targets = vec![];
709722
for (idx, variant) in adt.variants.iter().enumerate() {
723+
724+
// in case a variant is Copy, don't generate the manual Clone
725+
// match arm, instead let the copy_shim default deal with it
726+
let all_copy = variant.fields.iter().all(|field| {
727+
!field.ty(self.tcx, substs)
728+
.moves_by_default(self.tcx, param_env, self.span)
729+
});
730+
731+
if all_copy {
732+
continue;
733+
}
734+
710735
values.push(adt.discriminant_for_variant(self.tcx, idx));
711736

712737
let src_variant = receiver.clone().downcast(adt, idx);
@@ -729,8 +754,8 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
729754
let iter = variant.fields.iter().map(|field| field.ty(tcx, substs));
730755
self.tuple_like_shim(src_variant, dest_variant, iter);
731756
}
732-
// the nonexistant extra case
733-
targets.push(self.block(vec![], TerminatorKind::Abort, true));
757+
// In the default arm, fall back to a copy
758+
targets.push(self.copy_shim(dest, receiver));
734759
TerminatorKind::SwitchInt {
735760
discr: Operand::Move(discr),
736761
switch_ty: self.tcx.types.usize,

0 commit comments

Comments
 (0)