@@ -783,30 +783,34 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
783783 proj : ProjectionElem < VnIndex , Ty < ' tcx > > ,
784784 ) -> Option < ( PlaceTy < ' tcx > , VnIndex ) > {
785785 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 , |_| ( ) ) ?;
796787
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) ) ;
803802 }
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)
810814 // This pass is not aware of control-flow, so we do not know whether the
811815 // replacement we are doing is actually reachable. We could be in any arm of
812816 // ```
@@ -826,39 +830,30 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
826830 {
827831 return Some ( ( projection_ty, fields[ f. as_usize ( ) ] ) ) ;
828832 }
829- ProjectionElem :: Field ( f, ( ) )
830833 }
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) ) ;
836836 }
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) ) ;
854839 }
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) ) ;
857846 }
858- ProjectionElem :: OpaqueCast ( _) => ProjectionElem :: OpaqueCast ( ( ) ) ,
859- ProjectionElem :: Subtype ( _) => ProjectionElem :: Subtype ( ( ) ) ,
860- ProjectionElem :: UnwrapUnsafeBinder ( _) => ProjectionElem :: UnwrapUnsafeBinder ( ( ) ) ,
861- } ;
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+ }
862857
863858 let value = self . insert ( projection_ty. ty , Value :: Projection ( value, proj) ) ;
864859 Some ( ( projection_ty, value) )
0 commit comments