]> git.lizzy.rs Git - rust.git/commitdiff
Make resuming generators unsafe instead of the creation of immovable generators....
authorJohn Kåre Alsaker <john.kare.alsaker@gmail.com>
Mon, 19 Mar 2018 23:48:41 +0000 (00:48 +0100)
committerJohn Kåre Alsaker <john.kare.alsaker@gmail.com>
Tue, 20 Mar 2018 23:09:58 +0000 (00:09 +0100)
30 files changed:
src/doc/unstable-book/src/language-features/generators.md
src/liballoc/boxed.rs
src/libcore/ops/generator.rs
src/librustc_mir/diagnostics.rs
src/librustc_mir/transform/check_unsafety.rs
src/test/run-pass/dynamic-drop.rs
src/test/run-pass/generator/conditional-drop.rs
src/test/run-pass/generator/control-flow.rs
src/test/run-pass/generator/drop-env.rs
src/test/run-pass/generator/issue-44197.rs
src/test/run-pass/generator/iterator-count.rs
src/test/run-pass/generator/live-upvar-across-yield.rs
src/test/run-pass/generator/nested_generators.rs
src/test/run-pass/generator/panic-drops.rs
src/test/run-pass/generator/panic-safe.rs
src/test/run-pass/generator/resume-after-return.rs
src/test/run-pass/generator/smoke.rs
src/test/run-pass/generator/static-generators.rs
src/test/run-pass/generator/xcrate-reachable.rs
src/test/run-pass/generator/xcrate.rs
src/test/ui/generator/borrowing.rs
src/test/ui/generator/borrowing.stderr
src/test/ui/generator/dropck.rs
src/test/ui/generator/sized-yield.rs
src/test/ui/generator/sized-yield.stderr
src/test/ui/generator/unsafe-immovable.rs [deleted file]
src/test/ui/generator/unsafe-immovable.stderr [deleted file]
src/test/ui/generator/yield-while-iterating.rs
src/test/ui/generator/yield-while-local-borrowed.rs
src/test/ui/generator/yield-while-ref-reborrowed.rs

index e8e2132dca254e01aae972b8f7c86c51abffd808..8e888de90a95149ecf786f9b62e8588114623547 100644 (file)
@@ -36,11 +36,11 @@ fn main() {
         return "foo"
     };
 
-    match generator.resume() {
+    match unsafe { generator.resume() } {
         GeneratorState::Yielded(1) => {}
         _ => panic!("unexpected value from resume"),
     }
-    match generator.resume() {
+    match unsafe { generator.resume() } {
         GeneratorState::Complete("foo") => {}
         _ => panic!("unexpected value from resume"),
     }
@@ -69,9 +69,9 @@ fn main() {
     };
 
     println!("1");
-    generator.resume();
+    unsafe { generator.resume() };
     println!("3");
-    generator.resume();
+    unsafe { generator.resume() };
     println!("5");
 }
 ```
@@ -92,7 +92,7 @@ The `Generator` trait in `std::ops` currently looks like:
 pub trait Generator {
     type Yield;
     type Return;
-    fn resume(&mut self) -> GeneratorState<Self::Yield, Self::Return>;
+    unsafe fn resume(&mut self) -> GeneratorState<Self::Yield, Self::Return>;
 }
 ```
 
@@ -175,8 +175,8 @@ fn main() {
         return ret
     };
 
-    generator.resume();
-    generator.resume();
+    unsafe { generator.resume() };
+    unsafe { generator.resume() };
 }
 ```
 
@@ -200,7 +200,7 @@ fn main() {
             type Yield = i32;
             type Return = &'static str;
 
-            fn resume(&mut self) -> GeneratorState<i32, &'static str> {
+            unsafe fn resume(&mut self) -> GeneratorState<i32, &'static str> {
                 use std::mem;
                 match mem::replace(self, __Generator::Done) {
                     __Generator::Start(s) => {
@@ -223,8 +223,8 @@ fn main() {
         __Generator::Start(ret)
     };
 
-    generator.resume();
-    generator.resume();
+    unsafe { generator.resume() };
+    unsafe { generator.resume() };
 }
 ```
 
