1
Fork 0

Make async fn in traits work

This commit is contained in:
Michael Goulet 2022-09-02 15:57:31 +00:00
parent ed2a32f22c
commit 5be30f9d79
10 changed files with 46 additions and 41 deletions

View file

@ -334,3 +334,14 @@ pub struct InclusiveRangeWithNoEnd {
#[primary_span]
pub span: Span,
}
#[derive(SessionDiagnostic, Clone, Copy)]
#[diag(ast_lowering::trait_fn_async, code = "E0706")]
#[note]
#[note(ast_lowering::note2)]
pub struct TraitFnAsync {
#[primary_span]
pub fn_span: Span,
#[label]
pub span: Span,
}

View file

@ -851,7 +851,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.lower_lifetime_binder(closure_id, generic_params, |lctx, bound_generic_params| {
// Lower outside new scope to preserve `is_in_loop_condition`.
let fn_decl = lctx.lower_fn_decl(decl, None, FnDeclKind::Closure, None);
let fn_decl = lctx.lower_fn_decl(decl, None, fn_decl_span, FnDeclKind::Closure, None);
let c = lctx.arena.alloc(hir::Closure {
binder: binder_clause,
@ -955,7 +955,8 @@ 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 = lctx.lower_fn_decl(&outer_decl, None, FnDeclKind::Closure, None);
let fn_decl =
lctx.lower_fn_decl(&outer_decl, None, fn_decl_span, FnDeclKind::Closure, None);
let c = lctx.arena.alloc(hir::Closure {
binder: binder_clause,

View file

@ -269,7 +269,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let mut itctx = ImplTraitContext::Universal;
let (generics, decl) = this.lower_generics(generics, id, &mut itctx, |this| {
let ret_id = asyncness.opt_return_id();
this.lower_fn_decl(&decl, Some(id), FnDeclKind::Fn, ret_id)
this.lower_fn_decl(&decl, Some(id), fn_sig_span, FnDeclKind::Fn, ret_id)
});
let sig = hir::FnSig {
decl,
@ -661,7 +661,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.lower_generics(generics, i.id, &mut itctx, |this| {
(
// Disallow `impl Trait` in foreign items.
this.lower_fn_decl(fdec, None, FnDeclKind::ExternFn, None),
this.lower_fn_decl(
fdec,
None,
sig.span,
FnDeclKind::ExternFn,
None,
),
this.lower_fn_params_to_names(fdec),
)
});
@ -1240,12 +1246,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
sig: &FnSig,
id: NodeId,
kind: FnDeclKind,
is_async: Option<NodeId>,
is_async: Option<(NodeId, Span)>,
) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) {
let header = self.lower_fn_header(sig.header);
let mut itctx = ImplTraitContext::Universal;
let (generics, decl) = self.lower_generics(generics, id, &mut itctx, |this| {
this.lower_fn_decl(&sig.decl, Some(id), kind, is_async)
this.lower_fn_decl(&sig.decl, Some(id), sig.span, kind, is_async)
});
(generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
}

View file

@ -42,7 +42,7 @@
#[macro_use]
extern crate tracing;
use crate::errors::{AssocTyParentheses, AssocTyParenthesesSub, MisplacedImplTrait};
use crate::errors::{AssocTyParentheses, AssocTyParenthesesSub, MisplacedImplTrait, TraitFnAsync};
use rustc_arena::declare_arena;
use rustc_ast::ptr::P;
@ -1274,7 +1274,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
generic_params,
unsafety: lctx.lower_unsafety(f.unsafety),
abi: lctx.lower_extern(f.ext),
decl: lctx.lower_fn_decl(&f.decl, None, FnDeclKind::Pointer, None),
decl: lctx.lower_fn_decl(&f.decl, None, t.span, FnDeclKind::Pointer, None),
param_names: lctx.lower_fn_params_to_names(&f.decl),
}))
})
@ -1677,19 +1677,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// `fn_def_id`: if `Some`, impl Trait arguments are lowered into generic parameters on the
// given DefId, otherwise impl Trait is disallowed. Must be `Some` if
// `make_ret_async` is also `Some`.
// `impl_trait_return_allow`: determines whether `impl Trait` can be used in return position.
// This guards against trait declarations and implementations where `impl Trait` is
// disallowed.
// `make_ret_async`: if `Some`, converts `-> T` into `-> impl Future<Output = T>` in the
// return type. This is used for `async fn` declarations. The `NodeId` is the ID of the
// return type `impl Trait` item.
// return type `impl Trait` item, and the `Span` points to the `async` keyword.
#[instrument(level = "debug", skip(self))]
fn lower_fn_decl(
&mut self,
decl: &FnDecl,
fn_node_id: Option<NodeId>,
fn_span: Span,
kind: FnDeclKind,
make_ret_async: Option<NodeId>,
make_ret_async: Option<(NodeId, Span)>,
) -> &'hir hir::FnDecl<'hir> {
let c_variadic = decl.c_variadic();
@ -1720,7 +1718,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
}));
let output = if let Some(ret_id) = make_ret_async {
let output = if let Some((ret_id, span)) = make_ret_async {
if !self.tcx.features().return_position_impl_trait_in_trait {
self.tcx.sess.emit_feature_err(
TraitFnAsync { fn_span, span },
sym::return_position_impl_trait_in_trait,
);
}
self.lower_async_fn_ret_ty(
&decl.output,
fn_node_id.expect("`make_ret_async` but no `fn_def_id`"),