diff options
| author | Matthew Jasper <mjjasper1@gmail.com> | 2019-06-29 15:38:20 +0100 |
|---|---|---|
| committer | Matthew Jasper <mjjasper1@gmail.com> | 2019-07-06 21:56:03 +0100 |
| commit | de5c6ec1f4a6bbd8600fda0e7c1574d914ac35bd (patch) | |
| tree | 7f35c15a9f202554d9491e1b6a38782b7993dca8 | |
| parent | db6f77f0d74934a95eb91d74bda19e5b0e8258e3 (diff) | |
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.
| -rw-r--r-- | src/librustc/cfg/construct.rs | 13 | ||||
| -rw-r--r-- | src/test/ui/borrowck/issue-62107-match-arm-scopes.rs | 12 | ||||
| -rw-r--r-- | src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr | 9 |
3 files changed, 28 insertions, 6 deletions
diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index f81d1869413..ca852fe7622 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -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 diff --git a/src/test/ui/borrowck/issue-62107-match-arm-scopes.rs b/src/test/ui/borrowck/issue-62107-match-arm-scopes.rs new file mode 100644 index 00000000000..220b2ecf04d --- /dev/null +++ b/src/test/ui/borrowck/issue-62107-match-arm-scopes.rs @@ -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; + } + _ => (), + } +} diff --git a/src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr b/src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr new file mode 100644 index 00000000000..9701343d2b1 --- /dev/null +++ b/src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr @@ -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`. |
