From d15ca96eda708de1c4d2c02bb5014d8e4fe7ca18 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Sat, 6 Feb 2016 04:28:20 +0100 Subject: [PATCH] Split dummy in region inference graph into distinct source and sink nodes. Why do this: The RegionGraph representation previously conflated all of the non-variable regions (i.e. the concrete regions such as lifetime parameters to the current function) into a single dummy node. A single dummy node leads DFS on a graph `'a -> '_#1 -> '_#0 -> 'b` to claim that `'_#1` is reachable from `'_#0` (due to `'a` and `'b` being conflated in the graph representation), which is incorrect (and can lead to soundness bugs later on in compilation, see #30438). Splitting the dummy node ensures that DFS will never introduce new ancestor relationships between nodes for variable regions in the graph. --- src/librustc/middle/infer/region_inference/mod.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/librustc/middle/infer/region_inference/mod.rs b/src/librustc/middle/infer/region_inference/mod.rs index 2c2b69ff85b4e..bfc770d53aaba 100644 --- a/src/librustc/middle/infer/region_inference/mod.rs +++ b/src/librustc/middle/infer/region_inference/mod.rs @@ -1105,7 +1105,14 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { for _ in 0..num_vars { graph.add_node(()); } - let dummy_idx = graph.add_node(()); + + // Issue #30438: two distinct dummy nodes, one for incoming + // edges (dummy_source) and another for outgoing edges + // (dummy_sink). In `dummy -> a -> b -> dummy`, using one + // dummy node leads one to think (erroneously) there exists a + // path from `b` to `a`. Two dummy nodes sidesteps the issue. + let dummy_source = graph.add_node(()); + let dummy_sink = graph.add_node(()); for (constraint, _) in constraints.iter() { match *constraint { @@ -1115,10 +1122,10 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { *constraint); } ConstrainRegSubVar(_, b_id) => { - graph.add_edge(dummy_idx, NodeIndex(b_id.index as usize), *constraint); + graph.add_edge(dummy_source, NodeIndex(b_id.index as usize), *constraint); } ConstrainVarSubReg(a_id, _) => { - graph.add_edge(NodeIndex(a_id.index as usize), dummy_idx, *constraint); + graph.add_edge(NodeIndex(a_id.index as usize), dummy_sink, *constraint); } } }