Fix control flow handling in generator_interior

All tests pass now! The issue was that we weren't handling all edges
correctly, but now they are handled consistently.

This includes code to dump a graphviz file for the CFG we built for drop
tracking.

Also removes old DropRanges tests.
This commit is contained in:
Eric Holk 2021-11-17 17:53:47 -08:00
parent c7afaa1686
commit b39fb9bb7b
5 changed files with 78 additions and 22 deletions

View file

@ -4388,6 +4388,7 @@ dependencies = [
"rustc_attr",
"rustc_data_structures",
"rustc_errors",
"rustc_graphviz",
"rustc_hir",
"rustc_hir_pretty",
"rustc_index",

View file

@ -15,6 +15,7 @@ rustc_middle = { path = "../rustc_middle" }
rustc_attr = { path = "../rustc_attr" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_graphviz = { path = "../rustc_graphviz" }
rustc_hir = { path = "../rustc_hir" }
rustc_hir_pretty = { path = "../rustc_hir_pretty" }
rustc_target = { path = "../rustc_target" }

View file

@ -26,9 +26,6 @@ use rustc_span::Span;
use smallvec::SmallVec;
use tracing::debug;
#[cfg(test)]
mod tests;
mod drop_ranges;
struct InteriorVisitor<'a, 'tcx> {
@ -255,6 +252,7 @@ pub fn resolve_interior<'a, 'tcx>(
intravisit::walk_body(&mut drop_range_visitor, body);
drop_range_visitor.drop_ranges.propagate_to_fixpoint();
// drop_range_visitor.drop_ranges.save_graph("drop_ranges.dot");
InteriorVisitor {
fcx,
@ -877,18 +875,18 @@ impl<'tcx> Visitor<'tcx> for DropRangeVisitor<'tcx> {
reinit = Some(lhs);
}
ExprKind::Loop(body, ..) => {
let loop_begin = self.expr_count;
let loop_begin = self.expr_count + 1;
self.visit_block(body);
self.drop_ranges.add_control_edge(self.expr_count, loop_begin);
}
ExprKind::Match(scrutinee, arms, ..) => {
self.visit_expr(scrutinee);
let fork = self.expr_count - 1;
let fork = self.expr_count;
let arm_end_ids = arms
.iter()
.map(|Arm { pat, body, guard, .. }| {
self.drop_ranges.add_control_edge(fork, self.expr_count);
self.drop_ranges.add_control_edge(fork, self.expr_count + 1);
self.visit_pat(pat);
match guard {
Some(Guard::If(expr)) => self.visit_expr(expr),
@ -914,8 +912,8 @@ impl<'tcx> Visitor<'tcx> for DropRangeVisitor<'tcx> {
_ => intravisit::walk_expr(self, expr),
}
self.drop_ranges.add_node_mapping(expr.hir_id, self.expr_count);
self.expr_count += 1;
self.drop_ranges.add_node_mapping(expr.hir_id, self.expr_count);
self.consume_expr(expr);
if let Some(expr) = reinit {
self.reinit_expr(expr);

View file

@ -2,6 +2,7 @@ use std::collections::BTreeMap;
use std::fmt::Debug;
use std::mem::swap;
use rustc_graphviz as dot;
use rustc_hir::{HirId, HirIdMap};
use rustc_index::bit_set::BitSet;
use rustc_index::vec::IndexVec;
@ -182,7 +183,9 @@ impl DropRanges {
changed
};
while propagate() {}
while propagate() {
trace!("drop_state changed, re-running propagation");
}
trace!("after fixpoint: {:#?}", self);
}
@ -200,6 +203,73 @@ impl DropRanges {
}
preds
}
// pub fn save_graph(&self, filename: &str) {
// use std::fs::File;
// dot::render(self, &mut File::create(filename).unwrap()).unwrap();
// }
}
impl<'a> dot::GraphWalk<'a> for DropRanges {
type Node = PostOrderId;
type Edge = (PostOrderId, PostOrderId);
fn nodes(&'a self) -> dot::Nodes<'a, Self::Node> {
self.nodes.iter_enumerated().map(|(i, _)| i).collect()
}
fn edges(&'a self) -> dot::Edges<'a, Self::Edge> {
self.nodes
.iter_enumerated()
.flat_map(|(i, node)| {
if node.successors.len() == 0 {
vec![(i, PostOrderId::from_usize(i.index() + 1))]
} else {
node.successors.iter().map(move |&s| (i, s)).collect()
}
})
.collect()
}
fn source(&'a self, edge: &Self::Edge) -> Self::Node {
edge.0
}
fn target(&'a self, edge: &Self::Edge) -> Self::Node {
edge.1
}
}
impl<'a> dot::Labeller<'a> for DropRanges {
type Node = PostOrderId;
type Edge = (PostOrderId, PostOrderId);
fn graph_id(&'a self) -> dot::Id<'a> {
dot::Id::new("drop_ranges").unwrap()
}
fn node_id(&'a self, n: &Self::Node) -> dot::Id<'a> {
dot::Id::new(format!("id{}", n.index())).unwrap()
}
fn node_label(&'a self, n: &Self::Node) -> dot::LabelText<'a> {
dot::LabelText::LabelStr(
format!(
"{:?}, local_id: {}",
n,
self.post_order_map
.iter()
.find(|(_hir_id, &post_order_id)| post_order_id == n.index())
.map_or("<unknown>".into(), |(hir_id, _)| format!(
"{}",
hir_id.local_id.index()
))
)
.into(),
)
}
}
#[derive(Debug)]

View file

@ -1,14 +0,0 @@
use super::DropRange;
#[test]
fn drop_range_uses_last_event() {
let mut range = DropRange::empty();
range.drop(10);
range.reinit(10);
assert!(!range.is_dropped_at(10));
let mut range = DropRange::empty();
range.reinit(10);
range.drop(10);
assert!(range.is_dropped_at(10));
}