@@ -800,81 +800,80 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
800
800
proj : ProjectionElem < VnIndex , Ty < ' tcx > > ,
801
801
) -> Option < ( PlaceTy < ' tcx > , VnIndex ) > {
802
802
let projection_ty = place_ty. projection_ty ( self . tcx , proj) ;
803
- let proj = match proj {
804
- ProjectionElem :: Deref => {
805
- if let Some ( Mutability :: Not ) = place_ty. ty . ref_mutability ( )
803
+ let proj = proj. try_map ( Some , |_| ( ) ) ?;
804
+
805
+ if let ProjectionElem :: Deref = proj
806
+ && !(
807
+ // An immutable borrow `_x` always points to the same value for the
808
+ // lifetime of the borrow, so we can merge all instances of `*_x`.
809
+ place_ty. ty . ref_mutability ( ) == Some ( Mutability :: Not )
806
810
&& projection_ty. ty . is_freeze ( self . tcx , self . typing_env ( ) )
807
- {
808
- if let Value :: Address { base, projection, .. } = self . get ( value)
809
- && let Some ( value) = self . dereference_address ( base, projection)
810
- {
811
- return Some ( ( projection_ty, value) ) ;
812
- }
811
+ )
812
+ {
813
+ return None ;
814
+ }
813
815
814
- // An immutable borrow `_x` always points to the same value for the
815
- // lifetime of the borrow, so we can merge all instances of `*_x`.
816
- return Some ( ( projection_ty, self . insert_deref ( projection_ty. ty , value) ) ) ;
817
- } else {
818
- return None ;
819
- }
816
+ match ( proj, self . get ( value) ) {
817
+ ( ProjectionElem :: Deref , Value :: Address { base, projection, .. } )
818
+ if let Some ( deref) = self . dereference_address ( base, projection) =>
819
+ {
820
+ return Some ( ( projection_ty, deref) ) ;
820
821
}
821
- ProjectionElem :: Downcast ( name, index) => ProjectionElem :: Downcast ( name, index) ,
822
- ProjectionElem :: Field ( f, _) => match self . get ( value) {
823
- Value :: Aggregate ( _, fields) => return Some ( ( projection_ty, fields[ f. as_usize ( ) ] ) ) ,
824
- Value :: Union ( active, field) if active == f => return Some ( ( projection_ty, field) ) ,
825
- Value :: Projection ( outer_value, ProjectionElem :: Downcast ( _, read_variant) )
826
- if let Value :: Aggregate ( written_variant, fields) = self . get ( outer_value)
827
- // This pass is not aware of control-flow, so we do not know whether the
828
- // replacement we are doing is actually reachable. We could be in any arm of
829
- // ```
830
- // match Some(x) {
831
- // Some(y) => /* stuff */,
832
- // None => /* other */,
833
- // }
834
- // ```
835
- //
836
- // In surface rust, the current statement would be unreachable.
837
- //
838
- // However, from the reference chapter on enums and RFC 2195,
839
- // accessing the wrong variant is not UB if the enum has repr.
840
- // So it's not impossible for a series of MIR opts to generate
841
- // a downcast to an inactive variant.
842
- && written_variant == read_variant =>
843
- {
844
- return Some ( ( projection_ty, fields[ f. as_usize ( ) ] ) ) ;
845
- }
846
- _ => ProjectionElem :: Field ( f, ( ) ) ,
847
- } ,
848
- ProjectionElem :: Index ( idx) => {
849
- if let Value :: Repeat ( inner, _) = self . get ( value) {
850
- return Some ( ( projection_ty, inner) ) ;
851
- }
852
- ProjectionElem :: Index ( idx)
822
+ ( ProjectionElem :: Deref , _) => {
823
+ return Some ( ( projection_ty, self . insert_deref ( projection_ty. ty , value) ) ) ;
853
824
}
854
- ProjectionElem :: ConstantIndex { offset, min_length, from_end } => {
855
- match self . get ( value) {
856
- Value :: Repeat ( inner, _) => {
857
- return Some ( ( projection_ty, inner) ) ;
858
- }
859
- Value :: Aggregate ( _, operands) => {
860
- let offset = if from_end {
861
- operands. len ( ) - offset as usize
862
- } else {
863
- offset as usize
864
- } ;
865
- let value = operands. get ( offset) . copied ( ) ?;
866
- return Some ( ( projection_ty, value) ) ;
867
- }
868
- _ => { }
869
- } ;
870
- ProjectionElem :: ConstantIndex { offset, min_length, from_end }
825
+ ( ProjectionElem :: Field ( f, _) , Value :: Aggregate ( _, fields) ) => {
826
+ return Some ( ( projection_ty, fields[ f. as_usize ( ) ] ) ) ;
871
827
}
872
- ProjectionElem :: Subslice { from , to , from_end } => {
873
- ProjectionElem :: Subslice { from , to , from_end }
828
+ ( ProjectionElem :: Field ( f , _ ) , Value :: Union ( active , field ) ) if active == f => {
829
+ return Some ( ( projection_ty , field ) ) ;
874
830
}
875
- ProjectionElem :: OpaqueCast ( _) => ProjectionElem :: OpaqueCast ( ( ) ) ,
876
- ProjectionElem :: UnwrapUnsafeBinder ( _) => ProjectionElem :: UnwrapUnsafeBinder ( ( ) ) ,
877
- } ;
831
+ (
832
+ ProjectionElem :: Field ( f, _) ,
833
+ Value :: Projection ( outer_value, ProjectionElem :: Downcast ( _, read_variant) ) ,
834
+ ) if let Value :: Aggregate ( written_variant, fields) = self . get ( outer_value)
835
+ // This pass is not aware of control-flow, so we do not know whether the
836
+ // replacement we are doing is actually reachable. We could be in any arm of
837
+ // ```
838
+ // match Some(x) {
839
+ // Some(y) => /* stuff */,
840
+ // None => /* other */,
841
+ // }
842
+ // ```
843
+ //
844
+ // In surface rust, the current statement would be unreachable.
845
+ //
846
+ // However, from the reference chapter on enums and RFC 2195,
847
+ // accessing the wrong variant is not UB if the enum has repr.
848
+ // So it's not impossible for a series of MIR opts to generate
849
+ // a downcast to an inactive variant.
850
+ && written_variant == read_variant =>
851
+ {
852
+ return Some ( ( projection_ty, fields[ f. as_usize ( ) ] ) ) ;
853
+ }
854
+ ( ProjectionElem :: Index ( _) , Value :: Repeat ( inner, _) ) => {
855
+ return Some ( ( projection_ty, inner) ) ;
856
+ }
857
+ ( ProjectionElem :: ConstantIndex { .. } , Value :: Repeat ( inner, _) ) => {
858
+ return Some ( ( projection_ty, inner) ) ;
859
+ }
860
+ (
861
+ ProjectionElem :: ConstantIndex { offset, from_end : false , .. } ,
862
+ Value :: Aggregate ( _, operands) ,
863
+ ) => {
864
+ let value = operands. get ( offset as usize ) . copied ( ) ?;
865
+ return Some ( ( projection_ty, value) ) ;
866
+ }
867
+ (
868
+ ProjectionElem :: ConstantIndex { offset, from_end : true , .. } ,
869
+ Value :: Aggregate ( _, operands) ,
870
+ ) => {
871
+ let offset = operands. len ( ) . checked_sub ( offset as usize ) ?;
872
+ let value = operands[ offset] ;
873
+ return Some ( ( projection_ty, value) ) ;
874
+ }
875
+ _ => { }
876
+ }
878
877
879
878
let value = self . insert ( projection_ty. ty , Value :: Projection ( value, proj) ) ;
880
879
Some ( ( projection_ty, value) )
0 commit comments