From a3fdee9a7523a72a5ee72cdb4c1cf3c2cec444bc Mon Sep 17 00:00:00 2001
From: Wim Looman <wim@nemo157.com>
Date: Thu, 4 Oct 2018 20:49:38 +0200
Subject: [PATCH 1/7] Change generator trait to use pinning

---
 .../src/language-features/generators.md       | 31 +++++++++-------
 src/liballoc/boxed.rs                         | 13 +++----
 src/libcore/ops/generator.rs                  | 37 ++++++++++++-------
 src/librustc_mir/diagnostics.rs               | 25 ++++++++-----
 src/libstd/future.rs                          |  4 +-
 src/test/run-pass/drop/dynamic-drop.rs        |  3 +-
 .../run-pass/generator/auxiliary/xcrate.rs    |  3 +-
 .../run-pass/generator/conditional-drop.rs    |  9 +++--
 src/test/run-pass/generator/control-flow.rs   |  6 ++-
 src/test/run-pass/generator/drop-env.rs       |  5 ++-
 src/test/run-pass/generator/issue-44197.rs    |  7 ++--
 src/test/run-pass/generator/iterator-count.rs |  8 ++--
 .../generator/live-upvar-across-yield.rs      |  3 +-
 .../run-pass/generator/nested_generators.rs   |  9 ++---
 src/test/run-pass/generator/panic-drops.rs    |  5 ++-
 src/test/run-pass/generator/panic-safe.rs     |  5 ++-
 .../run-pass/generator/resume-after-return.rs |  5 ++-
 src/test/run-pass/generator/smoke.rs          | 29 ++++++++-------
 .../run-pass/generator/static-generators.rs   | 10 +++--
 .../run-pass/generator/xcrate-reachable.rs    |  3 +-
 src/test/run-pass/generator/xcrate.rs         |  7 ++--
 src/test/ui/generator/borrowing.nll.stderr    | 16 ++++----
 src/test/ui/generator/borrowing.rs            |  3 +-
 src/test/ui/generator/borrowing.stderr        | 12 +++---
 src/test/ui/generator/dropck.nll.stderr       |  4 +-
 src/test/ui/generator/dropck.rs               |  3 +-
 src/test/ui/generator/dropck.stderr           |  4 +-
 .../generator-region-requirements.ast.stderr  |  2 +-
 .../generator-region-requirements.nll.stderr  |  2 +-
 .../generator-region-requirements.rs          |  3 +-
 .../ref-escapes-but-not-over-yield.nll.stderr |  2 +-
 .../ref-escapes-but-not-over-yield.rs         |  5 +--
 .../ref-escapes-but-not-over-yield.stderr     |  2 +-
 src/test/ui/generator/sized-yield.rs          |  3 +-
 src/test/ui/generator/sized-yield.stderr      |  8 ++--
 .../yield-while-iterating.nll.stderr          |  8 ++--
 .../ui/generator/yield-while-iterating.rs     | 13 ++++---
 .../ui/generator/yield-while-iterating.stderr |  6 +--
 .../generator/yield-while-local-borrowed.rs   | 13 ++++---
 .../yield-while-local-borrowed.stderr         |  8 ++--
 .../yield-while-ref-reborrowed.nll.stderr     |  6 +--
 .../generator/yield-while-ref-reborrowed.rs   | 13 ++++---
 .../yield-while-ref-reborrowed.stderr         |  4 +-
 src/test/ui/nll/issue-55850.rs                | 12 +++---
 44 files changed, 209 insertions(+), 170 deletions(-)

diff --git a/src/doc/unstable-book/src/language-features/generators.md b/src/doc/unstable-book/src/language-features/generators.md
index 968534e58bd9e..426fc01a6b051 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<Self::Yield, Self::Return>;
+    fn resume(self: Pin<&mut Self>) -> GeneratorState<Self::Yield, Self::Return>;
 }
 ```
 
@@ -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<i32, &'static str> {
+            fn resume(mut self: Pin<&mut Self>) -> GeneratorState<i32, &'static str> {
                 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 1c459f5c4250e..1fd8aa98cc355 100644
--- a/src/liballoc/boxed.rs
+++ b/src/liballoc/boxed.rs
@@ -873,13 +873,12 @@ impl<T: ?Sized> AsMut<T> for Box<T> {
 impl<T: ?Sized> Unpin for Box<T> { }
 
 #[unstable(feature = "generator_trait", issue = "43122")]
-impl<T> Generator for Box<T>
-    where T: Generator + ?Sized
-{
-    type Yield = T::Yield;
-    type Return = T::Return;
-    unsafe fn resume(&mut self) -> GeneratorState<Self::Yield, Self::Return> {
-        (**self).resume()
+impl<G: ?Sized + Generator + Unpin> Generator for Box<G> {
+    type Yield = G::Yield;
+    type Return = G::Return;
+
+    fn resume(mut self: Pin<&mut Self>) -> GeneratorState<Self::Yield, Self::Return> {
+        G::resume(Pin::new(&mut *self))
     }
 }
 
diff --git a/src/libcore/ops/generator.rs b/src/libcore/ops/generator.rs
index 1542cd6397e78..5401fff860e9b 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<Y, R> {
 /// #![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<Y, R> {
 ///         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<Self::Yield, Self::Return>;
+    fn resume(self: Pin<&mut Self>) -> GeneratorState<Self::Yield, Self::Return>;
+}
+
+#[unstable(feature = "generator_trait", issue = "43122")]
+impl<G: ?Sized + Generator> Generator for Pin<&mut G> {
+    type Yield = G::Yield;
+    type Return = G::Return;
+
+    fn resume(mut self: Pin<&mut Self>) -> GeneratorState<Self::Yield, Self::Return> {
+        G::resume((*self).as_mut())
+    }
 }
 
 #[unstable(feature = "generator_trait", issue = "43122")]
-impl<T> Generator for &mut T
-    where T: Generator + ?Sized
-{
-    type Yield = T::Yield;
-    type Return = T::Return;
-    unsafe fn resume(&mut self) -> GeneratorState<Self::Yield, Self::Return> {
-        (**self).resume()
+impl<G: ?Sized + Generator + Unpin> Generator for &mut G {
+    type Yield = G::Yield;
+    type Return = G::Return;
+
+    fn resume(mut self: Pin<&mut Self>) -> GeneratorState<Self::Yield, Self::Return> {
+        G::resume(Pin::new(&mut *self))
     }
 }
diff --git a/src/librustc_mir/diagnostics.rs b/src/librustc_mir/diagnostics.rs
index 74394165a5f84..eb72175421638 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 <https://github.com/rust-lang/rust/issues/43122>.
diff --git a/src/libstd/future.rs b/src/libstd/future.rs
index 22900c3067b11..d1203be3cf011 100644
--- a/src/libstd/future.rs
+++ b/src/libstd/future.rs
@@ -33,7 +33,9 @@ impl<T: Generator<Yield = ()>> !Unpin for GenFuture<T> {}
 impl<T: Generator<Yield = ()>> Future for GenFuture<T> {
     type Output = T::Return;
     fn poll(self: Pin<&mut Self>, lw: &LocalWaker) -> Poll<Self::Output> {
-        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 41814f2af16b4..97e4cded80b9a 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 8e08de28bc6b2..831c248bf909c 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<Yield = (), Return = ()> {
@@ -10,7 +11,7 @@ pub fn foo() -> impl Generator<Yield = (), Return = ()> {
     }
 }
 
-pub fn bar<T: 'static>(t: T) -> Box<Generator<Yield = T, Return = ()>> {
+pub fn bar<T: Unpin + 'static>(t: T) -> Box<Generator<Yield = T, Return = ()> + 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 766eef9e3f3c3..907f7a3c06de7 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 2f499834796cc..df70e013bd330 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<T>(mut amt: usize, mut t: T) -> T::Return
-    where T: Generator<Yield = ()>
+    where T: Generator<Yield = ()> + 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 252f2c0f07da7..ac4e06656285e 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 4a6e5b88b235a..6efaff50c1e62 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<Yield = String, Return = ()> {
 }
 
 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 1011d54bdb33c..ac7e122dd5802 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>(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> {
+impl<T: Generator<Return = ()> + Unpin> Iterator for W<T> {
     type Item = T::Yield;
 
     fn next(&mut self) -> Option<Self::Item> {
-        match unsafe { self.0.resume() } {
+        match Pin::new(&mut self.0).resume() {
             GeneratorState::Complete(..) => None,
             GeneratorState::Yielded(v) => Some(v),
         }
     }
 }
 
-fn test() -> impl Generator<Return=(), Yield=u8> {
+fn test() -> impl Generator<Return=(), Yield=u8> + 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 b643809e50382..a1064165b2f7a 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 e837e5fc9c1fe..b56cce1dc44f1 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 8640a6539195b..5ac97585f4b57 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 134debdd23bc5..5f6778674dce1 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 2213c2f3fbae3..71a68ff684af3 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 8582941d610ca..533f2399084fa 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 eeaba3fe3c4c3..965d3c61c22d5 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 403c920786e9c..9483ad7395ea1 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 571b8fa9170f4..febf5c3583f30 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 af6ec4941d890..3c9221d28e74d 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 88a0cf9a77a54..9f8fc7483f64d 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 3f5d32e1c3358..169e4a8561c1d 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 1f6b7db2bd853..a90a47fe9aa01 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 1b0c1ebe517b4..65c61fbaac4e2 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 281c9647bc3e1..fdaa5cfbae3e6 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 6a423aea7eceb..8a96d187f6b1c 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 6a423aea7eceb..8a96d187f6b1c 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 2cda483b6a1c2..9738f6c3932ed 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 72a4654dec8b2..01eea627351fb 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 332e074e9fe64..8c576581ad8dd 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 e1d718e847f8f..29299b2405a00 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 e34731a4406d9..f64849b3149b8 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 4f59f2c1c6ab3..c98f42e62168e 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 <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
diff --git a/src/test/ui/generator/yield-while-iterating.nll.stderr b/src/test/ui/generator/yield-while-iterating.nll.stderr
index bcbd68ab85d5c..2dc12f843b220 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 b0966d2e921b7..e42781d1279e7 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<i32>) {
     // 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 aa66047feb227..1e3e31470e9d6 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 a895f05b34cae..38061e71358c4 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 765267a58b4a7..56f425b7e70a0 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 9a99b6ad02518..d0d6a98301e59 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 540907a421dfb..f54a4f468f6a0 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 d70ef189ebc9a..5c9de279c02d8 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 eafbfd21700c8..8b5887224d19a 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>(G);
 
 impl <G> Iterator for GenIter<G>
 where
-    G: Generator,
+    G: Generator + Unpin,
 {
     type Item = G::Yield;
 
     fn next(&mut self) -> Option<Self::Item> {
-        unsafe {
-            match self.0.resume() {
-                Yielded(y) => Some(y),
-                _ => None
-            }
+        match Pin::new(&mut self.0).resume() {
+            Yielded(y) => Some(y),
+            _ => None
         }
     }
 }

From 730b18b6e5f49091878739498793676f0c0ca28b Mon Sep 17 00:00:00 2001
From: Wim Looman <wim@nemo157.com>
Date: Sun, 4 Nov 2018 22:07:55 +0100
Subject: [PATCH 2/7] Mark static generators as !Unpin

---
 src/libcore/marker.rs                         |  1 +
 src/librustc/middle/lang_items.rs             |  1 +
 src/librustc/traits/select.rs                 |  6 ++++++
 src/test/ui/generator/static-not-unpin.rs     | 13 +++++++++++++
 src/test/ui/generator/static-not-unpin.stderr | 15 +++++++++++++++
 5 files changed, 36 insertions(+)
 create mode 100644 src/test/ui/generator/static-not-unpin.rs
 create mode 100644 src/test/ui/generator/static-not-unpin.stderr

diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs
index 65752ba032104..457d556e4fa6d 100644
--- a/src/libcore/marker.rs
+++ b/src/libcore/marker.rs
@@ -627,6 +627,7 @@ unsafe impl<T: ?Sized> Freeze for &mut T {}
 /// [`Pin`]: ../pin/struct.Pin.html
 /// [`pin module`]: ../../std/pin/index.html
 #[stable(feature = "pin", since = "1.33.0")]
+#[cfg_attr(not(stage0), lang = "unpin")]
 pub auto trait Unpin {}
 
 /// A marker type which does not implement `Unpin`.
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index c203ea96f3d64..e324bde1f17bf 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -299,6 +299,7 @@ language_item_table! {
 
     GeneratorStateLangItem,      "generator_state",    gen_state,               Target::Enum;
     GeneratorTraitLangItem,      "generator",          gen_trait,               Target::Trait;
+    UnpinTraitLangItem,          "unpin",              unpin_trait,             Target::Trait;
 
     EqTraitLangItem,             "eq",                 eq_trait,                Target::Trait;
     PartialOrdTraitLangItem,     "partial_ord",        partial_ord_trait,       Target::Trait;
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 9a0610f45dec2..7a244b7e80e6a 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -2017,6 +2017,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                     // the auto impl might apply, we don't know
                     candidates.ambiguous = true;
                 }
+                ty::Generator(_, _, hir::GeneratorMovability::Static)
+                    if self.tcx().lang_items().unpin_trait() == Some(def_id) =>
+                {
+                    // Immovable generators are never `Unpin`, so suppress the
+                    // normal auto-impl candidate for it.
+                }
                 _ => candidates.vec.push(AutoImplCandidate(def_id.clone())),
             }
         }
diff --git a/src/test/ui/generator/static-not-unpin.rs b/src/test/ui/generator/static-not-unpin.rs
new file mode 100644
index 0000000000000..7586faf1842ba
--- /dev/null
+++ b/src/test/ui/generator/static-not-unpin.rs
@@ -0,0 +1,13 @@
+#![feature(generators)]
+
+use std::marker::Unpin;
+
+fn assert_unpin<T: Unpin>(_: T) {
+}
+
+fn main() {
+    let mut generator = static || {
+        yield;
+    };
+    assert_unpin(generator); //~ ERROR std::marker::Unpin` is not satisfied
+}
diff --git a/src/test/ui/generator/static-not-unpin.stderr b/src/test/ui/generator/static-not-unpin.stderr
new file mode 100644
index 0000000000000..7a1243f5783d4
--- /dev/null
+++ b/src/test/ui/generator/static-not-unpin.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `[static generator@$DIR/static-not-unpin.rs:9:25: 11:6 _]: std::marker::Unpin` is not satisfied
+  --> $DIR/static-not-unpin.rs:12:5
+   |
+LL |     assert_unpin(generator); //~ ERROR std::marker::Unpin` is not satisfied
+   |     ^^^^^^^^^^^^ the trait `std::marker::Unpin` is not implemented for `[static generator@$DIR/static-not-unpin.rs:9:25: 11:6 _]`
+   |
+note: required by `assert_unpin`
+  --> $DIR/static-not-unpin.rs:5:1
+   |
+LL | fn assert_unpin<T: Unpin>(_: T) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.

From 0c203965e2a5aca6750f90777003adad2b79849f Mon Sep 17 00:00:00 2001
From: Wim Looman <wim@nemo157.com>
Date: Tue, 6 Nov 2018 19:47:18 +0100
Subject: [PATCH 3/7] impl Generator for Pin<Box<Generator>>

---
 src/liballoc/boxed.rs                            | 10 ++++++++++
 src/test/run-pass/generator/pin-box-generator.rs | 13 +++++++++++++
 2 files changed, 23 insertions(+)
 create mode 100644 src/test/run-pass/generator/pin-box-generator.rs

diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs
index 1fd8aa98cc355..14a1242e3e569 100644
--- a/src/liballoc/boxed.rs
+++ b/src/liballoc/boxed.rs
@@ -882,6 +882,16 @@ impl<G: ?Sized + Generator + Unpin> Generator for Box<G> {
     }
 }
 
+#[unstable(feature = "generator_trait", issue = "43122")]
+impl<G: ?Sized + Generator> Generator for Pin<Box<G>> {
+    type Yield = G::Yield;
+    type Return = G::Return;
+
+    fn resume(mut self: Pin<&mut Self>) -> GeneratorState<Self::Yield, Self::Return> {
+        G::resume((*self).as_mut())
+    }
+}
+
 #[unstable(feature = "futures_api", issue = "50547")]
 impl<F: ?Sized + Future + Unpin> Future for Box<F> {
     type Output = F::Output;
diff --git a/src/test/run-pass/generator/pin-box-generator.rs b/src/test/run-pass/generator/pin-box-generator.rs
new file mode 100644
index 0000000000000..c3136f5c0ec82
--- /dev/null
+++ b/src/test/run-pass/generator/pin-box-generator.rs
@@ -0,0 +1,13 @@
+// run-pass
+
+#![feature(generators, generator_trait)]
+
+use std::ops::Generator;
+
+fn assert_generator<G: Generator>(_: G) {
+}
+
+fn main() {
+    assert_generator(static || yield);
+    assert_generator(Box::pin(static || yield));
+}

From be3989301aea41777bdbc65d5c3537b7036ec407 Mon Sep 17 00:00:00 2001
From: Wim Looman <wim@nemo157.com>
Date: Wed, 7 Nov 2018 00:11:58 +0100
Subject: [PATCH 4/7] Update generator transform and generated function
 signature

---
 src/libcore/pin.rs                      |  1 +
 src/librustc/middle/lang_items.rs       |  1 +
 src/librustc/ty/instance.rs             |  5 +++
 src/librustc_mir/transform/generator.rs | 45 +++++++++++++++++++++++++
 4 files changed, 52 insertions(+)

diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs
index 7c09a36d89883..56a32c928fb3d 100644
--- a/src/libcore/pin.rs
+++ b/src/libcore/pin.rs
@@ -117,6 +117,7 @@ use ops::{Deref, DerefMut, Receiver, CoerceUnsized, DispatchFromDyn};
 // implementations, are allowed because they all only use `&P`, so they cannot move
 // the value behind `pointer`.
 #[stable(feature = "pin", since = "1.33.0")]
+#[cfg_attr(not(stage0), lang = "pin")]
 #[fundamental]
 #[repr(transparent)]
 #[derive(Copy, Clone, Hash, Eq, Ord)]
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index e324bde1f17bf..87107f727a05d 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -300,6 +300,7 @@ language_item_table! {
     GeneratorStateLangItem,      "generator_state",    gen_state,               Target::Enum;
     GeneratorTraitLangItem,      "generator",          gen_trait,               Target::Trait;
     UnpinTraitLangItem,          "unpin",              unpin_trait,             Target::Trait;
+    PinTypeLangItem,             "pin",                pin_type,                Target::Struct;
 
     EqTraitLangItem,             "eq",                 eq_trait,                Target::Trait;
     PartialOrdTraitLangItem,     "partial_ord",        partial_ord_trait,       Target::Trait;
diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs
index 78b6ffaa54e17..bc43fedef0f34 100644
--- a/src/librustc/ty/instance.rs
+++ b/src/librustc/ty/instance.rs
@@ -76,6 +76,11 @@ impl<'a, 'tcx> Instance<'tcx> {
                 let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv);
                 let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty);
 
+                let pin_did = tcx.lang_items().pin_type().unwrap();
+                let pin_adt_ref = tcx.adt_def(pin_did);
+                let pin_substs = tcx.intern_substs(&[env_ty.into()]);
+                let env_ty = tcx.mk_adt(pin_adt_ref, pin_substs);
+
                 sig.map_bound(|sig| {
                     let state_did = tcx.lang_items().gen_state().unwrap();
                     let state_adt_ref = tcx.adt_def(state_did);
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index ec0c118634d0f..f5cc6a43e28b9 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -113,6 +113,33 @@ impl<'tcx> MutVisitor<'tcx> for DerefArgVisitor {
     }
 }
 
+struct PinArgVisitor<'tcx> {
+    ref_gen_ty: Ty<'tcx>,
+}
+
+impl<'tcx> MutVisitor<'tcx> for PinArgVisitor<'tcx> {
+    fn visit_local(&mut self,
+                   local: &mut Local,
+                   _: PlaceContext<'tcx>,
+                   _: Location) {
+        assert_ne!(*local, self_arg());
+    }
+
+    fn visit_place(&mut self,
+                    place: &mut Place<'tcx>,
+                    context: PlaceContext<'tcx>,
+                    location: Location) {
+        if *place == Place::Local(self_arg()) {
+            *place = Place::Projection(Box::new(Projection {
+                base: place.clone(),
+                elem: ProjectionElem::Field(Field::new(0), self.ref_gen_ty),
+            }));
+        } else {
+            self.super_place(place, context, location);
+        }
+    }
+}
+
 fn self_arg() -> Local {
     Local::new(1)
 }
