Skip to content

Commit 382ab92

Browse files
committed
Auto merge of #33998 - nikomatsakis:incr-comp-dep-node-trait, r=mw
Incr. comp. dep-node for traits, tests Introduce new tests and also make dep-node for trait selection a bit more selective. Fixes #33850 r? @michaelwoerister
2 parents 4fb1458 + e548c46 commit 382ab92

File tree

19 files changed

+447
-82
lines changed

19 files changed

+447
-82
lines changed

src/librustc/dep_graph/dep_node.rs

+16-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,16 @@
1010

1111
use std::fmt::Debug;
1212

13-
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
13+
macro_rules! try_opt {
14+
($e:expr) => (
15+
match $e {
16+
Some(r) => r,
17+
None => return None,
18+
}
19+
)
20+
}
21+
22+
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
1423
pub enum DepNode<D: Clone + Debug> {
1524
// The `D` type is "how definitions are identified".
1625
// During compilation, it is always `DefId`, but when serializing
@@ -116,7 +125,7 @@ pub enum DepNode<D: Clone + Debug> {
116125
// which would yield an overly conservative dep-graph.
117126
TraitItems(D),
118127
ReprHints(D),
119-
TraitSelect(D),
128+
TraitSelect(D, Vec<D>),
120129
}
121130

122131
impl<D: Clone + Debug> DepNode<D> {
@@ -212,7 +221,11 @@ impl<D: Clone + Debug> DepNode<D> {
212221
TraitImpls(ref d) => op(d).map(TraitImpls),
213222
TraitItems(ref d) => op(d).map(TraitItems),
214223
ReprHints(ref d) => op(d).map(ReprHints),
215-
TraitSelect(ref d) => op(d).map(TraitSelect),
224+
TraitSelect(ref d, ref type_ds) => {
225+
let d = try_opt!(op(d));
226+
let type_ds = try_opt!(type_ds.iter().map(|d| op(d)).collect());
227+
Some(TraitSelect(d, type_ds))
228+
}
216229
}
217230
}
218231
}

src/librustc/dep_graph/query.rs

+12-12
Original file line numberDiff line numberDiff line change
@@ -47,26 +47,26 @@ impl<D: Clone + Debug + Hash + Eq> DepGraphQuery<D> {
4747
self.indices.contains_key(&node)
4848
}
4949

