@@ -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:: BitSet ;
@@ -234,6 +234,8 @@ struct VnState<'body, 'tcx> {
234234 evaluated : IndexVec < VnIndex , Option < OpTy < ' tcx > > > ,
235235 /// Counter to generate different values.
236236 next_opaque : usize ,
237+ /// Cache the deref values.
238+ derefs : Vec < VnIndex > ,
237239 /// Cache the value of the `unsized_locals` features, to avoid fetching it repeatedly in a loop.
238240 feature_unsized_locals : bool ,
239241 ssa : & ' body SsaLocals ,
@@ -266,6 +268,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
266268 values : FxIndexSet :: with_capacity_and_hasher ( num_values, Default :: default ( ) ) ,
267269 evaluated : IndexVec :: with_capacity ( num_values) ,
268270 next_opaque : 1 ,
271+ derefs : Vec :: new ( ) ,
269272 feature_unsized_locals : tcx. features ( ) . unsized_locals ( ) ,
270273 ssa,
271274 dominators,
@@ -364,6 +367,21 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
364367 self . insert ( Value :: Aggregate ( AggregateTy :: Tuple , VariantIdx :: ZERO , values) )
365368 }
366369
370+ fn insert_deref ( & mut self , value : VnIndex ) -> VnIndex {
371+ let value = self . insert ( Value :: Projection ( value, ProjectionElem :: Deref ) ) ;
372+ self . derefs . push ( value) ;
373+ value
374+ }
375+
376+ fn invalidate_derefs ( & mut self ) {
377+ let mut derefs = Vec :: new ( ) ;
378+ std:: mem:: swap ( & mut derefs, & mut self . derefs ) ;
379+ for deref in derefs {
380+ let opaque = self . next_opaque ( ) ;
381+ * self . values . get_index_mut2 ( deref. index ( ) ) . unwrap ( ) = Value :: Opaque ( opaque) ;
382+ }
383+ }
384+
367385 #[ instrument( level = "trace" , skip( self ) , ret) ]
368386 fn eval_to_const ( & mut self , value : VnIndex ) -> Option < OpTy < ' tcx > > {
369387 use Value :: * ;
@@ -624,7 +642,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
624642 {
625643 // An immutable borrow `_x` always points to the same value for the
626644 // lifetime of the borrow, so we can merge all instances of `*_x`.
627- ProjectionElem :: Deref
645+ return Some ( self . insert_deref ( value ) ) ;
628646 } else {
629647 return None ;
630648 }
@@ -1626,6 +1644,8 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
16261644 self . assign ( local, value) ;
16271645 Some ( value)
16281646 } else {
1647+ // Non-local assignments maybe invalidate deref.
1648+ self . invalidate_derefs ( ) ;
16291649 value
16301650 } ;
16311651 let Some ( value) = value else { return } ;
@@ -1645,12 +1665,16 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
16451665 }
16461666
16471667 fn visit_terminator ( & mut self , terminator : & mut Terminator < ' tcx > , location : Location ) {
1648- if let Terminator { kind : TerminatorKind :: Call { destination, .. } , .. } = terminator
1649- && let Some ( local) = destination. as_local ( )
1650- && self . ssa . is_ssa ( local)
1651- {
1652- let opaque = self . new_opaque ( ) ;
1653- self . assign ( local, opaque) ;
1668+ if let Terminator { kind : TerminatorKind :: Call { destination, .. } , .. } = terminator {
1669+ if let Some ( local) = destination. as_local ( )
1670+ && self . ssa . is_ssa ( local)
1671+ {
1672+ let opaque = self . new_opaque ( ) ;
1673+ self . assign ( local, opaque) ;
1674+ }
1675+ // Function calls maybe invalidate nested deref, and non-local assignments maybe invalidate deref.
1676+ // Currently, no distinction is made between these two cases.
1677+ self . invalidate_derefs ( ) ;
16541678 }
16551679 self . super_terminator ( terminator, location) ;
16561680 }
0 commit comments