Skip to content

ICE with impl Generator: self.has_escaping_regions #49537

Closed
@Nemo157

Description

@Nemo157
#![feature(generators, generator_trait)]

use std::ops::Generator;

macro_rules! yield_from {
    ($e:expr) => {{
        let mut gen = $e;
        loop {
            match unsafe { ::std::ops::Generator::resume(&mut gen) } {
                ::std::ops::GeneratorState::Yielded(e) => yield e,
                ::std::ops::GeneratorState::Complete(e) => break e,
            }
        }
    }};
}

pub fn unpinned<'a, T: 'a, F, G>(
    data: &'a mut T,
    f: F,
) -> impl Generator<Yield = G::Yield, Return = G::Return> + 'a
where
    F: FnOnce(&'a mut T) -> G + 'a,
    G: Generator + 'a,
{
    move || yield_from!(f(data))
}

#[derive(Debug)]
struct Foo;

impl Foo {
    pub fn foo(&mut self) {
        println!("{:?} at {:?}", *self, &*self as *const Self);
    }
}

fn bar<'a>(foo: &'a mut Foo) -> impl Generator<Yield = (), Return = ()> + 'a {
    move || {
        let inner = unpinned(foo, |foo| {
            move || {
                foo.foo();
                yield ();
                foo.foo();
            }
        });
        yield_from!(inner)
    }
}

fn main() {
    let mut foo = Foo;
    let mut baz = bar(&mut foo);
    println!("{:?}", unsafe { baz.resume() });
    println!("{:?}", unsafe { baz.resume() });
}

(playground), errors:

thread 'rustc' panicked at 'assertion failed: !self.has_escaping_regions()', librustc/ty/mod.rs:1165:9

note: rustc 1.26.0-nightly (80785a547 2018-03-30) running on x86_64-unknown-linux-gnu
note: compiler flags: -C codegen-units=1 -C debuginfo=2 --crate-type bin
note: some of the compiler flags provided by cargo are hidden
click to see original with Pin as well

Throwing all the new features together is always the best idea, right?

#![feature(pin, generators, generator_trait, arbitrary_self_types)]

use std::mem::Pin;
use std::ops::Generator;

macro_rules! yield_from {
    ($e:expr) => ({
        let mut gen = $e;
        loop {
            let gen = &mut gen;
            // The above is to force a borrow across yield point to ensure we're
            // in an immovable generator, just in case $e is an immovable
            // generator (hopefully we can detect this in the future somehow).
            match unsafe { ::std::ops::Generator::resume(gen) } {
                ::std::ops::GeneratorState::Yielded(e) => yield e,
                ::std::ops::GeneratorState::Complete(e) => break e,
            }
        }
    })
}

pub fn pinned<'a, T: 'a, F, G>(
    data: T,
    f: F,
) -> impl Generator<Yield = G::Yield, Return = G::Return> + 'a
where
    F: FnOnce(Pin<'a, T>) -> G + 'a,
    G: Generator + 'a,
{
    static move || {
        let data = data;
        yield_from!(f(unsafe { Pin::new_unchecked(&mut data) }))
    }
}

#[derive(Debug)]
struct Foo;

impl Foo {
    pub fn foo(self: Pin<Self>) {
        println!("{:?} at {:?}", *self, &*self as *const Self);
    }
}

fn bar() -> impl Generator<Yield = (), Return = ()> {
    static move || {
        let inner = pinned(Foo, |foo| {
            static move || {
                foo.foo();
                yield ();
                foo.foo();
            }
        });
        yield_from!(inner)
    }
}

fn main() {
    let mut baz = bar();
    println!("{:?}", unsafe { baz.resume() });
    println!("{:?}", unsafe { baz.resume() });
}

(playground), error:

thread 'rustc' panicked at 'assertion failed: !self.has_escaping_regions()', librustc/ty/mod.rs:1165:9

note: rustc 1.26.0-nightly (80785a547 2018-03-30) running on x86_64-unknown-linux-gnu
note: compiler flags: -C codegen-units=1 -C debuginfo=2 --crate-type bin
note: some of the compiler flags provided by cargo are hidden

I'll try and simplify this down, presumably it should be reproducible with normal references instead of Pins.

EDIT: Updated playground for breaking Pin changes: https://play.rust-lang.org/?gist=4c62d656bec128a07ea2df1d12385b66&version=nightly&mode=debug

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-coroutinesArea: CoroutinesC-bugCategory: This is a bug.I-ICEIssue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions