diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 7a244b7e80e..6fe4a7a52be 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 831c248bf90..613c495832f 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 { } } -pub fn bar(t: T) -> Box + Unpin> { +pub fn bar(t: T) -> Box + 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 00000000000..96d0a8e2833 --- /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) { +} + +fn main() { + // Even though this generator holds a `PhantomPinned` in its environment, it + // remains `Unpin`. + assert_unpin(|| { + let pinned = PhantomPinned; + yield; + drop(pinned); + }); +}