Skip to content

Commit 5be30f9

Browse files
Make async fn in traits work
1 parent ed2a32f commit 5be30f9

File tree

10 files changed

+46
-41
lines changed

10 files changed

+46
-41
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2367,9 +2367,9 @@ impl Async {
23672367
}
23682368

23692369
/// In this case this is an `async` return, the `NodeId` for the generated `impl Trait` item.
2370-
pub fn opt_return_id(self) -> Option<NodeId> {
2370+
pub fn opt_return_id(self) -> Option<(NodeId, Span)> {
23712371
match self {
2372-
Async::Yes { return_impl_trait_id, .. } => Some(return_impl_trait_id),
2372+
Async::Yes { return_impl_trait_id, span, .. } => Some((return_impl_trait_id, span)),
23732373
Async::No => None,
23742374
}
23752375
}

compiler/rustc_ast_lowering/src/errors.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,3 +334,14 @@ pub struct InclusiveRangeWithNoEnd {
334334
#[primary_span]
335335
pub span: Span,
336336
}
337+
338+
#[derive(SessionDiagnostic, Clone, Copy)]
339+
#[diag(ast_lowering::trait_fn_async, code = "E0706")]
340+
#[note]
341+
#[note(ast_lowering::note2)]
342+
pub struct TraitFnAsync {
343+
#[primary_span]
344+
pub fn_span: Span,
345+
#[label]
346+
pub span: Span,
347+
}

compiler/rustc_ast_lowering/src/expr.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -851,7 +851,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
851851

852852
self.lower_lifetime_binder(closure_id, generic_params, |lctx, bound_generic_params| {
853853
// Lower outside new scope to preserve `is_in_loop_condition`.
854-
let fn_decl = lctx.lower_fn_decl(decl, None, FnDeclKind::Closure, None);
854+
let fn_decl = lctx.lower_fn_decl(decl, None, fn_decl_span, FnDeclKind::Closure, None);
855855

856856
let c = lctx.arena.alloc(hir::Closure {
857857
binder: binder_clause,
@@ -955,7 +955,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
955955
// We need to lower the declaration outside the new scope, because we
956956
// have to conserve the state of being inside a loop condition for the
957957
// closure argument types.
958-
let fn_decl = lctx.lower_fn_decl(&outer_decl, None, FnDeclKind::Closure, None);
958+
let fn_decl =
959+
lctx.lower_fn_decl(&outer_decl, None, fn_decl_span, FnDeclKind::Closure, None);
959960

960961
let c = lctx.arena.alloc(hir::Closure {
961962
binder: binder_clause,

compiler/rustc_ast_lowering/src/item.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
269269
let mut itctx = ImplTraitContext::Universal;
270270
let (generics, decl) = this.lower_generics(generics, id, &mut itctx, |this| {
271271
let ret_id = asyncness.opt_return_id();
272-
this.lower_fn_decl(&decl, Some(id), FnDeclKind::Fn, ret_id)
272+
this.lower_fn_decl(&decl, Some(id), fn_sig_span, FnDeclKind::Fn, ret_id)
273273
});
274274
let sig = hir::FnSig {
275275
decl,
@@ -661,7 +661,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
661661
self.lower_generics(generics, i.id, &mut itctx, |this| {
662662
(
663663
// Disallow `impl Trait` in foreign items.
664-
this.lower_fn_decl(fdec, None, FnDeclKind::ExternFn, None),
664+
this.lower_fn_decl(
665+
fdec,
666+
None,
667+
sig.span,
668+
FnDeclKind::ExternFn,
669+
None,
670+
),
665671
this.lower_fn_params_to_names(fdec),
666672
)
667673
});
@@ -1240,12 +1246,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
12401246
sig: &FnSig,
12411247
id: NodeId,
12421248
kind: FnDeclKind,
1243-
is_async: Option<NodeId>,
1249+
is_async: Option<(NodeId, Span)>,
12441250
) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) {
12451251
let header = self.lower_fn_header(sig.header);
12461252
let mut itctx = ImplTraitContext::Universal;
12471253
let (generics, decl) = self.lower_generics(generics, id, &mut itctx, |this| {
1248-
this.lower_fn_decl(&sig.decl, Some(id), kind, is_async)
1254+
this.lower_fn_decl(&sig.decl, Some(id), sig.span, kind, is_async)
12491255
});
12501256
(generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
12511257
}

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
#[macro_use]
4343
extern crate tracing;
4444

45-
use crate::errors::{AssocTyParentheses, AssocTyParenthesesSub, MisplacedImplTrait};
45+
use crate::errors::{AssocTyParentheses, AssocTyParenthesesSub, MisplacedImplTrait, TraitFnAsync};
4646

4747
use rustc_arena::declare_arena;
4848
use rustc_ast::ptr::P;
@@ -1274,7 +1274,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
12741274
generic_params,
12751275
unsafety: lctx.lower_unsafety(f.unsafety),
12761276
abi: lctx.lower_extern(f.ext),
1277-
decl: lctx.lower_fn_decl(&f.decl, None, FnDeclKind::Pointer, None),
1277+
decl: lctx.lower_fn_decl(&f.decl, None, t.span, FnDeclKind::Pointer, None),
12781278
param_names: lctx.lower_fn_params_to_names(&f.decl),
12791279
}))
12801280
})
@@ -1677,19 +1677,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
16771677
// `fn_def_id`: if `Some`, impl Trait arguments are lowered into generic parameters on the
16781678
// given DefId, otherwise impl Trait is disallowed. Must be `Some` if
16791679
// `make_ret_async` is also `Some`.
1680-
// `impl_trait_return_allow`: determines whether `impl Trait` can be used in return position.
1681-
// This guards against trait declarations and implementations where `impl Trait` is
1682-
// disallowed.
16831680
// `make_ret_async`: if `Some`, converts `-> T` into `-> impl Future<Output = T>` in the
16841681
// return type. This is used for `async fn` declarations. The `NodeId` is the ID of the
1685-
// return type `impl Trait` item.
1682+
// return type `impl Trait` item, and the `Span` points to the `async` keyword.
16861683
#[instrument(level = "debug", skip(self))]
16871684
fn lower_fn_decl(
16881685
&mut self,
16891686
decl: &FnDecl,
16901687
fn_node_id: Option<NodeId>,
1688+
fn_span: Span,
16911689
kind: FnDeclKind,
1692-
make_ret_async: Option<NodeId>,
1690+
make_ret_async: Option<(NodeId, Span)>,
16931691
) -> &'hir hir::FnDecl<'hir> {
16941692
let c_variadic = decl.c_variadic();
16951693

@@ -1720,7 +1718,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
17201718
}
17211719
}));
17221720

