1
+ use crate :: un_derefer:: UnDerefer ;
1
2
use rustc_index:: vec:: IndexVec ;
2
3
use rustc_middle:: mir:: tcx:: RvalueInitializationState ;
3
4
use rustc_middle:: mir:: * ;
@@ -19,6 +20,7 @@ struct MoveDataBuilder<'a, 'tcx> {
19
20
param_env : ty:: ParamEnv < ' tcx > ,
20
21
data : MoveData < ' tcx > ,
21
22
errors : Vec < ( Place < ' tcx > , MoveError < ' tcx > ) > ,
23
+ un_derefer : UnDerefer < ' tcx > ,
22
24
}
23
25
24
26
impl < ' a , ' tcx > MoveDataBuilder < ' a , ' tcx > {
@@ -32,6 +34,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
32
34
tcx,
33
35
param_env,
34
36
errors : Vec :: new ( ) ,
37
+ un_derefer : UnDerefer { tcx : tcx, derefer_sidetable : Default :: default ( ) } ,
35
38
data : MoveData {
36
39
moves : IndexVec :: new ( ) ,
37
40
loc_map : LocationMap :: new ( body) ,
@@ -94,6 +97,10 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
94
97
///
95
98
/// Maybe we should have separate "borrowck" and "moveck" modes.
96
99
fn move_path_for ( & mut self , place : Place < ' tcx > ) -> Result < MovePathIndex , MoveError < ' tcx > > {
100
+ if let Some ( new_place) = self . builder . un_derefer . derefer ( place. as_ref ( ) ) {
101
+ return self . move_path_for ( new_place) ;
102
+ }
103
+
97
104
debug ! ( "lookup({:?})" , place) ;
98
105
let mut base = self . builder . data . rev_lookup . locals [ place. local ] ;
99
106
@@ -224,6 +231,8 @@ pub(super) fn gather_moves<'tcx>(
224
231
param_env : ty:: ParamEnv < ' tcx > ,
225
232
) -> Result < MoveData < ' tcx > , ( MoveData < ' tcx > , Vec < ( Place < ' tcx > , MoveError < ' tcx > ) > ) > {
226
233
let mut builder = MoveDataBuilder :: new ( body, tcx, param_env) ;
234
+ let mut un_derefer = UnDerefer { tcx : tcx, derefer_sidetable : Default :: default ( ) } ;
235
+ un_derefer. ref_finder ( body) ;
227
236
228
237
builder. gather_args ( ) ;
229
238
@@ -276,6 +285,10 @@ struct Gatherer<'b, 'a, 'tcx> {
276
285
impl < ' b , ' a , ' tcx > Gatherer < ' b , ' a , ' tcx > {
277
286
fn gather_statement ( & mut self , stmt : & Statement < ' tcx > ) {
278
287
match & stmt. kind {
288
+ StatementKind :: Assign ( box ( place, Rvalue :: VirtualRef ( reffed) ) ) => {
289
+ assert ! ( place. projection. is_empty( ) ) ;
290
+ self . builder . un_derefer . derefer_sidetable . insert ( place. local , * reffed) ;
291
+ }
279
292
StatementKind :: Assign ( box ( place, rval) ) => {
280
293
self . create_move_path ( * place) ;
281
294
if let RvalueInitializationState :: Shallow = rval. initialization_state ( ) {
@@ -294,7 +307,10 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
294
307
}
295
308
StatementKind :: StorageLive ( _) => { }
296
309
StatementKind :: StorageDead ( local) => {
297
- self . gather_move ( Place :: from ( * local) ) ;
310
+ // DerefTemp locals (results of VirtualRef) don't actually move anything.
311
+ if !self . builder . un_derefer . derefer_sidetable . contains_key ( & local) {
312
+ self . gather_move ( Place :: from ( * local) ) ;
313
+ }
298
314
}
299
315
StatementKind :: SetDiscriminant { .. } | StatementKind :: Deinit ( ..) => {
300
316
span_bug ! (
@@ -328,6 +344,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
328
344
self . gather_operand ( operand) ;
329
345
}
330
346
}
347
+ Rvalue :: VirtualRef ( ..) => unreachable ! ( ) ,
331
348
Rvalue :: Ref ( ..)
332
349
| Rvalue :: AddressOf ( ..)
333
350
| Rvalue :: Discriminant ( ..)
@@ -439,6 +456,10 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
439
456
440
457
fn gather_move ( & mut self , place : Place < ' tcx > ) {
441
458
debug ! ( "gather_move({:?}, {:?})" , self . loc, place) ;
459
+ if let Some ( new_place) = self . builder . un_derefer . derefer ( place. as_ref ( ) ) {
460
+ self . gather_move ( new_place) ;
461
+ return ;
462
+ }
442
463
443
464
if let [ ref base @ .., ProjectionElem :: Subslice { from, to, from_end : false } ] =
444
465
* * place. projection
@@ -494,6 +515,11 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
494
515
fn gather_init ( & mut self , place : PlaceRef < ' tcx > , kind : InitKind ) {
495
516
debug ! ( "gather_init({:?}, {:?})" , self . loc, place) ;
496
517
518
+ if let Some ( new_place) = self . builder . un_derefer . derefer ( place) {
519
+ self . gather_init ( new_place. as_ref ( ) , kind) ;
520
+ return ;
521
+ }
522
+
497
523
let mut place = place;
498
524
499
525
// Check if we are assigning into a field of a union, if so, lookup the place
0 commit comments