mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-08 05:08:40 +00:00
detect "bootstrap outputs" when serializing the dep-graph
Fixes #39828.
This commit is contained in:
parent
3954c70537
commit
b576abd2cc
@ -23,6 +23,11 @@ use super::directory::DefPathIndex;
|
|||||||
pub struct SerializedDepGraph {
|
pub struct SerializedDepGraph {
|
||||||
pub edges: Vec<SerializedEdgeSet>,
|
pub edges: Vec<SerializedEdgeSet>,
|
||||||
|
|
||||||
|
/// These are output nodes that have no incoming edges. We track
|
||||||
|
/// these separately so that when we reload all edges, we don't
|
||||||
|
/// lose track of these nodes.
|
||||||
|
pub bootstrap_outputs: Vec<DepNode<DefPathIndex>>,
|
||||||
|
|
||||||
/// These are hashes of two things:
|
/// These are hashes of two things:
|
||||||
/// - the HIR nodes in this crate
|
/// - the HIR nodes in this crate
|
||||||
/// - the metadata nodes from dependent crates we use
|
/// - the metadata nodes from dependent crates we use
|
||||||
|
@ -184,6 +184,18 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Recreate bootstrap outputs, which are outputs that have no incoming edges (and hence cannot
|
||||||
|
// be dirty).
|
||||||
|
for bootstrap_output in &serialized_dep_graph.bootstrap_outputs {
|
||||||
|
if let Some(n) = retraced.map(bootstrap_output) {
|
||||||
|
if let DepNode::WorkProduct(ref wp) = n {
|
||||||
|
clean_work_products.insert(wp.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
tcx.dep_graph.with_task(n, || ()); // create the node with no inputs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Subtle. Sometimes we have intermediate nodes that we can't recreate in the new graph.
|
// Subtle. Sometimes we have intermediate nodes that we can't recreate in the new graph.
|
||||||
// This is pretty unusual but it arises in a scenario like this:
|
// This is pretty unusual but it arises in a scenario like this:
|
||||||
//
|
//
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
use rustc::dep_graph::{DepGraphQuery, DepNode};
|
use rustc::dep_graph::{DepGraphQuery, DepNode};
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_data_structures::graph::Graph;
|
use rustc_data_structures::graph::{Graph, NodeIndex};
|
||||||
|
|
||||||
use super::hash::*;
|
use super::hash::*;
|
||||||
use ich::Fingerprint;
|
use ich::Fingerprint;
|
||||||
@ -28,6 +28,14 @@ pub struct Predecessors<'query> {
|
|||||||
// of the graph down.
|
// of the graph down.
|
||||||
pub reduced_graph: Graph<&'query DepNode<DefId>, ()>,
|
pub reduced_graph: Graph<&'query DepNode<DefId>, ()>,
|
||||||
|
|
||||||
|
// These are output nodes that have no incoming edges. We have to
|
||||||
|
// track these specially because, when we load the data back up
|
||||||
|
// again, we want to make sure and recreate these nodes (we want
|
||||||
|
// to recreate the nodes where all incoming edges are clean; but
|
||||||
|
// since we ordinarily just serialize edges, we wind up just
|
||||||
|
// forgetting that bootstrap outputs even exist in that case.)
|
||||||
|
pub bootstrap_outputs: Vec<&'query DepNode<DefId>>,
|
||||||
|
|
||||||
// For the inputs (hir/foreign-metadata), we include hashes.
|
// For the inputs (hir/foreign-metadata), we include hashes.
|
||||||
pub hashes: FxHashMap<&'query DepNode<DefId>, Fingerprint>,
|
pub hashes: FxHashMap<&'query DepNode<DefId>, Fingerprint>,
|
||||||
}
|
}
|
||||||
@ -57,7 +65,7 @@ impl<'q> Predecessors<'q> {
|
|||||||
|
|
||||||
// Reduce the graph to the most important nodes.
|
// Reduce the graph to the most important nodes.
|
||||||
let compress::Reduction { graph, input_nodes } =
|
let compress::Reduction { graph, input_nodes } =
|
||||||
compress::reduce_graph(&query.graph, HashContext::is_hashable, is_output);
|
compress::reduce_graph(&query.graph, HashContext::is_hashable, |n| is_output(n));
|
||||||
|
|
||||||
let mut hashes = FxHashMap();
|
let mut hashes = FxHashMap();
|
||||||
for input_index in input_nodes {
|
for input_index in input_nodes {
|
||||||
@ -67,8 +75,17 @@ impl<'q> Predecessors<'q> {
|
|||||||
.or_insert_with(|| hcx.hash(input).unwrap());
|
.or_insert_with(|| hcx.hash(input).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let bootstrap_outputs: Vec<&'q DepNode<DefId>> =
|
||||||
|
(0 .. graph.len_nodes())
|
||||||
|
.map(NodeIndex)
|
||||||
|
.filter(|&n| graph.incoming_edges(n).next().is_none())
|
||||||
|
.map(|n| *graph.node_data(n))
|
||||||
|
.filter(|n| is_output(n))
|
||||||
|
.collect();
|
||||||
|
|
||||||
Predecessors {
|
Predecessors {
|
||||||
reduced_graph: graph,
|
reduced_graph: graph,
|
||||||
|
bootstrap_outputs: bootstrap_outputs,
|
||||||
hashes: hashes,
|
hashes: hashes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -204,11 +204,15 @@ pub fn encode_dep_graph(preds: &Predecessors,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create the serialized dep-graph.
|
// Create the serialized dep-graph.
|
||||||
|
let bootstrap_outputs = preds.bootstrap_outputs.iter()
|
||||||
|
.map(|n| builder.map(n))
|
||||||
|
.collect();
|
||||||
let edges = edges.into_iter()
|
let edges = edges.into_iter()
|
||||||
.map(|(k, v)| SerializedEdgeSet { source: k, targets: v })
|
.map(|(k, v)| SerializedEdgeSet { source: k, targets: v })
|
||||||
.collect();
|
.collect();
|
||||||
let graph = SerializedDepGraph {
|
let graph = SerializedDepGraph {
|
||||||
edges: edges,
|
bootstrap_outputs,
|
||||||
|
edges,
|
||||||
hashes: preds.hashes
|
hashes: preds.hashes
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(&dep_node, &hash)| {
|
.map(|(&dep_node, &hash)| {
|
||||||
@ -221,6 +225,7 @@ pub fn encode_dep_graph(preds: &Predecessors,
|
|||||||
};
|
};
|
||||||
|
|
||||||
if tcx.sess.opts.debugging_opts.incremental_info {
|
if tcx.sess.opts.debugging_opts.incremental_info {
|
||||||
|
println!("incremental: {} nodes in reduced dep-graph", preds.reduced_graph.len_nodes());
|
||||||
println!("incremental: {} edges in serialized dep-graph", graph.edges.len());
|
println!("incremental: {} edges in serialized dep-graph", graph.edges.len());
|
||||||
println!("incremental: {} hashes in serialized dep-graph", graph.hashes.len());
|
println!("incremental: {} hashes in serialized dep-graph", graph.hashes.len());
|
||||||
}
|
}
|
||||||
|
18
src/test/incremental/issue-39828/auxiliary/generic.rs
Normal file
18
src/test/incremental/issue-39828/auxiliary/generic.rs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// revisions:rpass1 rpass2
|
||||||
|
// compile-flags: -Z query-dep-graph
|
||||||
|
|
||||||
|
#![rustc_partition_reused(module="__rustc_fallback_codegen_unit", cfg="rpass2")]
|
||||||
|
#![feature(rustc_attrs)]
|
||||||
|
|
||||||
|
#![crate_type="rlib"]
|
||||||
|
pub fn foo<T>() { }
|
22
src/test/incremental/issue-39828/issue-39828.rs
Normal file
22
src/test/incremental/issue-39828/issue-39828.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// Regression test for #39828. If you make use of a module that
|
||||||
|
// consists only of generics, no code is generated, just a dummy
|
||||||
|
// module. The reduced graph consists of a single node (for that
|
||||||
|
// module) with no inputs. Since we only serialize edges, when we
|
||||||
|
// reload, we would consider that node dirty since it is not recreated
|
||||||
|
// (it is not the target of any edges).
|
||||||
|
|
||||||
|
// revisions:rpass1 rpass2
|
||||||
|
// aux-build:generic.rs
|
||||||
|
|
||||||
|
extern crate generic;
|
||||||
|
fn main() { }
|
Loading…
Reference in New Issue
Block a user