index b776556d59f11b033500d34cafd1ec13b4cf4435..a86ab87ec185f857cbc531bab9e35adbcdffd12a 100644 (file)
@@ -892,7 +892,7 @@ impl<T> Generator for Box<T>
 {
     type Yield = T::Yield;
     type Return = T::Return;
-    fn resume(&mut self) -> GeneratorState<Self::Yield, Self::Return> {
+    unsafe fn resume(&mut self) -> GeneratorState<Self::Yield, Self::Return> {
         (**self).resume()
     }
 }
index dc7669d195c1397435a0da4baccef83cc24b0682..4b70c5398be4f1e138cab935b7bc54cfed3d8b00 100644 (file)
@@ -56,11 +56,11 @@ pub enum GeneratorState<Y, R> {
 ///         return "foo"
 ///     };
 ///
-///     match generator.resume() {
+///     match unsafe { generator.resume() } {
 ///         GeneratorState::Yielded(1) => {}
 ///         _ => panic!("unexpected return from resume"),
 ///     }
-///     match generator.resume() {
+///     match unsafe { generator.resume() } {
 ///         GeneratorState::Complete("foo") => {}
 ///         _ => panic!("unexpected return from resume"),
 ///     }
@@ -98,6 +98,10 @@ pub trait Generator {
     /// generator will continue executing until it either yields or returns, at
     /// which point this function will return.
     ///
+    /// The function is unsafe because it can be used on an immovable generator.
+    /// After such a call, the immovable generator must not move again, but
+    /// this is not enforced by the compiler.
+    ///
     /// # Return value
     ///
     /// The `GeneratorState` enum returned from this function indicates what
@@ -116,7 +120,7 @@ pub trait Generator {
     /// been returned previously. While generator literals in the language are
     /// guaranteed to panic on resuming after `Complete`, this is not guaranteed
     /// for all implementations of the `Generator` trait.
-    fn resume(&mut self) -> GeneratorState<Self::Yield, Self::Return>;
+    unsafe fn resume(&mut self) -> GeneratorState<Self::Yield, Self::Return>;
 }
 
 #[unstable(feature = "generator_trait", issue = "43122")]
@@ -125,7 +129,7 @@ impl<'a, T> Generator for &'a mut T
 {
     type Yield = T::Yield;
     type Return = T::Return;
-    fn resume(&mut self) -> GeneratorState<Self::Yield, Self::Return> {
+    unsafe fn resume(&mut self) -> GeneratorState<Self::Yield, Self::Return> {
         (**self).resume()
     }
 }
index 2000ebea25d7e3337bc47ef01a508b653668a537..4f36c3888b961fe75711a18696cc083645ee52b3 100644 (file)
@@ -2247,7 +2247,7 @@ struct Foo<'a> {
     yield (); // ...is still in scope here, when the yield occurs.
     println!("{}", a);
 };
-b.resume();
+unsafe { b.resume() };
 ```
 
 At present, it is not permitted to have a yield that occurs while a
@@ -2265,7 +2265,7 @@ struct Foo<'a> {
     yield ();
     println!("{}", a);
 };
-b.resume();
+unsafe { b.resume() };
 ```
 
 This is a very simple case, of course. In more complex cases, we may
@@ -2283,7 +2283,7 @@ struct Foo<'a> {
     yield x; // ...when this yield occurs.
   }
 };
-b.resume();
+unsafe { b.resume() };
 ```
 
 Such cases can sometimes be resolved by iterating "by value" (or using
@@ -2298,7 +2298,7 @@ struct Foo<'a> {
     yield x; // <-- Now yield is OK.
   }
 };
-b.resume();
+unsafe { b.resume() };
 ```
 
 If taking ownership is not an option, using indices can work too:
@@ -2314,7 +2314,7 @@ struct Foo<'a> {
     yield x; // <-- Now yield is OK.
   }
 };
-b.resume();
+unsafe { b.resume() };
 
 // (*) -- Unfortunately, these temporaries are currently required.
 // See <https://github.com/rust-lang/rust/issues/43122>.
index 86d08dec2b9c363621b76bcf73c5e38511d74ad7..033fb493d735cc49a80604384cb71cb176d5a3c3 100644 (file)
@@ -125,21 +125,13 @@ fn visit_rvalue(&mut self,
                 &AggregateKind::Array(..) |
                 &AggregateKind::Tuple |
                 &AggregateKind::Adt(..) => {}
-                &AggregateKind::Closure(def_id, _) => {
+                &AggregateKind::Closure(def_id, _) |
+                &AggregateKind::Generator(def_id, _, _) => {
                     let UnsafetyCheckResult {
                         violations, unsafe_blocks
                     } = self.tcx.unsafety_check_result(def_id);
                     self.register_violations(&violations, &unsafe_blocks);
                 }
-                &AggregateKind::Generator(def_id, _, interior) => {
-                    let UnsafetyCheckResult {
-                        violations, unsafe_blocks
-                    } = self.tcx.unsafety_check_result(def_id);
-                    self.register_violations(&violations, &unsafe_blocks);
-                    if !interior.movable {
-                        self.require_unsafe("construction of immovable generator")
-                    }
-                }
             }
         }
         self.super_rvalue(rvalue, location);
index 4d0bd3f3412f1f7fd0933363af3779e4b0cd4807..abbce16b77cf669915abd73e32984efe60d11266 100644 (file)
@@ -178,7 +178,7 @@ fn generator(a: &Allocator, run_count: usize) {
          );
     };
     for _ in 0..run_count {
-        gen.resume();
+        unsafe { gen.resume(); }
     }
 }
 
index 8329684e1a39b8ad343a49ba97b9dbe39ca59e5a..3d39c46186be32bf10f578639f372ee96ecc03de 100644 (file)
@@ -42,9 +42,9 @@ fn t1() {
     };
 
     let n = A.load(Ordering::SeqCst);
-    a.resume();
+    unsafe { a.resume() };
     assert_eq!(A.load(Ordering::SeqCst), n + 1);
-    a.resume();
+    unsafe { a.resume() };
     assert_eq!(A.load(Ordering::SeqCst), n + 1);
 }
 
@@ -58,8 +58,8 @@ fn t2() {
     };
 
     let n = A.load(Ordering::SeqCst);
-    a.resume();
+    unsafe { a.resume() };
     assert_eq!(A.load(Ordering::SeqCst), n);
-    a.resume();
+    unsafe { a.resume() };
     assert_eq!(A.load(Ordering::SeqCst), n + 1);
 }