50-
pub fn nodes(&self) -> Vec<DepNode<D>> {
50+
pub fn nodes(&self) -> Vec<&DepNode<D>> {
5151
self.graph.all_nodes()
5252
.iter()
53-
.map(|n| n.data.clone())
53+
.map(|n| &n.data)
5454
.collect()
5555
}
5656

57-
pub fn edges(&self) -> Vec<(DepNode<D>,DepNode<D>)> {
57+
pub fn edges(&self) -> Vec<(&DepNode<D>,&DepNode<D>)> {
5858
self.graph.all_edges()
5959
.iter()
6060
.map(|edge| (edge.source(), edge.target()))
61-
.map(|(s, t)| (self.graph.node_data(s).clone(),
62-
self.graph.node_data(t).clone()))
61+
.map(|(s, t)| (self.graph.node_data(s),
62+
self.graph.node_data(t)))
6363
.collect()
6464
}
6565

66-
fn reachable_nodes(&self, node: DepNode<D>, direction: Direction) -> Vec<DepNode<D>> {
67-
if let Some(&index) = self.indices.get(&node) {
66+
fn reachable_nodes(&self, node: &DepNode<D>, direction: Direction) -> Vec<&DepNode<D>> {
67+
if let Some(&index) = self.indices.get(node) {
6868
self.graph.depth_traverse(index, direction)
69-
.map(|s| self.graph.node_data(s).clone())
69+
.map(|s| self.graph.node_data(s))
7070
.collect()
7171
} else {
7272
vec![]
@@ -75,20 +75,20 @@ impl<D: Clone + Debug + Hash + Eq> DepGraphQuery<D> {
7575

7676
/// All nodes reachable from `node`. In other words, things that
7777
/// will have to be recomputed if `node` changes.
78-
pub fn transitive_successors(&self, node: DepNode<D>) -> Vec<DepNode<D>> {
78+
pub fn transitive_successors(&self, node: &DepNode<D>) -> Vec<&DepNode<D>> {
7979
self.reachable_nodes(node, OUTGOING)
8080
}
8181

8282
/// All nodes that can reach `node`.
83-
pub fn transitive_predecessors(&self, node: DepNode<D>) -> Vec<DepNode<D>> {
83+
pub fn transitive_predecessors(&self, node: &DepNode<D>) -> Vec<&DepNode<D>> {
8484
self.reachable_nodes(node, INCOMING)
8585
}
8686

8787
/// Just the outgoing edges from `node`.
88-
pub fn immediate_successors(&self, node: DepNode<D>) -> Vec<DepNode<D>> {
88+
pub fn immediate_successors(&self, node: &DepNode<D>) -> Vec<&DepNode<D>> {
8989
if let Some(&index) = self.indices.get(&node) {
9090
self.graph.successor_nodes(index)
91-
.map(|s| self.graph.node_data(s).clone())
91+
.map(|s| self.graph.node_data(s))
9292
.collect()
9393
} else {
9494
vec![]

src/librustc/dep_graph/raii.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,20 @@ use super::thread::{DepGraphThreadData, DepMessage};
1414

1515
pub struct DepTask<'graph> {
1616
data: &'graph DepGraphThreadData,
17-
key: DepNode<DefId>,
17+
key: Option<DepNode<DefId>>,
1818
}
1919

2020
impl<'graph> DepTask<'graph> {
2121
pub fn new(data: &'graph DepGraphThreadData, key: DepNode<DefId>)
2222
-> DepTask<'graph> {
23-
data.enqueue(DepMessage::PushTask(key));
24-
DepTask { data: data, key: key }
23+
data.enqueue(DepMessage::PushTask(key.clone()));
24+
DepTask { data: data, key: Some(key) }
2525
}
2626
}
2727

2828
impl<'graph> Drop for DepTask<'graph> {
2929
fn drop(&mut self) {
30-
self.data.enqueue(DepMessage::PopTask(self.key));
30+
self.data.enqueue(DepMessage::PopTask(self.key.take().unwrap()));
3131
}
3232
}
3333

src/librustc/dep_graph/visit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ pub fn visit_all_items_in_krate<'a, 'tcx, V, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
3939
fn visit_item(&mut self, i: &'tcx hir::Item) {
4040
let item_def_id = self.tcx.map.local_def_id(i.id);
4141
let task_id = (self.dep_node_fn)(item_def_id);
42-
let _task = self.tcx.dep_graph.in_task(task_id);
42+
let _task = self.tcx.dep_graph.in_task(task_id.clone());
4343
debug!("Started task {:?}", task_id);
4444
self.tcx.dep_graph.read(DepNode::Hir(item_def_id));
4545
self.visitor.visit_item(i);

src/librustc/ty/mod.rs

+27-7
Original file line numberDiff line numberDiff line change
@@ -946,7 +946,28 @@ impl<'tcx> TraitPredicate<'tcx> {
946946

947947
/// Creates the dep-node for selecting/evaluating this trait reference.
948948
fn dep_node(&self) -> DepNode<DefId> {
949-
DepNode::TraitSelect(self.def_id())
949+
// Ideally, the dep-node would just have all the input types
950+
// in it. But they are limited to including def-ids. So as an
951+
// approximation we include the def-ids for all nominal types
952+
// found somewhere. This means that we will e.g. conflate the
953+
// dep-nodes for `u32: SomeTrait` and `u64: SomeTrait`, but we
954+
// would have distinct dep-nodes for `Vec<u32>: SomeTrait`,
955+
// `Rc<u32>: SomeTrait`, and `(Vec<u32>, Rc<u32>): SomeTrait`.
956+
// Note that it's always sound to conflate dep-nodes, it just
957+
// leads to more recompilation.
958+
let def_ids: Vec<_> =
959+
self.input_types()
960+
.iter()
961+
.flat_map(|t| t.walk())
962+
.filter_map(|t| match t.sty {
963+
ty::TyStruct(adt_def, _) |
964+
ty::TyEnum(adt_def, _) =>
965+
Some(adt_def.did),
966+
_ =>
967+
None
968+
})
969+
.collect();
970+
DepNode::TraitSelect(self.def_id(), def_ids)
950971
}
951972

952973
pub fn input_types(&self) -> &[Ty<'tcx>] {
@@ -1768,9 +1789,8 @@ impl<'a, 'tcx> AdtDefData<'tcx, 'tcx> {
17681789
stack: &mut Vec<AdtDefMaster<'tcx>>)
17691790
{
17701791

1771-
let dep_node = DepNode::SizedConstraint(self.did);
1772-
1773-
if self.sized_constraint.get(dep_node).is_some() {
1792+
let dep_node = || DepNode::SizedConstraint(self.did);
1793+
if self.sized_constraint.get(dep_node()).is_some() {
17741794
return;
17751795
}
17761796

@@ -1780,7 +1800,7 @@ impl<'a, 'tcx> AdtDefData<'tcx, 'tcx> {
17801800
//
17811801
// Consider the type as Sized in the meanwhile to avoid
17821802
// further errors.
1783-
self.sized_constraint.fulfill(dep_node, tcx.types.err);
1803+
self.sized_constraint.fulfill(dep_node(), tcx.types.err);
17841804
return;
17851805
}
17861806

@@ -1803,14 +1823,14 @@ impl<'a, 'tcx> AdtDefData<'tcx, 'tcx> {
18031823
_ => tcx.mk_tup(tys)
18041824
};
18051825

1806-
match self.sized_constraint.get(dep_node) {
1826+
match self.sized_constraint.get(dep_node()) {
18071827
Some(old_ty) => {
18081828
debug!("calculate_sized_constraint: {:?} recurred", self);
18091829
assert_eq!(old_ty, tcx.types.err)
18101830
}
18111831
None => {
18121832
debug!("calculate_sized_constraint: {:?} => {:?}", self, ty);
1813-
self.sized_constraint.fulfill(dep_node, ty)
1833+
self.sized_constraint.fulfill(dep_node(), ty)
18141834
}
18151835
}
18161836
}

src/librustc_incremental/assert_dep_graph.rs

+40-40
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ fn check_paths<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
195195
}
196196
};
197197

198-
for &(_, source_def_id, source_dep_node) in sources {
198+
for &(_, source_def_id, ref source_dep_node) in sources {
199199
let dependents = query.transitive_successors(source_dep_node);
200200
for &(target_span, ref target_pass, _, ref target_dep_node) in targets {
201201
if !dependents.contains(&target_dep_node) {
@@ -239,7 +239,7 @@ fn dump_graph(tcx: TyCtxt) {
239239
{ // dump a .txt file with just the edges:
240240
let txt_path = format!("{}.txt", path);
241241
let mut file = File::create(&txt_path).unwrap();
242-
for &(source, target) in &edges {
242+
for &(ref source, ref target) in &edges {
243243
write!(file, "{:?} -> {:?}\n", source, target).unwrap();
244244
}
245245
}
@@ -252,51 +252,51 @@ fn dump_graph(tcx: TyCtxt) {
252252
}
253253
}
254254

255-
pub struct GraphvizDepGraph(FnvHashSet<DepNode<DefId>>,
256-
Vec<(DepNode<DefId>, DepNode<DefId>)>);
255+
pub struct GraphvizDepGraph<'q>(FnvHashSet<&'q DepNode<DefId>>,
256+
Vec<(&'q DepNode<DefId>, &'q DepNode<DefId>)>);
257257

258-
impl<'a, 'tcx> dot::GraphWalk<'a> for GraphvizDepGraph {
259-
type Node = DepNode<DefId>;
260-
type Edge = (DepNode<DefId>, DepNode<DefId>);
261-
fn nodes(&self) -> dot::Nodes<DepNode<DefId>> {
258+
impl<'a, 'tcx, 'q> dot::GraphWalk<'a> for GraphvizDepGraph<'q> {
259+
type Node = &'q DepNode<DefId>;
260+
type Edge = (&'q DepNode<DefId>, &'q DepNode<DefId>);
261+
fn nodes(&self) -> dot::Nodes<&'q DepNode<DefId>> {
262262
let nodes: Vec<_> = self.0.iter().cloned().collect();
263263
nodes.into_cow()
264264
}
265-
fn edges(&self) -> dot::Edges<(DepNode<DefId>, DepNode<DefId>)> {
265+
fn edges(&self) -> dot::Edges<(&'q DepNode<DefId>, &'q DepNode<DefId>)> {
266266
self.1[..].into_cow()
267267
}
268-
fn source(&self, edge: &(DepNode<DefId>, DepNode<DefId>)) -> DepNode<DefId> {
268+
fn source(&self, edge: &(&'q DepNode<DefId>, &'q DepNode<DefId>)) -> &'q DepNode<DefId> {
269269
edge.0
270270
}
271-
fn target(&self, edge: &(DepNode<DefId>, DepNode<DefId>)) -> DepNode<DefId> {
271+
fn target(&self, edge: &(&'q DepNode<DefId>, &'q DepNode<DefId>)) -> &'q DepNode<DefId> {
272272
edge.1
273273
}
274274
}
275275

276-
impl<'a, 'tcx> dot::Labeller<'a> for GraphvizDepGraph {
277-
type Node = DepNode<DefId>;
278-
type Edge = (DepNode<DefId>, DepNode<DefId>);
276+
impl<'a, 'tcx, 'q> dot::Labeller<'a> for GraphvizDepGraph<'q> {
277+
type Node = &'q DepNode<DefId>;
278+
type Edge = (&'q DepNode<DefId>, &'q DepNode<DefId>);
279279
fn graph_id(&self) -> dot::Id {
280280
dot::Id::new("DependencyGraph").unwrap()
281281
}
282-
fn node_id(&self, n: &DepNode<DefId>) -> dot::Id {
282+
fn node_id(&self, n: &&'q DepNode<DefId>) -> dot::Id {
283283
let s: String =
284284
format!("{:?}", n).chars()
285285
.map(|c| if c == '_' || c.is_alphanumeric() { c } else { '_' })
286286
.collect();
287287
debug!("n={:?} s={:?}", n, s);
288288
dot::Id::new(s).unwrap()
289289
}
290-
fn node_label(&self, n: &DepNode<DefId>) -> dot::LabelText {
290+
fn node_label(&self, n: &&'q DepNode<DefId>) -> dot::LabelText {
291291
dot::LabelText::label(format!("{:?}", n))
292292
}
293293
}
294294

295295
// Given an optional filter like `"x,y,z"`, returns either `None` (no
296296
// filter) or the set of nodes whose labels contain all of those
297297
// substrings.
298-
fn node_set(query: &DepGraphQuery<DefId>, filter: &DepNodeFilter)
299-
-> Option<FnvHashSet<DepNode<DefId>>>
298+
fn node_set<'q>(query: &'q DepGraphQuery<DefId>, filter: &DepNodeFilter)
299+
-> Option<FnvHashSet<&'q DepNode<DefId>>>
300300
{
301301
debug!("node_set(filter={:?})", filter);
302302

@@ -307,10 +307,10 @@ fn node_set(query: &DepGraphQuery<DefId>, filter: &DepNodeFilter)
307307
Some(query.nodes().into_iter().filter(|n| filter.test(n)).collect())
308308
}
309309

310-
fn filter_nodes(query: &DepGraphQuery<DefId>,
311-
sources: &Option<FnvHashSet<DepNode<DefId>>>,
312-
targets: &Option<FnvHashSet<DepNode<DefId>>>)
313-
-> FnvHashSet<DepNode<DefId>>
310+
fn filter_nodes<'q>(query: &'q DepGraphQuery<DefId>,
311+
sources: &Option<FnvHashSet<&'q DepNode<DefId>>>,
312+
targets: &Option<FnvHashSet<&'q DepNode<DefId>>>)
313+
-> FnvHashSet<&'q DepNode<DefId>>
314314
{
315315
if let &Some(ref sources) = sources {
316316
if let &Some(ref targets) = targets {
@@ -325,21 +325,21 @@ fn filter_nodes(query: &DepGraphQuery<DefId>,
325325
}
326326
}
327327

328-
fn walk_nodes(query: &DepGraphQuery<DefId>,
329-
starts: &FnvHashSet<DepNode<DefId>>,
330-
direction: Direction)
331-
-> FnvHashSet<DepNode<DefId>>
328+
fn walk_nodes<'q>(query: &'q DepGraphQuery<DefId>,
329+
starts: &FnvHashSet<&'q DepNode<DefId>>,
330+
direction: Direction)
331+
-> FnvHashSet<&'q DepNode<DefId>>
332332
{
333333
let mut set = FnvHashSet();
334-
for start in starts {
334+
for &start in starts {
335335
debug!("walk_nodes: start={:?} outgoing?={:?}", start, direction == OUTGOING);
336-
if set.insert(*start) {
336+
if set.insert(start) {
337337
let mut stack = vec![query.indices[start]];
338338
while let Some(index) = stack.pop() {
339339
for (_, edge) in query.graph.adjacent_edges(index, direction) {
340340
let neighbor_index = edge.source_or_target(direction);
341341
let neighbor = query.graph.node_data(neighbor_index);
342-
if set.insert(*neighbor) {
342+
if set.insert(neighbor) {
343343
stack.push(neighbor_index);
344344
}
345345
}
@@ -349,10 +349,10 @@ fn walk_nodes(query: &DepGraphQuery<DefId>,
349349
set
350350
}
351351

352-
fn walk_between(query: &DepGraphQuery<DefId>,
353-
sources: &FnvHashSet<DepNode<DefId>>,
354-
targets: &FnvHashSet<DepNode<DefId>>)
355-
-> FnvHashSet<DepNode<DefId>>
352+
fn walk_between<'q>(query: &'q DepGraphQuery<DefId>,
353+
sources: &FnvHashSet<&'q DepNode<DefId>>,
354+
targets: &FnvHashSet<&'q DepNode<DefId>>)
355+
-> FnvHashSet<&'q DepNode<DefId>>
356356
{
357357
// This is a bit tricky. We want to include a node only if it is:
358358
// (a) reachable from a source and (b) will reach a target. And we
@@ -365,16 +365,16 @@ fn walk_between(query: &DepGraphQuery<DefId>,
365365
let mut node_states = vec![State::Undecided; query.graph.len_nodes()];
366366

367367
for &target in targets {
368-
node_states[query.indices[&target].0] = State::Included;
368+
node_states[query.indices[target].0] = State::Included;
369369
}
370370

371-
for source in sources.iter().map(|n| query.indices[n]) {
371+
for source in sources.iter().map(|&n| query.indices[n]) {
372372
recurse(query, &mut node_states, source);
373373
}
374374

375375
return query.nodes()
376376
.into_iter()
377-
.filter(|n| {
377+
.filter(|&n| {
378378
let index = query.indices[n];
379379
node_states[index.0] == State::Included
380380
})
@@ -417,12 +417,12 @@ fn walk_between(query: &DepGraphQuery<DefId>,
417417
}
418418
}
419419

420-
fn filter_edges(query: &DepGraphQuery<DefId>,
421-
nodes: &FnvHashSet<DepNode<DefId>>)
422-
-> Vec<(DepNode<DefId>, DepNode<DefId>)>
420+
fn filter_edges<'q>(query: &'q DepGraphQuery<DefId>,
421+
nodes: &FnvHashSet<&'q DepNode<DefId>>)
422+
-> Vec<(&'q DepNode<DefId>, &'q DepNode<DefId>)>
423423
{
424424
query.edges()
425425
.into_iter()
426-
.filter(|&(source, target)| nodes.contains(&source) && nodes.contains(&target))
426+
.filter(|&(source, target)| nodes.contains(source) && nodes.contains(target))
427427
.collect()
428428
}

0 commit comments

Comments
 (0)