@@ -93,7 +93,7 @@ use rustc_const_eval::interpret::{
93
93
ImmTy , Immediate , InterpCx , MemPlaceMeta , MemoryKind , OpTy , Projectable , Scalar ,
94
94
intern_const_alloc_for_constprop,
95
95
} ;
96
- use rustc_data_structures:: fx:: FxIndexSet ;
96
+ use rustc_data_structures:: fx:: { FxIndexSet , MutableValues } ;
97
97
use rustc_data_structures:: graph:: dominators:: Dominators ;
98
98
use rustc_hir:: def:: DefKind ;
99
99
use rustc_index:: bit_set:: BitSet ;
@@ -234,6 +234,8 @@ struct VnState<'body, 'tcx> {
234
234
evaluated : IndexVec < VnIndex , Option < OpTy < ' tcx > > > ,
235
235
/// Counter to generate different values.
236
236
next_opaque : usize ,
237
+ /// Cache the deref values.
238
+ derefs : Vec < VnIndex > ,
237
239
/// Cache the value of the `unsized_locals` features, to avoid fetching it repeatedly in a loop.
238
240
feature_unsized_locals : bool ,
239
241
ssa : & ' body SsaLocals ,
@@ -266,6 +268,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
266
268
values : FxIndexSet :: with_capacity_and_hasher ( num_values, Default :: default ( ) ) ,
267
269
evaluated : IndexVec :: with_capacity ( num_values) ,
268
270
next_opaque : 1 ,
271
+ derefs : Vec :: new ( ) ,
269
272
feature_unsized_locals : tcx. features ( ) . unsized_locals ( ) ,
270
273
ssa,
271
274
dominators,
@@ -364,6 +367,19 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
364
367
self . insert ( Value :: Aggregate ( AggregateTy :: Tuple , VariantIdx :: ZERO , values) )
365
368
}
366
369
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
+
367
383
#[ instrument( level = "trace" , skip( self ) , ret) ]
368
384
fn eval_to_const ( & mut self , value : VnIndex ) -> Option < OpTy < ' tcx > > {
369
385
use Value :: * ;
@@ -624,7 +640,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
624
640
{
625
641
// An immutable borrow `_x` always points to the same value for the
626
642
// lifetime of the borrow, so we can merge all instances of `*_x`.
627
- ProjectionElem :: Deref
643
+ return Some ( self . insert_deref ( value ) ) ;
628
644
} else {
629
645
return None ;
630
646
}
@@ -1626,6 +1642,8 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
1626
1642
self . assign ( local, value) ;
1627
1643
Some ( value)
1628
1644
} else {
1645
+ // Non-local assignments maybe invalidate deref.
1646
+ self . invalidate_derefs ( ) ;
1629
1647
value
1630
1648
} ;
1631
1649
let Some ( value) = value else { return } ;
@@ -1645,12 +1663,16 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
1645
1663
}
1646
1664
1647
1665
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 ( ) ;
1654
1676
}
1655
1677
self . super_terminator ( terminator, location) ;
1656
1678
}
0 commit comments