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