@@ -237,7 +237,13 @@ enum Value<'a, 'tcx> {
237237
238238 // Extractions.
239239 /// This is the *value* obtained by projecting another value.
240- Projection ( VnIndex , ProjectionElem < VnIndex , ( ) > ) ,
240+ Projection {
241+ base : VnIndex ,
242+ elem : ProjectionElem < VnIndex , ( ) > ,
243+ /// Some values may be a borrow or pointer.
244+ /// Give them a different provenance, so we don't merge them.
245+ provenance : Option < VnOpaque > ,
246+ } ,
241247 /// Discriminant of the given value.
242248 Discriminant ( VnIndex ) ,
243249
@@ -286,6 +292,7 @@ impl<'a, 'tcx> ValueSet<'a, 'tcx> {
286292 debug_assert ! ( match value {
287293 Value :: Opaque ( _) | Value :: Address { .. } => true ,
288294 Value :: Constant { disambiguator, .. } => disambiguator. is_some( ) ,
295+ Value :: Projection { provenance, .. } => provenance. is_some( ) ,
289296 _ => false ,
290297 } ) ;
291298
@@ -527,7 +534,21 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
527534 }
528535
529536 fn insert_deref ( & mut self , ty : Ty < ' tcx > , value : VnIndex ) -> VnIndex {
530- self . insert ( ty, Value :: Projection ( value, ProjectionElem :: Deref ) )
537+ if ty. is_any_ptr ( ) {
538+ // Give each borrow and pointer a different provenance, so we don't merge them.
539+ let index = self . insert_unique ( ty, |provenance| Value :: Projection {
540+ base : value,
541+ elem : ProjectionElem :: Deref ,
542+ provenance : Some ( provenance) ,
543+ } ) ;
544+ self . evaluated [ index] = Some ( None ) ;
545+ index
546+ } else {
547+ self . insert (
548+ ty,
549+ Value :: Projection { base : value, elem : ProjectionElem :: Deref , provenance : None } ,
550+ )
551+ }
531552 }
532553
533554 #[ instrument( level = "trace" , skip( self ) , ret) ]
@@ -625,7 +646,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
625646 ImmTy :: from_immediate ( ptr_imm, ty) . into ( )
626647 }
627648
628- Projection ( base, elem) => {
649+ Projection { base, elem, .. } => {
629650 let base = self . eval_to_const ( base) ?;
630651 // `Index` by constants should have been replaced by `ConstantIndex` by
631652 // `simplify_place_projection`.
@@ -803,8 +824,9 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
803824 ProjectionElem :: Field ( f, _) => match self . get ( value) {
804825 Value :: Aggregate ( _, fields) => return Some ( ( projection_ty, fields[ f. as_usize ( ) ] ) ) ,
805826 Value :: Union ( active, field) if active == f => return Some ( ( projection_ty, field) ) ,
806- Value :: Projection ( outer_value, ProjectionElem :: Downcast ( _, read_variant) )
807- if let Value :: Aggregate ( written_variant, fields) = self . get ( outer_value)
827+ Value :: Projection {
828+ base, elem : ProjectionElem :: Downcast ( _, read_variant) , ..
829+ } if let Value :: Aggregate ( written_variant, fields) = self . get ( base)
808830 // This pass is not aware of control-flow, so we do not know whether the
809831 // replacement we are doing is actually reachable. We could be in any arm of
810832 // ```
@@ -857,7 +879,10 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
857879 ProjectionElem :: UnwrapUnsafeBinder ( _) => ProjectionElem :: UnwrapUnsafeBinder ( ( ) ) ,
858880 } ;
859881
860- let value = self . insert ( projection_ty. ty , Value :: Projection ( value, proj) ) ;
882+ let value = self . insert (
883+ projection_ty. ty ,
884+ Value :: Projection { base : value, elem : proj, provenance : None } ,
885+ ) ;
861886 Some ( ( projection_ty, value) )
862887 }
863888
@@ -1090,11 +1115,17 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
10901115 fields : & [ VnIndex ] ,
10911116 ) -> Option < VnIndex > {
10921117 let Some ( & first_field) = fields. first ( ) else { return None } ;
1093- let Value :: Projection ( copy_from_value, _) = self . get ( first_field) else { return None } ;
1118+ let Value :: Projection { base : copy_from_value, .. } = self . get ( first_field) else {
1119+ return None ;
1120+ } ;
10941121
10951122 // All fields must correspond one-to-one and come from the same aggregate value.
10961123 if fields. iter ( ) . enumerate ( ) . any ( |( index, & v) | {
1097- if let Value :: Projection ( pointer, ProjectionElem :: Field ( from_index, _) ) = self . get ( v)
1124+ if let Value :: Projection {
1125+ base : pointer,
1126+ elem : ProjectionElem :: Field ( from_index, _) ,
1127+ ..
1128+ } = self . get ( v)
10981129 && copy_from_value == pointer
10991130 && from_index. index ( ) == index
11001131 {
@@ -1106,7 +1137,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
11061137 }
11071138
11081139 let mut copy_from_local_value = copy_from_value;
1109- if let Value :: Projection ( pointer, proj) = self . get ( copy_from_value)
1140+ if let Value :: Projection { base : pointer, elem : proj, .. } = self . get ( copy_from_value)
11101141 && let ProjectionElem :: Downcast ( _, read_variant) = proj
11111142 {
11121143 if variant_index == read_variant {
@@ -1819,7 +1850,7 @@ impl<'tcx> VnState<'_, '_, 'tcx> {
18191850 // If we are here, we failed to find a local, and we already have a `Deref`.
18201851 // Trying to add projections will only result in an ill-formed place.
18211852 return None ;
1822- } else if let Value :: Projection ( pointer, proj) = self . get ( index)
1853+ } else if let Value :: Projection { base : pointer, elem : proj, .. } = self . get ( index)
18231854 && ( allow_complex_projection || proj. is_stable_offset ( ) )
18241855 && let Some ( proj) = self . try_as_place_elem ( self . ty ( index) , proj, loc)
18251856 {
0 commit comments