@@ -286,6 +313,23 @@ fn make_generator_state_argument_indirect<'a, 'tcx>(
     DerefArgVisitor.visit_mir(mir);
 }
 
+fn make_generator_state_argument_pinned<'a, 'tcx>(
+                tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                mir: &mut Mir<'tcx>) {
+    let ref_gen_ty = mir.local_decls.raw[1].ty;
+
+    let pin_did = tcx.lang_items().pin_type().unwrap();
+    let pin_adt_ref = tcx.adt_def(pin_did);
+    let substs = tcx.intern_substs(&[ref_gen_ty.into()]);
+    let pin_ref_gen_ty = tcx.mk_adt(pin_adt_ref, substs);
+
+    // Replace the by ref generator argument
+    mir.local_decls.raw[1].ty = pin_ref_gen_ty;
+
+    // Add the Pin field access to accesses of the generator state
+    PinArgVisitor { ref_gen_ty }.visit_mir(mir);
+}
+
 fn replace_result_variable<'tcx>(
     ret_ty: Ty<'tcx>,
     mir: &mut Mir<'tcx>,
@@ -741,6 +785,7 @@ fn create_generator_resume_function<'a, 'tcx>(
     insert_switch(tcx, mir, cases, &transform, TerminatorKind::Unreachable);
 
     make_generator_state_argument_indirect(tcx, def_id, mir);
+    make_generator_state_argument_pinned(tcx, mir);
 
     no_landing_pads(tcx, mir);
 

From e7d66758cfce4dc2c87e3224b6ed47aee1fee257 Mon Sep 17 00:00:00 2001
From: Wim Looman <wim@nemo157.com>
Date: Wed, 7 Nov 2018 10:33:35 +0100
Subject: [PATCH 5/7] Update generator upvar debug info

---
 src/librustc_codegen_ssa/mir/mod.rs |  7 ++++++
 src/test/debuginfo/generators.rs    | 36 +++++++++++++++++++++++++++++
 2 files changed, 43 insertions(+)
 create mode 100644 src/test/debuginfo/generators.rs

diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs
index 85a663dacdcc5..c7e2131eed5da 100644
--- a/src/librustc_codegen_ssa/mir/mod.rs
+++ b/src/librustc_codegen_ssa/mir/mod.rs
@@ -586,10 +586,17 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
                 return;
             }
 
