Skip to content

Commit 082b97a

Browse files
authored
Rollup merge of #121044 - compiler-errors:mbe-async-trait-bounds, r=fmease
Support async trait bounds in macros r? fmease This is similar to your work on const trait bounds. This theoretically regresses `impl async $ident:ident` in macros, but I doubt this is occurring in practice.
2 parents 1d447a9 + 9c8b107 commit 082b97a

16 files changed

+228
-30
lines changed

compiler/rustc_parse/messages.ftl

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ parse_async_bound_modifier_in_2015 = `async` trait bounds are only allowed in Ru
2727
parse_async_fn_in_2015 = `async fn` is not permitted in Rust 2015
2828
.label = to use `async fn`, switch to Rust 2018 or later
2929
30+
parse_async_impl = `async` trait implementations are unsupported
31+
3032
parse_async_move_block_in_2015 = `async move` blocks are only allowed in Rust 2018 or later
3133
3234
parse_async_move_order_incorrect = the order of `move` and `async` is incorrect

compiler/rustc_parse/src/errors.rs

+7
Original file line numberDiff line numberDiff line change
@@ -2975,3 +2975,10 @@ pub(crate) struct ArrayIndexInOffsetOf(#[primary_span] pub Span);
29752975
#[derive(Diagnostic)]
29762976
#[diag(parse_invalid_offset_of)]
29772977
pub(crate) struct InvalidOffsetOf(#[primary_span] pub Span);
2978+
2979+
#[derive(Diagnostic)]
2980+
#[diag(parse_async_impl)]
2981+
pub(crate) struct AsyncImpl {
2982+
#[primary_span]
2983+
pub span: Span,
2984+
}

compiler/rustc_parse/src/parser/item.rs

+9
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,15 @@ impl<'a> Parser<'a> {
562562
self.sess.gated_spans.gate(sym::const_trait_impl, span);
563563
}
564564

565+
// Parse stray `impl async Trait`
566+
if (self.token.uninterpolated_span().at_least_rust_2018()
567+
&& self.token.is_keyword(kw::Async))
568+
|| self.is_kw_followed_by_ident(kw::Async)
569+
{
570+
self.bump();
571+
self.dcx().emit_err(errors::AsyncImpl { span: self.prev_token.span });
572+
}
573+
565574
let polarity = self.parse_polarity();
566575

567576
// Parse both types and traits as a type, then reinterpret if necessary.

compiler/rustc_parse/src/parser/ty.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -778,9 +778,10 @@ impl<'a> Parser<'a> {
778778
|| self.check(&token::Not)
779779
|| self.check(&token::Question)
780780
|| self.check(&token::Tilde)
781-
|| self.check_keyword(kw::Const)
782781
|| self.check_keyword(kw::For)
783782
|| self.check(&token::OpenDelim(Delimiter::Parenthesis))
783+
|| self.check_keyword(kw::Const)
784+
|| self.check_keyword(kw::Async)
784785
}
785786

786787
/// Parses a bound according to the grammar:
@@ -882,11 +883,13 @@ impl<'a> Parser<'a> {
882883
BoundConstness::Never
883884
};
884885

885-
let asyncness = if self.token.span.at_least_rust_2018() && self.eat_keyword(kw::Async) {
886+
let asyncness = if self.token.uninterpolated_span().at_least_rust_2018()
887+
&& self.eat_keyword(kw::Async)
888+
{
886889
self.sess.gated_spans.gate(sym::async_closure, self.prev_token.span);
887890
BoundAsyncness::Async(self.prev_token.span)
888891
} else if self.may_recover()
889-
&& self.token.span.is_rust_2015()
892+
&& self.token.uninterpolated_span().is_rust_2015()
890893
&& self.is_kw_followed_by_ident(kw::Async)
891894
{
892895
self.bump(); // eat `async`

tests/ui/async-await/async-fn/impl-header.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
struct F;
44

55
impl async Fn<()> for F {}
6-
//~^ ERROR expected type, found keyword `async`
6+
//~^ ERROR `async` trait implementations are unsupported
7+
//~| ERROR the precise format of `Fn`-family traits' type parameters is subject to change
8+
//~| ERROR manual implementations of `Fn` are experimental
9+
//~| ERROR expected a `FnMut()` closure, found `F`
10+
//~| ERROR not all trait items implemented, missing: `call`
711

812
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,47 @@
1-
error: expected type, found keyword `async`
1+
error: `async` trait implementations are unsupported
22
--> $DIR/impl-header.rs:5:6
33
|
44
LL | impl async Fn<()> for F {}
5-
| ^^^^^ expected type
5+
| ^^^^^
66

7-
error: aborting due to 1 previous error
7+
error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change
8+
--> $DIR/impl-header.rs:5:12
9+
|
10+
LL | impl async Fn<()> for F {}
11+
| ^^^^^^
12+
|
13+
= note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
14+
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
15+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
16+
17+
error[E0183]: manual implementations of `Fn` are experimental
18+
--> $DIR/impl-header.rs:5:12
19+
|
20+
LL | impl async Fn<()> for F {}
21+
| ^^^^^^ manual implementations of `Fn` are experimental
22+
|
23+
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
24+
25+
error[E0277]: expected a `FnMut()` closure, found `F`
26+
--> $DIR/impl-header.rs:5:23
27+
|
28+
LL | impl async Fn<()> for F {}
29+
| ^ expected an `FnMut()` closure, found `F`
30+
|
31+
= help: the trait `FnMut<()>` is not implemented for `F`
32+
= note: wrap the `F` in a closure with no arguments: `|| { /* code */ }`
33+
note: required by a bound in `Fn`
34+
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
35+
36+
error[E0046]: not all trait items implemented, missing: `call`
37+
--> $DIR/impl-header.rs:5:1
38+
|
39+
LL | impl async Fn<()> for F {}
40+
| ^^^^^^^^^^^^^^^^^^^^^^^ missing `call` in implementation
41+
|
42+
= help: implement the missing item: `fn call(&self, _: ()) -> <Self as FnOnce<()>>::Output { todo!() }`
43+
44+
error: aborting due to 5 previous errors
845

46+
Some errors have detailed explanations: E0046, E0183, E0277, E0658.
47+
For more information about an error, try `rustc --explain E0046`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Demonstrates and records a theoretical regressions / breaking changes caused by the
2+
// introduction of async trait bounds.
3+
4+
// Setting the edition to 2018 since we don't regress `demo! { dyn async }` in Rust <2018.
5+
//@ edition:2018
6+
7+
macro_rules! demo {
8+
($ty:ty) => { compile_error!("ty"); };
9+
//~^ ERROR ty
10+
//~| ERROR ty
11+
(impl $c:ident Trait) => {};
12+
(dyn $c:ident Trait) => {};
13+
}
14+
15+
demo! { impl async Trait }
16+
//~^ ERROR async closures are unstable
17+
18+
demo! { dyn async Trait }
19+
//~^ ERROR async closures are unstable
20+
21+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
error: ty
2+
--> $DIR/mbe-async-trait-bound-theoretical-regression.rs:8:19
3+
|
4+
LL | ($ty:ty) => { compile_error!("ty"); };
5+
| ^^^^^^^^^^^^^^^^^^^^
6+
...
7+
LL | demo! { impl async Trait }
8+
| -------------------------- in this macro invocation
9+
|
10+
= note: this error originates in the macro `demo` (in Nightly builds, run with -Z macro-backtrace for more info)
11+
12+
error: ty
13+
--> $DIR/mbe-async-trait-bound-theoretical-regression.rs:8:19
14+
|
15+
LL | ($ty:ty) => { compile_error!("ty"); };
16+
| ^^^^^^^^^^^^^^^^^^^^
17+
...
18+
LL | demo! { dyn async Trait }
19+
| ------------------------- in this macro invocation
20+
|
21+
= note: this error originates in the macro `demo` (in Nightly builds, run with -Z macro-backtrace for more info)
22+
23+
error[E0658]: async closures are unstable
24+
--> $DIR/mbe-async-trait-bound-theoretical-regression.rs:15:14
25+
|
26+
LL | demo! { impl async Trait }
27+
| ^^^^^
28+
|
29+
= note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
30+
= help: add `#![feature(async_closure)]` to the crate attributes to enable
31+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
32+
= help: to use an async block, remove the `||`: `async {`
33+
34+
error[E0658]: async closures are unstable
35+
--> $DIR/mbe-async-trait-bound-theoretical-regression.rs:18:13
36+
|
37+
LL | demo! { dyn async Trait }
38+
| ^^^^^
39+
|
40+
= note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
41+
= help: add `#![feature(async_closure)]` to the crate attributes to enable
42+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
43+
= help: to use an async block, remove the `||`: `async {`
44+
45+
error: aborting due to 4 previous errors
46+
47+
For more information about this error, try `rustc --explain E0658`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//@ edition: 2021
2+
3+
macro_rules! x {
4+
($x:item) => {}
5+
}
6+
7+
x! {
8+
async fn foo() -> impl async Fn() { }
9+
//~^ ERROR async closures are unstable
10+
}
11+
12+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0658]: async closures are unstable
2+
--> $DIR/trait-bounds-in-macro.rs:8:28
3+
|
4+
LL | async fn foo() -> impl async Fn() { }
5+
| ^^^^^
6+
|
7+
= note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
8+
= help: add `#![feature(async_closure)]` to the crate attributes to enable
9+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
10+
= help: to use an async block, remove the `||`: `async {`
11+
12+
error: aborting due to 1 previous error
13+
14+
For more information about this error, try `rustc --explain E0658`.

tests/ui/parser/bad-recover-kw-after-impl.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//@ check-pass
1+
// This is just `mbe-async-trait-bound-theoretical-regression.rs` in practice.
22

33
//@ edition:2021
44
// for the `impl` + keyword test
@@ -11,5 +11,7 @@ macro_rules! impl_primitive {
1111
}
1212

1313
impl_primitive!(impl async);
14+
//~^ ERROR expected identifier, found `<eof>`
15+
//~| ERROR async closures are unstable
1416

1517
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
error: expected identifier, found `<eof>`
2+
--> $DIR/bad-recover-kw-after-impl.rs:13:22
3+
|
4+
LL | ($ty:ty) => {
5+
| ------ while parsing argument for this `ty` macro fragment
6+
...
7+
LL | impl_primitive!(impl async);
8+
| ^^^^^ expected identifier
9+
10+
error[E0658]: async closures are unstable
11+
--> $DIR/bad-recover-kw-after-impl.rs:13:22
12+
|
13+
LL | impl_primitive!(impl async);
14+
| ^^^^^
15+
|
16+
= note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
17+
= help: add `#![feature(async_closure)]` to the crate attributes to enable
18+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
19+
= help: to use an async block, remove the `||`: `async {`
20+
21+
error: aborting due to 2 previous errors
22+
23+
For more information about this error, try `rustc --explain E0658`.

tests/ui/parser/trait-object-delimiters.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ fn foo2(_: &dyn (Drop + AsRef<str>)) {} //~ ERROR incorrect parentheses around t
88
fn foo2_no_space(_: &dyn(Drop + AsRef<str>)) {} //~ ERROR incorrect parentheses around trait bounds
99

1010
fn foo3(_: &dyn {Drop + AsRef<str>}) {} //~ ERROR expected parameter name, found `{`
11-
//~^ ERROR expected one of `!`, `(`, `)`, `*`, `,`, `?`, `const`, `for`, `~`, lifetime, or path, found `{`
11+
//~^ ERROR expected one of `!`, `(`, `)`, `*`, `,`, `?`, `async`, `const`, `for`, `~`, lifetime, or path, found `{`
1212
//~| ERROR at least one trait is required for an object type
1313

1414
fn foo4(_: &dyn <Drop + AsRef<str>>) {} //~ ERROR expected identifier, found `<`

tests/ui/parser/trait-object-delimiters.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ error: expected parameter name, found `{`
3434
LL | fn foo3(_: &dyn {Drop + AsRef<str>}) {}
3535
| ^ expected parameter name
3636

37-
error: expected one of `!`, `(`, `)`, `*`, `,`, `?`, `const`, `for`, `~`, lifetime, or path, found `{`
37+
error: expected one of `!`, `(`, `)`, `*`, `,`, `?`, `async`, `const`, `for`, `~`, lifetime, or path, found `{`
3838
--> $DIR/trait-object-delimiters.rs:10:17
3939
|
4040
LL | fn foo3(_: &dyn {Drop + AsRef<str>}) {}
41-
| -^ expected one of 11 possible tokens
41+
| -^ expected one of 12 possible tokens
4242
| |
4343
| help: missing `,`
4444

tests/ui/rfcs/rfc-2632-const-trait-impl/mbe-const-trait-bound-theoretical-regression.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,16 @@
66

77
macro_rules! demo {
88
($ty:ty) => { compile_error!("ty"); };
9-
(impl $c:ident) => {};
10-
(dyn $c:ident) => {};
9+
//~^ ERROR ty
10+
//~| ERROR ty
11+
(impl $c:ident Trait) => {};
12+
(dyn $c:ident Trait) => {};
1113
}
1214

13-
demo! { impl const }
14-
//~^ ERROR expected identifier, found `<eof>`
15+
demo! { impl const Trait }
16+
//~^ ERROR const trait impls are experimental
1517

16-
demo! { dyn const }
18+
demo! { dyn const Trait }
1719
//~^ ERROR const trait impls are experimental
18-
//~| ERROR expected identifier, found `<eof>`
1920

2021
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,45 @@
1-
error: expected identifier, found `<eof>`
2-
--> $DIR/mbe-const-trait-bound-theoretical-regression.rs:13:14
1+
error: ty
2+
--> $DIR/mbe-const-trait-bound-theoretical-regression.rs:8:19
33
|
44
LL | ($ty:ty) => { compile_error!("ty"); };
5-
| ------ while parsing argument for this `ty` macro fragment
5+
| ^^^^^^^^^^^^^^^^^^^^
66
...
7-
LL | demo! { impl const }
8-
| ^^^^^ expected identifier
7+
LL | demo! { impl const Trait }
8+
| -------------------------- in this macro invocation
9+
|
10+
= note: this error originates in the macro `demo` (in Nightly builds, run with -Z macro-backtrace for more info)
911

10-
error: expected identifier, found `<eof>`
11-
--> $DIR/mbe-const-trait-bound-theoretical-regression.rs:16:13
12+
error: ty
13+
--> $DIR/mbe-const-trait-bound-theoretical-regression.rs:8:19
1214
|
1315
LL | ($ty:ty) => { compile_error!("ty"); };
14-
| ------ while parsing argument for this `ty` macro fragment
16+
| ^^^^^^^^^^^^^^^^^^^^
1517
...
16-
LL | demo! { dyn const }
17-
| ^^^^^ expected identifier
18+
LL | demo! { dyn const Trait }
19+
| ------------------------- in this macro invocation
20+
|
21+
= note: this error originates in the macro `demo` (in Nightly builds, run with -Z macro-backtrace for more info)
22+
23+
error[E0658]: const trait impls are experimental
24+
--> $DIR/mbe-const-trait-bound-theoretical-regression.rs:15:14
25+
|
26+
LL | demo! { impl const Trait }
27+
| ^^^^^
28+
|
29+
= note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
30+
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
31+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
1832

1933
error[E0658]: const trait impls are experimental
20-
--> $DIR/mbe-const-trait-bound-theoretical-regression.rs:16:13
34+
--> $DIR/mbe-const-trait-bound-theoretical-regression.rs:18:13
2135
|
22-
LL | demo! { dyn const }
36+
LL | demo! { dyn const Trait }
2337
| ^^^^^
2438
|
2539
= note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
2640
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
2741
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
2842

29-
error: aborting due to 3 previous errors
43+
error: aborting due to 4 previous errors
3044

3145
For more information about this error, try `rustc --explain E0658`.

0 commit comments

Comments
 (0)