Skip to content

Commit 9901768

Browse files
committed
dont create MovePathIndex's for individual statics.
Instead, create a single MovePathIndex that represents all statics. (An alternative here would be to disallow representing statics at all. I am hesitant to do that right now, in part because it could impose a requirement that I thread checks for static data into the calling code, either as pre- or post-invocation of `fn move_path_for`.)
1 parent 9b67d09 commit 9901768

File tree

1 file changed

+63
-29
lines changed

1 file changed

+63
-29
lines changed

src/librustc_borrowck/borrowck/mir/gather_moves.rs

Lines changed: 63 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111

1212
use rustc::middle::ty;
13-
use rustc::middle::def_id::DefId;
1413
use rustc::mir::repr::{self, Mir, BasicBlock, Lvalue, Rvalue};
1514
use rustc::mir::repr::{StatementKind, Terminator};
1615
use rustc::util::nodemap::FnvHashMap;
@@ -75,7 +74,18 @@ pub struct MovePath<'tcx> {
7574
pub next_sibling: Option<MovePathIndex>,
7675
pub first_child: Option<MovePathIndex>,
7776
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,
7989
}
8090

8191
/// During construction of the MovePath's, we use PreMovePath to
@@ -86,15 +96,15 @@ struct PreMovePath<'tcx> {
8696
pub next_sibling: Option<MovePathIndex>,
8797
pub first_child: Cell<Option<MovePathIndex>>,
8898
pub parent: Option<MovePathIndex>,
89-
pub lvalue: Lvalue<'tcx>,
99+
pub content: MovePathContent<'tcx>,
90100
}
91101

92102
impl<'tcx> PreMovePath<'tcx> {
93103
fn into_move_path(self) -> MovePath<'tcx> {
94104
MovePath {
95105
next_sibling: self.next_sibling,
96106
parent: self.parent,
97-
lvalue: self.lvalue,
107+
content: self.content,
98108
first_child: self.first_child.get(),
99109
}
100110
}
@@ -112,7 +122,7 @@ impl<'tcx> fmt::Debug for MovePath<'tcx> {
112122
if let Some(next_sibling) = self.next_sibling {
113123
try!(write!(w, " next_sibling: {:?}", next_sibling));
114124
}
115-
write!(w, " lvalue: {:?} }}", self.lvalue)
125+
write!(w, " content: {:?} }}", self.content)
116126
}
117127
}
118128

@@ -219,13 +229,19 @@ pub struct MovePathLookup<'tcx> {
219229
vars: MovePathInverseMap,
220230
temps: MovePathInverseMap,
221231
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.
223235
return_ptr: Option<MovePathIndex>,
224236

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
229245
/// subsequent search so that it is solely relative to that
230246
/// base-lvalue). For the remaining lookup, we map the projection
231247
/// elem to the associated MovePathIndex.
@@ -269,7 +285,7 @@ impl<'tcx> MovePathLookup<'tcx> {
269285
vars: vec![],
270286
temps: vec![],
271287
args: vec![],
272-
statics: Default::default(),
288+
statics: None,
273289
return_ptr: None,
274290
projections: vec![],
275291
next_index: MovePathIndex::new(0),
@@ -318,16 +334,14 @@ impl<'tcx> MovePathLookup<'tcx> {
318334
&mut self.next_index)
319335
}
320336

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)
327341
}
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);
331345
Lookup(LookupKind::Generate, mpi)
332346
}
333347
}
@@ -374,7 +388,7 @@ impl<'tcx> MovePathLookup<'tcx> {
374388
Lvalue::Var(var_idx) => self.vars[var_idx as usize].unwrap(),
375389
Lvalue::Temp(temp_idx) => self.temps[temp_idx as usize].unwrap(),
376390
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(),
378392
Lvalue::ReturnPointer => self.return_ptr.unwrap(),
379393
Lvalue::Projection(ref proj) => {
380394
let base_index = self.find(&proj.base);
@@ -394,11 +408,16 @@ impl<'a, 'tcx> MovePathDataBuilder<'a, 'tcx> {
394408
let lookup = {
395409
let mut rev_lookup = self.rev_lookup.borrow_mut();
396410
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(),
402421
Lvalue::Projection(ref proj) => {
403422
// Manually drop the rev_lookup ...
404423
drop(rev_lookup);
@@ -423,16 +442,26 @@ impl<'a, 'tcx> MovePathDataBuilder<'a, 'tcx> {
423442
if let Lookup(LookupKind::Generate, mpi) = lookup {
424443
let parent;
425444
let sibling;
445+
// tracks whether content is Some non-static; statics map to None.
446+
let content: Option<&Lvalue<'tcx>>;
426447

427448
match *lval {
449+
Lvalue::Static(_) => {
450+
content = None;
451+
sibling = None;
452+
parent = None;
453+
}
454+
428455
Lvalue::Var(_) | Lvalue::Temp(_) | Lvalue::Arg(_) |
429-
Lvalue::Static(_) | Lvalue::ReturnPointer => {
456+
Lvalue::ReturnPointer => {
457+
content = Some(lval);
430458
sibling = None;
431459
parent = None;
432460
}
433461
Lvalue::Projection(ref proj) => {
434-
// Here, install new MovePath as new first_child.
462+
content = Some(lval);
435463

464+
// Here, install new MovePath as new first_child.
436465
drop(pre_move_paths);
437466

438467
// Note: `parent` previously allocated (Projection
@@ -449,10 +478,15 @@ impl<'a, 'tcx> MovePathDataBuilder<'a, 'tcx> {
449478
}
450479
};
451480

481+
let content = match content {
482+
Some(lval) => MovePathContent::Lvalue(lval.clone()),
483+
None => MovePathContent::Static,
484+
};
485+
452486
let move_path = PreMovePath {
453487
next_sibling: sibling,
454488
parent: parent,
455-
lvalue: lval.clone(),
489+
content: content,
456490
first_child: Cell::new(None),
457491
};
458492

0 commit comments

Comments
 (0)