index 60a00b4e467569ebac0f00e18a7f86fdc70c3d20..09971410e556d051ffe7d4b93f2c7e719aa8bf5e 100644 (file)
@@ -16,7 +16,7 @@ fn finish<T>(mut amt: usize, mut t: T) -> T::Return
     where T: Generator<Yield = ()>
 {
     loop {
-        match t.resume() {
+        match unsafe { t.resume() } {
             GeneratorState::Yielded(()) => amt = amt.checked_sub(1).unwrap(),
             GeneratorState::Complete(ret) => {
                 assert_eq!(amt, 0);
index ac42a25899dbbc7a3f2be339e789c518c9f7de1a..ef4dc24472e61b08892f2668be1a06688b19b726 100644 (file)
@@ -37,7 +37,7 @@ fn t1() {
     };
 
     let n = A.load(Ordering::SeqCst);
-    drop(foo.resume());
+    drop(unsafe { foo.resume() });
     assert_eq!(A.load(Ordering::SeqCst), n);
     drop(foo);
     assert_eq!(A.load(Ordering::SeqCst), n + 1);
@@ -50,7 +50,7 @@ fn t2() {
     };
 
     let n = A.load(Ordering::SeqCst);
-    drop(foo.resume());
+    drop(unsafe { foo.resume() });
     assert_eq!(A.load(Ordering::SeqCst), n + 1);
     drop(foo);
     assert_eq!(A.load(Ordering::SeqCst), n + 1);
index 7cb80ea8b21b7403766a67d16c912278529fabf5..8ce4fc6affab38c3856e10d698fc3241935f9223 100644 (file)
@@ -35,6 +35,8 @@ fn bar2(baz: String) -> impl Generator<Yield = String, Return = ()> {
 }
 
 fn main() {
-    assert_eq!(bar(String::new()).resume(), GeneratorState::Yielded(String::new()));
-    assert_eq!(bar2(String::new()).resume(), GeneratorState::Complete(()));
+    unsafe {
+        assert_eq!(bar(String::new()).resume(), GeneratorState::Yielded(String::new()));
+        assert_eq!(bar2(String::new()).resume(), GeneratorState::Complete(()));
+    }
 }
index 9afe95f9e865cf957031b841b77cb4775a9db06c..654b18928c07796bf7ee42bfe4cd81169511b5c0 100644 (file)
 
 struct W<T>(T);
 
+// This impl isn't safe in general, but the generator used in this test is movable
+// so it won't cause problems.
 impl<T: Generator<Return = ()>> Iterator for W<T> {
     type Item = T::Yield;
 
     fn next(&mut self) -> Option<Self::Item> {
-        match self.0.resume() {
+        match unsafe { self.0.resume() } {
             GeneratorState::Complete(..) => None,
             GeneratorState::Yielded(v) => Some(v),
         }
index e34b0b3100c32983f865abd22f15561a8de12769..28e7da232ce09d38fbbc84ec293b4ccdf6ec8203 100644 (file)
@@ -17,5 +17,5 @@ fn main() {
     let mut a = || {
         b(yield);
     };
-    a.resume();
+    unsafe { a.resume() };
 }
index f70d4144a3c9ef4276899c9e31cb912007232df0..29808da85a7a9064ee9648b0d0ddcd3d05ba8e9d 100644 (file)
@@ -20,7 +20,7 @@ fn main() {
             yield 2;
         };
 
-        match sub_generator.resume() {
+        match unsafe { sub_generator.resume() } {
             GeneratorState::Yielded(x) => {
                 yield x;
             }
index 36e401a54bcddbebd11731d8682ccc9698006a89..3d7b60ab6b90132ee3d5e17c0d04f05ec0cf6b67 100644 (file)
@@ -42,7 +42,7 @@ fn main() {
 
     assert_eq!(A.load(Ordering::SeqCst), 0);
     let res = panic::catch_unwind(panic::AssertUnwindSafe(|| {
-        foo.resume()
+        unsafe { foo.resume() }
     }));
     assert!(res.is_err());
     assert_eq!(A.load(Ordering::SeqCst), 1);
@@ -57,7 +57,7 @@ fn main() {
 
     assert_eq!(A.load(Ordering::SeqCst), 1);
     let res = panic::catch_unwind(panic::AssertUnwindSafe(|| {
-        foo.resume()
+        unsafe { foo.resume() }
     }));
     assert!(res.is_err());
     assert_eq!(A.load(Ordering::SeqCst), 1);
index 0d5bae7876bd3bde4b091c5fee06d84ae1583338..ace5cdde51d85f726c2e17f65c46686d5b5074ba 100644 (file)
@@ -24,13 +24,13 @@ fn main() {
     };
 
     let res = panic::catch_unwind(panic::AssertUnwindSafe(|| {
-        foo.resume()
+        unsafe { foo.resume() }
     }));
     assert!(res.is_err());
 
     for _ in 0..10 {
         let res = panic::catch_unwind(panic::AssertUnwindSafe(|| {
-            foo.resume()
+            unsafe { foo.resume() }
         }));
         assert!(res.is_err());
     }
index 56511dcd53a6a93a3be76df26682d29f98b86cfb..06e7615d26191b3fe6aa403062af5c9f7ffd2d67 100644 (file)
@@ -23,12 +23,12 @@ fn main() {
         yield;
     };
 
-    match foo.resume() {
+    match unsafe { foo.resume() } {
         GeneratorState::Complete(()) => {}
         s => panic!("bad state: {:?}", s),
     }
 
-    match panic::catch_unwind(move || foo.resume()) {
+    match panic::catch_unwind(move || unsafe { foo.resume() }) {
         Ok(_) => panic!("generator successfully resumed"),
         Err(_) => {}
     }
index 8693964665d342c8a320fd2812b76673fea2d870..7395c8484c169acd16d937e1ea81ff1748860aa5 100644 (file)
@@ -24,7 +24,7 @@ fn simple() {
         }
     };
 
-    match foo.resume() {
+    match unsafe { foo.resume() } {
         GeneratorState::Complete(()) => {}
         s => panic!("bad state: {:?}", s),
     }
@@ -40,7 +40,7 @@ fn return_capture() {
         a
     };
 
-    match foo.resume() {
+    match unsafe { foo.resume() } {
         GeneratorState::Complete(ref s) if *s == "foo" => {}
         s => panic!("bad state: {:?}", s),
     }
@@ -52,11 +52,11 @@ fn simple_yield() {
         yield;
     };
 
-    match foo.resume() {
+    match unsafe { foo.resume() } {
         GeneratorState::Yielded(()) => {}
         s => panic!("bad state: {:?}", s),
     }
-    match foo.resume() {
+    match unsafe { foo.resume() } {
         GeneratorState::Complete(()) => {}
         s => panic!("bad state: {:?}", s),
     }
@@ -69,11 +69,11 @@ fn yield_capture() {
         yield b;
     };
 
-    match foo.resume() {
+    match unsafe { foo.resume() } {
         GeneratorState::Yielded(ref s) if *s == "foo" => {}
         s => panic!("bad state: {:?}", s),
     }
-    match foo.resume() {
+    match unsafe { foo.resume() } {
         GeneratorState::Complete(()) => {}
         s => panic!("bad state: {:?}", s),
     }
@@ -86,11 +86,11 @@ fn simple_yield_value() {
         return String::from("foo")
     };
 
-    match foo.resume() {
+    match unsafe { foo.resume() } {
         GeneratorState::Yielded(ref s) if *s == "bar" => {}
         s => panic!("bad state: {:?}", s),
     }
-    match foo.resume() {
+    match unsafe { foo.resume() } {
         GeneratorState::Complete(ref s) if *s == "foo" => {}
         s => panic!("bad state: {:?}", s),
     }
@@ -104,11 +104,11 @@ fn return_after_yield() {
         return a
     };
 
-    match foo.resume() {
+    match unsafe { foo.resume() } {
         GeneratorState::Yielded(()) => {}
         s => panic!("bad state: {:?}", s),
     }
-    match foo.resume() {
+    match unsafe { foo.resume() } {
         GeneratorState::Complete(ref s) if *s == "foo" => {}
         s => panic!("bad state: {:?}", s),
     }
@@ -156,11 +156,11 @@ fn assert_send_sync<T: Send + Sync>(_: T) {}
 fn send_over_threads() {
     let mut foo = || { yield };
     thread::spawn(move || {
-        match foo.resume() {
+        match unsafe { foo.resume() } {
             GeneratorState::Yielded(()) => {}
             s => panic!("bad state: {:?}", s),
         }
-        match foo.resume() {
+        match unsafe { foo.resume() } {
             GeneratorState::Complete(()) => {}
             s => panic!("bad state: {:?}", s),
         }
@@ -169,11 +169,11 @@ fn send_over_threads() {
     let a = String::from("a");
     let mut foo = || { yield a };
     thread::spawn(move || {
-        match foo.resume() {
+        match unsafe { foo.resume() } {
             GeneratorState::Yielded(ref s) if *s == "a" => {}
             s => panic!("bad state: {:?}", s),
         }
-        match foo.resume() {
+        match unsafe { foo.resume() } {
             GeneratorState::Complete(()) => {}
             s => panic!("bad state: {:?}", s),
         }
index 9504414d8b6f5768e79c3b29716e87e386b5bb80..ebc070eee09c1c7874d67c81fe414aa450e2d420 100644 (file)
 use std::ops::{Generator, GeneratorState};
 
 fn main() {
-    let mut generator = unsafe {
-        static || {
-            let a = true;
-            let b = &a;
-            yield;
-            assert_eq!(b as *const _, &a as *const _);
-        }
+    let mut generator = static || {
+        let a = true;
+        let b = &a;
+        yield;
+        assert_eq!(b as *const _, &a as *const _);
     };
-    assert_eq!(generator.resume(), GeneratorState::Yielded(()));
-    assert_eq!(generator.resume(), GeneratorState::Complete(()));
+    unsafe {
+        assert_eq!(generator.resume(), GeneratorState::Yielded(()));
+        assert_eq!(generator.resume(), GeneratorState::Complete(()));
+    }
 }
index dff5e08b9c20e3a54f0dafef49eb9c2cf227d20e..8eeb013314499e882b2c75c94af79ab70d9216bb 100644 (file)
@@ -17,5 +17,5 @@
 use std::ops::Generator;
 
 fn main() {
-    foo::foo().resume();
+    unsafe { foo::foo().resume(); }
 }
index dc7a6fdef9c7e76a4320f3b9b4fd3f4c9fcf647b..04791d51356772e52b93679abad2ce06f0717360 100644 (file)
 fn main() {
     let mut foo = xcrate::foo();
 
-    match foo.resume() {
+    match unsafe { foo.resume() } {
         GeneratorState::Complete(()) => {}
         s => panic!("bad state: {:?}", s),
     }
 
     let mut foo = xcrate::bar(3);
 
-    match foo.resume() {
+    match unsafe { foo.resume() } {
         GeneratorState::Yielded(3) => {}
         s => panic!("bad state: {:?}", s),
     }
-    match foo.resume() {
+    match unsafe { foo.resume() } {
         GeneratorState::Complete(()) => {}
         s => panic!("bad state: {:?}", s),
     }
index de10bdef4aee0585d496f20f497fd07c1b773638..e56927d81823131b1e38e66cbff0394b743489fe 100644 (file)
@@ -15,7 +15,7 @@
 fn main() {
     let _b = {
         let a = 3;
-        (|| yield &a).resume()
+        unsafe { (|| yield &a).resume() }
         //~^ ERROR: `a` does not live long enough
     };
 
index 2a5de3790ada94c3dafc9a8439cc3551ffd8cc0f..45d950b5aef646f9c24710e3159aa1fc1061a8ad 100644 (file)
@@ -1,10 +1,10 @@
 error[E0597]: `a` does not live long enough
-  --> $DIR/borrowing.rs:18:20
+  --> $DIR/borrowing.rs:18:29
    |
-LL |         (|| yield &a).resume()
-   |          --        ^ borrowed value does not live long enough
-   |          |
-   |          capture occurs here
+LL |         unsafe { (|| yield &a).resume() }
+   |                   --        ^ borrowed value does not live long enough
+   |                   |
+   |                   capture occurs here
 LL |         //~^ ERROR: `a` does not live long enough
 LL |     };
    |     - borrowed value only lives until here
index 0b143d7f5143ea9580595d35c6a0de11740d35d3..b2240fb225f58dd51045fd28580627e2d1bff70d 100644 (file)
@@ -23,6 +23,6 @@ fn main() {
         let _d = ref_.take(); //~ ERROR `ref_` does not live long enough
         yield;
     };
-    gen.resume();
+    unsafe { gen.resume(); }
     // drops the RefCell and then the Ref, leading to use-after-free
 }
index f38ebf8b9463669abdf23d6d63348ef5ee77ea06..a1c8ca77e41e8bf34ff228ae6c5470f98be8167a 100644 (file)
@@ -17,5 +17,5 @@ fn main() {
    let mut gen = move || { //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied
        yield s[..];
    };
-   gen.resume(); //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied
+   unsafe { gen.resume(); } //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied
 }
index fc99c7e3bd74751c07faef3225723c746c3d0910..957fac172c2588dd071245ec89e53b1bd7b5e1cd 100644 (file)
@@ -11,10 +11,10 @@ LL | |    };
    = note: the yield type of a generator must have a statically known size
 
 error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
-  --> $DIR/sized-yield.rs:20:8
+  --> $DIR/sized-yield.rs:20:17
    |
-LL |    gen.resume(); //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied
-   |        ^^^^^^ `str` does not have a constant size known at compile-time
+LL |    unsafe { gen.resume(); } //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied
+   |                 ^^^^^^ `str` does not have a constant size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `str`
 
diff --git a/src/test/ui/generator/unsafe-immovable.rs b/src/test/ui/generator/unsafe-immovable.rs
deleted file mode 100644 (file)
index 45acbf5..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// 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)]
-
-fn main() {
-    static || { //~ ERROR: construction of immovable generator requires unsafe
-        yield;
-    };
-}
diff --git a/src/test/ui/generator/unsafe-immovable.stderr b/src/test/ui/generator/unsafe-immovable.stderr
deleted file mode 100644 (file)
index b2add55..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0133]: construction of immovable generator requires unsafe function or block
-  --> $DIR/unsafe-immovable.rs:14:5
-   |
-LL | /     static || { //~ ERROR: construction of immovable generator requires unsafe
-LL | |         yield;
-LL | |     };
-   | |_____^ construction of immovable generator
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0133`.
index bc53448cb08e6d2ba02588aa1ebf91275bb599d2..b8a67a0e7b65d7a788a9667e15cb48a6e8c22796 100644 (file)
@@ -43,7 +43,7 @@ fn yield_during_iter_borrowed_slice_2() {
     println!("{:?}", x);
 }
 
-fn yield_during_iter_borrowed_slice_3() {
+unsafe fn yield_during_iter_borrowed_slice_3() {
     // OK to take a mutable ref to `x` and yield
     // up pointers from it:
     let mut x = vec![22_i32];
@@ -55,7 +55,7 @@ fn yield_during_iter_borrowed_slice_3() {
     b.resume();
 }
 
-fn yield_during_iter_borrowed_slice_4() {
+unsafe fn yield_during_iter_borrowed_slice_4() {
     // ...but not OK to do that while reading
     // from `x` too
     let mut x = vec![22_i32];
@@ -68,7 +68,7 @@ fn yield_during_iter_borrowed_slice_4() {
     b.resume();
 }
 
-fn yield_during_range_iter() {
+unsafe fn yield_during_range_iter() {
     // Should be OK.
     let mut b = || {
         let v = vec![1,2,3];
index 11bd4ed05caca7082ab05294b1a5ffd635770bcc..3dc2650a2ecbf5e649f009af80cc347957e00cb2 100644 (file)
@@ -15,7 +15,7 @@
 use std::ops::{GeneratorState, Generator};
 use std::cell::Cell;
 
-fn borrow_local_inline() {
+unsafe fn borrow_local_inline() {
     // Not OK to yield with a borrow of a temporary.
     //
     // (This error occurs because the region shows up in the type of
@@ -30,7 +30,7 @@ fn borrow_local_inline() {
     b.resume();
 }
 
-fn borrow_local_inline_done() {
+unsafe fn borrow_local_inline_done() {
     // No error here -- `a` is not in scope at the point of `yield`.
     let mut b = move || {
         {
@@ -41,7 +41,7 @@ fn borrow_local_inline_done() {
     b.resume();
 }
 
-fn borrow_local() {
+unsafe fn borrow_local() {
     // Not OK to yield with a borrow of a temporary.
     //
     // (This error occurs because the region shows up in the type of
index b9c963ae740777a55a2cc5163da6dec4edecb1b9..573dd4377bb2c170629b05d169358f40e464aee3 100644 (file)
@@ -13,7 +13,7 @@
 use std::ops::{GeneratorState, Generator};
 use std::cell::Cell;
 
-fn reborrow_shared_ref(x: &i32) {
+unsafe fn reborrow_shared_ref(x: &i32) {
     // This is OK -- we have a borrow live over the yield, but it's of
     // data that outlives the generator.
     let mut b = move || {
@@ -24,7 +24,7 @@ fn reborrow_shared_ref(x: &i32) {
     b.resume();
 }
 
-fn reborrow_mutable_ref(x: &mut i32) {
+unsafe fn reborrow_mutable_ref(x: &mut i32) {
     // This is OK -- we have a borrow live over the yield, but it's of
     // data that outlives the generator.
     let mut b = move || {
@@ -35,7 +35,7 @@ fn reborrow_mutable_ref(x: &mut i32) {
     b.resume();
 }
 
-fn reborrow_mutable_ref_2(x: &mut i32) {
+unsafe fn reborrow_mutable_ref_2(x: &mut i32) {
     // ...but not OK to go on using `x`.
     let mut b = || {
         let a = &mut *x;