@@ -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,19 @@ 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+ for deref in std:: mem:: take ( & mut self . derefs ) {
378+ let opaque = self . next_opaque ( ) ;
379+ * self . values . get_index_mut2 ( deref. index ( ) ) . unwrap ( ) = Value :: Opaque ( opaque) ;
380+ }
381+ }
382+
367383 #[ instrument( level = "trace" , skip( self ) , ret) ]
368384 fn eval_to_const ( & mut self , value : VnIndex ) -> Option < OpTy < ' tcx > > {
369385 use Value :: * ;
@@ -624,7 +640,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
624640 {
625641 // An immutable borrow `_x` always points to the same value for the
626642 // lifetime of the borrow, so we can merge all instances of `*_x`.
627- ProjectionElem :: Deref
643+ return Some ( self . insert_deref ( value ) ) ;
628644 } else {
629645 return None ;
630646 }
@@ -1626,6 +1642,8 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
16261642 self . assign ( local, value) ;
16271643 Some ( value)
16281644 } else {
1645+ // Non-local assignments maybe invalidate deref.
1646+ self . invalidate_derefs ( ) ;
16291647 value
16301648 } ;
16311649 let Some ( value) = value else { return } ;
@@ -1645,12 +1663,16 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
16451663 }
16461664
16471665 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) ;
1666+ if let Terminator { kind : TerminatorKind :: Call { destination, .. } , .. } = terminator {
1667+ if let Some ( local) = destination. as_local ( )
1668+ && self . ssa . is_ssa ( local)
1669+ {
1670+ let opaque = self . new_opaque ( ) ;
1671+ self . assign ( local, opaque) ;
1672+ }
1673+ // Function calls maybe invalidate nested deref, and non-local assignments maybe invalidate deref.
1674+ // Currently, no distinction is made between these two cases.
1675+ self . invalidate_derefs ( ) ;
16541676 }
16551677 self . super_terminator ( terminator, location) ;
16561678 }
0 commit comments