Lower return types for gen fn to impl Iterator
This commit is contained in:
parent
bc0d10d4b0
commit
c104f3b629
7 changed files with 167 additions and 80 deletions
|
@ -1,3 +1,5 @@
|
||||||
|
use crate::FnReturnTransformation;
|
||||||
|
|
||||||
use super::errors::{InvalidAbi, InvalidAbiReason, InvalidAbiSuggestion, MisplacedRelaxTraitBound};
|
use super::errors::{InvalidAbi, InvalidAbiReason, InvalidAbiSuggestion, MisplacedRelaxTraitBound};
|
||||||
use super::ResolverAstLoweringExt;
|
use super::ResolverAstLoweringExt;
|
||||||
use super::{AstOwner, ImplTraitContext, ImplTraitPosition};
|
use super::{AstOwner, ImplTraitContext, ImplTraitPosition};
|
||||||
|
@ -207,13 +209,33 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
// only cares about the input argument patterns in the function
|
// only cares about the input argument patterns in the function
|
||||||
// declaration (decl), not the return types.
|
// declaration (decl), not the return types.
|
||||||
let asyncness = header.asyncness;
|
let asyncness = header.asyncness;
|
||||||
let body_id =
|
let genness = header.genness;
|
||||||
this.lower_maybe_async_body(span, hir_id, decl, asyncness, body.as_deref());
|
let body_id = this.lower_maybe_coroutine_body(
|
||||||
|
span,
|
||||||
|
hir_id,
|
||||||
|
decl,
|
||||||
|
asyncness,
|
||||||
|
genness,
|
||||||
|
body.as_deref(),
|
||||||
|
);
|
||||||
|
|
||||||
let itctx = ImplTraitContext::Universal;
|
let itctx = ImplTraitContext::Universal;
|
||||||
let (generics, decl) =
|
let (generics, decl) =
|
||||||
this.lower_generics(generics, header.constness, id, &itctx, |this| {
|
this.lower_generics(generics, header.constness, id, &itctx, |this| {
|
||||||
let ret_id = asyncness.opt_return_id();
|
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, ret_id)
|
||||||
});
|
});
|
||||||
let sig = hir::FnSig {
|
let sig = hir::FnSig {
|
||||||
|
@ -732,20 +754,31 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
sig,
|
sig,
|
||||||
i.id,
|
i.id,
|
||||||
FnDeclKind::Trait,
|
FnDeclKind::Trait,
|
||||||
asyncness.opt_return_id(),
|
asyncness
|
||||||
|
.opt_return_id()
|
||||||
|
.map(|(node_id, span)| crate::FnReturnTransformation::Async(node_id, span)),
|
||||||
);
|
);
|
||||||
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false)
|
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false)
|
||||||
}
|
}
|
||||||
AssocItemKind::Fn(box Fn { sig, generics, body: Some(body), .. }) => {
|
AssocItemKind::Fn(box Fn { sig, generics, body: Some(body), .. }) => {
|
||||||
let asyncness = sig.header.asyncness;
|
let asyncness = sig.header.asyncness;
|
||||||
let body_id =
|
let genness = sig.header.genness;
|
||||||
self.lower_maybe_async_body(i.span, hir_id, &sig.decl, asyncness, Some(body));
|
let body_id = self.lower_maybe_coroutine_body(
|
||||||
|
i.span,
|
||||||
|
hir_id,
|
||||||
|
&sig.decl,
|
||||||
|
asyncness,
|
||||||
|
genness,
|
||||||
|
Some(body),
|
||||||
|
);
|
||||||
let (generics, sig) = self.lower_method_sig(
|
let (generics, sig) = self.lower_method_sig(
|
||||||
generics,
|
generics,
|
||||||
sig,
|
sig,
|
||||||
i.id,
|
i.id,
|
||||||
FnDeclKind::Trait,
|
FnDeclKind::Trait,
|
||||||
asyncness.opt_return_id(),
|
asyncness
|
||||||
|
.opt_return_id()
|
||||||
|
.map(|(node_id, span)| crate::FnReturnTransformation::Async(node_id, span)),
|
||||||
);
|
);
|
||||||
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), true)
|
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), true)
|
||||||
}
|
}
|
||||||
|
@ -835,11 +868,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
),
|
),
|
||||||
AssocItemKind::Fn(box Fn { sig, generics, body, .. }) => {
|
AssocItemKind::Fn(box Fn { sig, generics, body, .. }) => {
|
||||||
let asyncness = sig.header.asyncness;
|
let asyncness = sig.header.asyncness;
|
||||||
let body_id = self.lower_maybe_async_body(
|
let genness = sig.header.genness;
|
||||||
|
let body_id = self.lower_maybe_coroutine_body(
|
||||||
i.span,
|
i.span,
|
||||||
hir_id,
|
hir_id,
|
||||||
&sig.decl,
|
&sig.decl,
|
||||||
asyncness,
|
asyncness,
|
||||||
|
genness,
|
||||||
body.as_deref(),
|
body.as_deref(),
|
||||||
);
|
);
|
||||||
let (generics, sig) = self.lower_method_sig(
|
let (generics, sig) = self.lower_method_sig(
|
||||||
|
@ -847,7 +882,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
sig,
|
sig,
|
||||||
i.id,
|
i.id,
|
||||||
if self.is_in_trait_impl { FnDeclKind::Impl } else { FnDeclKind::Inherent },
|
if self.is_in_trait_impl { FnDeclKind::Impl } else { FnDeclKind::Inherent },
|
||||||
asyncness.opt_return_id(),
|
asyncness
|
||||||
|
.opt_return_id()
|
||||||
|
.map(|(node_id, span)| crate::FnReturnTransformation::Async(node_id, span)),
|
||||||
);
|
);
|
||||||
|
|
||||||
(generics, hir::ImplItemKind::Fn(sig, body_id))
|
(generics, hir::ImplItemKind::Fn(sig, body_id))
|
||||||
|
@ -1011,16 +1048,22 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_maybe_async_body(
|
/// Takes what may be the body of an `async fn` or a `gen fn` and wraps it in an `async {}` or
|
||||||
|
/// `gen {}` block as appropriate.
|
||||||
|
fn lower_maybe_coroutine_body(
|
||||||
&mut self,
|
&mut self,
|
||||||
span: Span,
|
span: Span,
|
||||||
fn_id: hir::HirId,
|
fn_id: hir::HirId,
|
||||||
decl: &FnDecl,
|
decl: &FnDecl,
|
||||||
asyncness: Async,
|
asyncness: Async,
|
||||||
|
genness: Gen,
|
||||||
body: Option<&Block>,
|
body: Option<&Block>,
|
||||||
) -> hir::BodyId {
|
) -> hir::BodyId {
|
||||||
let (closure_id, body) = match (asyncness, body) {
|
let (closure_id, body) = match (asyncness, genness, body) {
|
||||||
(Async::Yes { closure_id, .. }, Some(body)) => (closure_id, 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),
|
||||||
_ => return self.lower_fn_body_block(span, decl, body),
|
_ => return self.lower_fn_body_block(span, decl, body),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1163,21 +1206,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
parameters.push(new_parameter);
|
parameters.push(new_parameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
let async_expr = this.make_async_expr(
|
let mkbody = |this: &mut LoweringContext<'_, 'hir>| {
|
||||||
CaptureBy::Value { move_kw: rustc_span::DUMMY_SP },
|
|
||||||
closure_id,
|
|
||||||
None,
|
|
||||||
body.span,
|
|
||||||
hir::CoroutineSource::Fn,
|
|
||||||
|this| {
|
|
||||||
// Create a block from the user's function body:
|
// Create a block from the user's function body:
|
||||||
let user_body = this.lower_block_expr(body);
|
let user_body = this.lower_block_expr(body);
|
||||||
|
|
||||||
// Transform into `drop-temps { <user-body> }`, an expression:
|
// Transform into `drop-temps { <user-body> }`, an expression:
|
||||||
let desugared_span =
|
let desugared_span =
|
||||||
this.mark_span_with_reason(DesugaringKind::Async, user_body.span, None);
|
this.mark_span_with_reason(DesugaringKind::Async, user_body.span, None);
|
||||||
let user_body =
|
let user_body = this.expr_drop_temps(desugared_span, this.arena.alloc(user_body));
|
||||||
this.expr_drop_temps(desugared_span, this.arena.alloc(user_body));
|
|
||||||
|
|
||||||
// As noted above, create the final block like
|
// As noted above, create the final block like
|
||||||
//
|
//
|
||||||
|
@ -1195,12 +1231,30 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
);
|
);
|
||||||
|
|
||||||
this.expr_block(body)
|
this.expr_block(body)
|
||||||
},
|
};
|
||||||
);
|
let coroutine_expr = match (asyncness, genness) {
|
||||||
|
(Async::Yes { .. }, _) => this.make_async_expr(
|
||||||
|
CaptureBy::Value { move_kw: rustc_span::DUMMY_SP },
|
||||||
|
closure_id,
|
||||||
|
None,
|
||||||
|
body.span,
|
||||||
|
hir::CoroutineSource::Fn,
|
||||||
|
mkbody,
|
||||||
|
),
|
||||||
|
(_, Gen::Yes { .. }) => this.make_gen_expr(
|
||||||
|
CaptureBy::Value { move_kw: rustc_span::DUMMY_SP },
|
||||||
|
closure_id,
|
||||||
|
None,
|
||||||
|
body.span,
|
||||||
|
hir::CoroutineSource::Fn,
|
||||||
|
mkbody,
|
||||||
|
),
|
||||||
|
_ => unreachable!("we must have either an async fn or a gen fn"),
|
||||||
|
};
|
||||||
|
|
||||||
let hir_id = this.lower_node_id(closure_id);
|
let hir_id = this.lower_node_id(closure_id);
|
||||||
this.maybe_forward_track_caller(body.span, fn_id, hir_id);
|
this.maybe_forward_track_caller(body.span, fn_id, hir_id);
|
||||||
let expr = hir::Expr { hir_id, kind: async_expr, span: this.lower_span(body.span) };
|
let expr = hir::Expr { hir_id, kind: coroutine_expr, span: this.lower_span(body.span) };
|
||||||
|
|
||||||
(this.arena.alloc_from_iter(parameters), expr)
|
(this.arena.alloc_from_iter(parameters), expr)
|
||||||
})
|
})
|
||||||
|
@ -1212,13 +1266,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
sig: &FnSig,
|
sig: &FnSig,
|
||||||
id: NodeId,
|
id: NodeId,
|
||||||
kind: FnDeclKind,
|
kind: FnDeclKind,
|
||||||
is_async: Option<(NodeId, Span)>,
|
transform_return_type: Option<FnReturnTransformation>,
|
||||||
) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) {
|
) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) {
|
||||||
let header = self.lower_fn_header(sig.header);
|
let header = self.lower_fn_header(sig.header);
|
||||||
let itctx = ImplTraitContext::Universal;
|
let itctx = ImplTraitContext::Universal;
|
||||||
let (generics, decl) =
|
let (generics, decl) =
|
||||||
self.lower_generics(generics, sig.header.constness, id, &itctx, |this| {
|
self.lower_generics(generics, sig.header.constness, id, &itctx, |this| {
|
||||||
this.lower_fn_decl(&sig.decl, id, sig.span, kind, is_async)
|
this.lower_fn_decl(&sig.decl, id, sig.span, kind, transform_return_type)
|
||||||
});
|
});
|
||||||
(generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
|
(generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
|
||||||
}
|
}
|
||||||
|
|
|
@ -493,6 +493,21 @@ enum ParenthesizedGenericArgs {
|
||||||
Err,
|
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> {
|
impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
fn create_def(
|
fn create_def(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -1778,13 +1793,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lowers a function declaration.
|
/// Lowers a function declaration.
|
||||||
//
|
///
|
||||||
// `decl`: the unlowered (AST) function declaration.
|
/// `decl`: the unlowered (AST) function declaration.
|
||||||
// `fn_node_id`: `impl Trait` arguments are lowered into generic parameters on the given `NodeId`.
|
///
|
||||||
// `make_ret_async`: if `Some`, converts `-> T` into `-> impl Future<Output = T>` in the
|
/// `fn_node_id`: `impl Trait` arguments are lowered into generic parameters on the given
|
||||||
// return type. This is used for `async fn` declarations. The `NodeId` is the ID of the
|
/// `NodeId`.
|
||||||
// return type `impl Trait` item, and the `Span` points to the `async` keyword.
|
///
|
||||||
|
/// `transform_return_type`: if `Some`, applies some conversion to the return type, such as is
|
||||||
|
/// needed for `async fn` and `gen fn`. See [`FnReturnTransformation`] for more details.
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
fn lower_fn_decl(
|
fn lower_fn_decl(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -1792,7 +1809,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
fn_node_id: NodeId,
|
fn_node_id: NodeId,
|
||||||
fn_span: Span,
|
fn_span: Span,
|
||||||
kind: FnDeclKind,
|
kind: FnDeclKind,
|
||||||
make_ret_async: Option<(NodeId, Span)>,
|
transform_return_type: Option<FnReturnTransformation>,
|
||||||
) -> &'hir hir::FnDecl<'hir> {
|
) -> &'hir hir::FnDecl<'hir> {
|
||||||
let c_variadic = decl.c_variadic();
|
let c_variadic = decl.c_variadic();
|
||||||
|
|
||||||
|
@ -1821,11 +1838,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
self.lower_ty_direct(¶m.ty, &itctx)
|
self.lower_ty_direct(¶m.ty, &itctx)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let output = if let Some((ret_id, _span)) = make_ret_async {
|
let output = match transform_return_type {
|
||||||
|
Some(transform) => {
|
||||||
let fn_def_id = self.local_def_id(fn_node_id);
|
let fn_def_id = self.local_def_id(fn_node_id);
|
||||||
self.lower_async_fn_ret_ty(&decl.output, fn_def_id, ret_id, kind, fn_span)
|
self.lower_coroutine_fn_ret_ty(&decl.output, fn_def_id, transform, kind, fn_span)
|
||||||
} else {
|
}
|
||||||
match &decl.output {
|
None => match &decl.output {
|
||||||
FnRetTy::Ty(ty) => {
|
FnRetTy::Ty(ty) => {
|
||||||
let context = if kind.return_impl_trait_allowed() {
|
let context = if kind.return_impl_trait_allowed() {
|
||||||
let fn_def_id = self.local_def_id(fn_node_id);
|
let fn_def_id = self.local_def_id(fn_node_id);
|
||||||
|
@ -1849,7 +1867,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
hir::FnRetTy::Return(self.lower_ty(ty, &context))
|
hir::FnRetTy::Return(self.lower_ty(ty, &context))
|
||||||
}
|
}
|
||||||
FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(*span)),
|
FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(*span)),
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
self.arena.alloc(hir::FnDecl {
|
self.arena.alloc(hir::FnDecl {
|
||||||
|
@ -1888,17 +1906,22 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
// `fn_node_id`: `NodeId` of the parent function (used to create child impl trait definition)
|
// `fn_node_id`: `NodeId` of the parent function (used to create child impl trait definition)
|
||||||
// `opaque_ty_node_id`: `NodeId` of the opaque `impl Trait` type that should be created
|
// `opaque_ty_node_id`: `NodeId` of the opaque `impl Trait` type that should be created
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
fn lower_async_fn_ret_ty(
|
fn lower_coroutine_fn_ret_ty(
|
||||||
&mut self,
|
&mut self,
|
||||||
output: &FnRetTy,
|
output: &FnRetTy,
|
||||||
fn_def_id: LocalDefId,
|
fn_def_id: LocalDefId,
|
||||||
opaque_ty_node_id: NodeId,
|
transform: FnReturnTransformation,
|
||||||
fn_kind: FnDeclKind,
|
fn_kind: FnDeclKind,
|
||||||
fn_span: Span,
|
fn_span: Span,
|
||||||
) -> hir::FnRetTy<'hir> {
|
) -> hir::FnRetTy<'hir> {
|
||||||
let span = self.lower_span(fn_span);
|
let span = self.lower_span(fn_span);
|
||||||
let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::Async, span, None);
|
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 captured_lifetimes: Vec<_> = self
|
let captured_lifetimes: Vec<_> = self
|
||||||
.resolver
|
.resolver
|
||||||
.take_extra_lifetime_params(opaque_ty_node_id)
|
.take_extra_lifetime_params(opaque_ty_node_id)
|
||||||
|
@ -1914,8 +1937,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
span,
|
span,
|
||||||
opaque_ty_span,
|
opaque_ty_span,
|
||||||
|this| {
|
|this| {
|
||||||
let future_bound = this.lower_async_fn_output_type_to_future_bound(
|
let future_bound = this.lower_coroutine_fn_output_type_to_future_bound(
|
||||||
output,
|
output,
|
||||||
|
transform,
|
||||||
span,
|
span,
|
||||||
ImplTraitContext::ReturnPositionOpaqueTy {
|
ImplTraitContext::ReturnPositionOpaqueTy {
|
||||||
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
|
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
|
||||||
|
@ -1931,9 +1955,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transforms `-> T` into `Future<Output = T>`.
|
/// Transforms `-> T` into `Future<Output = T>`.
|
||||||
fn lower_async_fn_output_type_to_future_bound(
|
fn lower_coroutine_fn_output_type_to_future_bound(
|
||||||
&mut self,
|
&mut self,
|
||||||
output: &FnRetTy,
|
output: &FnRetTy,
|
||||||
|
transform: FnReturnTransformation,
|
||||||
span: Span,
|
span: Span,
|
||||||
nested_impl_trait_context: ImplTraitContext,
|
nested_impl_trait_context: ImplTraitContext,
|
||||||
) -> hir::GenericBound<'hir> {
|
) -> hir::GenericBound<'hir> {
|
||||||
|
@ -1948,17 +1973,23 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
FnRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])),
|
FnRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])),
|
||||||
};
|
};
|
||||||
|
|
||||||
// "<Output = T>"
|
// "<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 future_args = self.arena.alloc(hir::GenericArgs {
|
let future_args = self.arena.alloc(hir::GenericArgs {
|
||||||
args: &[],
|
args: &[],
|
||||||
bindings: arena_vec![self; self.output_ty_binding(span, output_ty)],
|
bindings: arena_vec![self; self.assoc_ty_binding(symbol, span, output_ty)],
|
||||||
parenthesized: hir::GenericArgsParentheses::No,
|
parenthesized: hir::GenericArgsParentheses::No,
|
||||||
span_ext: DUMMY_SP,
|
span_ext: DUMMY_SP,
|
||||||
});
|
});
|
||||||
|
|
||||||
hir::GenericBound::LangItemTrait(
|
hir::GenericBound::LangItemTrait(
|
||||||
// ::std::future::Future<future_params>
|
lang_item,
|
||||||
hir::LangItem::Future,
|
|
||||||
self.lower_span(span),
|
self.lower_span(span),
|
||||||
self.next_id(),
|
self.next_id(),
|
||||||
future_args,
|
future_args,
|
||||||
|
|
|
@ -389,7 +389,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
FnRetTy::Default(_) => self.arena.alloc(self.ty_tup(*span, &[])),
|
FnRetTy::Default(_) => self.arena.alloc(self.ty_tup(*span, &[])),
|
||||||
};
|
};
|
||||||
let args = smallvec![GenericArg::Type(self.arena.alloc(self.ty_tup(*inputs_span, inputs)))];
|
let args = smallvec![GenericArg::Type(self.arena.alloc(self.ty_tup(*inputs_span, inputs)))];
|
||||||
let binding = self.output_ty_binding(output_ty.span, output_ty);
|
let binding = self.assoc_ty_binding(hir::FN_OUTPUT_NAME, output_ty.span, output_ty);
|
||||||
(
|
(
|
||||||
GenericArgsCtor {
|
GenericArgsCtor {
|
||||||
args,
|
args,
|
||||||
|
@ -401,13 +401,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An associated type binding `Output = $ty`.
|
/// An associated type binding `$symbol = $ty`.
|
||||||
pub(crate) fn output_ty_binding(
|
pub(crate) fn assoc_ty_binding(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
symbol: rustc_span::Symbol,
|
||||||
span: Span,
|
span: Span,
|
||||||
ty: &'hir hir::Ty<'hir>,
|
ty: &'hir hir::Ty<'hir>,
|
||||||
) -> hir::TypeBinding<'hir> {
|
) -> hir::TypeBinding<'hir> {
|
||||||
let ident = Ident::with_dummy_span(hir::FN_OUTPUT_NAME);
|
let ident = Ident::with_dummy_span(symbol);
|
||||||
let kind = hir::TypeBindingKind::Equality { term: ty.into() };
|
let kind = hir::TypeBindingKind::Equality { term: ty.into() };
|
||||||
let args = arena_vec![self;];
|
let args = arena_vec![self;];
|
||||||
let bindings = arena_vec![self;];
|
let bindings = arena_vec![self;];
|
||||||
|
|
|
@ -2255,6 +2255,8 @@ pub enum ImplItemKind<'hir> {
|
||||||
|
|
||||||
/// The name of the associated type for `Fn` return types.
|
/// The name of the associated type for `Fn` return types.
|
||||||
pub const FN_OUTPUT_NAME: Symbol = sym::Output;
|
pub const FN_OUTPUT_NAME: Symbol = sym::Output;
|
||||||
|
/// The name of the associated type for `Iterator` item types.
|
||||||
|
pub const ITERATOR_ITEM_NAME: Symbol = sym::Item;
|
||||||
|
|
||||||
/// Bind a type to an associated type (i.e., `A = Foo`).
|
/// Bind a type to an associated type (i.e., `A = Foo`).
|
||||||
///
|
///
|
||||||
|
|
|
@ -651,9 +651,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Some(hir::CoroutineKind::Gen(hir::CoroutineSource::Fn)) => {
|
// For a `gen {}` block created as a `gen fn` body, we need the return type to be
|
||||||
todo!("gen closures do not exist yet")
|
// ().
|
||||||
}
|
Some(hir::CoroutineKind::Gen(hir::CoroutineSource::Fn)) => self.tcx.types.unit,
|
||||||
|
|
||||||
_ => astconv.ty_infer(None, decl.output.span()),
|
_ => astconv.ty_infer(None, decl.output.span()),
|
||||||
},
|
},
|
||||||
|
|
|
@ -2410,10 +2410,6 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Gen::Yes { span, .. } = genness {
|
|
||||||
self.sess.emit_err(errors::GenFn { span });
|
|
||||||
}
|
|
||||||
|
|
||||||
if !self.eat_keyword_case(kw::Fn, case) {
|
if !self.eat_keyword_case(kw::Fn, case) {
|
||||||
// It is possible for `expect_one_of` to recover given the contents of
|
// It is possible for `expect_one_of` to recover given the contents of
|
||||||
// `self.expected_tokens`, therefore, do not use `self.unexpected()` which doesn't
|
// `self.expected_tokens`, therefore, do not use `self.unexpected()` which doesn't
|
||||||
|
|
|
@ -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) {
|
fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
|
||||||
if let FnKind::Fn(_, _, sig, _, generics, body) = fn_kind {
|
if let FnKind::Fn(_, _, sig, _, generics, body) = fn_kind {
|
||||||
if let Async::Yes { closure_id, .. } = sig.header.asyncness {
|
// FIXME(eholk): handle `async gen fn`
|
||||||
|
if let (Async::Yes { closure_id, .. }, _) | (_, Gen::Yes { closure_id, .. }) =
|
||||||
|
(sig.header.asyncness, sig.header.genness)
|
||||||
|
{
|
||||||
self.visit_generics(generics);
|
self.visit_generics(generics);
|
||||||
|
|
||||||
// For async functions, we need to create their inner defs inside of a
|
// For async functions, we need to create their inner defs inside of a
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue