about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLeón Orell Valerian Liehr <me@fmease.dev>2024-02-21 16:32:56 +0100
committerGitHub <noreply@github.com>2024-02-21 16:32:56 +0100
commit082b97ad05f759c81b3961dceb9969f16181a593 (patch)
treebcfecfae7b7f978532c9fabe77f547ca6c194fd4
parent1d447a9946effc38c4b964a888ab408a3df3c246 (diff)
parent9c8b107955194b80941ce825646bc2f34edc5dd5 (diff)
downloadrust-082b97ad05f759c81b3961dceb9969f16181a593.tar.gz
rust-082b97ad05f759c81b3961dceb9969f16181a593.zip
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.
-rw-r--r--compiler/rustc_parse/messages.ftl2
-rw-r--r--compiler/rustc_parse/src/errors.rs7
-rw-r--r--compiler/rustc_parse/src/parser/item.rs9
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs9
-rw-r--r--tests/ui/async-await/async-fn/impl-header.rs6
-rw-r--r--tests/ui/async-await/async-fn/impl-header.stderr45
-rw-r--r--tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.rs21
-rw-r--r--tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.stderr47
-rw-r--r--tests/ui/async-await/async-fn/trait-bounds-in-macro.rs12
-rw-r--r--tests/ui/async-await/async-fn/trait-bounds-in-macro.stderr14
-rw-r--r--tests/ui/parser/bad-recover-kw-after-impl.rs4
-rw-r--r--tests/ui/parser/bad-recover-kw-after-impl.stderr23
-rw-r--r--tests/ui/parser/trait-object-delimiters.rs2
-rw-r--r--tests/ui/parser/trait-object-delimiters.stderr4
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/mbe-const-trait-bound-theoretical-regression.rs13
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/mbe-const-trait-bound-theoretical-regression.stderr40
16 files changed, 228 insertions, 30 deletions
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index 7c2ecf34c17..55baf6f9f2e 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -27,6 +27,8 @@ parse_async_bound_modifier_in_2015 = `async` trait bounds are only allowed in Ru
 parse_async_fn_in_2015 = `async fn` is not permitted in Rust 2015
     .label = to use `async fn`, switch to Rust 2018 or later
 
+parse_async_impl = `async` trait implementations are unsupported
+
 parse_async_move_block_in_2015 = `async move` blocks are only allowed in Rust 2018 or later
 
 parse_async_move_order_incorrect = the order of `move` and `async` is incorrect
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index fde67ac089a..2d4447a42c2 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -2975,3 +2975,10 @@ pub(crate) struct ArrayIndexInOffsetOf(#[primary_span] pub Span);
 #[derive(Diagnostic)]
 #[diag(parse_invalid_offset_of)]
 pub(crate) struct InvalidOffsetOf(#[primary_span] pub Span);
+
+#[derive(Diagnostic)]
+#[diag(parse_async_impl)]
+pub(crate) struct AsyncImpl {
+    #[primary_span]
+    pub span: Span,
+}
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index e7b9076bd3c..71453a88e2c 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -562,6 +562,15 @@ impl<'a> Parser<'a> {
             self.sess.gated_spans.gate(sym::const_trait_impl, span);
         }
 
+        // Parse stray `impl async Trait`
+        if (self.token.uninterpolated_span().at_least_rust_2018()
+            && self.token.is_keyword(kw::Async))
+            || self.is_kw_followed_by_ident(kw::Async)
+        {
+            self.bump();
+            self.dcx().emit_err(errors::AsyncImpl { span: self.prev_token.span });
+        }
+
         let polarity = self.parse_polarity();
 
         // Parse both types and traits as a type, then reinterpret if necessary.
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index f79f2a813b2..23a92e6dd3d 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -778,9 +778,10 @@ impl<'a> Parser<'a> {
             || self.check(&token::Not)
             || self.check(&token::Question)
             || self.check(&token::Tilde)
-            || self.check_keyword(kw::Const)
             || self.check_keyword(kw::For)
             || self.check(&token::OpenDelim(Delimiter::Parenthesis))
+            || self.check_keyword(kw::Const)
+            || self.check_keyword(kw::Async)
     }
 
     /// Parses a bound according to the grammar:
@@ -882,11 +883,13 @@ impl<'a> Parser<'a> {
             BoundConstness::Never
         };
 
-        let asyncness = if self.token.span.at_least_rust_2018() && self.eat_keyword(kw::Async) {
+        let asyncness = if self.token.uninterpolated_span().at_least_rust_2018()
+            && self.eat_keyword(kw::Async)
+        {
             self.sess.gated_spans.gate(sym::async_closure, self.prev_token.span);
             BoundAsyncness::Async(self.prev_token.span)
         } else if self.may_recover()
-            && self.token.span.is_rust_2015()
+            && self.token.uninterpolated_span().is_rust_2015()
             && self.is_kw_followed_by_ident(kw::Async)
         {
             self.bump(); // eat `async`
diff --git a/tests/ui/async-await/async-fn/impl-header.rs b/tests/ui/async-await/async-fn/impl-header.rs
index b9ae90292bb..9af5f1f42a9 100644
--- a/tests/ui/async-await/async-fn/impl-header.rs
+++ b/tests/ui/async-await/async-fn/impl-header.rs
@@ -3,6 +3,10 @@
 struct F;
 
 impl async Fn<()> for F {}
-//~^ ERROR expected type, found keyword `async`
+//~^ ERROR `async` trait implementations are unsupported
+//~| ERROR the precise format of `Fn`-family traits' type parameters is subject to change
+//~| ERROR manual implementations of `Fn` are experimental
+//~| ERROR expected a `FnMut()` closure, found `F`
+//~| ERROR not all trait items implemented, missing: `call`
 
 fn main() {}
diff --git a/tests/ui/async-await/async-fn/impl-header.stderr b/tests/ui/async-await/async-fn/impl-header.stderr
index 02cb4326242..2fb862af04e 100644
--- a/tests/ui/async-await/async-fn/impl-header.stderr
+++ b/tests/ui/async-await/async-fn/impl-header.stderr
@@ -1,8 +1,47 @@
-error: expected type, found keyword `async`
+error: `async` trait implementations are unsupported
   --> $DIR/impl-header.rs:5:6
    |
 LL | impl async Fn<()> for F {}
-   |      ^^^^^ expected type
+   |      ^^^^^
 
-error: aborting due to 1 previous error
+error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change
+  --> $DIR/impl-header.rs:5:12
+   |
+LL | impl async Fn<()> for F {}
+   |            ^^^^^^
+   |
+   = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
+   = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0183]: manual implementations of `Fn` are experimental
+  --> $DIR/impl-header.rs:5:12
+   |
+LL | impl async Fn<()> for F {}
+   |            ^^^^^^ manual implementations of `Fn` are experimental
+   |
+   = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
+
+error[E0277]: expected a `FnMut()` closure, found `F`
+  --> $DIR/impl-header.rs:5:23
+   |
+LL | impl async Fn<()> for F {}
+   |                       ^ expected an `FnMut()` closure, found `F`
+   |
+   = help: the trait `FnMut<()>` is not implemented for `F`
+   = note: wrap the `F` in a closure with no arguments: `|| { /* code */ }`
+note: required by a bound in `Fn`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
+
+error[E0046]: not all trait items implemented, missing: `call`
+  --> $DIR/impl-header.rs:5:1
+   |
+LL | impl async Fn<()> for F {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^ missing `call` in implementation
+   |
+   = help: implement the missing item: `fn call(&self, _: ()) -> <Self as FnOnce<()>>::Output { todo!() }`
+
+error: aborting due to 5 previous errors
 
+Some errors have detailed explanations: E0046, E0183, E0277, E0658.
+For more information about an error, try `rustc --explain E0046`.
diff --git a/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.rs b/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.rs
new file mode 100644
index 00000000000..abc429772fd
--- /dev/null
+++ b/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.rs
@@ -0,0 +1,21 @@
+// Demonstrates and records a theoretical regressions / breaking changes caused by the
+// introduction of async trait bounds.
+
+// Setting the edition to 2018 since we don't regress `demo! { dyn async }` in Rust <2018.
+//@ edition:2018
+
+macro_rules! demo {
+    ($ty:ty) => { compile_error!("ty"); };
+    //~^ ERROR ty
+    //~| ERROR ty
+    (impl $c:ident Trait) => {};
+    (dyn $c:ident Trait) => {};
+}
+
+demo! { impl async Trait }
+//~^ ERROR async closures are unstable
+
+demo! { dyn async Trait }
+//~^ ERROR async closures are unstable
+
+fn main() {}
diff --git a/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.stderr b/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.stderr
new file mode 100644
index 00000000000..13b8e72b49d
--- /dev/null
+++ b/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.stderr
@@ -0,0 +1,47 @@
+error: ty
+  --> $DIR/mbe-async-trait-bound-theoretical-regression.rs:8:19
+   |
+LL |     ($ty:ty) => { compile_error!("ty"); };
+   |                   ^^^^^^^^^^^^^^^^^^^^
+...
+LL | demo! { impl async Trait }
+   | -------------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `demo` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: ty
+  --> $DIR/mbe-async-trait-bound-theoretical-regression.rs:8:19
+   |
+LL |     ($ty:ty) => { compile_error!("ty"); };
+   |                   ^^^^^^^^^^^^^^^^^^^^
+...
+LL | demo! { dyn async Trait }
+   | ------------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `demo` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0658]: async closures are unstable
+  --> $DIR/mbe-async-trait-bound-theoretical-regression.rs:15:14
+   |
+LL | demo! { impl async Trait }
+   |              ^^^^^
+   |
+   = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
+   = help: add `#![feature(async_closure)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: to use an async block, remove the `||`: `async {`
+
+error[E0658]: async closures are unstable
+  --> $DIR/mbe-async-trait-bound-theoretical-regression.rs:18:13
+   |
+LL | demo! { dyn async Trait }
+   |             ^^^^^
+   |
+   = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
+   = help: add `#![feature(async_closure)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: to use an async block, remove the `||`: `async {`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/async-await/async-fn/trait-bounds-in-macro.rs b/tests/ui/async-await/async-fn/trait-bounds-in-macro.rs
new file mode 100644
index 00000000000..329a1528e8b
--- /dev/null
+++ b/tests/ui/async-await/async-fn/trait-bounds-in-macro.rs
@@ -0,0 +1,12 @@
+//@ edition: 2021
+
+macro_rules! x {
+    ($x:item) => {}
+}
+
+x! {
+    async fn foo() -> impl async Fn() { }
+    //~^ ERROR async closures are unstable
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/async-fn/trait-bounds-in-macro.stderr b/tests/ui/async-await/async-fn/trait-bounds-in-macro.stderr
new file mode 100644
index 00000000000..f68c09737db
--- /dev/null
+++ b/tests/ui/async-await/async-fn/trait-bounds-in-macro.stderr
@@ -0,0 +1,14 @@
+error[E0658]: async closures are unstable
+  --> $DIR/trait-bounds-in-macro.rs:8:28
+   |
+LL |     async fn foo() -> impl async Fn() { }
+   |                            ^^^^^
+   |
+   = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
+   = help: add `#![feature(async_closure)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: to use an async block, remove the `||`: `async {`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/parser/bad-recover-kw-after-impl.rs b/tests/ui/parser/bad-recover-kw-after-impl.rs
index 23abceaf493..15c0b377c8a 100644
--- a/tests/ui/parser/bad-recover-kw-after-impl.rs
+++ b/tests/ui/parser/bad-recover-kw-after-impl.rs
@@ -1,4 +1,4 @@
-//@ check-pass
+// This is just `mbe-async-trait-bound-theoretical-regression.rs` in practice.
 
 //@ edition:2021
 // for the `impl` + keyword test
@@ -11,5 +11,7 @@ macro_rules! impl_primitive {
 }
 
 impl_primitive!(impl async);
+//~^ ERROR expected identifier, found `<eof>`
+//~| ERROR async closures are unstable
 
 fn main() {}
diff --git a/tests/ui/parser/bad-recover-kw-after-impl.stderr b/tests/ui/parser/bad-recover-kw-after-impl.stderr
new file mode 100644
index 00000000000..f617cf65498
--- /dev/null
+++ b/tests/ui/parser/bad-recover-kw-after-impl.stderr
@@ -0,0 +1,23 @@
+error: expected identifier, found `<eof>`
+  --> $DIR/bad-recover-kw-after-impl.rs:13:22
+   |
+LL |     ($ty:ty) => {
+   |      ------ while parsing argument for this `ty` macro fragment
+...
+LL | impl_primitive!(impl async);
+   |                      ^^^^^ expected identifier
+
+error[E0658]: async closures are unstable
+  --> $DIR/bad-recover-kw-after-impl.rs:13:22
+   |
+LL | impl_primitive!(impl async);
+   |                      ^^^^^
+   |
+   = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
+   = help: add `#![feature(async_closure)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: to use an async block, remove the `||`: `async {`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/parser/trait-object-delimiters.rs b/tests/ui/parser/trait-object-delimiters.rs
index 84cd16c2796..d6bc629aa11 100644
--- a/tests/ui/parser/trait-object-delimiters.rs
+++ b/tests/ui/parser/trait-object-delimiters.rs
@@ -8,7 +8,7 @@ fn foo2(_: &dyn (Drop + AsRef<str>)) {} //~ ERROR incorrect parentheses around t
 fn foo2_no_space(_: &dyn(Drop + AsRef<str>)) {} //~ ERROR incorrect parentheses around trait bounds
 
 fn foo3(_: &dyn {Drop + AsRef<str>}) {} //~ ERROR expected parameter name, found `{`
-//~^ ERROR expected one of `!`, `(`, `)`, `*`, `,`, `?`, `const`, `for`, `~`, lifetime, or path, found `{`
+//~^ ERROR expected one of `!`, `(`, `)`, `*`, `,`, `?`, `async`, `const`, `for`, `~`, lifetime, or path, found `{`
 //~| ERROR at least one trait is required for an object type
 
 fn foo4(_: &dyn <Drop + AsRef<str>>) {} //~ ERROR expected identifier, found `<`
diff --git a/tests/ui/parser/trait-object-delimiters.stderr b/tests/ui/parser/trait-object-delimiters.stderr
index 2ddb734cee0..2b1f8df991f 100644
--- a/tests/ui/parser/trait-object-delimiters.stderr
+++ b/tests/ui/parser/trait-object-delimiters.stderr
@@ -34,11 +34,11 @@ error: expected parameter name, found `{`
 LL | fn foo3(_: &dyn {Drop + AsRef<str>}) {}
    |                 ^ expected parameter name
 
-error: expected one of `!`, `(`, `)`, `*`, `,`, `?`, `const`, `for`, `~`, lifetime, or path, found `{`
+error: expected one of `!`, `(`, `)`, `*`, `,`, `?`, `async`, `const`, `for`, `~`, lifetime, or path, found `{`
   --> $DIR/trait-object-delimiters.rs:10:17
    |
 LL | fn foo3(_: &dyn {Drop + AsRef<str>}) {}
-   |                -^ expected one of 11 possible tokens
+   |                -^ expected one of 12 possible tokens
    |                |
    |                help: missing `,`
 
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/mbe-const-trait-bound-theoretical-regression.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/mbe-const-trait-bound-theoretical-regression.rs
index 99806922ba5..3dcdb0cad94 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/mbe-const-trait-bound-theoretical-regression.rs
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/mbe-const-trait-bound-theoretical-regression.rs
@@ -6,15 +6,16 @@
 
 macro_rules! demo {
     ($ty:ty) => { compile_error!("ty"); };
-    (impl $c:ident) => {};
-    (dyn $c:ident) => {};
+    //~^ ERROR ty
+    //~| ERROR ty
+    (impl $c:ident Trait) => {};
+    (dyn $c:ident Trait) => {};
 }
 
-demo! { impl const }
-//~^ ERROR expected identifier, found `<eof>`
+demo! { impl const Trait }
+//~^ ERROR const trait impls are experimental
 
-demo! { dyn const }
+demo! { dyn const Trait }
 //~^ ERROR const trait impls are experimental
-//~| ERROR expected identifier, found `<eof>`
 
 fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/mbe-const-trait-bound-theoretical-regression.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/mbe-const-trait-bound-theoretical-regression.stderr
index fd9184b9dff..f4b401b7386 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/mbe-const-trait-bound-theoretical-regression.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/mbe-const-trait-bound-theoretical-regression.stderr
@@ -1,31 +1,45 @@
-error: expected identifier, found `<eof>`
-  --> $DIR/mbe-const-trait-bound-theoretical-regression.rs:13:14
+error: ty
+  --> $DIR/mbe-const-trait-bound-theoretical-regression.rs:8:19
    |
 LL |     ($ty:ty) => { compile_error!("ty"); };
-   |      ------ while parsing argument for this `ty` macro fragment
+   |                   ^^^^^^^^^^^^^^^^^^^^
 ...
-LL | demo! { impl const }
-   |              ^^^^^ expected identifier
+LL | demo! { impl const Trait }
+   | -------------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `demo` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: expected identifier, found `<eof>`
-  --> $DIR/mbe-const-trait-bound-theoretical-regression.rs:16:13
+error: ty
+  --> $DIR/mbe-const-trait-bound-theoretical-regression.rs:8:19
    |
 LL |     ($ty:ty) => { compile_error!("ty"); };
-   |      ------ while parsing argument for this `ty` macro fragment
+   |                   ^^^^^^^^^^^^^^^^^^^^
 ...
-LL | demo! { dyn const }
-   |             ^^^^^ expected identifier
+LL | demo! { dyn const Trait }
+   | ------------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `demo` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0658]: const trait impls are experimental
+  --> $DIR/mbe-const-trait-bound-theoretical-regression.rs:15:14
+   |
+LL | demo! { impl const Trait }
+   |              ^^^^^
+   |
+   = note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
+   = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: const trait impls are experimental
-  --> $DIR/mbe-const-trait-bound-theoretical-regression.rs:16:13
+  --> $DIR/mbe-const-trait-bound-theoretical-regression.rs:18:13
    |
-LL | demo! { dyn const }
+LL | demo! { dyn const Trait }
    |             ^^^^^
    |
    = note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
    = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0658`.