Skip to content

Commit fe3514e

Browse files
committed
Rollup merge of rust-lang#24209 - nikomatsakis:refactor-unification, r=nrc
I'm on a quest to slowly refactor a lot of the inference code. A first step for that is moving the \"pure data structures\" out so as to simplify what's left. This PR moves `snapshot_vec`, `graph`, and `unify` into their own crate (`librustc_data_structures`). They can then be unit-tested, benchmarked, etc more easily. As a benefit, I improved the performance of unification slightly on the benchmark I added vs the original code. r? @nrc
2 parents e4f9ddb + ead4631 commit fe3514e

File tree

18 files changed

+785
-384
lines changed

18 files changed

+785
-384
lines changed

mk/crates.mk

+7-4
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ TARGET_CRATES := libc std flate arena term \
5454
log graphviz core rbml alloc \
5555
unicode rustc_bitflags
5656
RUSTC_CRATES := rustc rustc_typeck rustc_borrowck rustc_resolve rustc_driver \
57-
rustc_trans rustc_back rustc_llvm rustc_privacy rustc_lint
57+
rustc_trans rustc_back rustc_llvm rustc_privacy rustc_lint \
58+
rustc_data_structures
5859
HOST_CRATES := syntax $(RUSTC_CRATES) rustdoc fmt_macros
5960
CRATES := $(TARGET_CRATES) $(HOST_CRATES)
6061
TOOLS := compiletest rustdoc rustc rustbook
@@ -80,9 +81,10 @@ DEPS_rustc_resolve := rustc log syntax
8081
DEPS_rustc_privacy := rustc log syntax
8182
DEPS_rustc_lint := rustc log syntax
8283
DEPS_rustc := syntax flate arena serialize getopts rbml \
83-
log graphviz rustc_llvm rustc_back
84+
log graphviz rustc_llvm rustc_back rustc_data_structures
8485
DEPS_rustc_llvm := native:rustllvm libc std
8586
DEPS_rustc_back := std syntax rustc_llvm flate log libc
87+
DEPS_rustc_data_structures := std log serialize
8688
DEPS_rustdoc := rustc rustc_driver native:hoedown serialize getopts \
8789
test rustc_lint
8890
DEPS_rustc_bitflags := core
@@ -141,16 +143,17 @@ DOC_CRATES := $(filter-out rustc, \
141143
$(filter-out rustc_trans, \
142144
$(filter-out rustc_typeck, \
143145
$(filter-out rustc_borrowck, \
146+
$(filter-out rustc_data_structures, \
144147
$(filter-out rustc_resolve, \
145148
$(filter-out rustc_driver, \
146149
$(filter-out rustc_privacy, \
147150
$(filter-out rustc_lint, \
148151
$(filter-out log, \
149152
$(filter-out getopts, \
150-
$(filter-out syntax, $(CRATES))))))))))))
153+
$(filter-out syntax, $(CRATES)))))))))))))
151154
#endif
152155
#endif
153-
COMPILER_DOC_CRATES := rustc rustc_trans rustc_borrowck rustc_resolve \
156+
COMPILER_DOC_CRATES := rustc rustc_trans rustc_borrowck rustc_data_structures rustc_resolve \
154157
rustc_typeck rustc_driver syntax rustc_privacy \
155158
rustc_lint
156159

