Support async trait bounds in macros
This commit is contained in:
parent
29f87ade9d
commit
9c8b107955
@ -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
|
parse_async_fn_in_2015 = `async fn` is not permitted in Rust 2015
|
||||||
.label = to use `async fn`, switch to Rust 2018 or later
|
.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_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
|
parse_async_move_order_incorrect = the order of `move` and `async` is incorrect
|
||||||
|
@ -2975,3 +2975,10 @@ pub(crate) struct ArrayIndexInOffsetOf(#[primary_span] pub Span);
|
|||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(parse_invalid_offset_of)]
|
#[diag(parse_invalid_offset_of)]
|
||||||
pub(crate) struct InvalidOffsetOf(#[primary_span] pub Span);
|
pub(crate) struct InvalidOffsetOf(#[primary_span] pub Span);
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(parse_async_impl)]
|
||||||
|
pub(crate) struct AsyncImpl {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
@ -562,6 +562,15 @@ impl<'a> Parser<'a> {
|
|||||||
self.sess.gated_spans.gate(sym::const_trait_impl, span);
|
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();
|
let polarity = self.parse_polarity();
|
||||||
|
|
||||||
// Parse both types and traits as a type, then reinterpret if necessary.
|
// Parse both types and traits as a type, then reinterpret if necessary.
|
||||||
|
@ -778,9 +778,10 @@ impl<'a> Parser<'a> {
|
|||||||
|| self.check(&token::Not)
|
|| self.check(&token::Not)
|
||||||
|| self.check(&token::Question)
|
|| self.check(&token::Question)
|
||||||
|| self.check(&token::Tilde)
|
|| self.check(&token::Tilde)
|
||||||
|| self.check_keyword(kw::Const)
|
|
||||||
|| self.check_keyword(kw::For)
|
|| self.check_keyword(kw::For)
|
||||||
|| self.check(&token::OpenDelim(Delimiter::Parenthesis))
|
|| self.check(&token::OpenDelim(Delimiter::Parenthesis))
|
||||||
|
|| self.check_keyword(kw::Const)
|
||||||
|
|| self.check_keyword(kw::Async)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a bound according to the grammar:
|
/// Parses a bound according to the grammar:
|
||||||
@ -882,11 +883,13 @@ impl<'a> Parser<'a> {
|
|||||||
BoundConstness::Never
|
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);
|
self.sess.gated_spans.gate(sym::async_closure, self.prev_token.span);
|
||||||
BoundAsyncness::Async(self.prev_token.span)
|
BoundAsyncness::Async(self.prev_token.span)
|
||||||
} else if self.may_recover()
|
} 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.is_kw_followed_by_ident(kw::Async)
|
||||||
{
|
{
|
||||||
self.bump(); // eat `async`
|
self.bump(); // eat `async`
|
||||||
|
@ -3,6 +3,10 @@
|
|||||||
struct F;
|
struct F;
|
||||||
|
|
||||||
impl async Fn<()> for 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() {}
|
fn main() {}
|
||||||
|
@ -1,8 +1,47 @@
|
|||||||
error: expected type, found keyword `async`
|
error: `async` trait implementations are unsupported
|
||||||
--> $DIR/impl-header.rs:5:6
|
--> $DIR/impl-header.rs:5:6
|
||||||
|
|
|
|
||||||
LL | impl async Fn<()> for F {}
|
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`.
|
||||||
|
@ -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() {}
|
@ -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`.
|
12
tests/ui/async-await/async-fn/trait-bounds-in-macro.rs
Normal file
12
tests/ui/async-await/async-fn/trait-bounds-in-macro.rs
Normal file
@ -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() {}
|
14
tests/ui/async-await/async-fn/trait-bounds-in-macro.stderr
Normal file
14
tests/ui/async-await/async-fn/trait-bounds-in-macro.stderr
Normal file
@ -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`.
|
@ -1,4 +1,4 @@
|
|||||||
//@ check-pass
|
// This is just `mbe-async-trait-bound-theoretical-regression.rs` in practice.
|
||||||
|
|
||||||
//@ edition:2021
|
//@ edition:2021
|
||||||
// for the `impl` + keyword test
|
// for the `impl` + keyword test
|
||||||
@ -11,5 +11,7 @@ macro_rules! impl_primitive {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl_primitive!(impl async);
|
impl_primitive!(impl async);
|
||||||
|
//~^ ERROR expected identifier, found `<eof>`
|
||||||
|
//~| ERROR async closures are unstable
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
23
tests/ui/parser/bad-recover-kw-after-impl.stderr
Normal file
23
tests/ui/parser/bad-recover-kw-after-impl.stderr
Normal file
@ -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`.
|
@ -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 foo2_no_space(_: &dyn(Drop + AsRef<str>)) {} //~ ERROR incorrect parentheses around trait bounds
|
||||||
|
|
||||||
fn foo3(_: &dyn {Drop + AsRef<str>}) {} //~ ERROR expected parameter name, found `{`
|
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
|
//~| ERROR at least one trait is required for an object type
|
||||||
|
|
||||||
fn foo4(_: &dyn <Drop + AsRef<str>>) {} //~ ERROR expected identifier, found `<`
|
fn foo4(_: &dyn <Drop + AsRef<str>>) {} //~ ERROR expected identifier, found `<`
|
||||||
|
@ -34,11 +34,11 @@ error: expected parameter name, found `{`
|
|||||||
LL | fn foo3(_: &dyn {Drop + AsRef<str>}) {}
|
LL | fn foo3(_: &dyn {Drop + AsRef<str>}) {}
|
||||||
| ^ expected parameter name
|
| ^ 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
|
--> $DIR/trait-object-delimiters.rs:10:17
|
||||||
|
|
|
|
||||||
LL | fn foo3(_: &dyn {Drop + AsRef<str>}) {}
|
LL | fn foo3(_: &dyn {Drop + AsRef<str>}) {}
|
||||||
| -^ expected one of 11 possible tokens
|
| -^ expected one of 12 possible tokens
|
||||||
| |
|
| |
|
||||||
| help: missing `,`
|
| help: missing `,`
|
||||||
|
|
||||||
|
@ -6,15 +6,16 @@
|
|||||||
|
|
||||||
macro_rules! demo {
|
macro_rules! demo {
|
||||||
($ty:ty) => { compile_error!("ty"); };
|
($ty:ty) => { compile_error!("ty"); };
|
||||||
(impl $c:ident) => {};
|
//~^ ERROR ty
|
||||||
(dyn $c:ident) => {};
|
//~| ERROR ty
|
||||||
|
(impl $c:ident Trait) => {};
|
||||||
|
(dyn $c:ident Trait) => {};
|
||||||
}
|
}
|
||||||
|
|
||||||
demo! { impl const }
|
demo! { impl const Trait }
|
||||||
//~^ ERROR expected identifier, found `<eof>`
|
//~^ ERROR const trait impls are experimental
|
||||||
|
|
||||||
demo! { dyn const }
|
demo! { dyn const Trait }
|
||||||
//~^ ERROR const trait impls are experimental
|
//~^ ERROR const trait impls are experimental
|
||||||
//~| ERROR expected identifier, found `<eof>`
|
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -1,31 +1,45 @@
|
|||||||
error: expected identifier, found `<eof>`
|
error: ty
|
||||||
--> $DIR/mbe-const-trait-bound-theoretical-regression.rs:13:14
|
--> $DIR/mbe-const-trait-bound-theoretical-regression.rs:8:19
|
||||||
|
|
|
|
||||||
LL | ($ty:ty) => { compile_error!("ty"); };
|
LL | ($ty:ty) => { compile_error!("ty"); };
|
||||||
| ------ while parsing argument for this `ty` macro fragment
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
...
|
...
|
||||||
LL | demo! { impl const }
|
LL | demo! { impl const Trait }
|
||||||
| ^^^^^ expected identifier
|
| -------------------------- 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>`
|
error: ty
|
||||||
--> $DIR/mbe-const-trait-bound-theoretical-regression.rs:16:13
|
--> $DIR/mbe-const-trait-bound-theoretical-regression.rs:8:19
|
||||||
|
|
|
|
||||||
LL | ($ty:ty) => { compile_error!("ty"); };
|
LL | ($ty:ty) => { compile_error!("ty"); };
|
||||||
| ------ while parsing argument for this `ty` macro fragment
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
...
|
...
|
||||||
LL | demo! { dyn const }
|
LL | demo! { dyn const Trait }
|
||||||
| ^^^^^ expected identifier
|
| ------------------------- 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
|
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:15:14
|
||||||
|
|
|
|
||||||
LL | demo! { dyn const }
|
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:18:13
|
||||||
|
|
|
||||||
|
LL | demo! { dyn const Trait }
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
|
|
||||||
= note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
|
= 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
|
= 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
|
= 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`.
|
For more information about this error, try `rustc --explain E0658`.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user