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