Port region inference code to use new graph
This commit is contained in:
parent
7429e7a114
commit
e706590e70
@ -18,6 +18,8 @@ use middle::ty::{re_scope, ReVar, ReSkolemized, br_fresh};
|
||||
use middle::typeck::infer::cres;
|
||||
use middle::typeck::infer::{RegionVariableOrigin, SubregionOrigin};
|
||||
use middle::typeck::infer;
|
||||
use middle::graph;
|
||||
use middle::graph::{Direction, NodeIndex};
|
||||
use util::common::indenter;
|
||||
use util::ppaux::{Repr};
|
||||
|
||||
@ -105,7 +107,7 @@ pub struct RegionVarBindings {
|
||||
// This contains the results of inference. It begins as an empty
|
||||
// cell and only acquires a value after inference is complete.
|
||||
// We use a cell vs a mutable option to circumvent borrowck errors.
|
||||
values: Cell<~[GraphNodeValue]>,
|
||||
values: Cell<~[VarValue]>,
|
||||
}
|
||||
|
||||
pub fn RegionVarBindings(tcx: ty::ctxt) -> RegionVarBindings {
|
||||
@ -168,7 +170,7 @@ impl RegionVarBindings {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn num_vars(&mut self) -> uint {
|
||||
pub fn num_vars(&self) -> uint {
|
||||
self.var_origins.len()
|
||||
}
|
||||
|
||||
@ -705,29 +707,14 @@ impl RegionVarBindings {
|
||||
|
||||
// ______________________________________________________________________
|
||||
|
||||
#[deriving(Eq)]
|
||||
enum Direction { Incoming = 0, Outgoing = 1 }
|
||||
|
||||
#[deriving(Eq)]
|
||||
enum Classification { Expanding, Contracting }
|
||||
|
||||
enum GraphNodeValue { NoValue, Value(Region), ErrorValue }
|
||||
enum VarValue { NoValue, Value(Region), ErrorValue }
|
||||
|
||||
struct GraphNode {
|
||||
origin: RegionVariableOrigin,
|
||||
struct VarData {
|
||||
classification: Classification,
|
||||
value: GraphNodeValue,
|
||||
head_edge: [uint, ..2],
|
||||
}
|
||||
|
||||
struct GraphEdge {
|
||||
next_edge: [uint, ..2],
|
||||
constraint: Constraint,
|
||||
}
|
||||
|
||||
struct Graph {
|
||||
nodes: ~[GraphNode],
|
||||
edges: ~[GraphEdge],
|
||||
value: VarValue,
|
||||
}
|
||||
|
||||
struct RegionAndOrigin {
|
||||
@ -735,97 +722,86 @@ struct RegionAndOrigin {
|
||||
origin: SubregionOrigin,
|
||||
}
|
||||
|
||||
type Graph = graph::Graph<(), Constraint>;
|
||||
type GraphNode = graph::Node<()>;
|
||||
type GraphEdge = graph::Edge<Constraint>;
|
||||
|
||||
impl RegionVarBindings {
|
||||
fn infer_variable_values(&mut self,
|
||||
errors: &mut OptVec<RegionResolutionError>)
|
||||
-> ~[GraphNodeValue] {
|
||||
let mut graph = self.construct_graph();
|
||||
self.expansion(&mut graph);
|
||||
self.contraction(&mut graph);
|
||||
-> ~[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, errors)
|
||||
self.extract_values_and_collect_conflicts(&graph, var_data, errors)
|
||||
}
|
||||
|
||||
fn construct_graph(&mut self) -> Graph {
|
||||
let num_vars = self.num_vars();
|
||||
let num_edges = self.constraints.len();
|
||||
|
||||
let nodes = vec::from_fn(num_vars, |var_idx| {
|
||||
GraphNode {
|
||||
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| {
|
||||
VarData {
|
||||
// All nodes are initially classified as contracting; during
|
||||
// the expansion phase, we will shift the classification for
|
||||
// those nodes that have a concrete region predecessor to
|
||||
// Expanding.
|
||||
classification: Contracting,
|
||||
origin: self.var_origins[var_idx],
|
||||
value: NoValue,
|
||||
head_edge: [uint::max_value, uint::max_value]
|
||||
}
|
||||
});
|
||||
|
||||
// It would be nice to write this using map():
|
||||
let mut edges = vec::with_capacity(num_edges);
|
||||
for self.constraints.iter().advance |(constraint, _)| {
|
||||
edges.push(GraphEdge {
|
||||
next_edge: [uint::max_value, uint::max_value],
|
||||
constraint: *constraint,
|
||||
});
|
||||
}
|
||||
|
||||
let mut graph = Graph {
|
||||
nodes: nodes,
|
||||
edges: edges
|
||||
};
|
||||
|
||||
for uint::range(0, num_edges) |edge_idx| {
|
||||
match graph.edges[edge_idx].constraint {
|
||||
ConstrainVarSubVar(a_id, b_id) => {
|
||||
insert_edge(&mut graph, a_id, Outgoing, edge_idx);
|
||||
insert_edge(&mut graph, b_id, Incoming, edge_idx);
|
||||
}
|
||||
ConstrainRegSubVar(_, b_id) => {
|
||||
insert_edge(&mut graph, b_id, Incoming, edge_idx);
|
||||
}
|
||||
ConstrainVarSubReg(a_id, _) => {
|
||||
insert_edge(&mut graph, a_id, Outgoing, edge_idx);
|
||||
}
|
||||
ConstrainRegSubReg(*) => {
|
||||
// Relations between two concrete regions do not
|
||||
// require an edge in the graph.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (graph);
|
||||
|
||||
fn insert_edge(graph: &mut Graph,
|
||||
node_id: RegionVid,
|
||||
edge_dir: Direction,
|
||||
edge_idx: uint) {
|
||||
//! Insert edge `edge_idx` on the link list of edges in direction
|
||||
//! `edge_dir` for the node `node_id`
|
||||
let edge_dir = edge_dir as uint;
|
||||
assert_eq!(graph.edges[edge_idx].next_edge[edge_dir],
|
||||
uint::max_value);
|
||||
let n = node_id.to_uint();
|
||||
let prev_head = graph.nodes[n].head_edge[edge_dir];
|
||||
graph.edges[edge_idx].next_edge[edge_dir] = prev_head;
|
||||
graph.nodes[n].head_edge[edge_dir] = edge_idx;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn expansion(&mut self, graph: &mut Graph) {
|
||||
do iterate_until_fixed_point(~"Expansion", graph) |nodes, edge| {
|
||||
match edge.constraint {
|
||||
fn expansion(&mut self, var_data: &mut [VarData]) {
|
||||
do self.iterate_until_fixed_point("Expansion") |constraint| {
|
||||
match *constraint {
|
||||
ConstrainRegSubVar(a_region, b_vid) => {
|
||||
let b_node = &mut nodes[b_vid.to_uint()];
|
||||
self.expand_node(a_region, b_vid, b_node)
|
||||
let b_data = &mut var_data[b_vid.to_uint()];
|
||||
self.expand_node(a_region, b_vid, b_data)
|
||||
}
|
||||
ConstrainVarSubVar(a_vid, b_vid) => {
|
||||
match nodes[a_vid.to_uint()].value {
|
||||
match var_data[a_vid.to_uint()].value {
|
||||
NoValue | ErrorValue => false,
|
||||
Value(a_region) => {
|
||||
let b_node = &mut nodes[b_vid.to_uint()];
|
||||
let b_node = &mut var_data[b_vid.to_uint()];
|
||||
self.expand_node(a_region, b_vid, b_node)
|
||||
}
|
||||
}
|
||||
@ -842,20 +818,20 @@ impl RegionVarBindings {
|
||||
}
|
||||
}
|
||||
|
||||
fn expand_node(&mut self,
|
||||
fn expand_node(&self,
|
||||
a_region: Region,
|
||||
b_vid: RegionVid,
|
||||
b_node: &mut GraphNode)
|
||||
b_data: &mut VarData)
|
||||
-> bool {
|
||||
debug!("expand_node(%?, %? == %?)",
|
||||
a_region, b_vid, b_node.value);
|
||||
a_region, b_vid, b_data.value);
|
||||
|
||||
b_node.classification = Expanding;
|
||||
match b_node.value {
|
||||
b_data.classification = Expanding;
|
||||
match b_data.value {
|
||||
NoValue => {
|
||||
debug!("Setting initial value of %? to %?", b_vid, a_region);
|
||||
|
||||
b_node.value = Value(a_region);
|
||||
b_data.value = Value(a_region);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -868,7 +844,7 @@ impl RegionVarBindings {
|
||||
debug!("Expanding value of %? from %? to %?",
|
||||
b_vid, cur_region, lub);
|
||||
|
||||
b_node.value = Value(lub);
|
||||
b_data.value = Value(lub);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -878,26 +854,26 @@ impl RegionVarBindings {
|
||||
}
|
||||
}
|
||||
|
||||
fn contraction(&mut self,
|
||||
graph: &mut Graph) {
|
||||
do iterate_until_fixed_point(~"Contraction", graph) |nodes, edge| {
|
||||
match edge.constraint {
|
||||
fn contraction(&self,
|
||||
var_data: &mut [VarData]) {
|
||||
do self.iterate_until_fixed_point("Contraction") |constraint| {
|
||||
match *constraint {
|
||||
ConstrainRegSubVar(*) => {
|
||||
// This is an expansion constraint. Ignore.
|
||||
false
|
||||
}
|
||||
ConstrainVarSubVar(a_vid, b_vid) => {
|
||||
match nodes[b_vid.to_uint()].value {
|
||||
match var_data[b_vid.to_uint()].value {
|
||||
NoValue | ErrorValue => false,
|
||||
Value(b_region) => {
|
||||
let a_node = &mut nodes[a_vid.to_uint()];
|
||||
self.contract_node(a_vid, a_node, b_region)
|
||||
let a_data = &mut var_data[a_vid.to_uint()];
|
||||
self.contract_node(a_vid, a_data, b_region)
|
||||
}
|
||||
}
|
||||
}
|
||||
ConstrainVarSubReg(a_vid, b_region) => {
|
||||
let a_node = &mut nodes[a_vid.to_uint()];
|
||||
self.contract_node(a_vid, a_node, b_region)
|
||||
let a_data = &mut var_data[a_vid.to_uint()];
|
||||
self.contract_node(a_vid, a_data, b_region)
|
||||
}
|
||||
ConstrainRegSubReg(*) => {
|
||||
// No region variables involved. Ignore.
|
||||
@ -907,18 +883,18 @@ impl RegionVarBindings {
|
||||
}
|
||||
}
|
||||
|
||||
fn contract_node(&mut self,
|
||||
fn contract_node(&self,
|
||||
a_vid: RegionVid,
|
||||
a_node: &mut GraphNode,
|
||||
a_data: &mut VarData,
|
||||
b_region: Region)
|
||||
-> bool {
|
||||
debug!("contract_node(%? == %?/%?, %?)",
|
||||
a_vid, a_node.value, a_node.classification, b_region);
|
||||
a_vid, a_data.value, a_data.classification, b_region);
|
||||
|
||||
return match a_node.value {
|
||||
return match a_data.value {
|
||||
NoValue => {
|
||||
assert_eq!(a_node.classification, Contracting);
|
||||
a_node.value = Value(b_region);
|
||||
assert_eq!(a_data.classification, Contracting);
|
||||
a_data.value = Value(b_region);
|
||||
true // changed
|
||||
}
|
||||
|
||||
@ -927,34 +903,34 @@ impl RegionVarBindings {
|
||||
}
|
||||
|
||||
Value(a_region) => {
|
||||
match a_node.classification {
|
||||
match a_data.classification {
|
||||
Expanding => {
|
||||
check_node(self, a_vid, a_node, a_region, b_region)
|
||||
check_node(self, a_vid, a_data, a_region, b_region)
|
||||
}
|
||||
Contracting => {
|
||||
adjust_node(self, a_vid, a_node, a_region, b_region)
|
||||
adjust_node(self, a_vid, a_data, a_region, b_region)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fn check_node(this: &mut RegionVarBindings,
|
||||
fn check_node(this: &RegionVarBindings,
|
||||
a_vid: RegionVid,
|
||||
a_node: &mut GraphNode,
|
||||
a_data: &mut VarData,
|
||||
a_region: Region,
|
||||
b_region: Region)
|
||||
-> bool {
|
||||
if !this.is_subregion_of(a_region, b_region) {
|
||||
debug!("Setting %? to ErrorValue: %? not subregion of %?",
|
||||
a_vid, a_region, b_region);
|
||||
a_node.value = ErrorValue;
|
||||
a_data.value = ErrorValue;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn adjust_node(this: &mut RegionVarBindings,
|
||||
fn adjust_node(this: &RegionVarBindings,
|
||||
a_vid: RegionVid,
|
||||
a_node: &mut GraphNode,
|
||||
a_data: &mut VarData,
|
||||
a_region: Region,
|
||||
b_region: Region)
|
||||
-> bool {
|
||||
@ -965,14 +941,14 @@ impl RegionVarBindings {
|
||||
} else {
|
||||
debug!("Contracting value of %? from %? to %?",
|
||||
a_vid, a_region, glb);
|
||||
a_node.value = Value(glb);
|
||||
a_data.value = Value(glb);
|
||||
true
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
debug!("Setting %? to ErrorValue: no glb of %?, %?",
|
||||
a_vid, a_region, b_region);
|
||||
a_node.value = ErrorValue;
|
||||
a_data.value = ErrorValue;
|
||||
false
|
||||
}
|
||||
}
|
||||
@ -980,16 +956,12 @@ impl RegionVarBindings {
|
||||
}
|
||||
|
||||
fn collect_concrete_region_errors(
|
||||
&mut self,
|
||||
&self,
|
||||
graph: &Graph,
|
||||
errors: &mut OptVec<RegionResolutionError>)
|
||||
{
|
||||
let num_edges = graph.edges.len();
|
||||
for uint::range(0, num_edges) |edge_idx| {
|
||||
let edge = &graph.edges[edge_idx];
|
||||
let origin = self.constraints.get_copy(&edge.constraint);
|
||||
|
||||
let (sub, sup) = match edge.constraint {
|
||||
for self.constraints.iter().advance |(constraint, _)| {
|
||||
let (sub, sup) = match *constraint {
|
||||
ConstrainVarSubVar(*) |
|
||||
ConstrainRegSubVar(*) |
|
||||
ConstrainVarSubReg(*) => {
|
||||
@ -1006,15 +978,17 @@ impl RegionVarBindings {
|
||||
|
||||
debug!("ConcreteFailure: !(sub <= sup): sub=%?, sup=%?",
|
||||
sub, sup);
|
||||
let origin = self.constraints.get_copy(constraint);
|
||||
errors.push(ConcreteFailure(origin, sub, sup));
|
||||
}
|
||||
}
|
||||
|
||||
fn extract_values_and_collect_conflicts(
|
||||
&mut self,
|
||||
&self,
|
||||
graph: &Graph,
|
||||
var_data: &[VarData],
|
||||
errors: &mut OptVec<RegionResolutionError>)
|
||||
-> ~[GraphNodeValue]
|
||||
-> ~[VarValue]
|
||||
{
|
||||
debug!("extract_values_and_collect_conflicts()");
|
||||
|
||||
@ -1029,10 +1003,10 @@ impl RegionVarBindings {
|
||||
// idea is to report errors that derive from independent
|
||||
// regions of the graph, but not those that derive from
|
||||
// overlapping locations.
|
||||
let mut dup_vec = graph.nodes.map(|_| uint::max_value);
|
||||
let mut dup_vec = vec::from_elem(self.num_vars(), uint::max_value);
|
||||
|
||||
graph.nodes.iter().enumerate().transform(|(idx, node)| {
|
||||
match node.value {
|
||||
for uint::range(0, self.num_vars()) |idx| {
|
||||
match var_data[idx].value {
|
||||
Value(_) => {
|
||||
/* Inference successful */
|
||||
}
|
||||
@ -1067,26 +1041,27 @@ impl RegionVarBindings {
|
||||
this portion of the code and think hard about it. =) */
|
||||
|
||||
let node_vid = RegionVid { id: idx };
|
||||
match node.classification {
|
||||
match var_data[idx].classification {
|
||||
Expanding => {
|
||||
self.collect_error_for_expanding_node(
|
||||
graph, dup_vec, node_vid, errors);
|
||||
graph, var_data, dup_vec, node_vid, errors);
|
||||
}
|
||||
Contracting => {
|
||||
self.collect_error_for_contracting_node(
|
||||
graph, dup_vec, node_vid, errors);
|
||||
graph, var_data, dup_vec, node_vid, errors);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
node.value
|
||||
}).collect()
|
||||
vec::from_fn(self.num_vars(), |idx| var_data[idx].value)
|
||||
}
|
||||
|
||||
fn collect_error_for_expanding_node(
|
||||
&mut self,
|
||||
&self,
|
||||
graph: &Graph,
|
||||
var_data: &[VarData],
|
||||
dup_vec: &mut [uint],
|
||||
node_idx: RegionVid,
|
||||
errors: &mut OptVec<RegionResolutionError>)
|
||||
@ -1094,9 +1069,11 @@ impl RegionVarBindings {
|
||||
// Errors in expanding nodes result from a lower-bound that is
|
||||
// not contained by an upper-bound.
|
||||
let (lower_bounds, lower_dup) =
|
||||
self.collect_concrete_regions(graph, node_idx, Incoming, dup_vec);
|
||||
self.collect_concrete_regions(graph, var_data, node_idx,
|
||||
graph::Incoming, dup_vec);
|
||||
let (upper_bounds, upper_dup) =
|
||||
self.collect_concrete_regions(graph, node_idx, Outgoing, dup_vec);
|
||||
self.collect_concrete_regions(graph, var_data, node_idx,
|
||||
graph::Outgoing, dup_vec);
|
||||
|
||||
if lower_dup || upper_dup {
|
||||
return;
|
||||
@ -1127,8 +1104,9 @@ impl RegionVarBindings {
|
||||
}
|
||||
|
||||
fn collect_error_for_contracting_node(
|
||||
&mut self,
|
||||
&self,
|
||||
graph: &Graph,
|
||||
var_data: &[VarData],
|
||||
dup_vec: &mut [uint],
|
||||
node_idx: RegionVid,
|
||||
errors: &mut OptVec<RegionResolutionError>)
|
||||
@ -1136,7 +1114,8 @@ impl RegionVarBindings {
|
||||
// Errors in contracting nodes result from two upper-bounds
|
||||
// that have no intersection.
|
||||
let (upper_bounds, dup_found) =
|
||||
self.collect_concrete_regions(graph, node_idx, Outgoing, dup_vec);
|
||||
self.collect_concrete_regions(graph, var_data, node_idx,
|
||||
graph::Outgoing, dup_vec);
|
||||
|
||||
if dup_found {
|
||||
return;
|
||||
@ -1168,8 +1147,9 @@ impl RegionVarBindings {
|
||||
upper_bounds.map(|x| x.region).repr(self.tcx)));
|
||||
}
|
||||
|
||||
fn collect_concrete_regions(&mut self,
|
||||
fn collect_concrete_regions(&self,
|
||||
graph: &Graph,
|
||||
var_data: &[VarData],
|
||||
orig_node_idx: RegionVid,
|
||||
dir: Direction,
|
||||
dup_vec: &mut [uint])
|
||||
@ -1194,7 +1174,7 @@ impl RegionVarBindings {
|
||||
|
||||
while !state.stack.is_empty() {
|
||||
let node_idx = state.stack.pop();
|
||||
let classification = graph.nodes[node_idx.to_uint()].classification;
|
||||
let classification = var_data[node_idx.to_uint()].classification;
|
||||
|
||||
// check whether we've visited this node on some previous walk
|
||||
if dup_vec[node_idx.to_uint()] == uint::max_value {
|
||||
@ -1210,8 +1190,8 @@ impl RegionVarBindings {
|
||||
// figure out the direction from which this node takes its
|
||||
// values, and search for concrete regions etc in that direction
|
||||
let dir = match classification {
|
||||
Expanding => Incoming,
|
||||
Contracting => Outgoing
|
||||
Expanding => graph::Incoming,
|
||||
Contracting => graph::Outgoing,
|
||||
};
|
||||
|
||||
process_edges(self, &mut state, graph, node_idx, dir);
|
||||
@ -1220,15 +1200,16 @@ impl RegionVarBindings {
|
||||
let WalkState {result, dup_found, _} = state;
|
||||
return (result, dup_found);
|
||||
|
||||
fn process_edges(this: &mut RegionVarBindings,
|
||||
fn process_edges(this: &RegionVarBindings,
|
||||
state: &mut WalkState,
|
||||
graph: &Graph,
|
||||
source_vid: RegionVid,
|
||||
dir: Direction) {
|
||||
debug!("process_edges(source_vid=%?, dir=%?)", source_vid, dir);
|
||||
|
||||
for this.each_edge(graph, source_vid, dir) |edge| {
|
||||
match edge.constraint {
|
||||
let source_node_index = NodeIndex(source_vid.to_uint());
|
||||
for graph.each_adjacent_edge(source_node_index, dir) |_, edge| {
|
||||
match edge.data {
|
||||
ConstrainVarSubVar(from_vid, to_vid) => {
|
||||
let opp_vid =
|
||||
if from_vid == source_vid {to_vid} else {from_vid};
|
||||
@ -1241,7 +1222,7 @@ impl RegionVarBindings {
|
||||
ConstrainVarSubReg(_, region) => {
|
||||
state.result.push(RegionAndOrigin {
|
||||
region: region,
|
||||
origin: this.constraints.get_copy(&edge.constraint)
|
||||
origin: this.constraints.get_copy(&edge.data)
|
||||
});
|
||||
}
|
||||
|
||||
@ -1251,42 +1232,40 @@ impl RegionVarBindings {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn each_edge(&self,
|
||||
graph: &Graph,
|
||||
node_idx: RegionVid,
|
||||
dir: Direction,
|
||||
op: &fn(edge: &GraphEdge) -> bool)
|
||||
-> bool {
|
||||
let mut edge_idx =
|
||||
graph.nodes[node_idx.to_uint()].head_edge[dir as uint];
|
||||
while edge_idx != uint::max_value {
|
||||
let edge_ptr = &graph.edges[edge_idx];
|
||||
if !op(edge_ptr) {
|
||||
return false;
|
||||
fn iterate_until_fixed_point(&self,
|
||||
tag: &str,
|
||||
body: &fn(constraint: &Constraint) -> bool) {
|
||||
let mut iteration = 0;
|
||||
let mut changed = true;
|
||||
while changed {
|
||||
changed = false;
|
||||
iteration += 1;
|
||||
debug!("---- %s Iteration #%u", tag, iteration);
|
||||
for self.constraints.iter().advance |(constraint, _)| {
|
||||
let edge_changed = body(constraint);
|
||||
if edge_changed {
|
||||
debug!("Updated due to constraint %s",
|
||||
constraint.repr(self.tcx));
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
edge_idx = edge_ptr.next_edge[dir as uint];
|
||||
}
|
||||
return true;
|
||||
debug!("---- %s Complete after %u iteration(s)", tag, iteration);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn iterate_until_fixed_point(
|
||||
tag: ~str,
|
||||
graph: &mut Graph,
|
||||
body: &fn(nodes: &mut [GraphNode], edge: &GraphEdge) -> bool)
|
||||
{
|
||||
let mut iteration = 0;
|
||||
let mut changed = true;
|
||||
let num_edges = graph.edges.len();
|
||||
while changed {
|
||||
changed = false;
|
||||
iteration += 1;
|
||||
debug!("---- %s Iteration #%u", tag, iteration);
|
||||
for uint::range(0, num_edges) |edge_idx| {
|
||||
changed |= body(graph.nodes, &graph.edges[edge_idx]);
|
||||
debug!(" >> Change after edge #%?: %?",
|
||||
edge_idx, graph.edges[edge_idx]);
|
||||
impl Repr for Constraint {
|
||||
fn repr(&self, tcx: ty::ctxt) -> ~str {
|
||||
match *self {
|
||||
ConstrainVarSubVar(a, b) => fmt!("ConstrainVarSubVar(%s, %s)",
|
||||
a.repr(tcx), b.repr(tcx)),
|
||||
ConstrainRegSubVar(a, b) => fmt!("ConstrainRegSubVar(%s, %s)",
|
||||
a.repr(tcx), b.repr(tcx)),
|
||||
ConstrainVarSubReg(a, b) => fmt!("ConstrainVarSubReg(%s, %s)",
|
||||
a.repr(tcx), b.repr(tcx)),
|
||||
ConstrainRegSubReg(a, b) => fmt!("ConstrainRegSubReg(%s, %s)",
|
||||
a.repr(tcx), b.repr(tcx)),
|
||||
}
|
||||
}
|
||||
debug!("---- %s Complete after %u iteration(s)", tag, iteration);
|
||||
}
|
||||
|
@ -751,6 +751,12 @@ impl Repr for typeck::method_param {
|
||||
}
|
||||
}
|
||||
|
||||
impl Repr for ty::RegionVid {
|
||||
fn repr(&self, tcx: ctxt) -> ~str {
|
||||
fmt!("%?", *self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Repr for ty::TraitStore {
|
||||
fn repr(&self, tcx: ctxt) -> ~str {
|
||||
match self {
|
||||
|
Loading…
x
Reference in New Issue
Block a user