Exit arm scopes correctly in the HIR CFG

When a match evaluates to false we jump to the next arm, when we do so
we need to make sure that we exit the scope for that arm.
This commit is contained in:
Matthew Jasper 2019-06-29 15:38:20 +01:00
parent db6f77f0d7
commit de5c6ec1f4
3 changed files with 28 additions and 6 deletions

View File

@ -371,7 +371,8 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
let expr_exit = self.add_ast_node(id, &[]);
// Keep track of the previous guard expressions
let mut prev_guards = Vec::new();
let mut prev_guard = None;
let match_scope = region::Scope { id, data: region::ScopeData::Node };
for arm in arms {
// Add an exit node for when we've visited all the
@ -389,7 +390,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
let guard_start = self.add_dummy_node(&[pat_exit]);
// Visit the guard expression
let guard_exit = match guard {
hir::Guard::If(ref e) => self.expr(e, guard_start),
hir::Guard::If(ref e) => (&**e, self.expr(e, guard_start)),
};
// #47295: We used to have very special case code
// here for when a pair of arms are both formed
@ -397,15 +398,15 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
// edges. But this was not actually sound without
// other constraints that we stopped enforcing at
// some point.
while let Some(prev) = prev_guards.pop() {
self.add_contained_edge(prev, guard_start);
if let Some((prev_guard, prev_index)) = prev_guard.take() {
self.add_exiting_edge(prev_guard, prev_index, match_scope, guard_start);
}
// Push the guard onto the list of previous guards
prev_guards.push(guard_exit);
prev_guard = Some(guard_exit);
// Update the exit node for the pattern
pat_exit = guard_exit;
pat_exit = guard_exit.1;
}
// Add an edge from the exit of this pattern to the

View File

@ -0,0 +1,12 @@
fn main() {
let e: i32;
match e {
//~^ ERROR use of possibly uninitialized variable
ref u if true => {}
ref v if true => {
let tx = 0;
&tx;
}
_ => (),
}
}

View File

@ -0,0 +1,9 @@
error[E0381]: use of possibly uninitialized variable: `e`
--> $DIR/issue-62107-match-arm-scopes.rs:3:11
|
LL | match e {
| ^ use of possibly uninitialized `e`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0381`.