@@ -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) ]
@@ -636,7 +654,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
636654 ImmTy :: from_immediate ( ptr_imm, ty) . into ( )
637655 }
638656
639- Projection ( base, elem) => {
657+ Projection { base, elem, .. } => {
640658 let base = self . eval_to_const ( base) ?;
641659 // `Index` by constants should have been replaced by `ConstantIndex` by
642660 // `simplify_place_projection`.
@@ -816,8 +834,9 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
816834 ProjectionElem :: Field ( f, _) => match self . get ( value) {
817835 Value :: Aggregate ( _, fields) => return Some ( ( projection_ty, fields[ f. as_usize ( ) ] ) ) ,
818836 Value :: Union ( active, field) if active == f => return Some ( ( projection_ty, field) ) ,
819- Value :: Projection ( outer_value, ProjectionElem :: Downcast ( _, read_variant) )
820- if let Value :: Aggregate ( written_variant, fields) = self . get ( outer_value)
837+ Value :: Projection {
838+ base, elem : ProjectionElem :: Downcast ( _, read_variant) , ..
839+ } if let Value :: Aggregate ( written_variant, fields) = self . get ( base)
821840 // This pass is not aware of control-flow, so we do not know whether the
822841 // replacement we are doing is actually reachable. We could be in any arm of
823842 // ```
@@ -870,7 +889,10 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
870889 ProjectionElem :: UnwrapUnsafeBinder ( _) => ProjectionElem :: UnwrapUnsafeBinder ( ( ) ) ,
871890 } ;
872891
873- let value = self . insert ( projection_ty. ty , Value :: Projection ( value, proj) ) ;
892+ let value = self . insert (
893+ projection_ty. ty ,
894+ Value :: Projection { base : value, elem : proj, provenance : None } ,
895+ ) ;
874896 Some ( ( projection_ty, value) )
875897 }
876898
@@ -1099,11 +1121,17 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
10991121 fields : & [ VnIndex ] ,
11001122 ) -> Option < VnIndex > {
11011123 let Some ( & first_field) = fields. first ( ) else { return None } ;
1102- let Value :: Projection ( copy_from_value, _) = self . get ( first_field) else { return None } ;
1124+ let Value :: Projection { base : copy_from_value, .. } = self . get ( first_field) else {
1125+ return None ;
1126+ } ;
11031127
11041128 // All fields must correspond one-to-one and come from the same aggregate value.
11051129 if fields. iter ( ) . enumerate ( ) . any ( |( index, & v) | {
1106- if let Value :: Projection ( pointer, ProjectionElem :: Field ( from_index, _) ) = self . get ( v)
1130+ if let Value :: Projection {
1131+ base : pointer,
1132+ elem : ProjectionElem :: Field ( from_index, _) ,
1133+ ..
1134+ } = self . get ( v)
11071135 && copy_from_value == pointer
11081136 && from_index. index ( ) == index
11091137 {
@@ -1115,7 +1143,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
11151143 }
11161144
11171145 let mut copy_from_local_value = copy_from_value;
1118- if let Value :: Projection ( pointer, proj) = self . get ( copy_from_value)
1146+ if let Value :: Projection { base : pointer, elem : proj, .. } = self . get ( copy_from_value)
11191147 && let ProjectionElem :: Downcast ( _, read_variant) = proj
11201148 {
11211149 if variant_index == read_variant {
@@ -1824,7 +1852,7 @@ impl<'tcx> VnState<'_, '_, 'tcx> {
18241852 // If we are here, we failed to find a local, and we already have a `Deref`.
18251853 // Trying to add projections will only result in an ill-formed place.
18261854 return None ;
1827- } else if let Value :: Projection ( pointer, proj) = self . get ( index)
1855+ } else if let Value :: Projection { base : pointer, elem : proj, .. } = self . get ( index)
18281856 && ( allow_complex_projection || proj. is_stable_offset ( ) )
18291857 && let Some ( proj) = self . try_as_place_elem ( self . ty ( index) , proj, loc)
18301858 {
0 commit comments