@@ -895,18 +895,13 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
895895
896896 fn simplify_aggregate_to_copy (
897897 & mut self ,
898- lhs : & Place < ' tcx > ,
899- rvalue : & mut Rvalue < ' tcx > ,
900- location : Location ,
901- fields : & [ VnIndex ] ,
898+ ty : Ty < ' tcx > ,
902899 variant_index : VariantIdx ,
900+ fields : & [ VnIndex ] ,
903901 ) -> Option < VnIndex > {
904- let Some ( & first_field) = fields. first ( ) else {
905- return None ;
906- } ;
907- let Value :: Projection ( copy_from_value, _) = * self . get ( first_field) else {
908- return None ;
909- } ;
902+ let Some ( & first_field) = fields. first ( ) else { return None } ;
903+ let Value :: Projection ( copy_from_value, _) = * self . get ( first_field) else { return None } ;
904+
910905 // All fields must correspond one-to-one and come from the same aggregate value.
911906 if fields. iter ( ) . enumerate ( ) . any ( |( index, & v) | {
912907 if let Value :: Projection ( pointer, ProjectionElem :: Field ( from_index, _) ) = * self . get ( v)
@@ -933,21 +928,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
933928 }
934929 }
935930
936- // Allow introducing places with non-constant offsets, as those are still better than
937- // reconstructing an aggregate.
938- if self . ty ( copy_from_local_value) == rvalue. ty ( self . local_decls , self . tcx )
939- && let Some ( place) = self . try_as_place ( copy_from_local_value, location, true )
940- {
941- // Avoid creating `*a = copy (*b)`, as they might be aliases resulting in overlapping assignments.
942- // FIXME: This also avoids any kind of projection, not just derefs. We can add allowed projections.
943- if lhs. as_local ( ) . is_some ( ) {
944- self . reused_locals . insert ( place. local ) ;
945- * rvalue = Rvalue :: Use ( Operand :: Copy ( place) ) ;
946- }
947- return Some ( copy_from_local_value) ;
948- }
949-
950- None
931+ // Both must be variants of the same type.
932+ if self . ty ( copy_from_local_value) == ty { Some ( copy_from_local_value) } else { None }
951933 }
952934
953935 fn simplify_aggregate (
@@ -1034,9 +1016,16 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
10341016 }
10351017 }
10361018
1037- if let Some ( value) =
1038- self . simplify_aggregate_to_copy ( lhs, rvalue, location, & fields, variant_index)
1039- {
1019+ if let Some ( value) = self . simplify_aggregate_to_copy ( ty, variant_index, & fields) {
1020+ // Allow introducing places with non-constant offsets, as those are still better than
1021+ // reconstructing an aggregate. But avoid creating `*a = copy (*b)`, as they might be
1022+ // aliases resulting in overlapping assignments.
1023+ let allow_complex_projection =
1024+ lhs. projection [ ..] . iter ( ) . all ( PlaceElem :: is_stable_offset) ;
1025+ if let Some ( place) = self . try_as_place ( value, location, allow_complex_projection) {
1026+ self . reused_locals . insert ( place. local ) ;
1027+ * rvalue = Rvalue :: Use ( Operand :: Copy ( place) ) ;
1028+ }
10401029 return Some ( value) ;
10411030 }
10421031
0 commit comments