+            let pin_did = tcx.lang_items().pin_type();
             // Or is it the closure environment?
             let (closure_layout, env_ref) = match arg.layout.ty.sty {
                 ty::RawPtr(ty::TypeAndMut { ty, .. }) |
                 ty::Ref(_, ty, _)  => (bx.layout_of(ty), true),
+                ty::Adt(def, substs) if Some(def.did) == pin_did => {
+                    match substs.type_at(0).sty {
+                        ty::Ref(_, ty, _)  => (bx.layout_of(ty), true),
+                        _ => (arg.layout, false),
+                    }
+                }
                 _ => (arg.layout, false)
             };
 
diff --git a/src/test/debuginfo/generators.rs b/src/test/debuginfo/generators.rs
new file mode 100644
index 0000000000000..b56d222e0e01e
--- /dev/null
+++ b/src/test/debuginfo/generators.rs
@@ -0,0 +1,36 @@
+// min-lldb-version: 310
+
+// compile-flags:-g
+
+// === GDB TESTS ===================================================================================
+
+// gdb-command:run
+// gdb-command:print a
+// gdb-check:$1 = 5
+
+// === LLDB TESTS ==================================================================================
+
+// lldb-command:run
+// lldb-command:print a
+// lldbg-check:(int) $0 = 5
+// lldbr-check:(int) a = 5
+
+#![feature(omit_gdb_pretty_printer_section, generators, generator_trait, pin)]
+#![omit_gdb_pretty_printer_section]
+
+use std::ops::Generator;
+use std::pin::Pin;
+
+fn main() {
+    let mut a = 5;
+    let mut b = || {
+        yield;
+        _zzz(); // #break
+        a = 6;
+    };
+    Pin::new(&mut b).resume();
+    Pin::new(&mut b).resume();
+    _zzz(); // #break
+}
+
+fn _zzz() {()}

