Change:
Today, nightly crashed on me when compiling my code: https://travis- I don't know what part of the code () is causing this and I don't know how to search for it. Compilation locally works correctly, with yesterday's or today's nightly. I'm trying that new feature. I managed to get this version info from travis in another job: I guess that travis log contains all the relevant information, but if not, please tell me what you need to know.
most likely the cause is . Can you remove the target directory and rebuild without it?
That seems to have helped… I to the job specification and now it passes. I didn't know travis keeps the directories intact between builds. The new log is https://travis- But I guess that makes it even harder to find out what is wrong.
Thanks for the bug report. This seems to be a problem with our new dependency graph reduction algorithm introduced in
I believe this was fixed -- can you verify?
I couldn't reproduce it reliably, it only crashed from time to time, so I have no way to explicitly verify it's fixed. But I haven't seen it crash for quite some time now, so I'd say it's probably solved.
OK, thanks! :)

Discussion:
// Recreate the edges in the graph that are still clean. let mut clean_work_products = FxHashSet(); let mut dirty_work_products = FxHashSet(); // incomplete; just used to suppress debug output <ins> let mut extra_edges = vec![]; </ins> for (source, targets) in &edge_map { for target in targets { <del> // If the target is dirty, skip the edge. If this is an edge // that targets a work-product, we can print the blame // information now. if let Some(blame) = dirty_raw_nodes.get(target) { if let DepNode::WorkProduct(ref wp) = *target { if tcx.sess.opts.debugging_opts.incremental_info { if dirty_work_products.insert(wp.clone()) { // It'd be nice to pretty-print these paths better than just // using the `Debug` impls, but wev. println!("incremental: module {:?} is dirty because {:?}  changed or was removed", wp, blame.map_def(|&index| { Some(directory.def_path_string(tcx, index)) }).unwrap()); } } } continue; } // If the source is dirty, the target will be dirty. assert!(!dirty_raw_nodes.contains_key(source)); // Retrace the source -> target edges to def-ids and then // create an edge in the graph. Retracing may yield none if // some of the data happens to have been removed; this ought // to be impossible unless it is dirty, so we can unwrap. let source_node = retraced.map(source).unwrap(); let target_node = retraced.map(target).unwrap(); let _task = tcx.dep_graph.in_task(target_node); tcx.dep_graph.read(source_node); if let DepNode::WorkProduct(ref wp) = *target { clean_work_products.insert(wp.clone()); } </del> <ins> process_edges(tcx, source, target, &edge_map, &directory, &retraced, &dirty_raw_nodes, &mut clean_work_products, &mut dirty_work_products, &mut extra_edges); </ins> } } <ins> // 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: // //     Hir(X) -> Foo(Y) -> Bar // // Note that the `Hir(Y)` is not an input to `Foo(Y)` -- this // almost never happens, but can happen in some obscure // scenarios. In that case, if `Y` is removed, then we can't // recreate `Foo(Y)` (the def-id `Y` no longer exists); what we do // then is to push the edge `Hir(X) -> Bar` onto `extra_edges` // (along with any other targets of `Foo(Y)`). We will then add // the edge from `Hir(X)` to `Bar` (or, if `Bar` itself cannot be // recreated, to the targets of `Bar`). while let Some((source, target)) = extra_edges.pop() { process_edges(tcx, source, target, &edge_map, &directory, &retraced, &dirty_raw_nodes, &mut clean_work_products, &mut dirty_work_products, &mut extra_edges); } </ins> // Add in work-products that are still clean, and delete those that are // dirty. reconcile_work_products(tcx, work_products, &clean_work_products);

serialized_hashes.index_map.len()); } <ins> fn process_edges<'a, 'tcx, 'edges>( tcx: TyCtxt<'a, 'tcx, 'tcx>, source: &'edges DepNode<DefPathIndex>, target: &'edges DepNode<DefPathIndex>, edges: &'edges FxHashMap<DepNode<DefPathIndex>, Vec<DepNode<DefPathIndex>>>, directory: &DefIdDirectory, retraced: &RetracedDefIdDirectory, dirty_raw_nodes: &DirtyNodes, clean_work_products: &mut FxHashSet<Arc<WorkProductId>>, dirty_work_products: &mut FxHashSet<Arc<WorkProductId>>, extra_edges: &mut Vec<(&'edges DepNode<DefPathIndex>, &'edges DepNode<DefPathIndex>)>) { // If the target is dirty, skip the edge. If this is an edge // that targets a work-product, we can print the blame // information now. if let Some(blame) = dirty_raw_nodes.get(target) { if let DepNode::WorkProduct(ref wp) = *target { if tcx.sess.opts.debugging_opts.incremental_info { if dirty_work_products.insert(wp.clone()) { // It'd be nice to pretty-print these paths better than just // using the `Debug` impls, but wev. println!("incremental: module {:?} is dirty because {:?}  changed or was removed", wp, blame.map_def(|&index| { Some(directory.def_path_string(tcx, index)) }).unwrap()); } } } return; } // If the source is dirty, the target will be dirty. assert!(!dirty_raw_nodes.contains_key(source)); // Retrace the source -> target edges to def-ids and then create // an edge in the graph. Retracing may yield none if some of the // data happens to have been removed. if let Some(source_node) = retraced.map(source) { if let Some(target_node) = retraced.map(target) { let _task = tcx.dep_graph.in_task(target_node); tcx.dep_graph.read(source_node); if let DepNode::WorkProduct(ref wp) = *target { clean_work_products.insert(wp.clone()); } } else { // As discussed in `decode_dep_graph` above, sometimes the // target cannot be recreated again, in which case we add // edges to go from `source` to the targets of `target`. extra_edges.extend( edges[target].iter().map(|t| (source, t))); } } else { // It's also possible that the source can't be created! But we // can ignore such cases, because (a) if `source` is a HIR // node, it would be considered dirty; and (b) in other cases, // there must be some input to this node that is clean, and so // we'll re-create the edges over in the case where target is // undefined. } } </ins>

<ins> // 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 a weird corner case in our dep-graph reduction // code. When we solve `CoerceUnsized<Foo>`, we find no impls, so we // don't end up with an edge to any HIR nodes, but it still gets // preserved in the dep graph. // revisions:rpass1 rpass2 // compile-flags: -Z query-dep-graph use std::sync::Arc; #[cfg(rpass1)] struct Foo { x: usize } #[cfg(rpass1)] fn main() { let x: Arc<Foo> = Arc::new(Foo { x: 22 }); let y: Arc<Foo> = x; } #[cfg(rpass2)] struct FooX { x: usize } #[cfg(rpass2)] fn main() { let x: Arc<FooX> = Arc::new(FooX { x: 22 }); let y: Arc<FooX> = x; } </ins>