Skip to content

Commit 6251e95

Browse files
authored
Rollup merge of rust-lang#40038 - nikomatsakis:issue-39828, r=michaelwoerister
detect "bootstrap outputs" when serializing the dep-graph Fixes rust-lang#39828. r? @michaelwoerister
2 parents e69d234 + b576abd commit 6251e95

File tree

6 files changed

+82
-3
lines changed

6 files changed

+82
-3
lines changed

src/librustc_incremental/persist/data.rs

+5
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ use super::directory::DefPathIndex;
2323
pub struct SerializedDepGraph {
2424
pub edges: Vec<SerializedEdgeSet>,
2525

26+
/// These are output nodes that have no incoming edges. We track
27+
/// these separately so that when we reload all edges, we don't
28+
/// lose track of these nodes.
29+
pub bootstrap_outputs: Vec<DepNode<DefPathIndex>>,
30+
2631
/// These are hashes of two things:
2732
/// - the HIR nodes in this crate
2833
/// - the metadata nodes from dependent crates we use

src/librustc_incremental/persist/load.rs

+12
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,18 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
184184
}
185185
}
186186

187+
// Recreate bootstrap outputs, which are outputs that have no incoming edges (and hence cannot
188+
// be dirty).
189+
for bootstrap_output in &serialized_dep_graph.bootstrap_outputs {
190+
if let Some(n) = retraced.map(bootstrap_output) {
191+
if let DepNode::WorkProduct(ref wp) = n {
192+
clean_work_products.insert(wp.clone());
193+
}
194+
195+
tcx.dep_graph.with_task(n, || ()); // create the node with no inputs
196+
}
197+
}
198+
187199
// Subtle. Sometimes we have intermediate nodes that we can't recreate in the new graph.
188200
// This is pretty unusual but it arises in a scenario like this:
189201
//

src/librustc_incremental/persist/preds/mod.rs

+19-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
use rustc::dep_graph::{DepGraphQuery, DepNode};
1212
use rustc::hir::def_id::DefId;
1313
use rustc_data_structures::fx::FxHashMap;
14-
use rustc_data_structures::graph::Graph;
14+
use rustc_data_structures::graph::{Graph, NodeIndex};
1515

1616
use super::hash::*;
1717
use ich::Fingerprint;
@@ -28,6 +28,14 @@ pub struct Predecessors<'query> {
2828
// of the graph down.
2929
pub reduced_graph: Graph<&'query DepNode<DefId>, ()>,
3030

31+
// These are output nodes that have no incoming edges. We have to
32+
// track these specially because, when we load the data back up
33+
// again, we want to make sure and recreate these nodes (we want
34+
// to recreate the nodes where all incoming edges are clean; but
35+
// since we ordinarily just serialize edges, we wind up just
36+
// forgetting that bootstrap outputs even exist in that case.)
37+
pub bootstrap_outputs: Vec<&'query DepNode<DefId>>,
38+
3139
// For the inputs (hir/foreign-metadata), we include hashes.
3240
pub hashes: FxHashMap<&'query DepNode<DefId>, Fingerprint>,
3341
}
@@ -57,7 +65,7 @@ impl<'q> Predecessors<'q> {
5765

5866
// Reduce the graph to the most important nodes.
5967
let compress::Reduction { graph, input_nodes } =
60-
compress::reduce_graph(&query.graph, HashContext::is_hashable, is_output);
68+
compress::reduce_graph(&query.graph, HashContext::is_hashable, |n| is_output(n));
6169

6270
let mut hashes = FxHashMap();
6371
for input_index in input_nodes {
@@ -67,8 +75,17 @@ impl<'q> Predecessors<'q> {
6775
.or_insert_with(|| hcx.hash(input).unwrap());
6876
}
6977

78+
let bootstrap_outputs: Vec<&'q DepNode<DefId>> =
79+
(0 .. graph.len_nodes())
80+
.map(NodeIndex)
81+
.filter(|&n| graph.incoming_edges(n).next().is_none())
82+
.map(|n| *graph.node_data(n))
83+
.filter(|n| is_output(n))
84+
.collect();
85+
7086
Predecessors {
7187
reduced_graph: graph,
88+
bootstrap_outputs: bootstrap_outputs,
7289
hashes: hashes,
7390
}
7491
}

src/librustc_incremental/persist/save.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -204,11 +204,15 @@ pub fn encode_dep_graph(preds: &Predecessors,
204204
}
205205

206206
// Create the serialized dep-graph.
207+
let bootstrap_outputs = preds.bootstrap_outputs.iter()
208+
.map(|n| builder.map(n))
209+
.collect();
207210
let edges = edges.into_iter()
208211
.map(|(k, v)| SerializedEdgeSet { source: k, targets: v })
209212
.collect();
210213
let graph = SerializedDepGraph {
211-
edges: edges,
214+
bootstrap_outputs,
215+
edges,
212216
hashes: preds.hashes
213217
.iter()
214218
.map(|(&dep_node, &hash)| {
@@ -221,6 +225,7 @@ pub fn encode_dep_graph(preds: &Predecessors,
221225
};
222226

223227
if tcx.sess.opts.debugging_opts.incremental_info {
228+
println!("incremental: {} nodes in reduced dep-graph", preds.reduced_graph.len_nodes());
224229
println!("incremental: {} edges in serialized dep-graph", graph.edges.len());
225230
println!("incremental: {} hashes in serialized dep-graph", graph.hashes.len());
226231
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 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+
// revisions:rpass1 rpass2
12+
// compile-flags: -Z query-dep-graph
13+
14+
#![rustc_partition_reused(module="__rustc_fallback_codegen_unit", cfg="rpass2")]
15+
#![feature(rustc_attrs)]
16+
17+
#![crate_type="rlib"]
18+
pub fn foo<T>() { }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 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+
// Regression test for #39828. If you make use of a module that
12+
// consists only of generics, no code is generated, just a dummy
13+
// module. The reduced graph consists of a single node (for that
14+
// module) with no inputs. Since we only serialize edges, when we
15+
// reload, we would consider that node dirty since it is not recreated
16+
// (it is not the target of any edges).
17+
18+
// revisions:rpass1 rpass2
19+
// aux-build:generic.rs
20+
21+
extern crate generic;
22+
fn main() { }

0 commit comments

Comments
 (0)