-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Coroutines should be able to implement for<'a> Coroutine<&'a mut T>
#68923
Comments
One question is how do you not store the argument in the generator state, it seems like this would require some extra syntax (or inference) to tell the transform not to store it. For example to support something like the async transform you essentially need to construct generators like this: let gen = |arg: &mut bool| {
*arg = true;
let arg = yield ();
*arg = false
let arg = yield ();
}; With the current generator transform this will have to allocate storage for the first two instances of |
@Nemo157 Generators already make sure to only capture variables that are actually live across a yield point. This also seems to work with your example (resulting generator state size is 4, so it only contains the state discriminant). |
The value not actually being stored in the state is an optimization, currently during type checking the values are still assumed to be live across the yield point (and making this be based on the actual data flow may not be wanted as it will mean minor changes to the code can have unintended impacts on what is live across the yield) |
Are you sure? I couldn't get the witness type to show up in error messages when I tried your example, so I couldn't see what typeck actually considers live, but I'm pretty sure it's already smart enough to ignore variables that are only accessed between two |
Ah, got it. Looks like you're right: |
Currently only blocks can prevent typeck from considering a value live across yields. Looks like the check is even before moves are checked, based on which errors are gotten. (playground) |
Just to make sure it doesn't get forgotten: type-checking needs to ensure distinct skolemizations for every That is, you shouldn't be able to e.g.: for<'a> |first: &mut &'a T| {
let second = yield;
mem::swap(first, second);
} because the
Wait ugh I forgot the fact that the lifetimes are only guaranteed by the resumer until the next That means even e.g. I would still try to get separate skolemizations, even if the lifetimes can be "cut" at the |
Blocked on #69663 |
for<'a> Generator<&'a mut T>
for<'a> Coroutine<&'a mut T>
Since I couldn't find this issue via search, let me add some keywords:
|
I've found one issue regarding the It feels like |
To add on to this, coroutines can currently not impl for<'a> Coroutine<&'a T> either? Right? I am not able to get this for the |
@andrewgazelka they currently cannot implement it for any type that has a lifetime parameter. |
Is there any workaround for this limitation available? |
You can always transmute lifetimes, but I would not recommend. |
Relevant RFC & Discussion rust-lang/rfcs#2781 |
With #68524, the
Coroutine
trait has gained a type parameter for the resume argument. Currently, this parameter will not be inferred to a type with late-bound regions. In some cases, this is required for soundness. For example, this coroutine stores the resume argument across ayield
, which means that it can not accept arbitrary lifetimes in it:This coroutine ends up implementing
Coroutine<&'x mut bool>
with a specific'x
, notfor<'x> Generator<&'x mut bool>
.However, if the resume argument doesn't get stored inside the generator state, it should be fine for the coroutine to implement
for<'x> Coroutine<&'x mut bool>
instead.This is already how closures behave, since they can also store their arguments inside upvars, so it shouldn't be terribly difficult to extend this to coroutines. It would be good to come up with lots of test cases beforehand though (perhaps inspired by the tests for closures).
The text was updated successfully, but these errors were encountered: