Merge Async and Gen into CoroutineKind
This commit is contained in:
parent
3887b1645a
commit
48d5f1f0f2
25 changed files with 442 additions and 238 deletions
|
@ -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),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(¶m.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 {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue