From a2fbe4d09a37f89285a0b0de41d3c076ecf298b8 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 10 Jul 2013 10:04:02 -0400 Subject: [PATCH] Construct the graph only when it is needed to report errors. --- .../typeck/infer/region_inference/mod.rs | 112 +++++++++--------- 1 file changed, 57 insertions(+), 55 deletions(-) diff --git a/src/librustc/middle/typeck/infer/region_inference/mod.rs b/src/librustc/middle/typeck/infer/region_inference/mod.rs index c41ce40a9958..c3b35aba5181 100644 --- a/src/librustc/middle/typeck/infer/region_inference/mod.rs +++ b/src/librustc/middle/typeck/infer/region_inference/mod.rs @@ -722,63 +722,21 @@ struct RegionAndOrigin { origin: SubregionOrigin, } -type Graph = graph::Graph<(), Constraint>; -type GraphNode = graph::Node<()>; -type GraphEdge = graph::Edge; +type RegionGraph = graph::Graph<(), Constraint>; impl RegionVarBindings { - fn infer_variable_values(&mut self, + fn infer_variable_values(&self, errors: &mut OptVec) -> ~[VarValue] { let mut var_data = self.construct_var_data(); self.expansion(var_data); self.contraction(var_data); - let graph = self.construct_graph(); - self.collect_concrete_region_errors(&graph, errors); - self.extract_values_and_collect_conflicts(&graph, var_data, errors) + self.collect_concrete_region_errors(errors); + self.extract_values_and_collect_conflicts(var_data, errors) } - fn construct_graph(&mut self) -> Graph { - let num_vars = self.num_vars(); - let num_edges = self.constraints.len(); - - let mut graph = graph::Graph::with_capacity(num_vars + 1, - num_edges); - - for uint::range(0, num_vars) |var_idx| { - graph.add_node(()); - } - let dummy_idx = graph.add_node(()); - - for self.constraints.iter().advance |(constraint, _)| { - match *constraint { - ConstrainVarSubVar(a_id, b_id) => { - graph.add_edge(NodeIndex(a_id.to_uint()), - NodeIndex(b_id.to_uint()), - *constraint); - } - ConstrainRegSubVar(_, b_id) => { - graph.add_edge(dummy_idx, - NodeIndex(b_id.to_uint()), - *constraint); - } - ConstrainVarSubReg(a_id, _) => { - graph.add_edge(NodeIndex(a_id.to_uint()), - dummy_idx, - *constraint); - } - ConstrainRegSubReg(*) => { - // Relations between two concrete regions do not - // require an edge in the graph. - } - } - } - - return graph; - } - - fn construct_var_data(&mut self) -> ~[VarData] { - vec::from_fn(self.num_vars(), |var_idx| { + fn construct_var_data(&self) -> ~[VarData] { + vec::from_fn(self.num_vars(), |_| { VarData { // All nodes are initially classified as contracting; during // the expansion phase, we will shift the classification for @@ -790,7 +748,7 @@ impl RegionVarBindings { }) } - fn expansion(&mut self, var_data: &mut [VarData]) { + fn expansion(&self, var_data: &mut [VarData]) { do self.iterate_until_fixed_point("Expansion") |constraint| { match *constraint { ConstrainRegSubVar(a_region, b_vid) => { @@ -957,7 +915,6 @@ impl RegionVarBindings { fn collect_concrete_region_errors( &self, - graph: &Graph, errors: &mut OptVec) { for self.constraints.iter().advance |(constraint, _)| { @@ -985,7 +942,6 @@ impl RegionVarBindings { fn extract_values_and_collect_conflicts( &self, - graph: &Graph, var_data: &[VarData], errors: &mut OptVec) -> ~[VarValue] @@ -1005,6 +961,8 @@ impl RegionVarBindings { // overlapping locations. let mut dup_vec = vec::from_elem(self.num_vars(), uint::max_value); + let mut opt_graph = None; + for uint::range(0, self.num_vars()) |idx| { match var_data[idx].value { Value(_) => { @@ -1040,6 +998,11 @@ impl RegionVarBindings { starts to create problems we'll have to revisit this portion of the code and think hard about it. =) */ + if opt_graph.is_none() { + opt_graph = Some(self.construct_graph()); + } + let graph = opt_graph.get_ref(); + let node_vid = RegionVid { id: idx }; match var_data[idx].classification { Expanding => { @@ -1058,9 +1021,48 @@ impl RegionVarBindings { vec::from_fn(self.num_vars(), |idx| var_data[idx].value) } + fn construct_graph(&self) -> RegionGraph { + let num_vars = self.num_vars(); + let num_edges = self.constraints.len(); + + let mut graph = graph::Graph::with_capacity(num_vars + 1, + num_edges); + + for uint::range(0, num_vars) |_| { + graph.add_node(()); + } + let dummy_idx = graph.add_node(()); + + for self.constraints.iter().advance |(constraint, _)| { + match *constraint { + ConstrainVarSubVar(a_id, b_id) => { + graph.add_edge(NodeIndex(a_id.to_uint()), + NodeIndex(b_id.to_uint()), + *constraint); + } + ConstrainRegSubVar(_, b_id) => { + graph.add_edge(dummy_idx, + NodeIndex(b_id.to_uint()), + *constraint); + } + ConstrainVarSubReg(a_id, _) => { + graph.add_edge(NodeIndex(a_id.to_uint()), + dummy_idx, + *constraint); + } + ConstrainRegSubReg(*) => { + // Relations between two concrete regions do not + // require an edge in the graph. + } + } + } + + return graph; + } + fn collect_error_for_expanding_node( &self, - graph: &Graph, + graph: &RegionGraph, var_data: &[VarData], dup_vec: &mut [uint], node_idx: RegionVid, @@ -1105,7 +1107,7 @@ impl RegionVarBindings { fn collect_error_for_contracting_node( &self, - graph: &Graph, + graph: &RegionGraph, var_data: &[VarData], dup_vec: &mut [uint], node_idx: RegionVid, @@ -1148,7 +1150,7 @@ impl RegionVarBindings { } fn collect_concrete_regions(&self, - graph: &Graph, + graph: &RegionGraph, var_data: &[VarData], orig_node_idx: RegionVid, dir: Direction, @@ -1202,7 +1204,7 @@ impl RegionVarBindings { fn process_edges(this: &RegionVarBindings, state: &mut WalkState, - graph: &Graph, + graph: &RegionGraph, source_vid: RegionVid, dir: Direction) { debug!("process_edges(source_vid=%?, dir=%?)", source_vid, dir);