about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorAriel Ben-Yehuda <ariel.byd@gmail.com>2017-12-06 02:10:24 +0200
committerAriel Ben-Yehuda <ariel.byd@gmail.com>2017-12-06 02:10:24 +0200
commit9d3558725b9110beaa6740e88847e3addc9c2d0d (patch)
treedbf060cf29942448dd691776e1b97a4d6a652966 /src
parent66c032cb2d5748e36c416e25c75b80f137f3a7fc (diff)
downloadrust-9d3558725b9110beaa6740e88847e3addc9c2d0d.tar.gz
rust-9d3558725b9110beaa6740e88847e3addc9c2d0d.zip
work around weird match arm lifetimes
Diffstat (limited to 'src')
-rw-r--r--src/librustc_mir/dataflow/impls/mod.rs26
-rw-r--r--src/test/run-pass/match-pipe-binding.rs1
2 files changed, 24 insertions, 3 deletions
diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs
index e7a25c212c3..db8ca0628c4 100644
--- a/src/librustc_mir/dataflow/impls/mod.rs
+++ b/src/librustc_mir/dataflow/impls/mod.rs
@@ -585,9 +585,29 @@ impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedLvals<'a, 'gcx, 'tcx> {
         sets.gen_all(&init_loc_map[location]);
 
         match stmt.kind {
-            mir::StatementKind::StorageDead(local) => {
-                // End inits for StorageDead, so that an immutable variable can
-                // be reinitialized on the next iteration of the loop.
+            mir::StatementKind::StorageDead(local) |
+            mir::StatementKind::StorageLive(local) => {
+                // End inits for StorageDead and StorageLive, so that an immutable
+                // variable can be reinitialized on the next iteration of the loop.
+                //
+                // FIXME(#46525): We *need* to do this for StorageLive as well as
+                // StorageDead, because lifetimes of match bindings with guards are
+                // weird - i.e. this code
+                //
+                // ```
+                //     fn main() {
+                //         match 0 {
+                //             a | a
+                //             if { println!("a={}", a); false } => {}
+                //             _ => {}
+                //         }
+                //     }
+                // ```
+                //
+                // runs the guard twice, using the same binding for `a`, and only
+                // storagedeads after everything ends, so if we don't regard the
+                // storagelive as killing storage, we would have a multiple assignment
+                // to immutable data error.
                 if let LookupResult::Exact(mpi) = rev_lookup.find(&mir::Place::Local(local)) {
                     debug!("stmt {:?} at loc {:?} clears the ever initialized status of {:?}",
                            stmt, location, &init_path_map[mpi]);
diff --git a/src/test/run-pass/match-pipe-binding.rs b/src/test/run-pass/match-pipe-binding.rs
index bda90d3aaec..9592da77a1b 100644
--- a/src/test/run-pass/match-pipe-binding.rs
+++ b/src/test/run-pass/match-pipe-binding.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// compile-flags: -Z borrowck=compare
 
 fn test1() {
     // from issue 6338