@@ -783,30 +783,34 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
783
783
proj : ProjectionElem < VnIndex , Ty < ' tcx > > ,
784
784
) -> Option < ( PlaceTy < ' tcx > , VnIndex ) > {
785
785
let projection_ty = place_ty. projection_ty ( self . tcx , proj) ;
786
- let proj = match proj {
787
- ProjectionElem :: Deref => {
788
- if let Some ( Mutability :: Not ) = place_ty. ty . ref_mutability ( )
789
- && projection_ty. ty . is_freeze ( self . tcx , self . typing_env ( ) )
790
- {
791
- if let Value :: Address { base, projection, .. } = self . get ( value)
792
- && let Some ( value) = self . dereference_address ( base, projection)
793
- {
794
- return Some ( ( projection_ty, value) ) ;
795
- }
786
+ let proj = proj. try_map ( Some , |_| ( ) ) ?;
796
787
797
- // An immutable borrow `_x` always points to the same value for the
798
- // lifetime of the borrow, so we can merge all instances of `*_x`.
799
- return Some ( ( projection_ty, self . insert_deref ( projection_ty. ty , value) ) ) ;
800
- } else {
801
- return None ;
802
- }
788
+ if let ProjectionElem :: Deref = proj
789
+ // An immutable borrow `_x` always points to the same value for the
790
+ // lifetime of the borrow, so we can merge all instances of `*_x`.
791
+ && !( place_ty. ty . ref_mutability ( ) == Some ( Mutability :: Not )
792
+ && projection_ty. ty . is_freeze ( self . tcx , self . typing_env ( ) ) )
793
+ {
794
+ return None ;
795
+ }
796
+
797
+ match ( proj, self . get ( value) ) {
798
+ ( ProjectionElem :: Deref , Value :: Address { base, projection, .. } )
799
+ if let Some ( deref) = self . dereference_address ( base, projection) =>
800
+ {
801
+ return Some ( ( projection_ty, deref) ) ;
803
802
}
804
- ProjectionElem :: Downcast ( name, index) => ProjectionElem :: Downcast ( name, index) ,
805
- ProjectionElem :: Field ( f, _) => {
806
- if let Value :: Aggregate ( _, fields) = self . get ( value) {
807
- return Some ( ( projection_ty, fields[ f. as_usize ( ) ] ) ) ;
808
- } else if let Value :: Projection ( outer_value, ProjectionElem :: Downcast ( _, read_variant) ) = self . get ( value)
809
- && let Value :: Aggregate ( written_variant, fields) = self . get ( outer_value)
803
+ ( ProjectionElem :: Deref , _) => {
804
+ return Some ( ( projection_ty, self . insert_deref ( projection_ty. ty , value) ) ) ;
805
+ }
806
+ ( ProjectionElem :: Field ( f, _) , Value :: Aggregate ( _, fields) ) => {
807
+ return Some ( ( projection_ty, fields[ f. as_usize ( ) ] ) ) ;
808
+ }
809
+ (
810
+ ProjectionElem :: Field ( f, _) ,
811
+ Value :: Projection ( outer_value, ProjectionElem :: Downcast ( _, read_variant) ) ,
812
+ ) => {
813
+ if let Value :: Aggregate ( written_variant, fields) = self . get ( outer_value)
810
814
// This pass is not aware of control-flow, so we do not know whether the
811
815
// replacement we are doing is actually reachable. We could be in any arm of
812
816
// ```
@@ -826,38 +830,30 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
826
830
{
827
831
return Some ( ( projection_ty, fields[ f. as_usize ( ) ] ) ) ;
828
832
}
829
- ProjectionElem :: Field ( f, ( ) )
830
833
}
831
- ProjectionElem :: Index ( idx) => {
832
- if let Value :: Repeat ( inner, _) = self . get ( value) {
833
- return Some ( ( projection_ty, inner) ) ;
834
- }
835
- ProjectionElem :: Index ( idx)
834
+ ( ProjectionElem :: Index ( _) , Value :: Repeat ( inner, _) ) => {
835
+ return Some ( ( projection_ty, inner) ) ;
836
836
}
837
- ProjectionElem :: ConstantIndex { offset, min_length, from_end } => {
838
- match self . get ( value) {
839
- Value :: Repeat ( inner, _) => {
840
- return Some ( ( projection_ty, inner) ) ;
841
- }
842
- Value :: Aggregate ( _, operands) => {
843
- let offset = if from_end {
844
- operands. len ( ) - offset as usize
845
- } else {
846
- offset as usize
847
- } ;
848
- let value = operands. get ( offset) . copied ( ) ?;
849
- return Some ( ( projection_ty, value) ) ;
850
- }
851
- _ => { }
852
- } ;
853
- ProjectionElem :: ConstantIndex { offset, min_length, from_end }
837
+ ( ProjectionElem :: ConstantIndex { .. } , Value :: Repeat ( inner, _) ) => {
838
+ return Some ( ( projection_ty, inner) ) ;
854
839
}
855
- ProjectionElem :: Subslice { from, to, from_end } => {
856
- ProjectionElem :: Subslice { from, to, from_end }
840
+ (
841
+ ProjectionElem :: ConstantIndex { offset, from_end : false , .. } ,
842
+ Value :: Aggregate ( _, operands) ,
843
+ ) => {
844
+ let value = operands. get ( offset as usize ) . copied ( ) ?;
845
+ return Some ( ( projection_ty, value) ) ;
857
846
}
858
- ProjectionElem :: OpaqueCast ( _) => ProjectionElem :: OpaqueCast ( ( ) ) ,
859
- ProjectionElem :: UnwrapUnsafeBinder ( _) => ProjectionElem :: UnwrapUnsafeBinder ( ( ) ) ,
860
- } ;
847
+ (
848
+ ProjectionElem :: ConstantIndex { offset, from_end : true , .. } ,
849
+ Value :: Aggregate ( _, operands) ,
850
+ ) => {
851
+ let offset = operands. len ( ) . checked_sub ( offset as usize ) ?;
852
+ let value = operands[ offset] ;
853
+ return Some ( ( projection_ty, value) ) ;
854
+ }
855
+ _ => { }
856
+ }
861
857
862
858
let value = self . insert ( projection_ty. ty , Value :: Projection ( value, proj) ) ;
863
859
Some ( ( projection_ty, value) )
0 commit comments