diff --git a/src/doc/unstable-book/src/language-features/generators.md b/src/doc/unstable-book/src/language-features/generators.md index 968534e58bd..426fc01a6b0 100644 --- a/src/doc/unstable-book/src/language-features/generators.md +++ b/src/doc/unstable-book/src/language-features/generators.md @@ -29,6 +29,7 @@ A syntactical example of a generator is: #![feature(generators, generator_trait)] use std::ops::{Generator, GeneratorState}; +use std::pin::Pin; fn main() { let mut generator = || { @@ -36,11 +37,11 @@ fn main() { return "foo" }; - match unsafe { generator.resume() } { + match Pin::new(&mut generator).resume() { GeneratorState::Yielded(1) => {} _ => panic!("unexpected value from resume"), } - match unsafe { generator.resume() } { + match Pin::new(&mut generator).resume() { GeneratorState::Complete("foo") => {} _ => panic!("unexpected value from resume"), } @@ -60,6 +61,7 @@ prints all numbers in order: #![feature(generators, generator_trait)] use std::ops::Generator; +use std::pin::Pin; fn main() { let mut generator = || { @@ -69,9 +71,9 @@ fn main() { }; println!("1"); - unsafe { generator.resume() }; + Pin::new(&mut generator).resume(); println!("3"); - unsafe { generator.resume() }; + Pin::new(&mut generator).resume(); println!("5"); } ``` @@ -86,13 +88,14 @@ Feedback on the design and usage is always appreciated! The `Generator` trait in `std::ops` currently looks like: ``` -# #![feature(generator_trait)] +# #![feature(arbitrary_self_types, generator_trait)] # use std::ops::GeneratorState; +# use std::pin::Pin; pub trait Generator { type Yield; type Return; - unsafe fn resume(&mut self) -> GeneratorState; + fn resume(self: Pin<&mut Self>) -> GeneratorState; } ``` @@ -167,6 +170,7 @@ Let's take a look at an example to see what's going on here: #![feature(generators, generator_trait)] use std::ops::Generator; +use std::pin::Pin; fn main() { let ret = "foo"; @@ -175,17 +179,18 @@ fn main() { return ret }; - unsafe { generator.resume() }; - unsafe { generator.resume() }; + Pin::new(&mut generator).resume(); + Pin::new(&mut generator).resume(); } ``` This generator literal will compile down to something similar to: ```rust -#![feature(generators, generator_trait)] +#![feature(arbitrary_self_types, generators, generator_trait)] use std::ops::{Generator, GeneratorState}; +use std::pin::Pin; fn main() { let ret = "foo"; @@ -200,9 +205,9 @@ fn main() { type Yield = i32; type Return = &'static str; - unsafe fn resume(&mut self) -> GeneratorState { + fn resume(mut self: Pin<&mut Self>) -> GeneratorState { use std::mem; - match mem::replace(self, __Generator::Done) { + match mem::replace(&mut *self, __Generator::Done) { __Generator::Start(s) => { *self = __Generator::Yield1(s); GeneratorState::Yielded(1) @@ -223,8 +228,8 @@ fn main() { __Generator::Start(ret) }; - unsafe { generator.resume() }; - unsafe { generator.resume() }; + Pin::new(&mut generator).resume(); + Pin::new(&mut generator).resume(); } ``` diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 1c459f5c425..1fd8aa98cc3 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -873,13 +873,12 @@ impl AsMut for Box { impl Unpin for Box { } #[unstable(feature = "generator_trait", issue = "43122")] -impl Generator for Box - where T: Generator + ?Sized -{ - type Yield = T::Yield; - type Return = T::Return; - unsafe fn resume(&mut self) -> GeneratorState { - (**self).resume() +impl Generator for Box { + type Yield = G::Yield; + type Return = G::Return; + + fn resume(mut self: Pin<&mut Self>) -> GeneratorState { + G::resume(Pin::new(&mut *self)) } } diff --git a/src/libcore/ops/generator.rs b/src/libcore/ops/generator.rs index 1542cd6397e..5401fff860e 100644 --- a/src/libcore/ops/generator.rs +++ b/src/libcore/ops/generator.rs @@ -1,3 +1,6 @@ +use crate::marker::Unpin; +use crate::pin::Pin; + /// The result of a generator resumption. /// /// This enum is returned from the `Generator::resume` method and indicates the @@ -39,6 +42,7 @@ pub enum GeneratorState { /// #![feature(generators, generator_trait)] /// /// use std::ops::{Generator, GeneratorState}; +/// use std::pin::Pin; /// /// fn main() { /// let mut generator = || { @@ -46,11 +50,11 @@ pub enum GeneratorState { /// return "foo" /// }; /// -/// match unsafe { generator.resume() } { +/// match Pin::new(&mut generator).resume() { /// GeneratorState::Yielded(1) => {} /// _ => panic!("unexpected return from resume"), /// } -/// match unsafe { generator.resume() } { +/// match Pin::new(&mut generator).resume() { /// GeneratorState::Complete("foo") => {} /// _ => panic!("unexpected return from resume"), /// } @@ -88,10 +92,6 @@ 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 @@ -110,16 +110,25 @@ 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. - unsafe fn resume(&mut self) -> GeneratorState; + fn resume(self: Pin<&mut Self>) -> GeneratorState; } #[unstable(feature = "generator_trait", issue = "43122")] -impl Generator for &mut T - where T: Generator + ?Sized -{ - type Yield = T::Yield; - type Return = T::Return; - unsafe fn resume(&mut self) -> GeneratorState { - (**self).resume() +impl Generator for Pin<&mut G> { + type Yield = G::Yield; + type Return = G::Return; + + fn resume(mut self: Pin<&mut Self>) -> GeneratorState { + G::resume((*self).as_mut()) + } +} + +#[unstable(feature = "generator_trait", issue = "43122")] +impl Generator for &mut G { + type Yield = G::Yield; + type Return = G::Return; + + fn resume(mut self: Pin<&mut Self>) -> GeneratorState { + G::resume(Pin::new(&mut *self)) } } diff --git a/src/librustc_mir/diagnostics.rs b/src/librustc_mir/diagnostics.rs index 74394165a5f..eb721754216 100644 --- a/src/librustc_mir/diagnostics.rs +++ b/src/librustc_mir/diagnostics.rs @@ -2119,14 +2119,15 @@ This error occurs because a borrow in a generator persists across a yield point. ```compile_fail,E0626 -# #![feature(generators, generator_trait)] +# #![feature(generators, generator_trait, pin)] # use std::ops::Generator; +# use std::pin::Pin; let mut b = || { let a = &String::new(); // <-- This borrow... yield (); // ...is still in scope here, when the yield occurs. println!("{}", a); }; -unsafe { b.resume() }; +Pin::new(&mut b).resume(); ``` At present, it is not permitted to have a yield that occurs while a @@ -2137,14 +2138,15 @@ resolve the previous example by removing the borrow and just storing the integer by value: ``` -# #![feature(generators, generator_trait)] +# #![feature(generators, generator_trait, pin)] # use std::ops::Generator; +# use std::pin::Pin; let mut b = || { let a = 3; yield (); println!("{}", a); }; -unsafe { b.resume() }; +Pin::new(&mut b).resume(); ``` This is a very simple case, of course. In more complex cases, we may @@ -2154,37 +2156,40 @@ in those cases, something like the `Rc` or `Arc` types may be useful. This error also frequently arises with iteration: ```compile_fail,E0626 -# #![feature(generators, generator_trait)] +# #![feature(generators, generator_trait, pin)] # use std::ops::Generator; +# use std::pin::Pin; let mut b = || { let v = vec![1,2,3]; for &x in &v { // <-- borrow of `v` is still in scope... yield x; // ...when this yield occurs. } }; -unsafe { b.resume() }; +Pin::new(&mut b).resume(); ``` Such cases can sometimes be resolved by iterating "by value" (or using `into_iter()`) to avoid borrowing: ``` -# #![feature(generators, generator_trait)] +# #![feature(generators, generator_trait, pin)] # use std::ops::Generator; +# use std::pin::Pin; let mut b = || { let v = vec![1,2,3]; for x in v { // <-- Take ownership of the values instead! yield x; // <-- Now yield is OK. } }; -unsafe { b.resume() }; +Pin::new(&mut b).resume(); ``` If taking ownership is not an option, using indices can work too: ``` -# #![feature(generators, generator_trait)] +# #![feature(generators, generator_trait, pin)] # use std::ops::Generator; +# use std::pin::Pin; let mut b = || { let v = vec![1,2,3]; let len = v.len(); // (*) @@ -2193,7 +2198,7 @@ let mut b = || { yield x; // <-- Now yield is OK. } }; -unsafe { b.resume() }; +Pin::new(&mut b).resume(); // (*) -- Unfortunately, these temporaries are currently required. // See . diff --git a/src/libstd/future.rs b/src/libstd/future.rs index 22900c3067b..d1203be3cf0 100644 --- a/src/libstd/future.rs +++ b/src/libstd/future.rs @@ -33,7 +33,9 @@ impl> !Unpin for GenFuture {} impl> Future for GenFuture { type Output = T::Return; fn poll(self: Pin<&mut Self>, lw: &LocalWaker) -> Poll { - set_task_waker(lw, || match unsafe { Pin::get_unchecked_mut(self).0.resume() } { + // Safe because we're !Unpin + !Drop mapping to a ?Unpin value + let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) }; + set_task_waker(lw, || match gen.resume() { GeneratorState::Yielded(()) => Poll::Pending, GeneratorState::Complete(x) => Poll::Ready(x), }) diff --git a/src/test/run-pass/drop/dynamic-drop.rs b/src/test/run-pass/drop/dynamic-drop.rs index 41814f2af16..97e4cded80b 100644 --- a/src/test/run-pass/drop/dynamic-drop.rs +++ b/src/test/run-pass/drop/dynamic-drop.rs @@ -12,6 +12,7 @@ use std::cell::{Cell, RefCell}; use std::ops::Generator; use std::panic; +use std::pin::Pin; use std::usize; struct InjectedFailure; @@ -172,7 +173,7 @@ fn generator(a: &Allocator, run_count: usize) { ); }; for _ in 0..run_count { - unsafe { gen.resume(); } + Pin::new(&mut gen).resume(); } } diff --git a/src/test/run-pass/generator/auxiliary/xcrate.rs b/src/test/run-pass/generator/auxiliary/xcrate.rs index 8e08de28bc6..831c248bf90 100644 --- a/src/test/run-pass/generator/auxiliary/xcrate.rs +++ b/src/test/run-pass/generator/auxiliary/xcrate.rs @@ -1,5 +1,6 @@ #![feature(generators, generator_trait)] +use std::marker::Unpin; use std::ops::Generator; pub fn foo() -> impl Generator { @@ -10,7 +11,7 @@ pub fn foo() -> impl Generator { } } -pub fn bar(t: T) -> Box> { +pub fn bar(t: T) -> Box + Unpin> { Box::new(|| { yield t; }) diff --git a/src/test/run-pass/generator/conditional-drop.rs b/src/test/run-pass/generator/conditional-drop.rs index 766eef9e3f3..907f7a3c06d 100644 --- a/src/test/run-pass/generator/conditional-drop.rs +++ b/src/test/run-pass/generator/conditional-drop.rs @@ -3,6 +3,7 @@ #![feature(generators, generator_trait)] use std::ops::Generator; +use std::pin::Pin; use std::sync::atomic::{AtomicUsize, Ordering}; static A: AtomicUsize = AtomicUsize::new(0); @@ -34,9 +35,9 @@ fn t1() { }; let n = A.load(Ordering::SeqCst); - unsafe { a.resume() }; + Pin::new(&mut a).resume(); assert_eq!(A.load(Ordering::SeqCst), n + 1); - unsafe { a.resume() }; + Pin::new(&mut a).resume(); assert_eq!(A.load(Ordering::SeqCst), n + 1); } @@ -50,8 +51,8 @@ fn t2() { }; let n = A.load(Ordering::SeqCst); - unsafe { a.resume() }; + Pin::new(&mut a).resume(); assert_eq!(A.load(Ordering::SeqCst), n); - unsafe { a.resume() }; + Pin::new(&mut a).resume(); assert_eq!(A.load(Ordering::SeqCst), n + 1); } diff --git a/src/test/run-pass/generator/control-flow.rs b/src/test/run-pass/generator/control-flow.rs index 2f499834796..df70e013bd3 100644 --- a/src/test/run-pass/generator/control-flow.rs +++ b/src/test/run-pass/generator/control-flow.rs @@ -2,13 +2,15 @@ #![feature(generators, generator_trait)] +use std::marker::Unpin; use std::ops::{GeneratorState, Generator}; +use std::pin::Pin; fn finish(mut amt: usize, mut t: T) -> T::Return - where T: Generator + where T: Generator + Unpin, { loop { - match unsafe { t.resume() } { + match Pin::new(&mut t).resume() { GeneratorState::Yielded(()) => amt = amt.checked_sub(1).unwrap(), GeneratorState::Complete(ret) => { assert_eq!(amt, 0); diff --git a/src/test/run-pass/generator/drop-env.rs b/src/test/run-pass/generator/drop-env.rs index 252f2c0f07d..ac4e0665628 100644 --- a/src/test/run-pass/generator/drop-env.rs +++ b/src/test/run-pass/generator/drop-env.rs @@ -3,6 +3,7 @@ #![feature(generators, generator_trait)] use std::ops::Generator; +use std::pin::Pin; use std::sync::atomic::{AtomicUsize, Ordering}; static A: AtomicUsize = AtomicUsize::new(0); @@ -29,7 +30,7 @@ fn t1() { }; let n = A.load(Ordering::SeqCst); - drop(unsafe { foo.resume() }); + drop(Pin::new(&mut foo).resume()); assert_eq!(A.load(Ordering::SeqCst), n); drop(foo); assert_eq!(A.load(Ordering::SeqCst), n + 1); @@ -42,7 +43,7 @@ fn t2() { }; let n = A.load(Ordering::SeqCst); - drop(unsafe { foo.resume() }); + drop(Pin::new(&mut foo).resume()); assert_eq!(A.load(Ordering::SeqCst), n + 1); drop(foo); assert_eq!(A.load(Ordering::SeqCst), n + 1); diff --git a/src/test/run-pass/generator/issue-44197.rs b/src/test/run-pass/generator/issue-44197.rs index 4a6e5b88b23..6efaff50c1e 100644 --- a/src/test/run-pass/generator/issue-44197.rs +++ b/src/test/run-pass/generator/issue-44197.rs @@ -3,6 +3,7 @@ #![feature(generators, generator_trait)] use std::ops::{ Generator, GeneratorState }; +use std::pin::Pin; fn foo(_: &str) -> String { String::new() @@ -27,8 +28,6 @@ fn bar2(baz: String) -> impl Generator { } fn main() { - unsafe { - assert_eq!(bar(String::new()).resume(), GeneratorState::Yielded(String::new())); - assert_eq!(bar2(String::new()).resume(), GeneratorState::Complete(())); - } + assert_eq!(Pin::new(&mut bar(String::new())).resume(), GeneratorState::Yielded(String::new())); + assert_eq!(Pin::new(&mut bar2(String::new())).resume(), GeneratorState::Complete(())); } diff --git a/src/test/run-pass/generator/iterator-count.rs b/src/test/run-pass/generator/iterator-count.rs index 1011d54bdb3..ac7e122dd58 100644 --- a/src/test/run-pass/generator/iterator-count.rs +++ b/src/test/run-pass/generator/iterator-count.rs @@ -2,24 +2,26 @@ #![feature(generators, generator_trait)] +use std::marker::Unpin; use std::ops::{GeneratorState, Generator}; +use std::pin::Pin; struct W(T); // This impl isn't safe in general, but the generator used in this test is movable // so it won't cause problems. -impl> Iterator for W { +impl + Unpin> Iterator for W { type Item = T::Yield; fn next(&mut self) -> Option { - match unsafe { self.0.resume() } { + match Pin::new(&mut self.0).resume() { GeneratorState::Complete(..) => None, GeneratorState::Yielded(v) => Some(v), } } } -fn test() -> impl Generator { +fn test() -> impl Generator + Unpin { || { for i in 1..6 { yield i diff --git a/src/test/run-pass/generator/live-upvar-across-yield.rs b/src/test/run-pass/generator/live-upvar-across-yield.rs index b643809e503..a1064165b2f 100644 --- a/src/test/run-pass/generator/live-upvar-across-yield.rs +++ b/src/test/run-pass/generator/live-upvar-across-yield.rs @@ -3,11 +3,12 @@ #![feature(generators, generator_trait)] use std::ops::Generator; +use std::pin::Pin; fn main() { let b = |_| 3; let mut a = || { b(yield); }; - unsafe { a.resume() }; + Pin::new(&mut a).resume(); } diff --git a/src/test/run-pass/generator/nested_generators.rs b/src/test/run-pass/generator/nested_generators.rs index e837e5fc9c1..b56cce1dc44 100644 --- a/src/test/run-pass/generator/nested_generators.rs +++ b/src/test/run-pass/generator/nested_generators.rs @@ -1,10 +1,9 @@ // run-pass -#![feature(generators)] -#![feature(generator_trait)] +#![feature(generators, generator_trait)] -use std::ops::Generator; -use std::ops::GeneratorState; +use std::ops::{Generator, GeneratorState}; +use std::pin::Pin; fn main() { let _generator = || { @@ -12,7 +11,7 @@ fn main() { yield 2; }; - match unsafe { sub_generator.resume() } { + match Pin::new(&mut sub_generator).resume() { GeneratorState::Yielded(x) => { yield x; } diff --git a/src/test/run-pass/generator/panic-drops.rs b/src/test/run-pass/generator/panic-drops.rs index 8640a653919..5ac97585f4b 100644 --- a/src/test/run-pass/generator/panic-drops.rs +++ b/src/test/run-pass/generator/panic-drops.rs @@ -6,6 +6,7 @@ use std::ops::Generator; use std::panic; +use std::pin::Pin; use std::sync::atomic::{AtomicUsize, Ordering}; static A: AtomicUsize = AtomicUsize::new(0); @@ -34,7 +35,7 @@ fn main() { assert_eq!(A.load(Ordering::SeqCst), 0); let res = panic::catch_unwind(panic::AssertUnwindSafe(|| { - unsafe { foo.resume() } + Pin::new(&mut foo).resume() })); assert!(res.is_err()); assert_eq!(A.load(Ordering::SeqCst), 1); @@ -49,7 +50,7 @@ fn main() { assert_eq!(A.load(Ordering::SeqCst), 1); let res = panic::catch_unwind(panic::AssertUnwindSafe(|| { - unsafe { foo.resume() } + Pin::new(&mut foo).resume() })); assert!(res.is_err()); assert_eq!(A.load(Ordering::SeqCst), 1); diff --git a/src/test/run-pass/generator/panic-safe.rs b/src/test/run-pass/generator/panic-safe.rs index 134debdd23b..5f6778674dc 100644 --- a/src/test/run-pass/generator/panic-safe.rs +++ b/src/test/run-pass/generator/panic-safe.rs @@ -5,6 +5,7 @@ #![feature(generators, generator_trait)] use std::ops::Generator; +use std::pin::Pin; use std::panic; fn main() { @@ -16,13 +17,13 @@ fn main() { }; let res = panic::catch_unwind(panic::AssertUnwindSafe(|| { - unsafe { foo.resume() } + Pin::new(&mut foo).resume() })); assert!(res.is_err()); for _ in 0..10 { let res = panic::catch_unwind(panic::AssertUnwindSafe(|| { - unsafe { foo.resume() } + Pin::new(&mut foo).resume() })); assert!(res.is_err()); } diff --git a/src/test/run-pass/generator/resume-after-return.rs b/src/test/run-pass/generator/resume-after-return.rs index 2213c2f3fba..71a68ff684a 100644 --- a/src/test/run-pass/generator/resume-after-return.rs +++ b/src/test/run-pass/generator/resume-after-return.rs @@ -5,6 +5,7 @@ #![feature(generators, generator_trait)] use std::ops::{GeneratorState, Generator}; +use std::pin::Pin; use std::panic; fn main() { @@ -15,12 +16,12 @@ fn main() { yield; }; - match unsafe { foo.resume() } { + match Pin::new(&mut foo).resume() { GeneratorState::Complete(()) => {} s => panic!("bad state: {:?}", s), } - match panic::catch_unwind(move || unsafe { foo.resume() }) { + match panic::catch_unwind(move || Pin::new(&mut foo).resume()) { Ok(_) => panic!("generator successfully resumed"), Err(_) => {} } diff --git a/src/test/run-pass/generator/smoke.rs b/src/test/run-pass/generator/smoke.rs index 8582941d610..533f2399084 100644 --- a/src/test/run-pass/generator/smoke.rs +++ b/src/test/run-pass/generator/smoke.rs @@ -6,6 +6,7 @@ #![feature(generators, generator_trait)] use std::ops::{GeneratorState, Generator}; +use std::pin::Pin; use std::thread; #[test] @@ -16,7 +17,7 @@ fn simple() { } }; - match unsafe { foo.resume() } { + match Pin::new(&mut foo).resume() { GeneratorState::Complete(()) => {} s => panic!("bad state: {:?}", s), } @@ -32,7 +33,7 @@ fn return_capture() { a }; - match unsafe { foo.resume() } { + match Pin::new(&mut foo).resume() { GeneratorState::Complete(ref s) if *s == "foo" => {} s => panic!("bad state: {:?}", s), } @@ -44,11 +45,11 @@ fn simple_yield() { yield; }; - match unsafe { foo.resume() } { + match Pin::new(&mut foo).resume() { GeneratorState::Yielded(()) => {} s => panic!("bad state: {:?}", s), } - match unsafe { foo.resume() } { + match Pin::new(&mut foo).resume() { GeneratorState::Complete(()) => {} s => panic!("bad state: {:?}", s), } @@ -61,11 +62,11 @@ fn yield_capture() { yield b; }; - match unsafe { foo.resume() } { + match Pin::new(&mut foo).resume() { GeneratorState::Yielded(ref s) if *s == "foo" => {} s => panic!("bad state: {:?}", s), } - match unsafe { foo.resume() } { + match Pin::new(&mut foo).resume() { GeneratorState::Complete(()) => {} s => panic!("bad state: {:?}", s), } @@ -78,11 +79,11 @@ fn simple_yield_value() { return String::from("foo") }; - match unsafe { foo.resume() } { + match Pin::new(&mut foo).resume() { GeneratorState::Yielded(ref s) if *s == "bar" => {} s => panic!("bad state: {:?}", s), } - match unsafe { foo.resume() } { + match Pin::new(&mut foo).resume() { GeneratorState::Complete(ref s) if *s == "foo" => {} s => panic!("bad state: {:?}", s), } @@ -96,11 +97,11 @@ fn return_after_yield() { return a }; - match unsafe { foo.resume() } { + match Pin::new(&mut foo).resume() { GeneratorState::Yielded(()) => {} s => panic!("bad state: {:?}", s), } - match unsafe { foo.resume() } { + match Pin::new(&mut foo).resume() { GeneratorState::Complete(ref s) if *s == "foo" => {} s => panic!("bad state: {:?}", s), } @@ -148,11 +149,11 @@ fn send_and_sync() { fn send_over_threads() { let mut foo = || { yield }; thread::spawn(move || { - match unsafe { foo.resume() } { + match Pin::new(&mut foo).resume() { GeneratorState::Yielded(()) => {} s => panic!("bad state: {:?}", s), } - match unsafe { foo.resume() } { + match Pin::new(&mut foo).resume() { GeneratorState::Complete(()) => {} s => panic!("bad state: {:?}", s), } @@ -161,11 +162,11 @@ fn send_over_threads() { let a = String::from("a"); let mut foo = || { yield a }; thread::spawn(move || { - match unsafe { foo.resume() } { + match Pin::new(&mut foo).resume() { GeneratorState::Yielded(ref s) if *s == "a" => {} s => panic!("bad state: {:?}", s), } - match unsafe { foo.resume() } { + match Pin::new(&mut foo).resume() { GeneratorState::Complete(()) => {} s => panic!("bad state: {:?}", s), } diff --git a/src/test/run-pass/generator/static-generators.rs b/src/test/run-pass/generator/static-generators.rs index eeaba3fe3c4..965d3c61c22 100644 --- a/src/test/run-pass/generator/static-generators.rs +++ b/src/test/run-pass/generator/static-generators.rs @@ -2,6 +2,7 @@ #![feature(generators, generator_trait)] +use std::pin::Pin; use std::ops::{Generator, GeneratorState}; fn main() { @@ -11,8 +12,9 @@ fn main() { yield; assert_eq!(b as *const _, &a as *const _); }; - unsafe { - assert_eq!(generator.resume(), GeneratorState::Yielded(())); - assert_eq!(generator.resume(), GeneratorState::Complete(())); - } + // Safety: We shadow the original generator variable so have no safe API to + // move it after this point. + let mut generator = unsafe { Pin::new_unchecked(&mut generator) }; + assert_eq!(generator.as_mut().resume(), GeneratorState::Yielded(())); + assert_eq!(generator.as_mut().resume(), GeneratorState::Complete(())); } diff --git a/src/test/run-pass/generator/xcrate-reachable.rs b/src/test/run-pass/generator/xcrate-reachable.rs index 403c920786e..9483ad7395e 100644 --- a/src/test/run-pass/generator/xcrate-reachable.rs +++ b/src/test/run-pass/generator/xcrate-reachable.rs @@ -7,7 +7,8 @@ extern crate xcrate_reachable as foo; use std::ops::Generator; +use std::pin::Pin; fn main() { - unsafe { foo::foo().resume(); } + Pin::new(&mut foo::foo()).resume(); } diff --git a/src/test/run-pass/generator/xcrate.rs b/src/test/run-pass/generator/xcrate.rs index 571b8fa9170..febf5c3583f 100644 --- a/src/test/run-pass/generator/xcrate.rs +++ b/src/test/run-pass/generator/xcrate.rs @@ -7,22 +7,23 @@ extern crate xcrate; use std::ops::{GeneratorState, Generator}; +use std::pin::Pin; fn main() { let mut foo = xcrate::foo(); - match unsafe { foo.resume() } { + match Pin::new(&mut foo).resume() { GeneratorState::Complete(()) => {} s => panic!("bad state: {:?}", s), } let mut foo = xcrate::bar(3); - match unsafe { foo.resume() } { + match Pin::new(&mut foo).resume() { GeneratorState::Yielded(3) => {} s => panic!("bad state: {:?}", s), } - match unsafe { foo.resume() } { + match Pin::new(&mut foo).resume() { GeneratorState::Complete(()) => {} s => panic!("bad state: {:?}", s), } diff --git a/src/test/ui/generator/borrowing.nll.stderr b/src/test/ui/generator/borrowing.nll.stderr index af6ec4941d8..3c9221d28e7 100644 --- a/src/test/ui/generator/borrowing.nll.stderr +++ b/src/test/ui/generator/borrowing.nll.stderr @@ -1,12 +1,12 @@ error[E0597]: `a` does not live long enough - --> $DIR/borrowing.rs:8:29 + --> $DIR/borrowing.rs:9:33 | -LL | unsafe { (|| yield &a).resume() } - | -----------^- - | || | - | || borrowed value does not live long enough - | |value captured here by generator - | a temporary with access to the borrow is created here ... +LL | Pin::new(&mut || yield &a).resume() + | ----------^ + | | | + | | borrowed value does not live long enough + | value captured here by generator + | a temporary with access to the borrow is created here ... LL | //~^ ERROR: `a` does not live long enough LL | }; | -- ... and the borrow might be used here, when that temporary is dropped and runs the destructor for generator @@ -16,7 +16,7 @@ LL | }; = note: The temporary is part of an expression at the end of a block. Consider forcing this temporary to be dropped sooner, before the block's local variables are dropped. For example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block. error[E0597]: `a` does not live long enough - --> $DIR/borrowing.rs:15:20 + --> $DIR/borrowing.rs:16:20 | LL | let _b = { | -- borrow later stored here diff --git a/src/test/ui/generator/borrowing.rs b/src/test/ui/generator/borrowing.rs index 88a0cf9a77a..9f8fc7483f6 100644 --- a/src/test/ui/generator/borrowing.rs +++ b/src/test/ui/generator/borrowing.rs @@ -1,11 +1,12 @@ #![feature(generators, generator_trait)] use std::ops::Generator; +use std::pin::Pin; fn main() { let _b = { let a = 3; - unsafe { (|| yield &a).resume() } + Pin::new(&mut || yield &a).resume() //~^ ERROR: `a` does not live long enough }; diff --git a/src/test/ui/generator/borrowing.stderr b/src/test/ui/generator/borrowing.stderr index 3f5d32e1c33..169e4a8561c 100644 --- a/src/test/ui/generator/borrowing.stderr +++ b/src/test/ui/generator/borrowing.stderr @@ -1,10 +1,10 @@ error[E0597]: `a` does not live long enough - --> $DIR/borrowing.rs:8:29 + --> $DIR/borrowing.rs:9:33 | -LL | unsafe { (|| yield &a).resume() } - | -- ^ borrowed value does not live long enough - | | - | capture occurs here +LL | Pin::new(&mut || 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 @@ -13,7 +13,7 @@ LL | } | - borrowed value needs to live until here error[E0597]: `a` does not live long enough - --> $DIR/borrowing.rs:15:20 + --> $DIR/borrowing.rs:16:20 | LL | || { | -- capture occurs here diff --git a/src/test/ui/generator/dropck.nll.stderr b/src/test/ui/generator/dropck.nll.stderr index 1f6b7db2bd8..a90a47fe9aa 100644 --- a/src/test/ui/generator/dropck.nll.stderr +++ b/src/test/ui/generator/dropck.nll.stderr @@ -1,5 +1,5 @@ error[E0597]: `*cell` does not live long enough - --> $DIR/dropck.rs:9:40 + --> $DIR/dropck.rs:10:40 | LL | let ref_ = Box::leak(Box::new(Some(cell.borrow_mut()))); | ^^^^ borrowed value does not live long enough @@ -13,7 +13,7 @@ LL | } = note: values in a scope are dropped in the opposite order they are defined error[E0597]: `ref_` does not live long enough - --> $DIR/dropck.rs:14:18 + --> $DIR/dropck.rs:15:18 | LL | gen = || { | -- value captured here by generator diff --git a/src/test/ui/generator/dropck.rs b/src/test/ui/generator/dropck.rs index 1b0c1ebe517..65c61fbaac4 100644 --- a/src/test/ui/generator/dropck.rs +++ b/src/test/ui/generator/dropck.rs @@ -2,6 +2,7 @@ use std::cell::RefCell; use std::ops::Generator; +use std::pin::Pin; fn main() { let (mut gen, cell); @@ -14,6 +15,6 @@ fn main() { let _d = ref_.take(); //~ ERROR `ref_` does not live long enough yield; }; - unsafe { gen.resume(); } + Pin::new(&mut gen).resume(); // drops the RefCell and then the Ref, leading to use-after-free } diff --git a/src/test/ui/generator/dropck.stderr b/src/test/ui/generator/dropck.stderr index 281c9647bc3..fdaa5cfbae3 100644 --- a/src/test/ui/generator/dropck.stderr +++ b/src/test/ui/generator/dropck.stderr @@ -1,5 +1,5 @@ error[E0597]: `*cell` does not live long enough - --> $DIR/dropck.rs:9:40 + --> $DIR/dropck.rs:10:40 | LL | let ref_ = Box::leak(Box::new(Some(cell.borrow_mut()))); | ^^^^ borrowed value does not live long enough @@ -10,7 +10,7 @@ LL | } = note: values in a scope are dropped in the opposite order they are created error[E0597]: `ref_` does not live long enough - --> $DIR/dropck.rs:14:18 + --> $DIR/dropck.rs:15:18 | LL | gen = || { | -- capture occurs here diff --git a/src/test/ui/generator/generator-region-requirements.ast.stderr b/src/test/ui/generator/generator-region-requirements.ast.stderr index 6a423aea7ec..8a96d187f6b 100644 --- a/src/test/ui/generator/generator-region-requirements.ast.stderr +++ b/src/test/ui/generator/generator-region-requirements.ast.stderr @@ -1,5 +1,5 @@ error[E0621]: explicit lifetime required in the type of `x` - --> $DIR/generator-region-requirements.rs:15:51 + --> $DIR/generator-region-requirements.rs:16:51 | LL | fn dangle(x: &mut i32) -> &'static mut i32 { | -------- help: add explicit lifetime `'static` to the type of `x`: `&'static mut i32` diff --git a/src/test/ui/generator/generator-region-requirements.nll.stderr b/src/test/ui/generator/generator-region-requirements.nll.stderr index 6a423aea7ec..8a96d187f6b 100644 --- a/src/test/ui/generator/generator-region-requirements.nll.stderr +++ b/src/test/ui/generator/generator-region-requirements.nll.stderr @@ -1,5 +1,5 @@ error[E0621]: explicit lifetime required in the type of `x` - --> $DIR/generator-region-requirements.rs:15:51 + --> $DIR/generator-region-requirements.rs:16:51 | LL | fn dangle(x: &mut i32) -> &'static mut i32 { | -------- help: add explicit lifetime `'static` to the type of `x`: `&'static mut i32` diff --git a/src/test/ui/generator/generator-region-requirements.rs b/src/test/ui/generator/generator-region-requirements.rs index 2cda483b6a1..9738f6c3932 100644 --- a/src/test/ui/generator/generator-region-requirements.rs +++ b/src/test/ui/generator/generator-region-requirements.rs @@ -4,6 +4,7 @@ #![feature(generators, generator_trait)] #![cfg_attr(nll, feature(nll))] use std::ops::{Generator, GeneratorState}; +use std::pin::Pin; fn dangle(x: &mut i32) -> &'static mut i32 { let mut g = || { @@ -11,7 +12,7 @@ fn dangle(x: &mut i32) -> &'static mut i32 { x }; loop { - match unsafe { g.resume() } { + match Pin::new(&mut g).resume() { GeneratorState::Complete(c) => return c, //[nll]~^ ERROR explicit lifetime required //[ast]~^^ ERROR explicit lifetime required diff --git a/src/test/ui/generator/ref-escapes-but-not-over-yield.nll.stderr b/src/test/ui/generator/ref-escapes-but-not-over-yield.nll.stderr index 72a4654dec8..01eea627351 100644 --- a/src/test/ui/generator/ref-escapes-but-not-over-yield.nll.stderr +++ b/src/test/ui/generator/ref-escapes-but-not-over-yield.nll.stderr @@ -1,5 +1,5 @@ error[E0521]: borrowed data escapes outside of generator - --> $DIR/ref-escapes-but-not-over-yield.rs:14:9 + --> $DIR/ref-escapes-but-not-over-yield.rs:11:9 | LL | let mut a = &3; | ----- `a` is declared here, outside of the generator body diff --git a/src/test/ui/generator/ref-escapes-but-not-over-yield.rs b/src/test/ui/generator/ref-escapes-but-not-over-yield.rs index 332e074e9fe..8c576581ad8 100644 --- a/src/test/ui/generator/ref-escapes-but-not-over-yield.rs +++ b/src/test/ui/generator/ref-escapes-but-not-over-yield.rs @@ -1,7 +1,4 @@ -#![feature(generators, generator_trait)] - -use std::ops::{GeneratorState, Generator}; -use std::cell::Cell; +#![feature(generators)] fn foo(x: &i32) { // In this case, a reference to `b` escapes the generator, but not diff --git a/src/test/ui/generator/ref-escapes-but-not-over-yield.stderr b/src/test/ui/generator/ref-escapes-but-not-over-yield.stderr index e1d718e847f..29299b2405a 100644 --- a/src/test/ui/generator/ref-escapes-but-not-over-yield.stderr +++ b/src/test/ui/generator/ref-escapes-but-not-over-yield.stderr @@ -1,5 +1,5 @@ error[E0597]: `b` does not live long enough - --> $DIR/ref-escapes-but-not-over-yield.rs:14:14 + --> $DIR/ref-escapes-but-not-over-yield.rs:11:14 | LL | a = &b; | ^ borrowed value does not live long enough diff --git a/src/test/ui/generator/sized-yield.rs b/src/test/ui/generator/sized-yield.rs index e34731a4406..f64849b3149 100644 --- a/src/test/ui/generator/sized-yield.rs +++ b/src/test/ui/generator/sized-yield.rs @@ -1,6 +1,7 @@ #![feature(generators, generator_trait)] use std::ops::Generator; +use std::pin::Pin; fn main() { let s = String::from("foo"); @@ -8,6 +9,6 @@ fn main() { //~^ ERROR the size for values of type yield s[..]; }; - unsafe { gen.resume(); } + Pin::new(&mut gen).resume(); //~^ ERROR the size for values of type } diff --git a/src/test/ui/generator/sized-yield.stderr b/src/test/ui/generator/sized-yield.stderr index 4f59f2c1c6a..c98f42e6216 100644 --- a/src/test/ui/generator/sized-yield.stderr +++ b/src/test/ui/generator/sized-yield.stderr @@ -1,5 +1,5 @@ error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/sized-yield.rs:7:26 + --> $DIR/sized-yield.rs:8:26 | LL | let mut gen = move || { | __________________________^ @@ -13,10 +13,10 @@ LL | | }; = note: the yield type of a generator must have a statically known size error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/sized-yield.rs:11:17 + --> $DIR/sized-yield.rs:12:23 | -LL | unsafe { gen.resume(); } - | ^^^^^^ doesn't have a size known at compile-time +LL | Pin::new(&mut gen).resume(); + | ^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `str` = note: to learn more, visit diff --git a/src/test/ui/generator/yield-while-iterating.nll.stderr b/src/test/ui/generator/yield-while-iterating.nll.stderr index bcbd68ab85d..2dc12f843b2 100644 --- a/src/test/ui/generator/yield-while-iterating.nll.stderr +++ b/src/test/ui/generator/yield-while-iterating.nll.stderr @@ -1,5 +1,5 @@ error[E0626]: borrow may still be in use when generator yields - --> $DIR/yield-while-iterating.rs:12:18 + --> $DIR/yield-while-iterating.rs:13:18 | LL | for p in &x { //~ ERROR | ^^ @@ -7,7 +7,7 @@ LL | yield(); | ------- possible yield occurs here error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable - --> $DIR/yield-while-iterating.rs:57:20 + --> $DIR/yield-while-iterating.rs:58:20 | LL | let mut b = || { | -- mutable borrow occurs here @@ -16,8 +16,8 @@ LL | for p in &mut x { ... LL | println!("{}", x[0]); //~ ERROR | ^ immutable borrow occurs here -LL | b.resume(); - | - mutable borrow later used here +LL | Pin::new(&mut b).resume(); + | ------ mutable borrow later used here error: aborting due to 2 previous errors diff --git a/src/test/ui/generator/yield-while-iterating.rs b/src/test/ui/generator/yield-while-iterating.rs index b0966d2e921..e42781d1279 100644 --- a/src/test/ui/generator/yield-while-iterating.rs +++ b/src/test/ui/generator/yield-while-iterating.rs @@ -2,6 +2,7 @@ use std::ops::{GeneratorState, Generator}; use std::cell::Cell; +use std::pin::Pin; fn yield_during_iter_owned_data(x: Vec) { // The generator owns `x`, so we error out when yielding with a @@ -33,7 +34,7 @@ fn yield_during_iter_borrowed_slice_2() { println!("{:?}", x); } -unsafe fn yield_during_iter_borrowed_slice_3() { +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]; @@ -42,10 +43,10 @@ unsafe fn yield_during_iter_borrowed_slice_3() { yield p; } }; - b.resume(); + Pin::new(&mut b).resume(); } -unsafe fn yield_during_iter_borrowed_slice_4() { +fn yield_during_iter_borrowed_slice_4() { // ...but not OK to do that while reading // from `x` too let mut x = vec![22_i32]; @@ -55,10 +56,10 @@ unsafe fn yield_during_iter_borrowed_slice_4() { } }; println!("{}", x[0]); //~ ERROR - b.resume(); + Pin::new(&mut b).resume(); } -unsafe fn yield_during_range_iter() { +fn yield_during_range_iter() { // Should be OK. let mut b = || { let v = vec![1,2,3]; @@ -68,7 +69,7 @@ unsafe fn yield_during_range_iter() { yield x; } }; - b.resume(); + Pin::new(&mut b).resume(); } fn main() { } diff --git a/src/test/ui/generator/yield-while-iterating.stderr b/src/test/ui/generator/yield-while-iterating.stderr index aa66047feb2..1e3e31470e9 100644 --- a/src/test/ui/generator/yield-while-iterating.stderr +++ b/src/test/ui/generator/yield-while-iterating.stderr @@ -1,5 +1,5 @@ error[E0626]: borrow may still be in use when generator yields - --> $DIR/yield-while-iterating.rs:12:19 + --> $DIR/yield-while-iterating.rs:13:19 | LL | for p in &x { //~ ERROR | ^ @@ -7,7 +7,7 @@ LL | yield(); | ------- possible yield occurs here error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable - --> $DIR/yield-while-iterating.rs:57:20 + --> $DIR/yield-while-iterating.rs:58:20 | LL | let mut b = || { | -- mutable borrow occurs here @@ -16,7 +16,7 @@ LL | for p in &mut x { ... LL | println!("{}", x[0]); //~ ERROR | ^ immutable borrow occurs here -LL | b.resume(); +LL | Pin::new(&mut b).resume(); LL | } | - mutable borrow ends here diff --git a/src/test/ui/generator/yield-while-local-borrowed.rs b/src/test/ui/generator/yield-while-local-borrowed.rs index a895f05b34c..38061e71358 100644 --- a/src/test/ui/generator/yield-while-local-borrowed.rs +++ b/src/test/ui/generator/yield-while-local-borrowed.rs @@ -4,8 +4,9 @@ use std::ops::{GeneratorState, Generator}; use std::cell::Cell; +use std::pin::Pin; -unsafe fn borrow_local_inline() { +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 @@ -17,10 +18,10 @@ unsafe fn borrow_local_inline() { yield(); println!("{}", a); }; - b.resume(); + Pin::new(&mut b).resume(); } -unsafe fn borrow_local_inline_done() { +fn borrow_local_inline_done() { // No error here -- `a` is not in scope at the point of `yield`. let mut b = move || { { @@ -28,10 +29,10 @@ unsafe fn borrow_local_inline_done() { } yield(); }; - b.resume(); + Pin::new(&mut b).resume(); } -unsafe fn borrow_local() { +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 @@ -46,7 +47,7 @@ unsafe fn borrow_local() { println!("{}", b); } }; - b.resume(); + Pin::new(&mut b).resume(); } fn main() { } diff --git a/src/test/ui/generator/yield-while-local-borrowed.stderr b/src/test/ui/generator/yield-while-local-borrowed.stderr index 765267a58b4..56f425b7e70 100644 --- a/src/test/ui/generator/yield-while-local-borrowed.stderr +++ b/src/test/ui/generator/yield-while-local-borrowed.stderr @@ -1,5 +1,5 @@ error[E0626]: borrow may still be in use when generator yields (Ast) - --> $DIR/yield-while-local-borrowed.rs:14:22 + --> $DIR/yield-while-local-borrowed.rs:15:22 | LL | let a = &mut 3; | ^ @@ -8,7 +8,7 @@ LL | yield(); | ------- possible yield occurs here error[E0626]: borrow may still be in use when generator yields (Ast) - --> $DIR/yield-while-local-borrowed.rs:42:22 + --> $DIR/yield-while-local-borrowed.rs:43:22 | LL | let b = &a; | ^ @@ -17,7 +17,7 @@ LL | yield(); | ------- possible yield occurs here error[E0626]: borrow may still be in use when generator yields (Mir) - --> $DIR/yield-while-local-borrowed.rs:14:17 + --> $DIR/yield-while-local-borrowed.rs:15:17 | LL | let a = &mut 3; | ^^^^^^ @@ -26,7 +26,7 @@ LL | yield(); | ------- possible yield occurs here error[E0626]: borrow may still be in use when generator yields (Mir) - --> $DIR/yield-while-local-borrowed.rs:42:21 + --> $DIR/yield-while-local-borrowed.rs:43:21 | LL | let b = &a; | ^^ diff --git a/src/test/ui/generator/yield-while-ref-reborrowed.nll.stderr b/src/test/ui/generator/yield-while-ref-reborrowed.nll.stderr index 9a99b6ad025..d0d6a98301e 100644 --- a/src/test/ui/generator/yield-while-ref-reborrowed.nll.stderr +++ b/src/test/ui/generator/yield-while-ref-reborrowed.nll.stderr @@ -1,5 +1,5 @@ error[E0501]: cannot borrow `x` as immutable because previous closure requires unique access - --> $DIR/yield-while-ref-reborrowed.rs:35:20 + --> $DIR/yield-while-ref-reborrowed.rs:36:20 | LL | let mut b = || { | -- generator construction occurs here @@ -8,8 +8,8 @@ LL | let a = &mut *x; ... LL | println!("{}", x); //~ ERROR | ^ second borrow occurs here -LL | b.resume(); - | - first borrow later used here +LL | Pin::new(&mut b).resume(); + | ------ first borrow later used here error: aborting due to previous error diff --git a/src/test/ui/generator/yield-while-ref-reborrowed.rs b/src/test/ui/generator/yield-while-ref-reborrowed.rs index 540907a421d..f54a4f468f6 100644 --- a/src/test/ui/generator/yield-while-ref-reborrowed.rs +++ b/src/test/ui/generator/yield-while-ref-reborrowed.rs @@ -2,8 +2,9 @@ use std::ops::{GeneratorState, Generator}; use std::cell::Cell; +use std::pin::Pin; -unsafe fn reborrow_shared_ref(x: &i32) { +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 || { @@ -11,10 +12,10 @@ unsafe fn reborrow_shared_ref(x: &i32) { yield(); println!("{}", a); }; - b.resume(); + Pin::new(&mut b).resume(); } -unsafe fn reborrow_mutable_ref(x: &mut i32) { +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 || { @@ -22,10 +23,10 @@ unsafe fn reborrow_mutable_ref(x: &mut i32) { yield(); println!("{}", a); }; - b.resume(); + Pin::new(&mut b).resume(); } -unsafe fn reborrow_mutable_ref_2(x: &mut i32) { +fn reborrow_mutable_ref_2(x: &mut i32) { // ...but not OK to go on using `x`. let mut b = || { let a = &mut *x; @@ -33,7 +34,7 @@ unsafe fn reborrow_mutable_ref_2(x: &mut i32) { println!("{}", a); }; println!("{}", x); //~ ERROR - b.resume(); + Pin::new(&mut b).resume(); } fn main() { } diff --git a/src/test/ui/generator/yield-while-ref-reborrowed.stderr b/src/test/ui/generator/yield-while-ref-reborrowed.stderr index d70ef189ebc..5c9de279c02 100644 --- a/src/test/ui/generator/yield-while-ref-reborrowed.stderr +++ b/src/test/ui/generator/yield-while-ref-reborrowed.stderr @@ -1,5 +1,5 @@ error[E0501]: cannot borrow `x` as immutable because previous closure requires unique access - --> $DIR/yield-while-ref-reborrowed.rs:35:20 + --> $DIR/yield-while-ref-reborrowed.rs:36:20 | LL | let mut b = || { | -- closure construction occurs here @@ -8,7 +8,7 @@ LL | let a = &mut *x; ... LL | println!("{}", x); //~ ERROR | ^ borrow occurs here -LL | b.resume(); +LL | Pin::new(&mut b).resume(); LL | } | - borrow from closure ends here diff --git a/src/test/ui/nll/issue-55850.rs b/src/test/ui/nll/issue-55850.rs index eafbfd21700..8b5887224d1 100644 --- a/src/test/ui/nll/issue-55850.rs +++ b/src/test/ui/nll/issue-55850.rs @@ -1,23 +1,23 @@ #![allow(unused_mut)] #![feature(generators, generator_trait)] +use std::marker::Unpin; use std::ops::Generator; use std::ops::GeneratorState::Yielded; +use std::pin::Pin; pub struct GenIter(G); impl Iterator for GenIter where - G: Generator, + G: Generator + Unpin, { type Item = G::Yield; fn next(&mut self) -> Option { - unsafe { - match self.0.resume() { - Yielded(y) => Some(y), - _ => None - } + match Pin::new(&mut self.0).resume() { + Yielded(y) => Some(y), + _ => None } } }