about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_mir/lib.rs2
-rw-r--r--src/librustc_mir/transform/cleanup_post_borrowck.rs62
-rw-r--r--src/librustc_mir/transform/mod.rs5
-rw-r--r--src/test/mir-opt/remove_fake_borrows.rs122
4 files changed, 188 insertions, 3 deletions
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index 4546e0bf253..a2d70bc05c1 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -14,7 +14,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
 
 */
 
-#![cfg_attr(not(stage0), feature(nll))]
+#![feature(nll)]
 #![feature(in_band_lifetimes)]
 #![feature(impl_header_lifetime_elision)]
 #![feature(slice_patterns)]
diff --git a/src/librustc_mir/transform/cleanup_post_borrowck.rs b/src/librustc_mir/transform/cleanup_post_borrowck.rs
index 9edb1a1f76a..aaba7ab8418 100644
--- a/src/librustc_mir/transform/cleanup_post_borrowck.rs
+++ b/src/librustc_mir/transform/cleanup_post_borrowck.rs
@@ -33,7 +33,8 @@
 use rustc_data_structures::fx::FxHashSet;
 
 use rustc::middle::region;
-use rustc::mir::{BasicBlock, Location, Mir, Rvalue, Statement, StatementKind};
+use rustc::mir::{BasicBlock, FakeReadCause, Local, Location, Mir, Place};
+use rustc::mir::{Rvalue, Statement, StatementKind};
 use rustc::mir::visit::{MutVisitor, Visitor, TyContext};
 use rustc::ty::{Ty, RegionKind, TyCtxt};
 use transform::{MirPass, MirSource};
@@ -135,3 +136,62 @@ impl<'tcx> MutVisitor<'tcx> for DeleteAscribeUserType {
         self.super_statement(block, statement, location);
     }
 }
+
+pub struct CleanFakeReadsAndBorrows;
+
+pub struct DeleteAndRecordFakeReads {
+    fake_borrow_temporaries: FxHashSet<Local>,
+}
+
+pub struct DeleteFakeBorrows {
+    fake_borrow_temporaries: FxHashSet<Local>,
+}
+
+// Removes any FakeReads from the MIR
+impl MirPass for CleanFakeReadsAndBorrows {
+    fn run_pass<'a, 'tcx>(&self,
+                          _tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                          _source: MirSource,
+                          mir: &mut Mir<'tcx>) {
+        let mut delete_reads = DeleteAndRecordFakeReads {
+            fake_borrow_temporaries: FxHashSet(),
+        };
+        delete_reads.visit_mir(mir);
+        let mut delete_borrows = DeleteFakeBorrows {
+            fake_borrow_temporaries: delete_reads.fake_borrow_temporaries,
+        };
+        delete_borrows.visit_mir(mir);
+    }
+}
+
+impl<'tcx> MutVisitor<'tcx> for DeleteAndRecordFakeReads {
+    fn visit_statement(&mut self,
+                       block: BasicBlock,
+                       statement: &mut Statement<'tcx>,
+                       location: Location) {
+        if let StatementKind::FakeRead(cause, ref place) = statement.kind {
+            if let FakeReadCause::ForMatchGuard = cause {
+                match *place {
+                    Place::Local(local) => self.fake_borrow_temporaries.insert(local),
+                    _ => bug!("Fake match guard read of non-local: {:?}", place),
+                };
+            }
+            statement.make_nop();
+        }
+        self.super_statement(block, statement, location);
+    }
+}
+
+impl<'tcx> MutVisitor<'tcx> for DeleteFakeBorrows {
+    fn visit_statement(&mut self,
+                       block: BasicBlock,
+                       statement: &mut Statement<'tcx>,
+                       location: Location) {
+        if let StatementKind::Assign(Place::Local(local), _) = statement.kind {
+            if self.fake_borrow_temporaries.contains(&local) {
+                statement.make_nop();
+            }
+        }
+        self.super_statement(block, statement, location);
+    }
+}
diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs
index 19fb35be9d4..d18836999dc 100644
--- a/src/librustc_mir/transform/mod.rs
+++ b/src/librustc_mir/transform/mod.rs
@@ -237,9 +237,12 @@ fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx
         no_landing_pads::NoLandingPads,
         simplify_branches::SimplifyBranches::new("initial"),
         remove_noop_landing_pads::RemoveNoopLandingPads,