src/librustc/lib.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ extern crate graphviz;
5454
extern crate libc;
5555
extern crate rustc_llvm;
5656
extern crate rustc_back;
57+
extern crate rustc_data_structures;
5758
extern crate serialize;
5859
extern crate rbml;
5960
extern crate collections;
@@ -103,7 +104,6 @@ pub mod middle {
103104
pub mod entry;
104105
pub mod expr_use_visitor;
105106
pub mod fast_reject;
106-
pub mod graph;
107107
pub mod intrinsicck;
108108
pub mod infer;
109109
pub mod lang_items;
@@ -141,7 +141,6 @@ pub mod util {
141141
pub mod common;
142142
pub mod ppaux;
143143
pub mod nodemap;
144-
pub mod snapshot_vec;
145144
pub mod lev_distance;
146145
}
147146

src/librustc/middle/cfg/construct.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use rustc_data_structures::graph;
1112
use middle::cfg::*;
1213
use middle::def;
13-
use middle::graph;
1414
use middle::pat_util;
1515
use middle::region::CodeExtent;
1616
use middle::ty;

src/librustc/middle/cfg/mod.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
//! Module that constructs a control-flow graph representing an item.
1212
//! Uses `Graph` as the underlying representation.
1313
14-
use middle::graph;
14+
use rustc_data_structures::graph;
1515
use middle::ty;
1616
use syntax::ast;
1717

@@ -24,7 +24,7 @@ pub struct CFG {
2424
pub exit: CFGIndex,
2525
}
2626

27-
#[derive(Copy, Clone, PartialEq)]
27+
#[derive(Copy, Clone, Debug, PartialEq)]
2828
pub enum CFGNodeData {
2929
AST(ast::NodeId),
3030
Entry,
@@ -43,6 +43,7 @@ impl CFGNodeData {
4343
}
4444
}
4545

46+
#[derive(Debug)]
4647
pub struct CFGEdgeData {
4748
pub exiting_scopes: Vec<ast::NodeId>
4849
}

src/librustc/middle/dataflow.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -530,10 +530,9 @@ impl<'a, 'b, 'tcx, O:DataFlowOperator> PropagationContext<'a, 'b, 'tcx, O> {
530530
pred_bits: &[usize],
531531
cfg: &cfg::CFG,
532532
cfgidx: CFGIndex) {
533-
cfg.graph.each_outgoing_edge(cfgidx, |_e_idx, edge| {
533+
for (_, edge) in cfg.graph.outgoing_edges(cfgidx) {
534534
self.propagate_bits_into_entry_set_for(pred_bits, edge);
535-
true
536-
});
535+
}
537536
}
538537

539538
fn propagate_bits_into_entry_set_for(&mut self,

src/librustc/middle/infer/freshen.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use middle::ty_fold::TypeFolder;
3737
use std::collections::hash_map::{self, Entry};
3838

3939
use super::InferCtxt;
40-
use super::unify::ToType;
40+
use super::unify_key::ToType;
4141

4242
pub struct TypeFreshener<'a, 'tcx:'a> {
4343
infcx: &'a InferCtxt<'a, 'tcx>,

src/librustc/middle/infer/mod.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use middle::ty::replace_late_bound_regions;
2929
use middle::ty::{self, Ty};
3030
use middle::ty_fold::{TypeFolder, TypeFoldable};
3131
use middle::ty_relate::{Relate, RelateResult, TypeRelation};
32+
use rustc_data_structures::unify::{self, UnificationTable};
3233
use std::cell::{RefCell};
3334
use std::fmt;
3435
use std::rc::Rc;
@@ -41,8 +42,8 @@ use util::ppaux::{Repr, UserString};
4142

4243
use self::combine::CombineFields;
4344
use self::region_inference::{RegionVarBindings, RegionSnapshot};
44-
use self::unify::{ToType, UnificationTable};
4545
use self::error_reporting::ErrorReporting;
46+
use self::unify_key::ToType;
4647

4748
pub mod bivariate;
4849
pub mod combine;
@@ -57,7 +58,7 @@ pub mod resolve;
5758
mod freshen;
5859
pub mod sub;
5960
pub mod type_variable;
60-
pub mod unify;
61+
pub mod unify_key;
6162

6263
pub type Bound<T> = Option<T>;
6364
pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result"

src/librustc/middle/infer/region_inference/mod.rs

+13-17
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,13 @@ use self::Classification::*;
2020

2121
use super::{RegionVariableOrigin, SubregionOrigin, TypeTrace, MiscVariable};
2222

23+
use rustc_data_structures::graph::{self, Direction, NodeIndex};
2324
use middle::region;
2425
use middle::ty::{self, Ty};
2526
use middle::ty::{BoundRegion, FreeRegion, Region, RegionVid};
2627
use middle::ty::{ReEmpty, ReStatic, ReInfer, ReFree, ReEarlyBound};
2728
use middle::ty::{ReLateBound, ReScope, ReVar, ReSkolemized, BrFresh};
2829
use middle::ty_relate::RelateResult;
29-
use middle::graph;
30-
use middle::graph::{Direction, NodeIndex};
3130
use util::common::indenter;
3231
use util::nodemap::{FnvHashMap, FnvHashSet};
3332
use util::ppaux::{Repr, UserString};
@@ -1325,10 +1324,8 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
13251324
let num_vars = self.num_vars();
13261325

13271326
let constraints = self.constraints.borrow();
1328-
let num_edges = constraints.len();
13291327

1330-
let mut graph = graph::Graph::with_capacity(num_vars as usize + 1,
1331-
num_edges);
1328+
let mut graph = graph::Graph::new();
13321329

13331330
for _ in 0..num_vars {
13341331
graph.add_node(());
@@ -1370,10 +1367,10 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
13701367
// not contained by an upper-bound.
13711368
let (mut lower_bounds, lower_dup) =
13721369
self.collect_concrete_regions(graph, var_data, node_idx,
1373-
graph::Incoming, dup_vec);
1370+
graph::INCOMING, dup_vec);
13741371
let (mut upper_bounds, upper_dup) =
13751372
self.collect_concrete_regions(graph, var_data, node_idx,
1376-
graph::Outgoing, dup_vec);
1373+
graph::OUTGOING, dup_vec);
13771374

13781375
if lower_dup || upper_dup {
13791376
return;
@@ -1433,7 +1430,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
14331430
// that have no intersection.
14341431
let (upper_bounds, dup_found) =
14351432
self.collect_concrete_regions(graph, var_data, node_idx,
1436-
graph::Outgoing, dup_vec);
1433+
graph::OUTGOING, dup_vec);
14371434

14381435
if dup_found {
14391436
return;
@@ -1508,8 +1505,8 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
15081505
// figure out the direction from which this node takes its
15091506
// values, and search for concrete regions etc in that direction
15101507
let dir = match classification {
1511-
Expanding => graph::Incoming,
1512-
Contracting => graph::Outgoing,
1508+
Expanding => graph::INCOMING,
1509+
Contracting => graph::OUTGOING,
15131510
};
15141511

15151512
process_edges(self, &mut state, graph, node_idx, dir);
@@ -1519,14 +1516,14 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
15191516
return (result, dup_found);
15201517

15211518
fn process_edges<'a, 'tcx>(this: &RegionVarBindings<'a, 'tcx>,
1522-
state: &mut WalkState<'tcx>,
1523-
graph: &RegionGraph,
1524-
source_vid: RegionVid,
1525-
dir: Direction) {
1519+
state: &mut WalkState<'tcx>,
1520+
graph: &RegionGraph,
1521+
source_vid: RegionVid,
1522+
dir: Direction) {
15261523
debug!("process_edges(source_vid={:?}, dir={:?})", source_vid, dir);
15271524

15281525
let source_node_index = NodeIndex(source_vid.index as usize);
1529-
graph.each_adjacent_edge(source_node_index, dir, |_, edge| {
1526+
for (_, edge) in graph.adjacent_edges(source_node_index, dir) {
15301527
match edge.data {
15311528
ConstrainVarSubVar(from_vid, to_vid) => {
15321529
let opp_vid =
@@ -1544,8 +1541,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
15441541
});
15451542
}
15461543
}
1547-
true
1548-
});
1544+
}
15491545
}
15501546
}
15511547

src/librustc/middle/infer/type_variable.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use std::cmp::min;
1717
use std::marker::PhantomData;
1818
use std::mem;
1919
use std::u32;
20-
use util::snapshot_vec as sv;
20+
use rustc_data_structures::snapshot_vec as sv;
2121

2222
pub struct TypeVariableTable<'tcx> {
2323
values: sv::SnapshotVec<Delegate<'tcx>>,
@@ -65,7 +65,7 @@ impl RelationDir {
6565

6666
impl<'tcx> TypeVariableTable<'tcx> {
6767
pub fn new() -> TypeVariableTable<'tcx> {
68-
TypeVariableTable { values: sv::SnapshotVec::new(Delegate(PhantomData)) }
68+
TypeVariableTable { values: sv::SnapshotVec::new() }
6969
}
7070

7171
fn relations<'a>(&'a mut self, a: ty::TyVid) -> &'a mut Vec<Relation> {
@@ -201,9 +201,7 @@ impl<'tcx> sv::SnapshotVecDelegate for Delegate<'tcx> {
201201
type Value = TypeVariableData<'tcx>;
202202
type Undo = UndoEntry;
203203

204-
fn reverse(&mut self,
205-
values: &mut Vec<TypeVariableData<'tcx>>,
206-
action: UndoEntry) {
204+
fn reverse(values: &mut Vec<TypeVariableData<'tcx>>, action: UndoEntry) {
207205
match action {
208206
SpecifyVar(vid, relations) => {
209207
values[vid.index as usize].value = Bounded(relations);
+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use middle::ty::{self, IntVarValue, Ty};
12+
use rustc_data_structures::unify::UnifyKey;
13+
use syntax::ast;
14+
15+
pub trait ToType<'tcx> {
16+
fn to_type(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx>;
17+
}
18+
19+
impl UnifyKey for ty::IntVid {
20+
type Value = Option<IntVarValue>;
21+
fn index(&self) -> u32 { self.index }
22+
fn from_index(i: u32) -> ty::IntVid { ty::IntVid { index: i } }
23+
fn tag(_: Option<ty::IntVid>) -> &'static str { "IntVid" }
24+
}
25+
26+
impl<'tcx> ToType<'tcx> for IntVarValue {
27+
fn to_type(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> {
28+
match *self {
29+
ty::IntType(i) => ty::mk_mach_int(tcx, i),
30+
ty::UintType(i) => ty::mk_mach_uint(tcx, i),
31+
}
32+
}
33+
}
34+
35+
// Floating point type keys
36+
37+
impl UnifyKey for ty::FloatVid {
38+
type Value = Option<ast::FloatTy>;
39+
fn index(&self) -> u32 { self.index }
40+
fn from_index(i: u32) -> ty::FloatVid { ty::FloatVid { index: i } }
41+
fn tag(_: Option<ty::FloatVid>) -> &'static str { "FloatVid" }
42+
}
43+
44+
impl<'tcx> ToType<'tcx> for ast::FloatTy {
45+
fn to_type(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> {
46+
ty::mk_mach_float(tcx, *self)
47+
}
48+
}
+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use std::iter;
12+
13+
/// A very simple BitVector type.
14+
pub struct BitVector {
15+
data: Vec<u64>
16+
}
17+
18+
impl BitVector {
19+
pub fn new(num_bits: usize) -> BitVector {
20+
let num_words = (num_bits + 63) / 64;
21+
BitVector { data: iter::repeat(0).take(num_words).collect() }
22+
}
23+
24+
fn word_mask(&self, bit: usize) -> (usize, u64) {
25+
let word = bit / 64;
26+
let mask = 1 << (bit % 64);
27+
(word, mask)
28+
}
29+
30+
pub fn contains(&self, bit: usize) -> bool {
31+
let (word, mask) = self.word_mask(bit);
32+
(self.data[word] & mask) != 0
33+
}
34+
35+
pub fn insert(&mut self, bit: usize) -> bool {
36+
let (word, mask) = self.word_mask(bit);
37+
let data = &mut self.data[word];
38+
let value = *data;
39+
*data = value | mask;
40+
(value | mask) != value
41+
}
42+
}

0 commit comments

Comments
 (0)