Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Borrow error when yielding with nested generators #45093

Closed
da-x opened this issue Oct 7, 2017 · 7 comments
Closed

Borrow error when yielding with nested generators #45093

da-x opened this issue Oct 7, 2017 · 7 comments
Labels
A-coroutines Area: Coroutines A-diagnostics Area: Messages for errors, warnings, and lints C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@da-x
Copy link
Member

da-x commented Oct 7, 2017

Hi, I got some feedback regarding the generator feature that is currently in nightly.

I am testing whether it is possible to yield out of a generator while another generator is in scope, for example:

fn main() {
    let mut generator = || {
        yield 1;

        let mut sub_generator = || {
            yield 2;
        };

        match sub_generator.resume() {
            GeneratorState::Yielded(x) => {
                yield x;
            }
            _ => panic!("unexpected value from resume"),
        }

        yield 3;

        return "foo"
    };

    match generator.resume() {
        GeneratorState::Yielded(1) => {}
        _ => panic!("unexpected value from resume"),
    }
    match generator.resume() {
        GeneratorState::Yielded(2) => {}
        _ => panic!("unexpected value from resume"),
    }
    match generator.resume() {
        GeneratorState::Yielded(3) => {}
        _ => panic!("unexpected value from resume"),
    }
    match generator.resume() {
        GeneratorState::Complete("foo") => {}
        _ => panic!("unexpected value from resume"),
    }
}

However I am getting:

error[E0626]: borrow may still be in use when generator yields
  --> src/main.rs:17:15
   |
17 |         match sub_generator.resume() {
   |               ^^^^^^^^^^^^^
...
24 |         yield 3;
   |         ------- possible yield occurs here

rustc: rustc 1.22.0-nightly (05cbece09 2017-10-06)

I am not sure what borrow this error is talking about.

Is sub_generator not owned?

Is there an intention to support such use cases?

@sinkuu
Copy link
Contributor

sinkuu commented Oct 7, 2017

This could be a bug that rustc is pointing out a wrong yield. If I comment out yield x;, which is during sub_generator borrow, E0626 disappears.

@da-x
Copy link
Member Author

da-x commented Oct 8, 2017

#43122 @aturon

@estebank estebank added A-diagnostics Area: Messages for errors, warnings, and lints E-needs-mentor A-coroutines Area: Coroutines labels Oct 11, 2017
@Zoxc
Copy link
Contributor

Zoxc commented Oct 14, 2017

The resume function borrows the generator and that borrow is considered to be in live for the entire match when we are looking for yields which conflicts with it. A workaround is to move that call outside the match.

let result = sub_generator.resume();
match result {
    GeneratorState::Yielded(x) => {
        yield x;
    }
    _ => panic!("unexpected value from resume"),
}

@da-x
Copy link
Member Author

da-x commented Oct 14, 2017

I see.

Is this somewhat related to #44100 ? I guess that the borrow checker could have narrowed the borrowing to the matched value.

@Zoxc
Copy link
Contributor

Zoxc commented Oct 14, 2017

@da-x No, it's the fault of the code which finds out which values could be stored in the generator.

@Arnavion
Copy link

Arnavion commented Oct 15, 2017

Duplicate of #44197 ?

@XAMPPRocky XAMPPRocky added the C-bug Category: This is a bug. label Jan 22, 2018
Zoxc added a commit to Zoxc/rust that referenced this issue Jan 23, 2018
bors added a commit that referenced this issue Jan 23, 2018
Immovable generators

This adds support for immovable generators which allow you to borrow local values inside generator across suspension points. These are declared using a `static` keyword:
```rust
let mut generator = static || {
    let local = &Vec::new();
    yield;
    local.push(0i8);
};
generator.resume();

// ERROR moving the generator after it has resumed would invalidate the interior reference
// drop(generator);
```

Region inference is no longer affected by the types stored in generators so the regions inside should be similar to other code (and unaffected by the presence of `yield` expressions). The borrow checker is extended to pick up the slack so interior references still result in errors for movable generators. This fixes #44197, #45259 and #45093.

This PR depends on [PR #44917 (immovable types)](#44917), I suggest potential reviewers ignore the first commit as it adds immovable types.
@Zoxc
Copy link
Contributor

Zoxc commented Jan 27, 2018

Fixed by #45337.

@Zoxc Zoxc closed this as completed Jan 27, 2018
@pnkfelix pnkfelix added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Nov 15, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-coroutines Area: Coroutines A-diagnostics Area: Messages for errors, warnings, and lints C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

7 participants