1
Fork 0

Merge Async and Gen into CoroutineKind

This commit is contained in:
Eric Holk 2023-11-30 14:54:39 -08:00
parent 3887b1645a
commit 48d5f1f0f2
No known key found for this signature in database
GPG key ID: 8EA6B43ED4CE0911
25 changed files with 442 additions and 238 deletions

View file

@ -195,39 +195,37 @@ impl<'hir> LoweringContext<'_, 'hir> {
binder,
capture_clause,
constness,
asyncness,
coro_kind,
movability,
fn_decl,
body,
fn_decl_span,
fn_arg_span,
}) => {
if let Async::Yes { closure_id, .. } = asyncness {
self.lower_expr_async_closure(
binder,
*capture_clause,
e.id,
hir_id,
*closure_id,
fn_decl,
body,
*fn_decl_span,
*fn_arg_span,
)
} else {
self.lower_expr_closure(
binder,
*capture_clause,
e.id,
*constness,
*movability,
fn_decl,
body,
*fn_decl_span,
*fn_arg_span,
)
}
}
}) => match coro_kind {
CoroutineKind::Async { closure_id, .. }
| CoroutineKind::Gen { closure_id, .. } => self.lower_expr_async_closure(
binder,
*capture_clause,
e.id,
hir_id,
*closure_id,
fn_decl,
body,
*fn_decl_span,
*fn_arg_span,
),
CoroutineKind::None => self.lower_expr_closure(
binder,
*capture_clause,
e.id,
*constness,
*movability,
fn_decl,
body,
*fn_decl_span,
*fn_arg_span,
),
},
ExprKind::Block(blk, opt_label) => {
let opt_label = self.lower_label(*opt_label);
hir::ExprKind::Block(self.lower_block(blk, opt_label.is_some()), opt_label)
@ -935,7 +933,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params);
// Lower outside new scope to preserve `is_in_loop_condition`.
let fn_decl = self.lower_fn_decl(decl, closure_id, fn_decl_span, FnDeclKind::Closure, None);
let fn_decl = self.lower_fn_decl(
decl,
closure_id,
fn_decl_span,
FnDeclKind::Closure,
CoroutineKind::None,
);
let c = self.arena.alloc(hir::Closure {
def_id: self.local_def_id(closure_id),
@ -1050,8 +1054,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
// We need to lower the declaration outside the new scope, because we
// have to conserve the state of being inside a loop condition for the
// closure argument types.
let fn_decl =
self.lower_fn_decl(&outer_decl, closure_id, fn_decl_span, FnDeclKind::Closure, None);
let fn_decl = self.lower_fn_decl(
&outer_decl,
closure_id,
fn_decl_span,
FnDeclKind::Closure,
CoroutineKind::None,
);
let c = self.arena.alloc(hir::Closure {
def_id: self.local_def_id(closure_id),

View file

@ -1,5 +1,3 @@
use crate::FnReturnTransformation;
use super::errors::{InvalidAbi, InvalidAbiReason, InvalidAbiSuggestion, MisplacedRelaxTraitBound};
use super::ResolverAstLoweringExt;
use super::{AstOwner, ImplTraitContext, ImplTraitPosition};
@ -208,35 +206,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
// `impl Future<Output = T>` here because lower_body
// only cares about the input argument patterns in the function
// declaration (decl), not the return types.
let asyncness = header.asyncness;
let genness = header.genness;
let coro_kind = header.coro_kind;
let body_id = this.lower_maybe_coroutine_body(
span,
hir_id,
decl,
asyncness,
genness,
coro_kind,
body.as_deref(),
);
let itctx = ImplTraitContext::Universal;
let (generics, decl) =
this.lower_generics(generics, header.constness, id, &itctx, |this| {
let ret_id = asyncness
.opt_return_id()
.map(|(node_id, span)| {
crate::FnReturnTransformation::Async(node_id, span)
})
.or_else(|| match genness {
Gen::Yes { span, closure_id: _, return_impl_trait_id } => {
Some(crate::FnReturnTransformation::Iterator(
return_impl_trait_id,
span,
))
}
_ => None,
});
this.lower_fn_decl(decl, id, *fn_sig_span, FnDeclKind::Fn, ret_id)
this.lower_fn_decl(decl, id, *fn_sig_span, FnDeclKind::Fn, coro_kind)
});
let sig = hir::FnSig {
decl,
@ -620,7 +602,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
i.id,
sig.span,
FnDeclKind::ExternFn,
None,
CoroutineKind::None,
),
this.lower_fn_params_to_names(fdec),
)
@ -747,28 +729,22 @@ impl<'hir> LoweringContext<'_, 'hir> {
(generics, kind, expr.is_some())
}
AssocItemKind::Fn(box Fn { sig, generics, body: None, .. }) => {
let asyncness = sig.header.asyncness;
let names = self.lower_fn_params_to_names(&sig.decl);
let (generics, sig) = self.lower_method_sig(
generics,
sig,
i.id,
FnDeclKind::Trait,
asyncness
.opt_return_id()
.map(|(node_id, span)| crate::FnReturnTransformation::Async(node_id, span)),
sig.header.coro_kind,
);
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false)
}
AssocItemKind::Fn(box Fn { sig, generics, body: Some(body), .. }) => {
let asyncness = sig.header.asyncness;
let genness = sig.header.genness;
let body_id = self.lower_maybe_coroutine_body(
i.span,
hir_id,
&sig.decl,
asyncness,
genness,
sig.header.coro_kind,
Some(body),
);
let (generics, sig) = self.lower_method_sig(
@ -776,9 +752,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
sig,
i.id,
FnDeclKind::Trait,
asyncness
.opt_return_id()
.map(|(node_id, span)| crate::FnReturnTransformation::Async(node_id, span)),
sig.header.coro_kind,
);
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), true)
}
@ -867,14 +841,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
},
),
AssocItemKind::Fn(box Fn { sig, generics, body, .. }) => {
let asyncness = sig.header.asyncness;
let genness = sig.header.genness;
self.current_item = Some(i.span);
let body_id = self.lower_maybe_coroutine_body(
i.span,
hir_id,
&sig.decl,
asyncness,
genness,
sig.header.coro_kind,
body.as_deref(),
);
let (generics, sig) = self.lower_method_sig(
@ -882,9 +854,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
sig,
i.id,
if self.is_in_trait_impl { FnDeclKind::Impl } else { FnDeclKind::Inherent },
asyncness
.opt_return_id()
.map(|(node_id, span)| crate::FnReturnTransformation::Async(node_id, span)),
sig.header.coro_kind,
);
(generics, hir::ImplItemKind::Fn(sig, body_id))
@ -1055,15 +1025,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
span: Span,
fn_id: hir::HirId,
decl: &FnDecl,
asyncness: Async,
genness: Gen,
coro_kind: CoroutineKind,
body: Option<&Block>,
) -> hir::BodyId {
let (closure_id, body) = match (asyncness, genness, body) {
// FIXME(eholk): do something reasonable for `async gen fn`. Probably that's an error
// for now since it's not supported.
(Async::Yes { closure_id, .. }, _, Some(body))
| (_, Gen::Yes { closure_id, .. }, Some(body)) => (closure_id, body),
let (closure_id, body) = match (coro_kind, body) {
(
CoroutineKind::Async { closure_id, .. } | CoroutineKind::Gen { closure_id, .. },
Some(body),
) => (closure_id, body),
_ => return self.lower_fn_body_block(span, decl, body),
};
@ -1232,8 +1201,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
this.expr_block(body)
};
let coroutine_expr = match (asyncness, genness) {
(Async::Yes { .. }, _) => this.make_async_expr(
let coroutine_expr = match coro_kind {
CoroutineKind::Async { .. } => this.make_async_expr(
CaptureBy::Value { move_kw: rustc_span::DUMMY_SP },
closure_id,
None,
@ -1241,7 +1210,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
hir::CoroutineSource::Fn,
mkbody,
),
(_, Gen::Yes { .. }) => this.make_gen_expr(
CoroutineKind::Gen { .. } => this.make_gen_expr(
CaptureBy::Value { move_kw: rustc_span::DUMMY_SP },
closure_id,
None,
@ -1249,7 +1218,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
hir::CoroutineSource::Fn,
mkbody,
),
_ => unreachable!("we must have either an async fn or a gen fn"),
CoroutineKind::None => unreachable!("we must have either an async fn or a gen fn"),
};
let hir_id = this.lower_node_id(closure_id);
@ -1266,21 +1235,26 @@ impl<'hir> LoweringContext<'_, 'hir> {
sig: &FnSig,
id: NodeId,
kind: FnDeclKind,
transform_return_type: Option<FnReturnTransformation>,
coro_kind: CoroutineKind,
) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) {
let header = self.lower_fn_header(sig.header);
let itctx = ImplTraitContext::Universal;
let (generics, decl) =
self.lower_generics(generics, sig.header.constness, id, &itctx, |this| {
this.lower_fn_decl(&sig.decl, id, sig.span, kind, transform_return_type)
this.lower_fn_decl(&sig.decl, id, sig.span, kind, coro_kind)
});
(generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
}
fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
let asyncness = if let CoroutineKind::Async { span, .. } = h.coro_kind {
hir::IsAsync::Async(span)
} else {
hir::IsAsync::NotAsync
};
hir::FnHeader {
unsafety: self.lower_unsafety(h.unsafety),
asyncness: self.lower_asyncness(h.asyncness),
asyncness: asyncness,
constness: self.lower_constness(h.constness),
abi: self.lower_extern(h.ext),
}
@ -1322,13 +1296,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
});
}
fn lower_asyncness(&mut self, a: Async) -> hir::IsAsync {
match a {
Async::Yes { span, .. } => hir::IsAsync::Async(span),
Async::No => hir::IsAsync::NotAsync,
}
}
pub(super) fn lower_constness(&mut self, c: Const) -> hir::Constness {
match c {
Const::Yes(_) => hir::Constness::Const,

View file

@ -493,21 +493,6 @@ enum ParenthesizedGenericArgs {
Err,
}
/// Describes a return type transformation that can be performed by `LoweringContext::lower_fn_decl`
#[derive(Debug)]
enum FnReturnTransformation {
/// Replaces a return type `T` with `impl Future<Output = T>`.
///
/// The `NodeId` is the ID of the return type `impl Trait` item, and the `Span` points to the
/// `async` keyword.
Async(NodeId, Span),
/// Replaces a return type `T` with `impl Iterator<Item = T>`.
///
/// The `NodeId` is the ID of the return type `impl Trait` item, and the `Span` points to the
/// `gen` keyword.
Iterator(NodeId, Span),
}
impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn create_def(
&mut self,
@ -1374,7 +1359,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
generic_params,
unsafety: self.lower_unsafety(f.unsafety),
abi: self.lower_extern(f.ext),
decl: self.lower_fn_decl(&f.decl, t.id, t.span, FnDeclKind::Pointer, None),
decl: self.lower_fn_decl(
&f.decl,
t.id,
t.span,
FnDeclKind::Pointer,
CoroutineKind::None,
),
param_names: self.lower_fn_params_to_names(&f.decl),
}))
}
@ -1809,7 +1800,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn_node_id: NodeId,
fn_span: Span,
kind: FnDeclKind,
transform_return_type: Option<FnReturnTransformation>,
coro: CoroutineKind,
) -> &'hir hir::FnDecl<'hir> {
let c_variadic = decl.c_variadic();
@ -1838,12 +1829,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.lower_ty_direct(&param.ty, &itctx)
}));
let output = match transform_return_type {
Some(transform) => {
let output = match coro {
CoroutineKind::Async { .. } | CoroutineKind::Gen { .. } => {
let fn_def_id = self.local_def_id(fn_node_id);
self.lower_coroutine_fn_ret_ty(&decl.output, fn_def_id, transform, kind, fn_span)
self.lower_coroutine_fn_ret_ty(&decl.output, fn_def_id, coro, kind, fn_span)
}
None => match &decl.output {
CoroutineKind::None => match &decl.output {
FnRetTy::Ty(ty) => {
let context = if kind.return_impl_trait_allowed() {
let fn_def_id = self.local_def_id(fn_node_id);
@ -1910,16 +1901,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
&mut self,
output: &FnRetTy,
fn_def_id: LocalDefId,
transform: FnReturnTransformation,
coro: CoroutineKind,
fn_kind: FnDeclKind,
fn_span: Span,
) -> hir::FnRetTy<'hir> {
let span = self.lower_span(fn_span);
let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::Async, span, None);
let opaque_ty_node_id = match transform {
FnReturnTransformation::Async(opaque_ty_node_id, _)
| FnReturnTransformation::Iterator(opaque_ty_node_id, _) => opaque_ty_node_id,
let opaque_ty_node_id = match coro {
CoroutineKind::Async { return_impl_trait_id, .. }
| CoroutineKind::Gen { return_impl_trait_id, .. } => return_impl_trait_id,
CoroutineKind::None => {
unreachable!("lower_coroutine_fn_ret_ty must be called with either Async or Gen")
}
};
let captured_lifetimes: Vec<_> = self
@ -1939,7 +1933,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|this| {
let future_bound = this.lower_coroutine_fn_output_type_to_future_bound(
output,
transform,
coro,
span,
ImplTraitContext::ReturnPositionOpaqueTy {
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
@ -1958,7 +1952,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_coroutine_fn_output_type_to_future_bound(
&mut self,
output: &FnRetTy,
transform: FnReturnTransformation,
coro: CoroutineKind,
span: Span,
nested_impl_trait_context: ImplTraitContext,
) -> hir::GenericBound<'hir> {
@ -1974,11 +1968,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
};
// "<Output|Item = T>"
let (symbol, lang_item) = match transform {
FnReturnTransformation::Async(..) => (hir::FN_OUTPUT_NAME, hir::LangItem::Future),
FnReturnTransformation::Iterator(..) => {
(hir::ITERATOR_ITEM_NAME, hir::LangItem::Iterator)
}
let (symbol, lang_item) = match coro {
CoroutineKind::Async { .. } => (hir::FN_OUTPUT_NAME, hir::LangItem::Future),
CoroutineKind::Gen { .. } => (hir::ITERATOR_ITEM_NAME, hir::LangItem::Iterator),
CoroutineKind::None => panic!("attemping to lower output type of non-coroutine fn"),
};
let future_args = self.arena.alloc(hir::GenericArgs {