@@ -238,7 +238,13 @@ enum Value<'a, 'tcx> {
238238
239239 // Extractions.
240240 /// This is the *value* obtained by projecting another value.
241- Projection ( VnIndex , ProjectionElem < VnIndex , ( ) > ) ,
241+ Projection {
242+ base : VnIndex ,
243+ elem : ProjectionElem < VnIndex , ( ) > ,
244+ /// Some values may be a borrow or pointer.
245+ /// Give them a different provenance, so we don't merge them.
246+ provenance : Option < VnOpaque > ,
247+ } ,
242248 /// Discriminant of the given value.
243249 Discriminant ( VnIndex ) ,
244250
@@ -287,6 +293,7 @@ impl<'a, 'tcx> ValueSet<'a, 'tcx> {
287293 debug_assert ! ( match value {
288294 Value :: Opaque ( _) | Value :: Parameter ( _) | Value :: Address { .. } => true ,
289295 Value :: Constant { disambiguator, .. } => disambiguator. is_some( ) ,
296+ Value :: Projection { provenance, .. } => provenance. is_some( ) ,
290297 _ => false ,
291298 } ) ;
292299
@@ -532,7 +539,18 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
532539 }
533540
534541 fn insert_deref ( & mut self , ty : Ty < ' tcx > , value : VnIndex ) -> VnIndex {
535- self . insert ( ty, Value :: Projection ( value, ProjectionElem :: Deref ) )
542+ if ty. is_any_ptr ( ) {
543+ // Give each borrow and pointer a different provenance, so we don't merge them.
544+ return self . insert_unique ( ty, true , |provenance| Value :: Projection {
545+ base : value,
546+ elem : ProjectionElem :: Deref ,
547+ provenance : Some ( provenance) ,
548+ } ) ;
549+ }
550+ self . insert (
551+ ty,
552+ Value :: Projection { base : value, elem : ProjectionElem :: Deref , provenance : None } ,
553+ )
536554 }
537555
538556 #[ instrument( level = "trace" , skip( self ) , ret) ]
@@ -615,7 +633,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
615633 ImmTy :: from_immediate ( ptr_imm, ty) . into ( )
616634 }
617635
618- Projection ( base, elem) => {
636+ Projection { base, elem, .. } => {
619637 let base = self . eval_to_const ( base) ?;
620638 // `Index` by constants should have been replaced by `ConstantIndex` by
621639 // `simplify_place_projection`.
@@ -827,8 +845,9 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
827845 ProjectionElem :: Field ( f, _) => match self . get ( value) {
828846 Value :: Aggregate ( _, fields) => return Some ( ( projection_ty, fields[ f. as_usize ( ) ] ) ) ,
829847 Value :: Union ( active, field) if active == f => return Some ( ( projection_ty, field) ) ,
830- Value :: Projection ( outer_value, ProjectionElem :: Downcast ( _, read_variant) )
831- if let Value :: Aggregate ( written_variant, fields) = self . get ( outer_value)
848+ Value :: Projection {
849+ base, elem : ProjectionElem :: Downcast ( _, read_variant) , ..
850+ } if let Value :: Aggregate ( written_variant, fields) = self . get ( base)
832851 // This pass is not aware of control-flow, so we do not know whether the
833852 // replacement we are doing is actually reachable. We could be in any arm of
834853 // ```
@@ -881,7 +900,10 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
881900 ProjectionElem :: UnwrapUnsafeBinder ( _) => ProjectionElem :: UnwrapUnsafeBinder ( ( ) ) ,
882901 } ;
883902
884- let value = self . insert ( projection_ty. ty , Value :: Projection ( value, proj) ) ;
903+ let value = self . insert (
904+ projection_ty. ty ,
905+ Value :: Projection { base : value, elem : proj, provenance : None } ,
906+ ) ;
885907 Some ( ( projection_ty, value) )
886908 }
887909
@@ -1108,11 +1130,17 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
11081130 fields : & [ VnIndex ] ,
11091131 ) -> Option < VnIndex > {
11101132 let Some ( & first_field) = fields. first ( ) else { return None } ;
1111- let Value :: Projection ( copy_from_value, _) = self . get ( first_field) else { return None } ;
1133+ let Value :: Projection { base : copy_from_value, .. } = self . get ( first_field) else {
1134+ return None ;
1135+ } ;
11121136
11131137 // All fields must correspond one-to-one and come from the same aggregate value.
11141138 if fields. iter ( ) . enumerate ( ) . any ( |( index, & v) | {
1115- if let Value :: Projection ( pointer, ProjectionElem :: Field ( from_index, _) ) = self . get ( v)
1139+ if let Value :: Projection {
1140+ base : pointer,
1141+ elem : ProjectionElem :: Field ( from_index, _) ,
1142+ ..
1143+ } = self . get ( v)
11161144 && copy_from_value == pointer
11171145 && from_index. index ( ) == index
11181146 {
@@ -1124,7 +1152,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
11241152 }
11251153
11261154 let mut copy_from_local_value = copy_from_value;
1127- if let Value :: Projection ( pointer, proj) = self . get ( copy_from_value)
1155+ if let Value :: Projection { base : pointer, elem : proj, .. } = self . get ( copy_from_value)
11281156 && let ProjectionElem :: Downcast ( _, read_variant) = proj
11291157 {
11301158 if variant_index == read_variant {
@@ -1829,7 +1857,7 @@ impl<'tcx> VnState<'_, '_, 'tcx> {
18291857 // If we are here, we failed to find a local, and we already have a `Deref`.
18301858 // Trying to add projections will only result in an ill-formed place.
18311859 return None ;
1832- } else if let Value :: Projection ( pointer, proj) = self . get ( index)
1860+ } else if let Value :: Projection { base : pointer, elem : proj, .. } = self . get ( index)
18331861 && ( allow_complex_projection || proj. is_stable_offset ( ) )
18341862 && let Some ( proj) = self . try_as_place_elem ( self . ty ( index) , proj, loc)
18351863 {
0 commit comments