part of Support gen syntax (feature gen_blocks) #16156#21987
part of Support gen syntax (feature gen_blocks) #16156#21987asukaminato0721 wants to merge 1 commit intorust-lang:masterfrom
Conversation
b4d4360 to
e737273
Compare
There was a problem hiding this comment.
Pull request overview
Adds initial support for the gen / async gen syntax (blocks and functions) across HIR lowering, type inference, and type display, including wiring up an AsyncIterator lang item and adding regression tests.
Changes:
- Introduce new HIR expression variants for
gen {}/async gen {}and lowergen fn/async gen fnbodies into them. - Extend type inference / solver interop and type display to represent
genasimpl Iterator<Item = ...>andasync genasimpl AsyncIterator<Item = ...>. - Add
AsyncIteratorminicore + lang item plumbing and new inference/coercion tests.
Reviewed changes
Copilot reviewed 22 out of 22 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| crates/test-utils/src/minicore.rs | Adds minicore support for core::async_iter::AsyncIterator plus #[lang] wiring for Option/Poll. |
| crates/intern/src/symbol/symbols.rs | Registers new symbols used by the async iterator/lang item plumbing. |
| crates/hir/src/display.rs | Displays gen fn/async gen fn and strips wrapped return types similarly to async fn. |
| crates/hir-ty/src/tests/simple.rs | Adds inference tests for gen/async gen blocks and functions. |
| crates/hir-ty/src/tests/coercion.rs | Adds coercion tests for yield inside gen/async gen blocks. |
| crates/hir-ty/src/next_solver/interner.rs | Updates solver interner to recognize Gen/AsyncGen and map AsyncIterator lang item. |
| crates/hir-ty/src/mir/lower.rs | Explicitly marks gen/async gen blocks as not supported in MIR lowering. |
| crates/hir-ty/src/infer/mutability.rs | Includes Gen/AsyncGen in mutability inference traversal. |
| crates/hir-ty/src/infer/expr.rs | Implements inference + coroutine type lowering for Gen/AsyncGen blocks. |
| crates/hir-ty/src/infer/closure/analysis.rs | Includes Gen/AsyncGen in closure capture analysis traversal. |
| crates/hir-ty/src/display.rs | Displays coroutine types originating from gen/async gen as impl Iterator/AsyncIterator. |
| crates/hir-ty/src/diagnostics/unsafe_check.rs | Traverses Gen/AsyncGen blocks in unsafe diagnostics. |
| crates/hir-ty/src/diagnostics/expr.rs | Validates Gen/AsyncGen blocks like other block expressions. |
| crates/hir-expand/src/mod_path.rs | Adds known path for core::async_iter::AsyncIterator. |
| crates/hir-def/src/signatures.rs | Adds GEN flag and is_gen() on function signatures. |
| crates/hir-def/src/lang_item.rs | Adds AsyncIterator to the lang item table. |
| crates/hir-def/src/hir.rs | Adds Expr::Gen and Expr::AsyncGen HIR variants. |
| crates/hir-def/src/expr_store/scope.rs | Ensures scopes are computed for Gen/AsyncGen blocks. |
| crates/hir-def/src/expr_store/pretty.rs | Pretty-prints gen and async gen blocks. |
| crates/hir-def/src/expr_store/lower.rs | Lowers gen/async gen blocks and wraps gen fn/async gen fn bodies; wraps function return type in Iterator/AsyncIterator impl-trait. |
| crates/hir-def/src/expr_store/body.rs | Threads is_gen_fn into body lowering. |
| crates/hir-def/src/expr_store.rs | Traversal updates to treat Gen/AsyncGen as block-like expressions. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
I prefer to wait with this until my closure rewrite will be merged, which will mean you will have a rebase to do, but gen blocks/closures will be supported much better. I can also direct you (after I finish my branch of course), we need to follow rustc closely. |
This comment has been minimized.
This comment has been minimized.
|
This PR was rebased onto a different master commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. |
|
So: my PR was merged, what you need to do now is complete the things:
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CoroutineKind {
Async,
Gen,
AsyncGen,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ClosureKind {
Closure,
OldCoroutine(Movability), // `#[coroutine]`, previously this variant was called `Coroutine`. I don't have a better name :(
Coroutine { kind: CoroutineKind, source: CoroutineSource }, // Previously `AsyncBlock`
CoroutineClosure(CoroutineKind), // Previously `AsyncClosure`
}
That's it I think! Feel free to ask me questions. |
There was a problem hiding this comment.
I have a suspect that you're using AI tools for code generation without disclosing that.
Please note that we require disclosure for AI usage, and properly understanding and reviewing their output.
| // all async closures would default to `FnOnce` as their calling mode. | ||
| CaptureBy::Ref, | ||
| let capture_by = match kind { | ||
| // Async closures use by-ref by default so they don't all collapse to `FnOnce`. |
There was a problem hiding this comment.
Nope, gen and async gen closures also need CaptureBy::Ref.
| const EXPLICIT_SAFE = 1 << 11; | ||
| const HAS_LEGACY_CONST_GENERICS = 1 << 12; | ||
| const RUSTC_INTRINSIC = 1 << 13; | ||
| const GEN = 1 << 14; |
There was a problem hiding this comment.
Put it near ASYNC?
| let body = this.collect_expr_opt(expr); | ||
| if awaitable == Awaitable::Yes { | ||
| this.lower_async_block_with_moved_arguments(params, body, CoroutineSource::Fn) | ||
| if is_gen_fn { |
There was a problem hiding this comment.
This should also just call lower_coroutine_with_moved_arguments().
| fn desugared_coroutine_expr( | ||
| &mut self, | ||
| source: CoroutineSource, | ||
| closure_kind: ClosureKind, |
There was a problem hiding this comment.
Take instead CoroutineKind and CoroutineSource?
| }; | ||
| ClosureKind::Coroutine(movability) | ||
| let closure_kind = if let Some(kind) = | ||
| if e.async_token().is_some() && e.gen_token().is_some() |
There was a problem hiding this comment.
I don't like the nested if here. Split it into a local.
| // would naturally unify these two trait hierarchies in the most | ||
| // general way. | ||
| let call_trait_choices = if self.shallow_resolve(adjusted_ty).is_coroutine_closure() { | ||
| let prefer_async_fn_traits = match self.shallow_resolve(adjusted_ty).kind() { |
There was a problem hiding this comment.
rustc doesn't do this and keeps the old self.shallow_resolve(adjusted_ty).is_coroutine_closure() check, so it's good enough for us.
| ClosureKind::Coroutine(_) => self.table.next_ty_var(), | ||
| ClosureKind::AsyncBlock { .. } => self.types.types.unit, | ||
| ClosureKind::OldCoroutine(_) | ||
| | ClosureKind::Coroutine { kind: CoroutineKind::Gen | CoroutineKind::AsyncGen, .. } => { |
There was a problem hiding this comment.
Did you look at the rustc code I linked? That's not what it does.
| .async_fn_trait_kind_from_def_id(trait_def_id) | ||
| .or_else(|| self.fn_trait_kind_from_def_id(trait_def_id)), | ||
| ClosureKind::CoroutineClosure(CoroutineKind::Gen) | ||
| | ClosureKind::CoroutineClosure(CoroutineKind::AsyncGen) => { |
There was a problem hiding this comment.
This is again not what rustc does. Look carefully.
| { | ||
| self.extract_sig_from_projection_and_future_bound(projection) | ||
| } | ||
| ClosureKind::CoroutineClosure(CoroutineKind::Gen | CoroutineKind::AsyncGen) |
part of #16156
add basic supports for
gen { }async gen { }gen fnasync gen fnfix some type signature show.
add some tests.