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.
This commit is contained in:
parent
e06f6928cb
commit
8801bdb6b0
@ -1105,7 +1105,14 @@ fn construct_graph(&self) -> RegionGraph {
|
||||
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 @@ fn construct_graph(&self) -> RegionGraph {
|
||||
*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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user