@@ -301,7 +301,7 @@ fn build_clone_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
301
301
let src = Place :: Local ( Local :: new ( 1 +0 ) ) . deref ( ) ;
302
302
303
303
match self_ty. sty {
304
- _ if is_copy => builder. copy_shim ( ) ,
304
+ _ if is_copy => { builder. copy_shim ( dest , src ) ; }
305
305
ty:: TyArray ( ty, len) => {
306
306
let len = len. val . to_const_int ( ) . unwrap ( ) . to_u64 ( ) . unwrap ( ) ;
307
307
builder. array_shim ( dest, src, ty, len)
@@ -402,15 +402,15 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
402
402
}
403
403
}
404
404
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 ;
407
407
let ret_statement = self . make_statement (
408
408
StatementKind :: Assign (
409
- Place :: Local ( RETURN_PLACE ) ,
409
+ dest ,
410
410
Rvalue :: Use ( Operand :: Copy ( rcvr) )
411
411
)
412
412
) ;
413
- self . block ( vec ! [ ret_statement] , TerminatorKind :: Return , false ) ;
413
+ self . block ( vec ! [ ret_statement] , TerminatorKind :: Return , false )
414
414
}
415
415
416
416
fn make_place ( & mut self , mutability : Mutability , ty : Ty < ' tcx > ) -> Place < ' tcx > {
@@ -679,6 +679,18 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
679
679
if !adt. is_enum ( ) {
680
680
bug ! ( "We only make Clone shims for enum ADTs" ) ;
681
681
}
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
+
682
694
// should be u128 maybe?
683
695
let discr_ty = adt. repr . discr_type ( ) . to_ty ( self . tcx ) ;
684
696
let discr = self . make_place ( Mutability :: Not , discr_ty) ;
@@ -691,7 +703,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
691
703
) ;
692
704
// insert dummy first block
693
705
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 ) ;
695
707
696
708
let source_info = self . source_info ( ) ;
697
709
self . blocks [ entry_block] . statements = vec ! [ assign_discr] ;
@@ -702,11 +714,24 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
702
714
substs : & ' tcx Substs < ' tcx > ,
703
715
discr : Place < ' tcx > ,
704
716
dest : Place < ' tcx > ,
705
- receiver : Place < ' tcx > ) -> TerminatorKind < ' tcx > {
717
+ receiver : Place < ' tcx > ,
718
+ param_env : ty:: ParamEnv < ' tcx > ) -> TerminatorKind < ' tcx > {
706
719
707
720
let mut values = vec ! [ ] ;
708
721
let mut targets = vec ! [ ] ;
709
722
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
+
710
735
values. push ( adt. discriminant_for_variant ( self . tcx , idx) ) ;
711
736
712
737
let src_variant = receiver. clone ( ) . downcast ( adt, idx) ;
@@ -729,8 +754,8 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
729
754
let iter = variant. fields . iter ( ) . map ( |field| field. ty ( tcx, substs) ) ;
730
755
self . tuple_like_shim ( src_variant, dest_variant, iter) ;
731
756
}
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 ) ) ;
734
759
TerminatorKind :: SwitchInt {
735
760
discr : Operand :: Move ( discr) ,
736
761
switch_ty : self . tcx . types . usize ,
0 commit comments