-
Notifications
You must be signed in to change notification settings - Fork 182
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
Implement generators #593
Implement generators #593
Conversation
f360594
to
ab3efa5
Compare
This is mostly working - however, I still need to figure out how to treat generator witness lifetime as existentially quantified when handling auto traits. |
58b87d4
to
1c6ef1d
Compare
@jackh726 @nikomatsakis This is ready for review |
`GeneratorDatum` and `GeneratorWitnessDatum` are introduced, which mirror `TyKind::Generator` and `TyKind::GeneratorWitness` in rustc. We handle auto traits for `GeneratorDatum` using the existing `constituent_types` method. For `GeneratorWitnessDatum`, we generate a `forall<'a, 'b, ... 'z>` goal to reflect the fact that our lifetimes are existentially bound. Unresolved questions: * The implementation of `GeneratorWitnessDatum` needs careful review - I'm not certain that I fully understand how `Binders` works. * The syntax implemented in `parser.lalrpop` can be bikesheeded. We might want to use something other than `for<>` for the witness types, to reflect that fact that we have existential rather than universal quantification. * The generator grammar only allows quantifying over liftimes for the witness types - however, this gets lowered to a `Binders`, which supports types and constants as well. Should we do anything else to ensure we never end up with types/consts where they're not expected? * I added a test to ensure that we treat the witness lifetimes as existentially quantified - for example, if we have `for<'a, 'b> Foo<'a, 'b>`, we should only be able to use an auto trait impl that is fully generic over lifetimes - e.g. `impl<'a> Send for Foo<'a, 'b>` will not be used. I *believe* that the test is showing this behavior - it ends up returning region constraints that require `'a` and `'b` to outlive each other. Since these are 'existential' lifetimes (which cannot be substituted), this is an unsatisfiable constraint. However, I'm not sure where we should be detecting that this is unsatisfiable.
1c6ef1d
to
457b8bb
Compare
I definitely don't know enough about generators to make a meaningful review of this, so will definitely have to defer to @nikomatsakis. However, the book builtin types table will need to be updated here. Additionally, I really want to push for us to document generators and generator witnesses in the chalk book. I don't think it needs to be in this PR, but I am somewhat worried that if it isn't at least loosely documented here, it'll get pushed aside. Particularly, I feel like documenting this is super important since there's almost no documentation in the rustc dev guide or in the rustc codebase (that I can find). |
I'll work on writing up some docs. |
Awesome! I do want to stress that I understand docs can sometimes be hard to write. But I would definitely error on the side of "some docs are better than no docs" and "don't let perfect be the enemy of good enough"; we can always expand upon/clarify the docs in subsequent PRs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great. I left a nit about the syntax but I'm inclined to land it.
* Resume/yield/return types - the types produced/consumed by various generator methods. | ||
These are not stored in the generator across yield points - they are only | ||
used when the generator is running. | ||
* Generator witness - see the `Generator Witness` section below. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thank you for writing docs! wonderful.
### Generator witness types | ||
|
||
The `GeneratorWitness` variant represents the generator witness of | ||
the generator with id `GeneratorId`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it'd be good to explain the purpose of a witness:
The witness type captures the types of all variables that may be live across a yield
point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just moved this entire block from a different section of the book :) - I'm happy to expand on it.
// If we have `Foo<'a, 'b>` stored as a witness type, we will | ||
// not currently use this information to determine a more precise | ||
// relationship between 'a and 'b. In the future, we will likely | ||
// do this to avoid incorrectly rejecting correct code. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another great comment.
tests/test/generators.rs
Outdated
|
||
generator send_any_lifetime<T>[resume = (), yield = ()] { | ||
upvars [] | ||
witnesses for<'a, 'b> [SendAnyLifetime<'a, 'b, T>; u8] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the for
syntax here seems a bit misleading, I guess?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, it's not great. Do you think exists<>
would be better?
@nikomatsakis: I've addressed your comments |
@bors r=nikomatsakis |
📌 Commit e7a0892 has been approved by |
☀️ Test successful - checks-actions |
GeneratorDatum
andGeneratorWitnessDatum
are introduced, whichmirror
TyKind::Generator
andTyKind::GeneratorWitness
in rustc.We handle auto traits for
GeneratorDatum
using the existingconstituent_types
method. ForGeneratorWitnessDatum
, we generate aforall<'a, 'b, ... 'z>
goal to reflect the fact that our lifetimes areexistentially bound.
Unresolved questions:
GeneratorWitnessDatum
needs careful review -I'm not certain that I fully understand how
Binders
works.parser.lalrpop
can be bikesheeded. Wemight want to use something other than
for<>
for the witness types,to reflect that fact that we have existential rather than universal
quantification.
witness types - however, this gets lowered to a
Binders
, whichsupports types and constants as well. Should we do anything else
to ensure we never end up with types/consts where they're not
expected?
existentially quantified - for example, if we have
for<'a, 'b> Foo<'a, 'b>
, we should only be able to use an autotrait impl that is fully generic over lifetimes - e.g.
impl<'a> Send for Foo<'a, 'b>
will not be used. I believethat the test is showing this behavior - it ends up returning
region constraints that require
'a
and'b
to outlive each other.Since these are 'existential' lifetimes (which cannot be substituted),
this is an unsatisfiable constraint. However, I'm not sure where we
should be detecting that this is unsatisfiable.