Auto merge of #118457 - eholk:genfn, r=compiler-errors
Add support for `gen fn` This builds on #116447 to add support for `gen fn` functions. For the most part we follow the same approach as desugaring `async fn`, but replacing `Future` with `Iterator` and `async {}` with `gen {}` for the body. The version implemented here uses the return type of a `gen fn` as the yield type. For example: ```rust gen fn count_to_three() -> i32 { yield 1; yield 2; yield 3; } ``` In the future, I think we should experiment with a syntax like `gen fn count_to_three() yield i32 { ... }`, but that can go in another PR. cc `@oli-obk` `@compiler-errors`
This commit is contained in:
commit
56278a6e28
36 changed files with 417 additions and 234 deletions
|
@ -156,7 +156,10 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
|
|||
|
||||
fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
|
||||
if let FnKind::Fn(_, _, sig, _, generics, body) = fn_kind {
|
||||
if let Async::Yes { closure_id, .. } = sig.header.asyncness {
|
||||
if let Some(
|
||||
CoroutineKind::Async { closure_id, .. } | CoroutineKind::Gen { closure_id, .. },
|
||||
) = sig.header.coro_kind
|
||||
{
|
||||
self.visit_generics(generics);
|
||||
|
||||
// For async functions, we need to create their inner defs inside of a
|
||||
|
@ -281,11 +284,12 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
|
|||
// Async closures desugar to closures inside of closures, so
|
||||
// we must create two defs.
|
||||
let closure_def = self.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span);
|
||||
match closure.asyncness {
|
||||
Async::Yes { closure_id, .. } => {
|
||||
self.create_def(closure_id, kw::Empty, DefKind::Closure, expr.span)
|
||||
}
|
||||
Async::No => closure_def,
|
||||
match closure.coro_kind {
|
||||
Some(
|
||||
CoroutineKind::Async { closure_id, .. }
|
||||
| CoroutineKind::Gen { closure_id, .. },
|
||||
) => self.create_def(closure_id, kw::Empty, DefKind::Closure, expr.span),
|
||||
None => closure_def,
|
||||
}
|
||||
}
|
||||
ExprKind::Gen(_, _, _) => {
|
||||
|
|
|
@ -916,8 +916,10 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
|
|||
&sig.decl.output,
|
||||
);
|
||||
|
||||
if let Some((async_node_id, _)) = sig.header.asyncness.opt_return_id() {
|
||||
this.record_lifetime_params_for_impl_trait(async_node_id);
|
||||
if let Some((coro_node_id, _)) =
|
||||
sig.header.coro_kind.map(|coro_kind| coro_kind.return_id())
|
||||
{
|
||||
this.record_lifetime_params_for_impl_trait(coro_node_id);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
@ -940,12 +942,13 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
|
|||
this.visit_generics(generics);
|
||||
|
||||
let declaration = &sig.decl;
|
||||
let async_node_id = sig.header.asyncness.opt_return_id();
|
||||
let coro_node_id =
|
||||
sig.header.coro_kind.map(|coro_kind| coro_kind.return_id());
|
||||
|
||||
this.with_lifetime_rib(
|
||||
LifetimeRibKind::AnonymousCreateParameter {
|
||||
binder: fn_id,
|
||||
report_in_path: async_node_id.is_some(),
|
||||
report_in_path: coro_node_id.is_some(),
|
||||
},
|
||||
|this| {
|
||||
this.resolve_fn_signature(
|
||||
|
@ -958,7 +961,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
|
|||
&declaration.output,
|
||||
);
|
||||
|
||||
if let Some((async_node_id, _)) = async_node_id {
|
||||
if let Some((async_node_id, _)) = coro_node_id {
|
||||
this.record_lifetime_params_for_impl_trait(async_node_id);
|
||||
}
|
||||
},
|
||||
|
@ -4288,8 +4291,10 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
// `async |x| ...` gets desugared to `|x| async {...}`, so we need to
|
||||
// resolve the arguments within the proper scopes so that usages of them inside the
|
||||
// closure are detected as upvars rather than normal closure arg usages.
|
||||
//
|
||||
// Similarly, `gen |x| ...` gets desugared to `|x| gen {...}`, so we handle that too.
|
||||
ExprKind::Closure(box ast::Closure {
|
||||
asyncness: Async::Yes { .. },
|
||||
coro_kind: Some(_),
|
||||
ref fn_decl,
|
||||
ref body,
|
||||
..
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue