Code change:
// 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);

Related discussion:
text: 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! :)