From c4bf5f9d63ea04b8907a3b41862f0372ed2afda8 Mon Sep 17 00:00:00 2001
From: Wim Looman <wim@nemo157.com>
Date: Wed, 7 Nov 2018 19:01:35 +0100
Subject: [PATCH 6/7] Temporary workaround for travis diagnostic difference

---
 src/test/ui/generator/static-not-unpin.rs     | 2 ++
 src/test/ui/generator/static-not-unpin.stderr | 8 ++++----
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/src/test/ui/generator/static-not-unpin.rs b/src/test/ui/generator/static-not-unpin.rs
index 7586faf1842ba..b271e982fb420 100644
--- a/src/test/ui/generator/static-not-unpin.rs
+++ b/src/test/ui/generator/static-not-unpin.rs
@@ -1,5 +1,7 @@
 #![feature(generators)]
 
+// normalize-stderr-test "std::pin::Unpin" -> "std::marker::Unpin"
+
 use std::marker::Unpin;
 
 fn assert_unpin<T: Unpin>(_: T) {
diff --git a/src/test/ui/generator/static-not-unpin.stderr b/src/test/ui/generator/static-not-unpin.stderr
index 7a1243f5783d4..caf92f0ec693e 100644
--- a/src/test/ui/generator/static-not-unpin.stderr
+++ b/src/test/ui/generator/static-not-unpin.stderr
@@ -1,11 +1,11 @@
-error[E0277]: the trait bound `[static generator@$DIR/static-not-unpin.rs:9:25: 11:6 _]: std::marker::Unpin` is not satisfied
-  --> $DIR/static-not-unpin.rs:12:5
+error[E0277]: the trait bound `[static generator@$DIR/static-not-unpin.rs:11:25: 13:6 _]: std::marker::Unpin` is not satisfied
+  --> $DIR/static-not-unpin.rs:14:5
    |
 LL |     assert_unpin(generator); //~ ERROR std::marker::Unpin` is not satisfied
-   |     ^^^^^^^^^^^^ the trait `std::marker::Unpin` is not implemented for `[static generator@$DIR/static-not-unpin.rs:9:25: 11:6 _]`
+   |     ^^^^^^^^^^^^ the trait `std::marker::Unpin` is not implemented for `[static generator@$DIR/static-not-unpin.rs:11:25: 13:6 _]`
    |
 note: required by `assert_unpin`
-  --> $DIR/static-not-unpin.rs:5:1
+  --> $DIR/static-not-unpin.rs:7:1
    |
 LL | fn assert_unpin<T: Unpin>(_: T) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

From a21c95f08e37a2e609a0cb523eb9c132d8c341f3 Mon Sep 17 00:00:00 2001
From: Wim Looman <wim@nemo157.com>
Date: Wed, 21 Nov 2018 15:32:51 +0100
Subject: [PATCH 7/7] Mark non-static generators as always Unpin

---
 src/librustc/traits/select.rs                  | 18 +++++++++++++++---
 .../run-pass/generator/auxiliary/xcrate.rs     |  2 +-
 .../run-pass/generator/non-static-is-unpin.rs  | 18 ++++++++++++++++++
 3 files changed, 34 insertions(+), 4 deletions(-)
 create mode 100644 src/test/run-pass/generator/non-static-is-unpin.rs

diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 7a244b7e80e6a..6fe4a7a52be86 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -2017,12 +2017,24 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                     // the auto impl might apply, we don't know
                     candidates.ambiguous = true;
                 }
