about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMatthew Jasper <mjjasper1@gmail.com>2019-06-29 15:38:20 +0100
committerMatthew Jasper <mjjasper1@gmail.com>2019-07-06 21:56:03 +0100
commitde5c6ec1f4a6bbd8600fda0e7c1574d914ac35bd (patch)
tree7f35c15a9f202554d9491e1b6a38782b7993dca8 /src
parentdb6f77f0d74934a95eb91d74bda19e5b0e8258e3 (diff)
downloadrust-de5c6ec1f4a6bbd8600fda0e7c1574d914ac35bd.tar.gz
rust-de5c6ec1f4a6bbd8600fda0e7c1574d914ac35bd.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/cfg/construct.rs13
-rw-r--r--src/test/ui/borrowck/issue-62107-match-arm-scopes.rs12
-rw-r--r--src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr9
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`.