Skip to content

Commit 9b67d09

Browse files
committed
Switch newtype Index wrappers to use NonZero instead of INVALID constants.
1 parent 7d53a25 commit 9b67d09

File tree

3 files changed

+88
-78
lines changed

3 files changed

+88
-78
lines changed

src/librustc_borrowck/borrowck/mir/dataflow.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ impl<'b, 'a: 'b, 'tcx: 'a> MirBorrowckCtxt<'b, 'a, 'tcx> {
5656
&move_data.move_paths,
5757
move_path_index,
5858
&|in_out, mpi| {
59-
in_out.clear_bit(mpi.idx().unwrap());
59+
in_out.clear_bit(mpi.idx());
6060
});
6161
},
6262
};
@@ -109,7 +109,7 @@ impl<'b, 'a: 'b, 'tcx: 'a> MirBorrowckCtxt<'b, 'a, 'tcx> {
109109
move_paths,
110110
move_path_index,
111111
&|kill_set, mpi| {
112-
kill_set.set_bit(mpi.idx().unwrap());
112+
kill_set.set_bit(mpi.idx());
113113
});
114114
}
115115
}
@@ -124,7 +124,7 @@ impl<'b, 'a: 'b, 'tcx: 'a> MirBorrowckCtxt<'b, 'a, 'tcx> {
124124
}
125125

126126
fn zero_to_one(gen_set: &mut [usize], move_index: MoveOutIndex) {
127-
let retval = gen_set.set_bit(move_index.idx().unwrap());
127+
let retval = gen_set.set_bit(move_index.idx());
128128
assert!(retval);
129129
}
130130
}
@@ -137,8 +137,6 @@ fn on_all_children_bits<Each>(set: &mut [usize],
137137
each_child: &Each)
138138
where Each: Fn(&mut [usize], MoveOutIndex)
139139
{
140-
assert!(move_path_index.idx().is_some());
141-
142140
// 1. invoke `each_child` callback for all moves that directly
143141
// influence path for `move_path_index`
144142
for move_index in &path_map[move_path_index] {
@@ -150,10 +148,10 @@ fn on_all_children_bits<Each>(set: &mut [usize],
150148
//
151149
// (Unnamed children are irrelevant to dataflow; by
152150
// definition they have no associated moves.)
153-
let mut child_index = move_paths[move_path_index].first_child;
154-
while let Some(_) = child_index.idx() {
151+
let mut next_child_index = move_paths[move_path_index].first_child;
152+
while let Some(child_index) = next_child_index {
155153
on_all_children_bits(set, path_map, move_paths, child_index, each_child);
156-
child_index = move_paths[child_index].next_sibling;
154+
next_child_index = move_paths[child_index].next_sibling;
157155
}
158156
}
159157

src/librustc_borrowck/borrowck/mir/gather_moves.rs

Lines changed: 80 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -20,36 +20,43 @@ use std::collections::hash_map::Entry;
2020
use std::fmt;
2121
use std::iter;
2222
use std::ops::Index;
23-
use std::usize;
2423

2524
use super::dataflow::BitDenotation;
2625
use super::abs_domain::{AbstractElem, Lift};
2726

28-
macro_rules! new_index {
29-
($Index:ident, $INVALID_INDEX:ident) => {
30-
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
31-
pub struct $Index(usize);
32-
33-
const $INVALID_INDEX: $Index = $Index(usize::MAX);
34-
35-
impl $Index {
36-
pub fn idx(&self) -> Option<usize> {
37-
if *self == $INVALID_INDEX {
38-
None
39-
} else {
40-
Some(self.0)
27+
// This submodule holds some newtype'd Index wrappers that are using
28+
// NonZero to ensure that Option<Index> occupies only a single word.
29+
// They are in a submodule to impose privacy restrictions; namely, to
30+
// ensure that other code does not accidentally access `index.0`
31+
// (which is likely to yield a subtle off-by-one error).
32+
mod indexes {
33+
use core::nonzero::NonZero;
34+
35+
macro_rules! new_index {
36+
($Index:ident) => {
37+
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
38+
pub struct $Index(NonZero<usize>);
39+
40+
impl $Index {
41+
pub fn new(idx: usize) -> Self {
42+
unsafe { $Index(NonZero::new(idx + 1)) }
43+
}
44+
pub fn idx(&self) -> usize {
45+
*self.0 - 1
4146
}
4247
}
4348
}
4449
}
45-
}
4650

47-
/// Index into MovePathData.move_paths
48-
new_index!(MovePathIndex, INVALID_MOVE_PATH_INDEX);
51+
/// Index into MovePathData.move_paths
52+
new_index!(MovePathIndex);
4953

50-
/// Index into MoveData.moves.
51-
new_index!(MoveOutIndex, INVALID_MOVE_OUT_INDEX);
54+
/// Index into MoveData.moves.
55+
new_index!(MoveOutIndex);
56+
}
5257

58+
pub use self::indexes::MovePathIndex;
59+
pub use self::indexes::MoveOutIndex;
5360

5461
/// `MovePath` is a canonicalized representation of a path that is
5562
/// moved or assigned to.
@@ -65,9 +72,9 @@ new_index!(MoveOutIndex, INVALID_MOVE_OUT_INDEX);
6572
/// they both have the MovePath representing `x` as their parent.
6673
#[derive(Clone)]
6774
pub struct MovePath<'tcx> {
68-
pub next_sibling: MovePathIndex,
69-
pub first_child: MovePathIndex,
70-
pub parent: MovePathIndex,
75+
pub next_sibling: Option<MovePathIndex>,
76+
pub first_child: Option<MovePathIndex>,
77+
pub parent: Option<MovePathIndex>,
7178
pub lvalue: Lvalue<'tcx>,
7279
}
7380

@@ -76,9 +83,9 @@ pub struct MovePath<'tcx> {
7683
/// children of each path.
7784
#[derive(Clone)]
7885
struct PreMovePath<'tcx> {
79-
pub next_sibling: MovePathIndex,
80-
pub first_child: Cell<MovePathIndex>,
81-
pub parent: MovePathIndex,
86+
pub next_sibling: Option<MovePathIndex>,
87+
pub first_child: Cell<Option<MovePathIndex>>,
88+
pub parent: Option<MovePathIndex>,
8289
pub lvalue: Lvalue<'tcx>,
8390
}
8491

@@ -96,14 +103,14 @@ impl<'tcx> PreMovePath<'tcx> {
96103
impl<'tcx> fmt::Debug for MovePath<'tcx> {
97104
fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
98105
try!(write!(w, "MovePath {{"));
99-
if self.parent != INVALID_MOVE_PATH_INDEX {
100-
try!(write!(w, " parent: {:?},", self.parent));
106+
if let Some(parent) = self.parent {
107+
try!(write!(w, " parent: {:?},", parent));
101108
}
102-
if self.first_child != INVALID_MOVE_PATH_INDEX {
103-
try!(write!(w, " first_child: {:?},", self.first_child));
109+
if let Some(first_child) = self.first_child {
110+
try!(write!(w, " first_child: {:?},", first_child));
104111
}
105-
if self.next_sibling != INVALID_MOVE_PATH_INDEX {
106-
try!(write!(w, " next_sibling: {:?}", self.next_sibling));
112+
if let Some(next_sibling) = self.next_sibling {
113+
try!(write!(w, " next_sibling: {:?}", next_sibling));
107114
}
108115
write!(w, " lvalue: {:?} }}", self.lvalue)
109116
}
@@ -147,8 +154,7 @@ pub struct PathMap {
147154
impl Index<MovePathIndex> for PathMap {
148155
type Output = [MoveOutIndex];
149156
fn index(&self, index: MovePathIndex) -> &Self::Output {
150-
assert!(index != INVALID_MOVE_PATH_INDEX);
151-
&self.map[index.0]
157+
&self.map[index.idx()]
152158
}
153159
}
154160

@@ -168,7 +174,7 @@ pub struct MoveOut {
168174

169175
impl fmt::Debug for MoveOut {
170176
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
171-
write!(fmt, "p{}@{:?}", self.path.0, self.source)
177+
write!(fmt, "p{}@{:?}", self.path.idx(), self.source)
172178
}
173179
}
174180

@@ -194,13 +200,13 @@ pub struct MovePathData<'tcx> {
194200
impl<'tcx> Index<MovePathIndex> for MovePathData<'tcx> {
195201
type Output = MovePath<'tcx>;
196202
fn index(&self, i: MovePathIndex) -> &MovePath<'tcx> {
197-
&self.move_paths[i.idx().unwrap()]
203+
&self.move_paths[i.idx()]
198204
}
199205
}
200206

201-
/// MovePathRevIndex maps from a uint in an lvalue-category to the
207+
/// MovePathInverseMap maps from a uint in an lvalue-category to the
202208
/// MovePathIndex for the MovePath for that lvalue.
203-
type MovePathRevIndex = Vec<MovePathIndex>;
209+
type MovePathInverseMap = Vec<Option<MovePathIndex>>;
204210

205211
struct MovePathDataBuilder<'a, 'tcx: 'a> {
206212
mir: &'a Mir<'tcx>,
@@ -210,9 +216,9 @@ struct MovePathDataBuilder<'a, 'tcx: 'a> {
210216

211217
/// Tables mapping from an l-value to its MovePathIndex.
212218
pub struct MovePathLookup<'tcx> {
213-
vars: MovePathRevIndex,
214-
temps: MovePathRevIndex,
215-
args: MovePathRevIndex,
219+
vars: MovePathInverseMap,
220+
temps: MovePathInverseMap,
221+
args: MovePathInverseMap,
216222
statics: FnvHashMap<DefId, MovePathIndex>,
217223
return_ptr: Option<MovePathIndex>,
218224

@@ -254,7 +260,7 @@ enum LookupKind { Generate, Reuse }
254260
struct Lookup<T>(LookupKind, T);
255261

256262
impl Lookup<MovePathIndex> {
257-
fn idx(&self) -> usize { (self.1).0 }
263+
fn idx(&self) -> usize { (self.1).idx() }
258264
}
259265

260266
impl<'tcx> MovePathLookup<'tcx> {
@@ -266,28 +272,31 @@ impl<'tcx> MovePathLookup<'tcx> {
266272
statics: Default::default(),
267273
return_ptr: None,
268274
projections: vec![],
269-
next_index: MovePathIndex(0),
275+
next_index: MovePathIndex::new(0),
270276
}
271277
}
272278

273279
fn next_index(next: &mut MovePathIndex) -> MovePathIndex {
274280
let i = *next;
275-
*next = MovePathIndex(i.0 + 1);
281+
*next = MovePathIndex::new(i.idx() + 1);
276282
i
277283
}
278284

279-
fn lookup_or_generate(vec: &mut Vec<MovePathIndex>,
285+
fn lookup_or_generate(vec: &mut Vec<Option<MovePathIndex>>,
280286
idx: u32,
281287
next_index: &mut MovePathIndex) -> Lookup<MovePathIndex> {
282288
let idx = idx as usize;
283-
vec.fill_to_with(idx, INVALID_MOVE_PATH_INDEX);
289+
vec.fill_to_with(idx, None);
284290
let entry = &mut vec[idx];
285-
if *entry == INVALID_MOVE_PATH_INDEX {
286-
let i = Self::next_index(next_index);
287-
*entry = i;
288-
Lookup(LookupKind::Generate, i)
289-
} else {
290-
Lookup(LookupKind::Reuse, *entry)
291+
match *entry {
292+
None => {
293+
let i = Self::next_index(next_index);
294+
*entry = Some(i);
295+
Lookup(LookupKind::Generate, i)
296+
}
297+
Some(entry_idx) => {
298+
Lookup(LookupKind::Reuse, entry_idx)
299+
}
291300
}
292301
}
293302

@@ -342,8 +351,8 @@ impl<'tcx> MovePathLookup<'tcx> {
342351
base: MovePathIndex) -> Lookup<MovePathIndex> {
343352
let MovePathLookup { ref mut projections,
344353
ref mut next_index, .. } = *self;
345-
projections.fill_to(base.0);
346-
match projections[base.0].entry(proj.elem.lift()) {
354+
projections.fill_to(base.idx());
355+
match projections[base.idx()].entry(proj.elem.lift()) {
347356
Entry::Occupied(ent) => {
348357
Lookup(LookupKind::Reuse, *ent.get())
349358
}
@@ -362,14 +371,14 @@ impl<'tcx> MovePathLookup<'tcx> {
362371
// unknown l-value; it will simply panic.
363372
pub fn find(&self, lval: &Lvalue<'tcx>) -> MovePathIndex {
364373
match *lval {
365-
Lvalue::Var(var_idx) => self.vars[var_idx as usize],
366-
Lvalue::Temp(temp_idx) => self.temps[temp_idx as usize],
367-
Lvalue::Arg(arg_idx) => self.args[arg_idx as usize],
374+
Lvalue::Var(var_idx) => self.vars[var_idx as usize].unwrap(),
375+
Lvalue::Temp(temp_idx) => self.temps[temp_idx as usize].unwrap(),
376+
Lvalue::Arg(arg_idx) => self.args[arg_idx as usize].unwrap(),
368377
Lvalue::Static(ref def_id) => self.statics[def_id],
369378
Lvalue::ReturnPointer => self.return_ptr.unwrap(),
370379
Lvalue::Projection(ref proj) => {
371380
let base_index = self.find(&proj.base);
372-
self.projections[base_index.0 as usize][&proj.elem.lift()]
381+
self.projections[base_index.idx()][&proj.elem.lift()]
373382
}
374383
}
375384
}
@@ -418,8 +427,8 @@ impl<'a, 'tcx> MovePathDataBuilder<'a, 'tcx> {
418427
match *lval {
419428
Lvalue::Var(_) | Lvalue::Temp(_) | Lvalue::Arg(_) |
420429
Lvalue::Static(_) | Lvalue::ReturnPointer => {
421-
sibling = INVALID_MOVE_PATH_INDEX;
422-
parent = INVALID_MOVE_PATH_INDEX;
430+
sibling = None;
431+
parent = None;
423432
}
424433
Lvalue::Projection(ref proj) => {
425434
// Here, install new MovePath as new first_child.
@@ -428,22 +437,23 @@ impl<'a, 'tcx> MovePathDataBuilder<'a, 'tcx> {
428437

429438
// Note: `parent` previously allocated (Projection
430439
// case of match above established this).
431-
parent = self.move_path_for(&proj.base);
440+
let idx = self.move_path_for(&proj.base);
441+
parent = Some(idx);
432442

433443
pre_move_paths = self.pre_move_paths.borrow_mut();
434-
let parent_move_path = &mut pre_move_paths[parent.0];
444+
let parent_move_path = &mut pre_move_paths[idx.idx()];
435445

436446
// At last: Swap in the new first_child.
437447
sibling = parent_move_path.first_child.get();
438-
parent_move_path.first_child.set(mpi);
448+
parent_move_path.first_child.set(Some(mpi));
439449
}
440450
};
441451

442452
let move_path = PreMovePath {
443453
next_sibling: sibling,
444454
parent: parent,
445455
lvalue: lval.clone(),
446-
first_child: Cell::new(INVALID_MOVE_PATH_INDEX),
456+
first_child: Cell::new(None),
447457
};
448458

449459
pre_move_paths.push(move_path);
@@ -610,8 +620,8 @@ fn gather_moves<'tcx>(mir: &Mir<'tcx>, tcx: &ty::TyCtxt<'tcx>) -> MoveData<'tcx>
610620
let mut seen: Vec<_> = move_paths.iter().map(|_| false).collect();
611621
for (j, &MoveOut { ref path, ref source }) in moves.iter().enumerate() {
612622
debug!("MovePathData moves[{}]: MoveOut {{ path: {:?} = {:?}, source: {:?} }}",
613-
j, path, move_paths[path.0], source);
614-
seen[path.0] = true;
623+
j, path, move_paths[path.idx()], source);
624+
seen[path.idx()] = true;
615625
}
616626
for (j, path) in move_paths.iter().enumerate() {
617627
if !seen[j] {
@@ -664,24 +674,24 @@ impl<'b, 'a: 'b, 'tcx: 'a> BlockContext<'b, 'a, 'tcx> {
664674
return;
665675
}
666676
let i = source.index;
667-
let index = MoveOutIndex(self.moves.len());
677+
let index = MoveOutIndex::new(self.moves.len());
668678

669679
let path = builder.move_path_for(lval);
670680
self.moves.push(MoveOut { path: path, source: source.clone() });
671-
self.path_map.fill_to(path.0);
681+
self.path_map.fill_to(path.idx());
672682

673683
debug!("ctxt: {:?} add consume of lval: {:?} \
674684
at index: {:?} \
675685
to path_map for path: {:?} and \
676686
to loc_map for loc: {:?}",
677687
stmt_kind, lval, index, path, source);
678688

679-
debug_assert!(path.0 < self.path_map.len());
689+
debug_assert!(path.idx() < self.path_map.len());
680690
// this is actually a questionable assert; at the very
681691
// least, incorrect input code can probably cause it to
682692
// fire.
683-
assert!(self.path_map[path.0].iter().find(|idx| **idx == index).is_none());
684-
self.path_map[path.0].push(index);
693+
assert!(self.path_map[path.idx()].iter().find(|idx| **idx == index).is_none());
694+
self.path_map[path.idx()].push(index);
685695

686696
debug_assert!(i < self.loc_map_bb.len());
687697
debug_assert!(self.loc_map_bb[i].iter().find(|idx| **idx == index).is_none());

src/librustc_borrowck/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#![feature(rustc_private)]
2525
#![feature(staged_api)]
2626
#![feature(associated_consts)]
27+
#![feature(nonzero)]
2728
#[macro_use] extern crate log;
2829
#[macro_use] extern crate syntax;
2930

@@ -33,6 +34,7 @@ extern crate graphviz as dot;
3334
extern crate rustc;
3435
extern crate rustc_front;
3536
extern crate rustc_mir;
37+
extern crate core; // for NonZero
3638

3739
pub use borrowck::check_crate;
3840
pub use borrowck::build_borrowck_dataflow_data_for_fn;

0 commit comments

Comments
 (0)