about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPaul Faria <Nashenas88@gmail.com>2017-07-17 22:26:21 -0400
committerPaul Faria <Nashenas88@gmail.com>2017-07-30 12:09:35 -0400
commitd2fc06e7f6068f3e30a21099f4cf4a2e423e9159 (patch)
tree08e079ebb88d93400ed0fd1e30841a96b1c9409f
parent5c71e4ef90ef79c1ac79c4132333cbc80f5b85b9 (diff)
downloadrust-d2fc06e7f6068f3e30a21099f4cf4a2e423e9159.tar.gz
rust-d2fc06e7f6068f3e30a21099f4cf4a2e423e9159.zip
Renumber regions as the first step of the non-lexical lifetimes inference
-rw-r--r--src/librustc_mir/transform/nll.rs94
1 files changed, 82 insertions, 12 deletions
diff --git a/src/librustc_mir/transform/nll.rs b/src/librustc_mir/transform/nll.rs
index 3273b4ff347..65294e9ef24 100644
--- a/src/librustc_mir/transform/nll.rs
+++ b/src/librustc_mir/transform/nll.rs
@@ -8,26 +8,90 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc::ty::TyCtxt;
-use rustc::mir::Mir;
+use rustc::ty::TypeFoldable;
+use rustc::ty::subst::Substs;
+use rustc::ty::{Ty, TyCtxt, ClosureSubsts};
+use rustc::mir::{Mir, Location, Rvalue, BasicBlock, Statement, StatementKind};
 use rustc::mir::visit::MutVisitor;
 use rustc::mir::transform::{MirPass, MirSource};
+use rustc::infer::{self, InferCtxt};
+use syntax_pos::Span;
 
 #[allow(dead_code)]
-struct NLLVisitor<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+struct NLLVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
+    infcx: InferCtxt<'a, 'gcx, 'tcx>,
+    source: Mir<'tcx>
 }
 
-impl<'a, 'tcx> NLLVisitor<'a, 'tcx> {
-    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self {
+impl<'a, 'gcx, 'tcx> NLLVisitor<'a, 'gcx, 'tcx> {
+    pub fn new(infcx: InferCtxt<'a, 'gcx, 'tcx>, source: Mir<'tcx>) -> Self {
         NLLVisitor {
-            tcx: tcx
+            infcx: infcx,
+            source: source,
         }
     }
+
+    fn renumber_regions<T>(&self, value: &T, span: Span) -> T where T: TypeFoldable<'tcx> {
+        self.infcx.tcx.fold_regions(value, &mut false, |_region, _depth| {
+            self.infcx.next_region_var(infer::MiscVariable(span))
+        })
+    }
 }
 
-impl<'a, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'tcx> {
-    // FIXME: Nashenas88: implement me!
+fn span_from_location<'tcx>(source: Mir<'tcx>, location: Location) -> Span {
+    source[location.block].statements[location.statement_index].source_info.span
+}
+
+impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
+    fn visit_ty(&mut self, ty: &mut Ty<'tcx>) {
+        let old_ty = *ty;
+        // FIXME: Nashenas88 - span should be narrowed down
+        *ty = self.renumber_regions(&old_ty, self.source.span);
+    }
+
+    fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>) {
+        // FIXME: Nashenas88 - span should be narrowed down
+        *substs = self.renumber_regions(&{*substs}, self.source.span);
+    }
+
+    fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) {
+        match *rvalue {
+            Rvalue::Ref(ref mut r, _, _) => {
+                let span = span_from_location(location);
+                let old_r = *r;
+                *r = self.renumber_regions(&old_r, span);
+            }
+            Rvalue::Use(..) |
+            Rvalue::Repeat(..) |
+            Rvalue::Len(..) |
+            Rvalue::Cast(..) |
+            Rvalue::BinaryOp(..) |
+            Rvalue::CheckedBinaryOp(..) |
+            Rvalue::UnaryOp(..) |
+            Rvalue::Discriminant(..) |
+            Rvalue::NullaryOp(..) |
+            Rvalue::Aggregate(..) => {
+                // These variants don't contain regions.
+            }
+        }
+        self.super_rvalue(rvalue, location);
+    }
+
+    fn visit_closure_substs(&mut self,
+                            substs: &mut ClosureSubsts<'tcx>) {
+        // FIXME: Nashenas88 - span should be narrowed down
+        *substs = self.renumber_regions(substs, self.source.span);
+    }
+
+    fn visit_statement(&mut self,
+                       block: BasicBlock,
+                       statement: &mut Statement<'tcx>,
+                       location: Location) {
+        if let StatementKind::EndRegion(_) = statement.kind {
+            statement.kind = StatementKind::Nop;
+        }
+        self.super_statement(block, statement, location);
+    }
 }
 
 // MIR Pass for non-lexical lifetimes
@@ -38,10 +102,16 @@ impl MirPass for NLL {
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           _: MirSource,
                           mir: &mut Mir<'tcx>) {
-        if tcx.sess.opts.debugging_opts.nll {
+        if !tcx.sess.opts.debugging_opts.nll {
+            return;
+        }
+
+        tcx.infer_ctxt().enter(|infcx| {
+            let mut visitor = NLLVisitor::new(infcx, mir.clone());
             // Clone mir so we can mutate it without disturbing the rest
             // of the compiler
-            NLLVisitor::new(tcx).visit_mir(&mut mir.clone());
-        }
+            let mut mir = mir.clone();
+            visitor.visit_mir(&mut mir);
+        })
     }
 }
\ No newline at end of file