@@ -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,21 @@ 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
+ 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
+
367
385
#[ instrument( level = "trace" , skip( self ) , ret) ]
368
386
fn eval_to_const ( & mut self , value : VnIndex ) -> Option < OpTy < ' tcx > > {
369
387
use Value :: * ;
@@ -624,7 +642,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
624
642
{
625
643
// An immutable borrow `_x` always points to the same value for the
626
644
// lifetime of the borrow, so we can merge all instances of `*_x`.
627
- ProjectionElem :: Deref
645
+ return Some ( self . insert_deref ( value ) ) ;
628
646
} else {
629
647
return None ;
630
648
}
@@ -1626,6 +1644,8 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
1626
1644
self . assign ( local, value) ;
1627
1645
Some ( value)
1628
1646
} else {
1647
+ // Non-local assignments maybe invalidate deref.
1648
+ self . invalidate_derefs ( ) ;
1629
1649
value
1630
1650
} ;
1631
1651
let Some ( value) = value else { return } ;
@@ -1645,12 +1665,16 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
1645
1665
}
1646
1666
1647
1667
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 ( ) ;
1654
1678
}
1655
1679
self . super_terminator ( terminator, location) ;
1656
1680
}
0 commit comments