@@ -243,7 +243,13 @@ enum Value<'a, 'tcx> {
243243
244244 // Extractions.
245245 /// This is the *value* obtained by projecting another value.
246- Projection ( VnIndex , ProjectionElem < VnIndex , ( ) > ) ,
246+ Projection {
247+ base : VnIndex ,
248+ elem : ProjectionElem < VnIndex , ( ) > ,
249+ /// Some values may be a borrow or pointer.
250+ /// Give them a different provenance, so we don't merge them.
251+ provenance : Option < VnOpaque > ,
252+ } ,
247253 /// Discriminant of the given value.
248254 Discriminant ( VnIndex ) ,
249255
@@ -292,6 +298,7 @@ impl<'a, 'tcx> ValueSet<'a, 'tcx> {
292298 debug_assert ! ( match value {
293299 Value :: Opaque ( _) | Value :: Address { .. } => true ,
294300 Value :: Constant { disambiguator, .. } => disambiguator. is_some( ) ,
301+ Value :: Projection { provenance, .. } => provenance. is_some( ) ,
295302 _ => false ,
296303 } ) ;
297304
@@ -545,7 +552,24 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
545552 }
546553
547554 fn insert_deref ( & mut self , ty : Ty < ' tcx > , value : VnIndex ) -> VnIndex {
548- let value = self . insert ( ty, Value :: Projection ( value, ProjectionElem :: Deref ) ) ;
555+ let value = if ty. is_any_ptr ( ) {
556+ // Give each borrow and pointer a different provenance, so we don't merge them.
557+ let index = self . values . insert_unique ( ty, |provenance| Value :: Projection {
558+ base : value,
559+ elem : ProjectionElem :: Deref ,
560+ provenance : Some ( provenance) ,
561+ } ) ;
562+ let _index = self . evaluated . push ( Some ( None ) ) ;
563+ debug_assert_eq ! ( index, _index) ;
564+ let _index = self . rev_locals . push ( SmallVec :: new ( ) ) ;
565+ debug_assert_eq ! ( index, _index) ;
566+ index
567+ } else {
568+ self . insert (
569+ ty,
570+ Value :: Projection { base : value, elem : ProjectionElem :: Deref , provenance : None } ,
571+ )
572+ } ;
549573 self . derefs . push ( value) ;
550574 value
551575 }
@@ -649,7 +673,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
649673 ImmTy :: from_immediate ( ptr_imm, ty) . into ( )
650674 }
651675
652- Projection ( base, elem) => {
676+ Projection { base, elem, .. } => {
653677 let base = self . eval_to_const ( base) ?;
654678 // `Index` by constants should have been replaced by `ConstantIndex` by
655679 // `simplify_place_projection`.
@@ -829,8 +853,9 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
829853 ProjectionElem :: Field ( f, _) => match self . get ( value) {
830854 Value :: Aggregate ( _, fields) => return Some ( ( projection_ty, fields[ f. as_usize ( ) ] ) ) ,
831855 Value :: Union ( active, field) if active == f => return Some ( ( projection_ty, field) ) ,
832- Value :: Projection ( outer_value, ProjectionElem :: Downcast ( _, read_variant) )
833- if let Value :: Aggregate ( written_variant, fields) = self . get ( outer_value)
856+ Value :: Projection {
857+ base, elem : ProjectionElem :: Downcast ( _, read_variant) , ..
858+ } if let Value :: Aggregate ( written_variant, fields) = self . get ( base)
834859 // This pass is not aware of control-flow, so we do not know whether the
835860 // replacement we are doing is actually reachable. We could be in any arm of
836861 // ```
@@ -883,7 +908,10 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
883908 ProjectionElem :: UnwrapUnsafeBinder ( _) => ProjectionElem :: UnwrapUnsafeBinder ( ( ) ) ,
884909 } ;
885910
886- let value = self . insert ( projection_ty. ty , Value :: Projection ( value, proj) ) ;
911+ let value = self . insert (
912+ projection_ty. ty ,
913+ Value :: Projection { base : value, elem : proj, provenance : None } ,
914+ ) ;
887915 Some ( ( projection_ty, value) )
888916 }
889917
@@ -1112,11 +1140,17 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
11121140 fields : & [ VnIndex ] ,
11131141 ) -> Option < VnIndex > {
11141142 let Some ( & first_field) = fields. first ( ) else { return None } ;
1115- let Value :: Projection ( copy_from_value, _) = self . get ( first_field) else { return None } ;
1143+ let Value :: Projection { base : copy_from_value, .. } = self . get ( first_field) else {
1144+ return None ;
1145+ } ;
11161146
11171147 // All fields must correspond one-to-one and come from the same aggregate value.
11181148 if fields. iter ( ) . enumerate ( ) . any ( |( index, & v) | {
1119- if let Value :: Projection ( pointer, ProjectionElem :: Field ( from_index, _) ) = self . get ( v)
1149+ if let Value :: Projection {
1150+ base : pointer,
1151+ elem : ProjectionElem :: Field ( from_index, _) ,
1152+ ..
1153+ } = self . get ( v)
11201154 && copy_from_value == pointer
11211155 && from_index. index ( ) == index
11221156 {
@@ -1128,7 +1162,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
11281162 }
11291163
11301164 let mut copy_from_local_value = copy_from_value;
1131- if let Value :: Projection ( pointer, proj) = self . get ( copy_from_value)
1165+ if let Value :: Projection { base : pointer, elem : proj, .. } = self . get ( copy_from_value)
11321166 && let ProjectionElem :: Downcast ( _, read_variant) = proj
11331167 {
11341168 if variant_index == read_variant {
@@ -1839,7 +1873,7 @@ impl<'tcx> VnState<'_, '_, 'tcx> {
18391873 // If we are here, we failed to find a local, and we already have a `Deref`.
18401874 // Trying to add projections will only result in an ill-formed place.
18411875 return None ;
1842- } else if let Value :: Projection ( pointer, proj) = self . get ( index)
1876+ } else if let Value :: Projection { base : pointer, elem : proj, .. } = self . get ( index)
18431877 && ( allow_complex_projection || proj. is_stable_offset ( ) )
18441878 && let Some ( proj) = self . try_as_place_elem ( self . ty ( index) , proj, loc)
18451879 {
0 commit comments