1723-
let output = if let Some(ret_id) = make_ret_async {
1721+
let output = if let Some((ret_id, span)) = make_ret_async {
1722+
if !self.tcx.features().return_position_impl_trait_in_trait {
1723+
self.tcx.sess.emit_feature_err(
1724+
TraitFnAsync { fn_span, span },
1725+
sym::return_position_impl_trait_in_trait,
1726+
);
1727+
}
1728+
17241729
self.lower_async_fn_ret_ty(
17251730
&decl.output,
17261731
fn_node_id.expect("`make_ret_async` but no `fn_def_id`"),

compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -290,12 +290,6 @@ impl<'a> AstValidator<'a> {
290290
}
291291
}
292292

293-
fn check_trait_fn_not_async(&self, fn_span: Span, asyncness: Async) {
294-
if let Async::Yes { span, .. } = asyncness {
295-
self.session.emit_err(TraitFnAsync { fn_span, span });
296-
}
297-
}
298-
299293
fn check_trait_fn_not_const(&self, constness: Const) {
300294
if let Const::Yes(span) = constness {
301295
self.session.emit_err(TraitFnConst { span });
@@ -1596,7 +1590,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
15961590
self.invalid_visibility(&item.vis, None);
15971591
if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind {
15981592
self.check_trait_fn_not_const(sig.header.constness);
1599-
self.check_trait_fn_not_async(item.span, sig.header.asyncness);
16001593
}
16011594
}
16021595

compiler/rustc_ast_passes/src/errors.rs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -79,17 +79,6 @@ pub enum InvalidVisibilityNote {
7979
IndividualForeignItems,
8080
}
8181

82-
#[derive(SessionDiagnostic)]
83-
#[diag(ast_passes::trait_fn_async, code = "E0706")]
84-
#[note]
85-
#[note(ast_passes::note2)]
86-
pub struct TraitFnAsync {
87-
#[primary_span]
88-
pub fn_span: Span,
89-
#[label]
90-
pub span: Span,
91-
}
92-
9382
#[derive(SessionDiagnostic)]
9483
#[diag(ast_passes::trait_fn_const, code = "E0379")]
9584
pub struct TraitFnConst {

compiler/rustc_error_messages/locales/en-US/ast_lowering.ftl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,9 @@ ast_lowering_arbitrary_expression_in_pattern =
131131
arbitrary expressions aren't allowed in patterns
132132
133133
ast_lowering_inclusive_range_with_no_end = inclusive range with no end
134+
135+
ast_lowering_trait_fn_async =
136+
functions in traits cannot be declared `async`
137+
.label = `async` because of this
138+
.note = `async` trait functions are not currently supported
139+
.note2 = consider using the `async-trait` crate: https://crates.io/crates/async-trait

compiler/rustc_error_messages/locales/en-US/ast_passes.ftl

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,6 @@ ast_passes_invalid_visibility =
2626
.individual_impl_items = place qualifiers on individual impl items instead
2727
.individual_foreign_items = place qualifiers on individual foreign items instead
2828
29-
ast_passes_trait_fn_async =
30-
functions in traits cannot be declared `async`
31-
.label = `async` because of this
32-
.note = `async` trait functions are not currently supported
33-
.note2 = consider using the `async-trait` crate: https://crates.io/crates/async-trait
34-
3529
ast_passes_trait_fn_const =
3630
functions in traits cannot be declared const
3731
.label = functions in traits cannot be const

compiler/rustc_resolve/src/late.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -851,7 +851,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
851851
// We include all lifetime parameters, either named or "Fresh".
852852
// The order of those parameters does not matter, as long as it is
853853
// deterministic.
854-
if let Some(async_node_id) = async_node_id {
854+
if let Some((async_node_id, _)) = async_node_id {
855855
let mut extra_lifetime_params = this
856856
.r
857857
.extra_lifetime_params_map

0 commit comments

Comments
 (0)