@@ -651,30 +651,34 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
651651 proj : ProjectionElem < VnIndex , Ty < ' tcx > > ,
652652 ) -> Option < ( PlaceTy < ' tcx > , VnIndex ) > {
653653 let projection_ty = place_ty. projection_ty ( self . tcx , proj) ;
654- let proj = match proj {
655- ProjectionElem :: Deref => {
656- if let Some ( Mutability :: Not ) = place_ty. ty . ref_mutability ( )
657- && projection_ty. ty . is_freeze ( self . tcx , self . typing_env ( ) )
658- {
659- if let Value :: Address { base, projection, .. } = self . get ( value)
660- && let Some ( value) = self . dereference_address ( base, projection)
661- {
662- return Some ( ( projection_ty, value) ) ;
663- }
654+ let proj = proj. try_map ( Some , |_| ( ) ) ?;
664655
665- // An immutable borrow `_x` always points to the same value for the
666- // lifetime of the borrow, so we can merge all instances of `*_x`.
667- return Some ( ( projection_ty, self . insert_deref ( projection_ty. ty , value) ) ) ;
668- } else {
669- return None ;
670- }
656+ if let ProjectionElem :: Deref = proj
657+ // An immutable borrow `_x` always points to the same value for the
658+ // lifetime of the borrow, so we can merge all instances of `*_x`.
659+ && !( place_ty. ty . ref_mutability ( ) == Some ( Mutability :: Not )
660+ && projection_ty. ty . is_freeze ( self . tcx , self . typing_env ( ) ) )
661+ {
662+ return None ;
663+ }
664+
665+ match ( proj, self . get ( value) ) {
666+ ( ProjectionElem :: Deref , Value :: Address { base, projection, .. } )
667+ if let Some ( deref) = self . dereference_address ( base, projection) =>
668+ {
669+ return Some ( ( projection_ty, deref) ) ;
671670 }
672- ProjectionElem :: Downcast ( name, index) => ProjectionElem :: Downcast ( name, index) ,
673- ProjectionElem :: Field ( f, _) => {
674- if let Value :: Aggregate ( _, fields) = self . get ( value) {
675- return Some ( ( projection_ty, fields[ f. as_usize ( ) ] ) ) ;
676- } else if let Value :: Projection ( outer_value, ProjectionElem :: Downcast ( _, read_variant) ) = self . get ( value)
677- && let Value :: Aggregate ( written_variant, fields) = self . get ( outer_value)
671+ ( ProjectionElem :: Deref , _) => {
672+ return Some ( ( projection_ty, self . insert_deref ( projection_ty. ty , value) ) ) ;
673+ }
674+ ( ProjectionElem :: Field ( f, _) , Value :: Aggregate ( _, fields) ) => {
675+ return Some ( ( projection_ty, fields[ f. as_usize ( ) ] ) ) ;
676+ }
677+ (
678+ ProjectionElem :: Field ( f, _) ,
679+ Value :: Projection ( outer_value, ProjectionElem :: Downcast ( _, read_variant) ) ,
680+ ) => {
681+ if let Value :: Aggregate ( written_variant, fields) = self . get ( outer_value)
678682 // This pass is not aware of control-flow, so we do not know whether the
679683 // replacement we are doing is actually reachable. We could be in any arm of
680684 // ```
@@ -694,39 +698,30 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
694698 {
695699 return Some ( ( projection_ty, fields[ f. as_usize ( ) ] ) ) ;
696700 }
697- ProjectionElem :: Field ( f, ( ) )
698701 }
699- ProjectionElem :: Index ( idx) => {
700- if let Value :: Repeat ( inner, _) = self . get ( value) {
701- return Some ( ( projection_ty, inner) ) ;
702- }
703- ProjectionElem :: Index ( idx)
702+ ( ProjectionElem :: Index ( _) , Value :: Repeat ( inner, _) ) => {
703+ return Some ( ( projection_ty, inner) ) ;
704704 }
705- ProjectionElem :: ConstantIndex { offset, min_length, from_end } => {
706- match self . get ( value) {
707- Value :: Repeat ( inner, _) => {
708- return Some ( ( projection_ty, inner) ) ;
709- }
710- Value :: Aggregate ( _, operands) => {
711- let offset = if from_end {
712- operands. len ( ) - offset as usize
713- } else {
714- offset as usize
715- } ;
716- let value = operands. get ( offset) . copied ( ) ?;
717- return Some ( ( projection_ty, value) ) ;
718- }
719- _ => { }
720- } ;
721- ProjectionElem :: ConstantIndex { offset, min_length, from_end }
705+ ( ProjectionElem :: ConstantIndex { .. } , Value :: Repeat ( inner, _) ) => {
706+ return Some ( ( projection_ty, inner) ) ;
722707 }
723- ProjectionElem :: Subslice { from, to, from_end } => {
724- ProjectionElem :: Subslice { from, to, from_end }
708+ (
709+ ProjectionElem :: ConstantIndex { offset, from_end : false , .. } ,
710+ Value :: Aggregate ( _, operands) ,
711+ ) => {
712+ let value = operands. get ( offset as usize ) . copied ( ) ?;
713+ return Some ( ( projection_ty, value) ) ;
725714 }
726- ProjectionElem :: OpaqueCast ( _) => ProjectionElem :: OpaqueCast ( ( ) ) ,
727- ProjectionElem :: Subtype ( _) => ProjectionElem :: Subtype ( ( ) ) ,
728- ProjectionElem :: UnwrapUnsafeBinder ( _) => ProjectionElem :: UnwrapUnsafeBinder ( ( ) ) ,
729- } ;
715+ (
716+ ProjectionElem :: ConstantIndex { offset, from_end : true , .. } ,
717+ Value :: Aggregate ( _, operands) ,
718+ ) => {
719+ let offset = operands. len ( ) . checked_sub ( offset as usize ) ?;
720+ let value = operands[ offset] ;
721+ return Some ( ( projection_ty, value) ) ;
722+ }
723+ _ => { }
724+ }
730725
731726 let value = self . insert ( projection_ty. ty , Value :: Projection ( value, proj) ) ;
732727 Some ( ( projection_ty, value) )
0 commit comments