Skip to content

Commit

Permalink
Exit arm scopes correctly in the HIR CFG
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
matthewjasper committed Jul 6, 2019
1 parent db6f77f commit de5c6ec
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 6 deletions.
13 changes: 7 additions & 6 deletions src/librustc/cfg/construct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -389,23 +390,23 @@ 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
// solely from constants, and if so, not add these
// 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
Expand Down
12 changes: 12 additions & 0 deletions src/test/ui/borrowck/issue-62107-match-arm-scopes.rs
Original file line number Diff line number Diff line change
@@ -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;
}
_ => (),
}
}
9 changes: 9 additions & 0 deletions src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit de5c6ec

Please sign in to comment.