@@ -93,7 +93,7 @@ use rustc_const_eval::interpret::{
9393 ImmTy , Immediate , InterpCx , MemPlaceMeta , MemoryKind , OpTy , Projectable , Scalar ,
9494 intern_const_alloc_for_constprop,
9595} ;
96- use rustc_data_structures:: fx:: FxIndexSet ;
96+ use rustc_data_structures:: fx:: { FxIndexSet , MutableValues } ;
9797use rustc_data_structures:: graph:: dominators:: Dominators ;
9898use rustc_hir:: def:: DefKind ;
9999use rustc_index:: bit_set:: DenseBitSet ;
@@ -238,6 +238,8 @@ struct VnState<'body, 'tcx> {
238238 evaluated : IndexVec < VnIndex , Option < OpTy < ' tcx > > > ,
239239 /// Counter to generate different values.
240240 next_opaque : usize ,
241+ /// Cache the deref values.
242+ derefs : Vec < VnIndex > ,
241243 /// Cache the value of the `unsized_locals` features, to avoid fetching it repeatedly in a loop.
242244 feature_unsized_locals : bool ,
243245 ssa : & ' body SsaLocals ,
@@ -270,6 +272,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
270272 values : FxIndexSet :: with_capacity_and_hasher ( num_values, Default :: default ( ) ) ,
271273 evaluated : IndexVec :: with_capacity ( num_values) ,
272274 next_opaque : 1 ,
275+ derefs : Vec :: new ( ) ,
273276 feature_unsized_locals : tcx. features ( ) . unsized_locals ( ) ,
274277 ssa,
275278 dominators,
@@ -368,6 +371,19 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
368371 self . insert ( Value :: Aggregate ( AggregateTy :: Tuple , VariantIdx :: ZERO , values) )
369372 }
370373
374+ fn insert_deref ( & mut self , value : VnIndex ) -> VnIndex {
375+ let value = self . insert ( Value :: Projection ( value, ProjectionElem :: Deref ) ) ;
376+ self . derefs . push ( value) ;
377+ value
378+ }
379+
380+ fn invalidate_derefs ( & mut self ) {
381+ for deref in std:: mem:: take ( & mut self . derefs ) {
382+ let opaque = self . next_opaque ( ) ;
383+ * self . values . get_index_mut2 ( deref. index ( ) ) . unwrap ( ) = Value :: Opaque ( opaque) ;
384+ }
385+ }
386+
371387 #[ instrument( level = "trace" , skip( self ) , ret) ]
372388 fn eval_to_const ( & mut self , value : VnIndex ) -> Option < OpTy < ' tcx > > {
373389 use Value :: * ;
@@ -634,7 +650,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
634650 {
635651 // An immutable borrow `_x` always points to the same value for the
636652 // lifetime of the borrow, so we can merge all instances of `*_x`.
637- ProjectionElem :: Deref
653+ return Some ( self . insert_deref ( value ) ) ;
638654 } else {
639655 return None ;
640656 }
@@ -1739,6 +1755,8 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
17391755 self . assign ( local, value) ;
17401756 Some ( value)
17411757 } else {
1758+ // Non-local assignments maybe invalidate deref.
1759+ self . invalidate_derefs ( ) ;
17421760 value
17431761 } ;
17441762 let Some ( value) = value else { return } ;
@@ -1758,12 +1776,16 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
17581776 }
17591777
17601778 fn visit_terminator ( & mut self , terminator : & mut Terminator < ' tcx > , location : Location ) {
1761- if let Terminator { kind : TerminatorKind :: Call { destination, .. } , .. } = terminator
1762- && let Some ( local) = destination. as_local ( )
1763- && self . ssa . is_ssa ( local)
1764- {
1765- let opaque = self . new_opaque ( ) ;
1766- self . assign ( local, opaque) ;
1779+ if let Terminator { kind : TerminatorKind :: Call { destination, .. } , .. } = terminator {
1780+ if let Some ( local) = destination. as_local ( )
1781+ && self . ssa . is_ssa ( local)
1782+ {
1783+ let opaque = self . new_opaque ( ) ;
1784+ self . assign ( local, opaque) ;
1785+ }
1786+ // Function calls maybe invalidate nested deref, and non-local assignments maybe invalidate deref.
1787+ // Currently, no distinction is made between these two cases.
1788+ self . invalidate_derefs ( ) ;
17671789 }
17681790 self . super_terminator ( terminator, location) ;
17691791 }
0 commit comments