about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>2017-08-30 11:13:01 +0200
committerOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>2017-08-30 13:16:27 +0200
commit58a59e9d231e36e3d39dd398b80c96094de591aa (patch)
treeb5cdd2c13f3cbcc9972541faa68315fd8aae425c
parent4b67bfab52ab7e9ded0b7bef2f70c64a972d93ee (diff)
downloadrust-58a59e9d231e36e3d39dd398b80c96094de591aa.tar.gz
rust-58a59e9d231e36e3d39dd398b80c96094de591aa.zip
Rustup (generator support)
-rw-r--r--src/librustc_mir/interpret/eval_context.rs27
-rw-r--r--src/librustc_mir/interpret/terminator/mod.rs9
-rw-r--r--src/librustc_mir/interpret/validation.rs6
-rw-r--r--tests/run-pass/generator_control_flow.rs65
4 files changed, 96 insertions, 11 deletions
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index b123ad7fd0b..b3d2617c9a3 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -480,15 +480,22 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
 
         // Subtract 1 because `local_decls` includes the ReturnMemoryPointer, but we don't store a local
         // `Value` for that.
-        let annotated_locals = collect_storage_annotations(mir);
         let num_locals = mir.local_decls.len() - 1;
-        let mut locals = vec![None; num_locals];
-        for i in 0..num_locals {
-            let local = mir::Local::new(i + 1);
-            if !annotated_locals.contains(&local) {
-                locals[i] = Some(Value::ByVal(PrimVal::Undef));
+
+        // FIXME: generators produce broken storage annotations (https://github.com/rust-lang/rust/issues/44179)
+        let locals = if mir.generator_layout.is_some() {
+            vec![Some(Value::ByVal(PrimVal::Undef)); num_locals]
+        } else {
+            let annotated_locals = collect_storage_annotations(mir);
+            let mut locals = vec![None; num_locals];
+            for i in 0..num_locals {
+                let local = mir::Local::new(i + 1);
+                if !annotated_locals.contains(&local) {
+                    locals[i] = Some(Value::ByVal(PrimVal::Undef));
+                }
             }
-        }
+            locals
+        };
 
         self.stack.push(Frame {
             mir,
@@ -2426,6 +2433,12 @@ fn resolve_associated_item<'a, 'tcx>(
             let substs = tcx.erase_regions(&substs);
             ty::Instance::new(def_id, substs)
         }
+        ::rustc::traits::VtableGenerator(closure_data) => {
+            ty::Instance {
+                def: ty::InstanceDef::Item(closure_data.closure_def_id),
+                substs: closure_data.substs.substs
+            }
+        }
         ::rustc::traits::VtableClosure(closure_data) => {
             let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_id).unwrap();
             resolve_closure(
diff --git a/src/librustc_mir/interpret/terminator/mod.rs b/src/librustc_mir/interpret/terminator/mod.rs
index ebd6649c447..bee0fe23f7f 100644
--- a/src/librustc_mir/interpret/terminator/mod.rs
+++ b/src/librustc_mir/interpret/terminator/mod.rs
@@ -137,8 +137,9 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
                 if expected == cond_val {
                     self.goto_block(target);
                 } else {
+                    use rustc::mir::AssertMessage::*;
                     return match *msg {
-                        mir::AssertMessage::BoundsCheck { ref len, ref index } => {
+                        BoundsCheck { ref len, ref index } => {
                             let span = terminator.source_info.span;
                             let len = self.eval_operand_to_primval(len)
                                 .expect("can't eval len")
@@ -148,13 +149,17 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
                                 .to_u64()?;
                             err!(ArrayIndexOutOfBounds(span, len, index))
                         }
-                        mir::AssertMessage::Math(ref err) => {
+                        Math(ref err) => {
                             err!(Math(terminator.source_info.span, err.clone()))
                         }
+                        GeneratorResumedAfterReturn |
+                        GeneratorResumedAfterPanic => unimplemented!(),
                     };
                 }
             }
 
+            Yield { .. } => unimplemented!("{:#?}", terminator.kind),
+            GeneratorDrop => unimplemented!(),
             DropAndReplace { .. } => unimplemented!(),
             Resume => unimplemented!(),
             Unreachable => return err!(Unreachable),
diff --git a/src/librustc_mir/interpret/validation.rs b/src/librustc_mir/interpret/validation.rs
index 6454e12e037..63872f3c9c6 100644
--- a/src/librustc_mir/interpret/validation.rs
+++ b/src/librustc_mir/interpret/validation.rs
@@ -355,7 +355,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
             TyRef(..) | TyFnPtr(..) | TyFnDef(..) | TyNever => true,
             TyAdt(adt, _) if adt.is_box() => true,
             TySlice(_) | TyAdt(_, _) | TyTuple(..) | TyClosure(..) | TyArray(..) |
-            TyDynamic(..) => false,
+            TyDynamic(..) | TyGenerator(..) => false,
             TyParam(_) | TyInfer(_) | TyProjection(_) | TyAnon(..) | TyError => {
                 bug!("I got an incomplete/unnormalized type for validation")
             }
@@ -630,7 +630,9 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
                 // Is there other things we can/should check?  Like vtable pointers?
                 Ok(())
             }
-            _ => bug!("We already establishd that this is a type we support."),
+            // FIXME: generators aren't validated right now
+            TyGenerator(..) => Ok(()),
+            _ => bug!("We already established that this is a type we support. ({})", query.ty),
         }
     }
 }
diff --git a/tests/run-pass/generator_control_flow.rs b/tests/run-pass/generator_control_flow.rs
new file mode 100644
index 00000000000..f15c7db9c20
--- /dev/null
+++ b/tests/run-pass/generator_control_flow.rs
@@ -0,0 +1,65 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(generators, generator_trait)]
+
+use std::ops::{GeneratorState, Generator};
+
+fn finish<T>(mut amt: usize, mut t: T) -> T::Return
+    where T: Generator<Yield = ()>
+{
+    loop {
+        match t.resume() {
+            GeneratorState::Yielded(()) => amt -= 1,
+            GeneratorState::Complete(ret) => {
+                assert_eq!(amt, 0);
+                return ret
+            }
+        }
+    }
+
+}
+
+fn main() {
+    finish(1, || yield);
+    finish(3, || {
+        let mut x = 0;
+        yield;
+        x += 1;
+        yield;
+        x += 1;
+        yield;
+        assert_eq!(x, 2);
+    });
+    finish(8, || {
+        for _ in 0..8 {
+            yield;
+        }
+    });
+    finish(1, || {
+        if true {
+            yield;
+        } else {
+        }
+    });
+    finish(1, || {
+        if false {
+        } else {
+            yield;
+        }
+    });
+    finish(2, || {
+        if { yield; false } {
+            yield;
+            panic!()
+        }
+        yield
+    });
+}