Handle reinits in match guards
This commit is contained in:
parent
2af02cf2c4
commit
4a70de7932
@ -133,11 +133,10 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
|
||||
ExprKind::Match(scrutinee, arms, ..) => {
|
||||
self.visit_expr(scrutinee);
|
||||
|
||||
let fork = self.expr_index;
|
||||
let arm_end_ids = arms
|
||||
.iter()
|
||||
.map(|hir::Arm { pat, body, guard, .. }| {
|
||||
self.drop_ranges.add_control_edge(fork, self.expr_index + 1);
|
||||
let (guard_exit, arm_end_ids) = arms.iter().fold(
|
||||
(self.expr_index, vec![]),
|
||||
|(incoming_edge, mut arm_end_ids), hir::Arm { pat, body, guard, .. }| {
|
||||
self.drop_ranges.add_control_edge(incoming_edge, self.expr_index + 1);
|
||||
self.visit_pat(pat);
|
||||
match guard {
|
||||
Some(Guard::If(expr)) => self.visit_expr(expr),
|
||||
@ -147,10 +146,16 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
|
||||
}
|
||||
None => (),
|
||||
}
|
||||
let to_next_arm = self.expr_index;
|
||||
// The default edge does not get added since we also have an explicit edge,
|
||||
// so we also need to add an edge to the next node as well.
|
||||
self.drop_ranges.add_control_edge(self.expr_index, self.expr_index + 1);
|
||||
self.visit_expr(body);
|
||||
self.expr_index
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
arm_end_ids.push(self.expr_index);
|
||||
(to_next_arm, arm_end_ids)
|
||||
},
|
||||
);
|
||||
self.drop_ranges.add_control_edge(guard_exit, self.expr_index + 1);
|
||||
arm_end_ids.into_iter().for_each(|arm_end| {
|
||||
self.drop_ranges.add_control_edge(arm_end, self.expr_index + 1)
|
||||
});
|
||||
|
@ -5,6 +5,15 @@
|
||||
|
||||
use super::{DropRangesBuilder, PostOrderId};
|
||||
|
||||
/// Writes the CFG for DropRangesBuilder to a .dot file for visualization.
|
||||
///
|
||||
/// It is not normally called, but is kept around to easily add debugging
|
||||
/// code when needed.
|
||||
#[allow(dead_code)]
|
||||
pub(super) fn write_graph_to_file(drop_ranges: &DropRangesBuilder, filename: &str) {
|
||||
dot::render(drop_ranges, &mut std::fs::File::create(filename).unwrap()).unwrap();
|
||||
}
|
||||
|
||||
impl<'a> dot::GraphWalk<'a> for DropRangesBuilder {
|
||||
type Node = PostOrderId;
|
||||
|
||||
|
25
src/test/ui/generator/reinit-in-match-guard.rs
Normal file
25
src/test/ui/generator/reinit-in-match-guard.rs
Normal file
@ -0,0 +1,25 @@
|
||||
// build-pass
|
||||
|
||||
#![feature(generators)]
|
||||
|
||||
#![allow(unused_assignments, dead_code)]
|
||||
|
||||
fn main() {
|
||||
let _ = || {
|
||||
let mut x = vec![22_usize];
|
||||
std::mem::drop(x);
|
||||
match y() {
|
||||
true if {
|
||||
x = vec![];
|
||||
false
|
||||
} => {}
|
||||
_ => {
|
||||
yield;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn y() -> bool {
|
||||
true
|
||||
}
|
Loading…
Reference in New Issue
Block a user