@@ -651,30 +651,34 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
651
651
proj : ProjectionElem < VnIndex , Ty < ' tcx > > ,
652
652
) -> Option < ( PlaceTy < ' tcx > , VnIndex ) > {
653
653
let projection_ty = place_ty. projection_ty ( self . tcx , proj) ;
654
- let proj = match proj {
655
- ProjectionElem :: Deref => {
656
- if let Some ( Mutability :: Not ) = place_ty. ty . ref_mutability ( )
657
- && projection_ty. ty . is_freeze ( self . tcx , self . typing_env ( ) )
658
- {
659
- if let Value :: Address { base, projection, .. } = self . get ( value)
660
- && let Some ( value) = self . dereference_address ( base, projection)
661
- {
662
- return Some ( ( projection_ty, value) ) ;
663
- }
654
+ let proj = proj. try_map ( Some , |_| ( ) ) ?;
664
655
665
- // An immutable borrow `_x` always points to the same value for the
666
- // lifetime of the borrow, so we can merge all instances of `*_x`.
667
- return Some ( ( projection_ty, self . insert_deref ( projection_ty. ty , value) ) ) ;
668
- } else {
669
- return None ;
670
- }
656
+ if let ProjectionElem :: Deref = proj
657
+ // An immutable borrow `_x` always points to the same value for the
658
+ // lifetime of the borrow, so we can merge all instances of `*_x`.
659
+ && !( place_ty. ty . ref_mutability ( ) == Some ( Mutability :: Not )
660
+ && projection_ty. ty . is_freeze ( self . tcx , self . typing_env ( ) ) )
661
+ {
662
+ return None ;
663
+ }
664
+
665
+ match ( proj, self . get ( value) ) {
666
+ ( ProjectionElem :: Deref , Value :: Address { base, projection, .. } )
667
+ if let Some ( deref) = self . dereference_address ( base, projection) =>
668
+ {
669
+ return Some ( ( projection_ty, deref) ) ;
671
670
}
672
- ProjectionElem :: Downcast ( name, index) => ProjectionElem :: Downcast ( name, index) ,
673
- ProjectionElem :: Field ( f, _) => {
674
- if let Value :: Aggregate ( _, fields) = self . get ( value) {
675
- return Some ( ( projection_ty, fields[ f. as_usize ( ) ] ) ) ;
676
- } else if let Value :: Projection ( outer_value, ProjectionElem :: Downcast ( _, read_variant) ) = self . get ( value)
677
- && let Value :: Aggregate ( written_variant, fields) = self . get ( outer_value)
671
+ ( ProjectionElem :: Deref , _) => {
672
+ return Some ( ( projection_ty, self . insert_deref ( projection_ty. ty , value) ) ) ;
673
+ }
674
+ ( ProjectionElem :: Field ( f, _) , Value :: Aggregate ( _, fields) ) => {
675
+ return Some ( ( projection_ty, fields[ f. as_usize ( ) ] ) ) ;
676
+ }
677
+ (
678
+ ProjectionElem :: Field ( f, _) ,
679
+ Value :: Projection ( outer_value, ProjectionElem :: Downcast ( _, read_variant) ) ,
680
+ ) => {
681
+ if let Value :: Aggregate ( written_variant, fields) = self . get ( outer_value)
678
682
// This pass is not aware of control-flow, so we do not know whether the
679
683
// replacement we are doing is actually reachable. We could be in any arm of
680
684
// ```
@@ -694,39 +698,30 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
694
698
{
695
699
return Some ( ( projection_ty, fields[ f. as_usize ( ) ] ) ) ;
696
700
}
697
- ProjectionElem :: Field ( f, ( ) )
698
701
}
699
- ProjectionElem :: Index ( idx) => {
700
- if let Value :: Repeat ( inner, _) = self . get ( value) {
701
- return Some ( ( projection_ty, inner) ) ;
702
- }
703
- ProjectionElem :: Index ( idx)
702
+ ( ProjectionElem :: Index ( _) , Value :: Repeat ( inner, _) ) => {
703
+ return Some ( ( projection_ty, inner) ) ;
704
704
}
705
- ProjectionElem :: ConstantIndex { offset, min_length, from_end } => {
706
- match self . get ( value) {
707
- Value :: Repeat ( inner, _) => {
708
- return Some ( ( projection_ty, inner) ) ;
709
- }
710
- Value :: Aggregate ( _, operands) => {
711
- let offset = if from_end {
712
- operands. len ( ) - offset as usize
713
- } else {
714
- offset as usize
715
- } ;
716
- let value = operands. get ( offset) . copied ( ) ?;
717
- return Some ( ( projection_ty, value) ) ;
718
- }
719
- _ => { }
720
- } ;
721
- ProjectionElem :: ConstantIndex { offset, min_length, from_end }
705
+ ( ProjectionElem :: ConstantIndex { .. } , Value :: Repeat ( inner, _) ) => {
706
+ return Some ( ( projection_ty, inner) ) ;
722
707
}
723
- ProjectionElem :: Subslice { from, to, from_end } => {
724
- ProjectionElem :: Subslice { from, to, from_end }
708
+ (
709
+ ProjectionElem :: ConstantIndex { offset, from_end : false , .. } ,
710
+ Value :: Aggregate ( _, operands) ,
711
+ ) => {
712
+ let value = operands. get ( offset as usize ) . copied ( ) ?;
713
+ return Some ( ( projection_ty, value) ) ;
725
714
}
726
- ProjectionElem :: OpaqueCast ( _) => ProjectionElem :: OpaqueCast ( ( ) ) ,
727
- ProjectionElem :: Subtype ( _) => ProjectionElem :: Subtype ( ( ) ) ,
728
- ProjectionElem :: UnwrapUnsafeBinder ( _) => ProjectionElem :: UnwrapUnsafeBinder ( ( ) ) ,
729
- } ;
715
+ (
716
+ ProjectionElem :: ConstantIndex { offset, from_end : true , .. } ,
717
+ Value :: Aggregate ( _, operands) ,
718
+ ) => {
719
+ let offset = operands. len ( ) . checked_sub ( offset as usize ) ?;
720
+ let value = operands[ offset] ;
721
+ return Some ( ( projection_ty, value) ) ;
722
+ }
723
+ _ => { }
724
+ }
730
725
731
726
let value = self . insert ( projection_ty. ty , Value :: Projection ( value, proj) ) ;
732
727
Some ( ( projection_ty, value) )
0 commit comments