]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_mir/transform/cleanup_post_borrowck.rs
Add a MIR transform to remove fake reads
[rust.git] / src / librustc_mir / transform / cleanup_post_borrowck.rs
index 9edb1a1f76a6d7bf6a92350d70d6e5fe0ba41535..aaba7ab8418f539ded32e4974d91a73b02dbd00e 100644 (file)
@@ -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 @@ fn visit_statement(&mut self,
         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);
+    }
+}