-                ty::Generator(_, _, hir::GeneratorMovability::Static)
+                ty::Generator(_, _, movability)
                     if self.tcx().lang_items().unpin_trait() == Some(def_id) =>
                 {
-                    // Immovable generators are never `Unpin`, so suppress the
-                    // normal auto-impl candidate for it.
+                    match movability {
+                        hir::GeneratorMovability::Static => {
+                            // Immovable generators are never `Unpin`, so
+                            // suppress the normal auto-impl candidate for it.
+                        }
+                        hir::GeneratorMovability::Movable => {
+                            // Movable generators are always `Unpin`, so add an
+                            // unconditional builtin candidate.
+                            candidates.vec.push(BuiltinCandidate {
+                                has_nested: false,
+                            });
+                        }
+                    }
                 }
+
                 _ => candidates.vec.push(AutoImplCandidate(def_id.clone())),
             }
         }
diff --git a/src/test/run-pass/generator/auxiliary/xcrate.rs b/src/test/run-pass/generator/auxiliary/xcrate.rs
index 831c248bf909c..613c495832f00 100644
--- a/src/test/run-pass/generator/auxiliary/xcrate.rs
+++ b/src/test/run-pass/generator/auxiliary/xcrate.rs
@@ -11,7 +11,7 @@ pub fn foo() -> impl Generator<Yield = (), Return = ()> {
     }
 }
 
-pub fn bar<T: Unpin + 'static>(t: T) -> Box<Generator<Yield = T, Return = ()> + Unpin> {
+pub fn bar<T: 'static>(t: T) -> Box<Generator<Yield = T, Return = ()> + Unpin> {
     Box::new(|| {
         yield t;
     })
diff --git a/src/test/run-pass/generator/non-static-is-unpin.rs b/src/test/run-pass/generator/non-static-is-unpin.rs
new file mode 100644
index 0000000000000..96d0a8e283372
--- /dev/null
+++ b/src/test/run-pass/generator/non-static-is-unpin.rs
@@ -0,0 +1,18 @@
+// run-pass
+
+#![feature(generators, generator_trait)]
+
+use std::marker::{PhantomPinned, Unpin};
+
+fn assert_unpin<G: Unpin>(_: G) {
+}
+
+fn main() {
+    // Even though this generator holds a `PhantomPinned` in its environment, it
+    // remains `Unpin`.
+    assert_unpin(|| {
+        let pinned = PhantomPinned;
+        yield;
+        drop(pinned);
+    });
+}