@@ -246,7 +246,13 @@ enum Value<'a, 'tcx> {
246246
247247 // Extractions.
248248 /// This is the *value* obtained by projecting another value.
249- Projection ( VnIndex , ProjectionElem < VnIndex , ( ) > ) ,
249+ Projection {
250+ base : VnIndex ,
251+ elem : ProjectionElem < VnIndex , ( ) > ,
252+ /// Some values may be a borrow or pointer.
253+ /// Give them a different provenance, so we don't merge them.
254+ provenance : Option < VnOpaque > ,
255+ } ,
250256 /// Discriminant of the given value.
251257 Discriminant ( VnIndex ) ,
252258
@@ -295,6 +301,7 @@ impl<'a, 'tcx> ValueSet<'a, 'tcx> {
295301 debug_assert ! ( match value {
296302 Value :: Opaque ( _) | Value :: Address { .. } => true ,
297303 Value :: Constant { disambiguator, .. } => disambiguator. is_some( ) ,
304+ Value :: Projection { provenance, .. } => provenance. is_some( ) ,
298305 _ => false ,
299306 } ) ;
300307
@@ -539,7 +546,18 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
539546 }
540547
541548 fn insert_deref ( & mut self , ty : Ty < ' tcx > , value : VnIndex ) -> VnIndex {
542- self . insert ( ty, Value :: Projection ( value, ProjectionElem :: Deref ) )
549+ if ty. is_any_ptr ( ) {
550+ // Give each borrow and pointer a different provenance, so we don't merge them.
551+ return self . insert_unique ( ty, true , |provenance| Value :: Projection {
552+ base : value,
553+ elem : ProjectionElem :: Deref ,
554+ provenance : Some ( provenance) ,
555+ } ) ;
556+ }
557+ self . insert (
558+ ty,
559+ Value :: Projection { base : value, elem : ProjectionElem :: Deref , provenance : None } ,
560+ )
543561 }
544562
545563 #[ instrument( level = "trace" , skip( self ) , ret) ]
@@ -622,7 +640,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
622640 ImmTy :: from_immediate ( ptr_imm, ty) . into ( )
623641 }
624642
625- Projection ( base, elem) => {
643+ Projection { base, elem, .. } => {
626644 let base = self . eval_to_const ( base) ?;
627645 // `Index` by constants should have been replaced by `ConstantIndex` by
628646 // `simplify_place_projection`.
@@ -813,8 +831,9 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
813831 ProjectionElem :: Field ( f, _) => match self . get ( value) {
814832 Value :: Aggregate ( _, fields) => return Some ( ( projection_ty, fields[ f. as_usize ( ) ] ) ) ,
815833 Value :: Union ( active, field) if active == f => return Some ( ( projection_ty, field) ) ,
816- Value :: Projection ( outer_value, ProjectionElem :: Downcast ( _, read_variant) )
817- if let Value :: Aggregate ( written_variant, fields) = self . get ( outer_value)
834+ Value :: Projection {
835+ base, elem : ProjectionElem :: Downcast ( _, read_variant) , ..
836+ } if let Value :: Aggregate ( written_variant, fields) = self . get ( base)
818837 // This pass is not aware of control-flow, so we do not know whether the
819838 // replacement we are doing is actually reachable. We could be in any arm of
820839 // ```
@@ -867,7 +886,10 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
867886 ProjectionElem :: UnwrapUnsafeBinder ( _) => ProjectionElem :: UnwrapUnsafeBinder ( ( ) ) ,
868887 } ;
869888
870- let value = self . insert ( projection_ty. ty , Value :: Projection ( value, proj) ) ;
889+ let value = self . insert (
890+ projection_ty. ty ,
891+ Value :: Projection { base : value, elem : proj, provenance : None } ,
892+ ) ;
871893 Some ( ( projection_ty, value) )
872894 }
873895
@@ -1096,11 +1118,17 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
10961118 fields : & [ VnIndex ] ,
10971119 ) -> Option < VnIndex > {
10981120 let Some ( & first_field) = fields. first ( ) else { return None } ;
1099- let Value :: Projection ( copy_from_value, _) = self . get ( first_field) else { return None } ;
1121+ let Value :: Projection { base : copy_from_value, .. } = self . get ( first_field) else {
1122+ return None ;
1123+ } ;
11001124
11011125 // All fields must correspond one-to-one and come from the same aggregate value.
11021126 if fields. iter ( ) . enumerate ( ) . any ( |( index, & v) | {
1103- if let Value :: Projection ( pointer, ProjectionElem :: Field ( from_index, _) ) = self . get ( v)
1127+ if let Value :: Projection {
1128+ base : pointer,
1129+ elem : ProjectionElem :: Field ( from_index, _) ,
1130+ ..
1131+ } = self . get ( v)
11041132 && copy_from_value == pointer
11051133 && from_index. index ( ) == index
11061134 {
@@ -1112,7 +1140,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
11121140 }
11131141
11141142 let mut copy_from_local_value = copy_from_value;
1115- if let Value :: Projection ( pointer, proj) = self . get ( copy_from_value)
1143+ if let Value :: Projection { base : pointer, elem : proj, .. } = self . get ( copy_from_value)
11161144 && let ProjectionElem :: Downcast ( _, read_variant) = proj
11171145 {
11181146 if variant_index == read_variant {
@@ -1817,7 +1845,7 @@ impl<'tcx> VnState<'_, '_, 'tcx> {
18171845 // If we are here, we failed to find a local, and we already have a `Deref`.
18181846 // Trying to add projections will only result in an ill-formed place.
18191847 return None ;
1820- } else if let Value :: Projection ( pointer, proj) = self . get ( index)
1848+ } else if let Value :: Projection { base : pointer, elem : proj, .. } = self . get ( index)
18211849 && ( allow_complex_projection || proj. is_stable_offset ( ) )
18221850 && let Some ( proj) = self . try_as_place_elem ( self . ty ( index) , proj, loc)
18231851 {
0 commit comments