-        simplify::SimplifyCfg::new("early-opt"),
         // Remove all `AscribeUserType` statements.
         cleanup_post_borrowck::CleanAscribeUserType,
+        // Remove all `FakeRead` statements and the borrows that are only
+        // used for checking matches
+        cleanup_post_borrowck::CleanFakeReadsAndBorrows,
+        simplify::SimplifyCfg::new("early-opt"),
 
         // These next passes must be executed together
         add_call_guards::CriticalCallEdges,
diff --git a/src/test/mir-opt/remove_fake_borrows.rs b/src/test/mir-opt/remove_fake_borrows.rs
new file mode 100644
index 00000000000..8411fba02e9
--- /dev/null
+++ b/src/test/mir-opt/remove_fake_borrows.rs
@@ -0,0 +1,122 @@
+// Test that the fake borrows for matches are removed after borrow checking.
+
+// ignore-wasm32-bare
+
+#![feature(nll)]
+
+fn match_guard(x: Option<&&i32>) -> i32 {
+    match x {
+        Some(0) if true => 0,
+        _ => 1,
+    }
+}
+
+fn main() {
+    match_guard(None);
+}
+
+// END RUST SOURCE
+
+// START rustc.match_guard.CleanFakeReadsAndBorrows.before.mir
+// bb0: {
+//     FakeRead(ForMatchedPlace, _1);
+//     _2 = discriminant(_1);
+//     _3 = &shallow _1;
+//     _4 = &shallow ((_1 as Some).0: &'<empty> &'<empty> i32);
+//     _5 = &shallow (*((_1 as Some).0: &'<empty> &'<empty> i32));
+//     _6 = &shallow (*(*((_1 as Some).0: &'<empty> &'<empty> i32)));
+//     switchInt(move _2) -> [1isize: bb6, otherwise: bb4];
+// }
+// bb1: {
+//     _0 = const 0i32;
+//     goto -> bb9;
+// }
+// bb2: {
+//     _0 = const 1i32;
+//     goto -> bb9;
+// }
+// bb3: {
+//     FakeRead(ForMatchGuard, _3);
+//     FakeRead(ForMatchGuard, _4);
+//     FakeRead(ForMatchGuard, _5);
+//     FakeRead(ForMatchGuard, _6);
+//     goto -> bb7;
+// }
+// bb4: {
+//     FakeRead(ForMatchGuard, _3);
+//     FakeRead(ForMatchGuard, _4);
+//     FakeRead(ForMatchGuard, _5);
+//     FakeRead(ForMatchGuard, _6);
+//     goto -> bb2;
+// }
+// bb5: {
+//     unreachable;
+// }
+// bb6: {
+//     switchInt((*(*((_1 as Some).0: &'<empty> &'<empty> i32)))) -> [0i32: bb3, otherwise: bb4];
+// }
+// bb7: {
+//     goto -> bb1;
+// }
+// bb8: {
+//     goto -> bb4;
+// }
+// bb9: {
+//     return;
+// }
+// bb10: {
+//     resume;
+// }
+// END rustc.match_guard.CleanFakeReadsAndBorrows.before.mir
+
+// START rustc.match_guard.CleanFakeReadsAndBorrows.after.mir
+// bb0: {
+//     nop;
+//     _2 = discriminant(_1);
+//     nop;
+//     nop;
+//     nop;
+//     nop;
+//     switchInt(move _2) -> [1isize: bb6, otherwise: bb4];
+// }
+// bb1: {
+//     _0 = const 0i32;
+//     goto -> bb9;
+// }
+// bb2: {
+//     _0 = const 1i32;
+//     goto -> bb9;
+// }
+// bb3: {
+//     nop;
+//     nop;
+//     nop;
+//     nop;
+//     goto -> bb7;
+// }
+// bb4: {
+//     nop;
+//     nop;
+//     nop;
+//     nop;
+//     goto -> bb2;
+// }
+// bb5: {
+//     unreachable;
+// }
+// bb6: {
+//     switchInt((*(*((_1 as Some).0: &'<empty> &'<empty> i32)))) -> [0i32: bb3, otherwise: bb4];
+// }
+// bb7: {
+//     goto -> bb1;
+// }
+// bb8: {
+//     goto -> bb4;
+// }
+// bb9: {
+//     return;
+// }
+// bb10: {
+//     resume;
+// }
+// END rustc.match_guard.CleanFakeReadsAndBorrows.after.mir