10
10
11
11
12
12
use rustc:: middle:: ty;
13
- use rustc:: middle:: def_id:: DefId ;
14
13
use rustc:: mir:: repr:: { self , Mir , BasicBlock , Lvalue , Rvalue } ;
15
14
use rustc:: mir:: repr:: { StatementKind , Terminator } ;
16
15
use rustc:: util:: nodemap:: FnvHashMap ;
@@ -75,7 +74,18 @@ pub struct MovePath<'tcx> {
75
74
pub next_sibling : Option < MovePathIndex > ,
76
75
pub first_child : Option < MovePathIndex > ,
77
76
pub parent : Option < MovePathIndex > ,
78
- pub lvalue : Lvalue < ' tcx > ,
77
+ pub content : MovePathContent < ' tcx > ,
78
+ }
79
+
80
+ /// MovePaths usually represent a single l-value. The exceptions are
81
+ /// forms that arise due to erroneous input code: static data holds
82
+ /// l-values that we cannot actually move out of. Therefore we map
83
+ /// statics to a special marker value (`MovePathContent::Static`)
84
+ /// representing an invalid origin.
85
+ #[ derive( Clone , Debug ) ]
86
+ pub enum MovePathContent < ' tcx > {
87
+ Lvalue ( Lvalue < ' tcx > ) ,
88
+ Static ,
79
89
}
80
90
81
91
/// During construction of the MovePath's, we use PreMovePath to
@@ -86,15 +96,15 @@ struct PreMovePath<'tcx> {
86
96
pub next_sibling : Option < MovePathIndex > ,
87
97
pub first_child : Cell < Option < MovePathIndex > > ,
88
98
pub parent : Option < MovePathIndex > ,
89
- pub lvalue : Lvalue < ' tcx > ,
99
+ pub content : MovePathContent < ' tcx > ,
90
100
}
91
101
92
102
impl < ' tcx > PreMovePath < ' tcx > {
93
103
fn into_move_path ( self ) -> MovePath < ' tcx > {
94
104
MovePath {
95
105
next_sibling : self . next_sibling ,
96
106
parent : self . parent ,
97
- lvalue : self . lvalue ,
107
+ content : self . content ,
98
108
first_child : self . first_child . get ( ) ,
99
109
}
100
110
}
@@ -112,7 +122,7 @@ impl<'tcx> fmt::Debug for MovePath<'tcx> {
112
122
if let Some ( next_sibling) = self . next_sibling {
113
123
try!( write ! ( w, " next_sibling: {:?}" , next_sibling) ) ;
114
124
}
115
- write ! ( w, " lvalue : {:?} }}" , self . lvalue )
125
+ write ! ( w, " content : {:?} }}" , self . content )
116
126
}
117
127
}
118
128
@@ -219,13 +229,19 @@ pub struct MovePathLookup<'tcx> {
219
229
vars : MovePathInverseMap ,
220
230
temps : MovePathInverseMap ,
221
231
args : MovePathInverseMap ,
222
- statics : FnvHashMap < DefId , MovePathIndex > ,
232
+
233
+ /// The move path representing the return value is constructed
234
+ /// lazily when we first encounter it in the input MIR.
223
235
return_ptr : Option < MovePathIndex > ,
224
236
225
- /// This is the only non-trivial lookup to explain: projections
226
- /// are made from a base-lvalue and a projection elem. The
227
- /// base-lvalue will have a unique MovePathIndex; we use the
228
- /// latter as the index into the outer vector (narrowing
237
+ /// A single move path (representing any static data referenced)
238
+ /// is constructed lazily when we first encounter statics in the
239
+ /// input MIR.
240
+ statics : Option < MovePathIndex > ,
241
+
242
+ /// projections are made from a base-lvalue and a projection
243
+ /// elem. The base-lvalue will have a unique MovePathIndex; we use
244
+ /// the latter as the index into the outer vector (narrowing
229
245
/// subsequent search so that it is solely relative to that
230
246
/// base-lvalue). For the remaining lookup, we map the projection
231
247
/// elem to the associated MovePathIndex.
@@ -269,7 +285,7 @@ impl<'tcx> MovePathLookup<'tcx> {
269
285
vars : vec ! [ ] ,
270
286
temps : vec ! [ ] ,
271
287
args : vec ! [ ] ,
272
- statics : Default :: default ( ) ,
288
+ statics : None ,
273
289
return_ptr : None ,
274
290
projections : vec ! [ ] ,
275
291
next_index : MovePathIndex :: new ( 0 ) ,
@@ -318,16 +334,14 @@ impl<'tcx> MovePathLookup<'tcx> {
318
334
& mut self . next_index )
319
335
}
320
336
321
- fn lookup_static ( & mut self , static_id : DefId ) -> Lookup < MovePathIndex > {
322
- let & mut MovePathLookup { ref mut statics,
323
- ref mut next_index, .. } = self ;
324
- match statics. entry ( static_id. clone ( ) ) {
325
- Entry :: Occupied ( ent) => {
326
- Lookup ( LookupKind :: Reuse , * ent. get ( ) )
337
+ fn lookup_static ( & mut self ) -> Lookup < MovePathIndex > {
338
+ match self . statics {
339
+ Some ( mpi) => {
340
+ Lookup ( LookupKind :: Reuse , mpi)
327
341
}
328
- Entry :: Vacant ( ent ) => {
329
- let mpi = Self :: next_index ( next_index) ;
330
- ent . insert ( mpi) ;
342
+ ref mut ret @ None => {
343
+ let mpi = Self :: next_index ( & mut self . next_index ) ;
344
+ * ret = Some ( mpi) ;
331
345
Lookup ( LookupKind :: Generate , mpi)
332
346
}
333
347
}
@@ -374,7 +388,7 @@ impl<'tcx> MovePathLookup<'tcx> {
374
388
Lvalue :: Var ( var_idx) => self . vars [ var_idx as usize ] . unwrap ( ) ,
375
389
Lvalue :: Temp ( temp_idx) => self . temps [ temp_idx as usize ] . unwrap ( ) ,
376
390
Lvalue :: Arg ( arg_idx) => self . args [ arg_idx as usize ] . unwrap ( ) ,
377
- Lvalue :: Static ( ref def_id ) => self . statics [ def_id ] ,
391
+ Lvalue :: Static ( ref _def_id ) => self . statics . unwrap ( ) ,
378
392
Lvalue :: ReturnPointer => self . return_ptr . unwrap ( ) ,
379
393
Lvalue :: Projection ( ref proj) => {
380
394
let base_index = self . find ( & proj. base ) ;
@@ -394,11 +408,16 @@ impl<'a, 'tcx> MovePathDataBuilder<'a, 'tcx> {
394
408
let lookup = {
395
409
let mut rev_lookup = self . rev_lookup . borrow_mut ( ) ;
396
410
match * lval {
397
- Lvalue :: Var ( var_idx) => rev_lookup. lookup_var ( var_idx) ,
398
- Lvalue :: Temp ( temp_idx) => rev_lookup. lookup_temp ( temp_idx) ,
399
- Lvalue :: Arg ( arg_idx) => rev_lookup. lookup_arg ( arg_idx) ,
400
- Lvalue :: Static ( def_id) => rev_lookup. lookup_static ( def_id) ,
401
- Lvalue :: ReturnPointer => rev_lookup. lookup_return_pointer ( ) ,
411
+ Lvalue :: Var ( var_idx) =>
412
+ rev_lookup. lookup_var ( var_idx) ,
413
+ Lvalue :: Temp ( temp_idx) =>
414
+ rev_lookup. lookup_temp ( temp_idx) ,
415
+ Lvalue :: Arg ( arg_idx) =>
416
+ rev_lookup. lookup_arg ( arg_idx) ,
417
+ Lvalue :: Static ( _def_id) =>
418
+ rev_lookup. lookup_static ( ) ,
419
+ Lvalue :: ReturnPointer =>
420
+ rev_lookup. lookup_return_pointer ( ) ,
402
421
Lvalue :: Projection ( ref proj) => {
403
422
// Manually drop the rev_lookup ...
404
423
drop ( rev_lookup) ;
@@ -423,16 +442,26 @@ impl<'a, 'tcx> MovePathDataBuilder<'a, 'tcx> {
423
442
if let Lookup ( LookupKind :: Generate , mpi) = lookup {
424
443
let parent;
425
444
let sibling;
445
+ // tracks whether content is Some non-static; statics map to None.
446
+ let content: Option < & Lvalue < ' tcx > > ;
426
447
427
448
match * lval {
449
+ Lvalue :: Static ( _) => {
450
+ content = None ;
451
+ sibling = None ;
452
+ parent = None ;
453
+ }
454
+
428
455
Lvalue :: Var ( _) | Lvalue :: Temp ( _) | Lvalue :: Arg ( _) |
429
- Lvalue :: Static ( _) | Lvalue :: ReturnPointer => {
456
+ Lvalue :: ReturnPointer => {
457
+ content = Some ( lval) ;
430
458
sibling = None ;
431
459
parent = None ;
432
460
}
433
461
Lvalue :: Projection ( ref proj) => {
434
- // Here, install new MovePath as new first_child.
462
+ content = Some ( lval ) ;
435
463
464
+ // Here, install new MovePath as new first_child.
436
465
drop ( pre_move_paths) ;
437
466
438
467
// Note: `parent` previously allocated (Projection
@@ -449,10 +478,15 @@ impl<'a, 'tcx> MovePathDataBuilder<'a, 'tcx> {
449
478
}
450
479
} ;
451
480
481
+ let content = match content {
482
+ Some ( lval) => MovePathContent :: Lvalue ( lval. clone ( ) ) ,
483
+ None => MovePathContent :: Static ,
484
+ } ;
485
+
452
486
let move_path = PreMovePath {
453
487
next_sibling : sibling,
454
488
parent : parent,
455
- lvalue : lval . clone ( ) ,
489
+ content : content ,
456
490
first_child : Cell :: new ( None ) ,
457
491
} ;
458
492
0 commit comments