diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index e9c05eb5f455f..a11721ba0213a 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -332,6 +332,15 @@ impl FnDeclKind { _ => false, } } + + fn async_fn_allowed(&self, tcx: TyCtxt<'_>) -> bool { + match self { + FnDeclKind::Fn | FnDeclKind::Inherent => true, + FnDeclKind::Impl if tcx.features().async_fn_in_trait => true, + FnDeclKind::Trait if tcx.features().async_fn_in_trait => true, + _ => false, + } + } } #[derive(Copy, Clone)] @@ -1692,14 +1701,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { })); let output = if let Some((ret_id, span)) = make_ret_async { - if !kind.impl_trait_allowed(self.tcx) { + if !kind.async_fn_allowed(self.tcx) { match kind { FnDeclKind::Trait | FnDeclKind::Impl => { self.tcx .sess .create_feature_err( TraitFnAsync { fn_span, span }, - sym::return_position_impl_trait_in_trait, + sym::async_fn_in_trait, ) .emit(); } @@ -1917,9 +1926,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let future_bound = this.lower_async_fn_output_type_to_future_bound( output, span, - ImplTraitContext::ReturnPositionOpaqueTy { - origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), - in_trait, + if in_trait && !this.tcx.features().return_position_impl_trait_in_trait { + ImplTraitContext::Disallowed(ImplTraitPosition::TraitReturn) + } else { + ImplTraitContext::ReturnPositionOpaqueTy { + origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), + in_trait, + } }, ); diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index ad28595ca82b3..4c891fbf16e94 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -312,6 +312,8 @@ declare_features! ( (active, associated_type_defaults, "1.2.0", Some(29661), None), /// Allows `async || body` closures. (active, async_closure, "1.37.0", Some(62290), None), + /// Alows async functions to be declared, implemented, and used in traits. + (incomplete, async_fn_in_trait, "CURRENT_RUSTC_VERSION", Some(91611), None), /// Allows `extern "C-unwind" fn` to enable unwinding across ABI boundaries. (active, c_unwind, "1.52.0", Some(74990), None), /// Allows using C-variadics. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 7785d29c15f2c..502ef67fc6767 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -396,6 +396,7 @@ symbols! { assume_init, async_await, async_closure, + async_fn_in_trait, atomic, atomic_mod, atomics, diff --git a/src/test/ui/async-await/async-trait-fn.stderr b/src/test/ui/async-await/async-trait-fn.stderr index e5c584e31e815..4fa54c6e36960 100644 --- a/src/test/ui/async-await/async-trait-fn.stderr +++ b/src/test/ui/async-await/async-trait-fn.stderr @@ -9,7 +9,7 @@ LL | async fn foo() {} = note: `async` trait functions are not currently supported = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information - = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable error[E0706]: functions in traits cannot be declared `async` --> $DIR/async-trait-fn.rs:5:5 @@ -22,7 +22,7 @@ LL | async fn bar(&self) {} = note: `async` trait functions are not currently supported = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information - = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable error[E0706]: functions in traits cannot be declared `async` --> $DIR/async-trait-fn.rs:7:5 @@ -35,7 +35,7 @@ LL | async fn baz() { = note: `async` trait functions are not currently supported = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information - = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable error[E0308]: mismatched types --> $DIR/async-trait-fn.rs:3:20 diff --git a/src/test/ui/async-await/edition-deny-async-fns-2015.stderr b/src/test/ui/async-await/edition-deny-async-fns-2015.stderr index 8c2902d9b00d1..62a243e69e743 100644 --- a/src/test/ui/async-await/edition-deny-async-fns-2015.stderr +++ b/src/test/ui/async-await/edition-deny-async-fns-2015.stderr @@ -90,7 +90,7 @@ LL | async fn foo() {} = note: `async` trait functions are not currently supported = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information - = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable error[E0308]: mismatched types --> $DIR/edition-deny-async-fns-2015.rs:18:20 diff --git a/src/test/ui/async-await/feature-gate-async_fn_in_trait.rs b/src/test/ui/async-await/feature-gate-async_fn_in_trait.rs new file mode 100644 index 0000000000000..792f378cb57f1 --- /dev/null +++ b/src/test/ui/async-await/feature-gate-async_fn_in_trait.rs @@ -0,0 +1,25 @@ +// edition:2021 + +// RPITIT is not enough to allow use of async functions +#![allow(incomplete_features)] +#![feature(return_position_impl_trait_in_trait)] + +trait T { + async fn foo(); //~ ERROR functions in traits cannot be declared `async` +} + +// Both return_position_impl_trait_in_trait and async_fn_in_trait are required for this (see also +// feature-gate-return_position_impl_trait_in_trait.rs) +trait T2 { + async fn foo() -> impl Sized; //~ ERROR functions in traits cannot be declared `async` +} + +trait T3 { + fn foo() -> impl std::future::Future<Output = ()>; +} + +impl T3 for () { + async fn foo() {} //~ ERROR functions in traits cannot be declared `async` +} + +fn main() {} diff --git a/src/test/ui/async-await/feature-gate-async_fn_in_trait.stderr b/src/test/ui/async-await/feature-gate-async_fn_in_trait.stderr new file mode 100644 index 0000000000000..2a5fbd1ecd03d --- /dev/null +++ b/src/test/ui/async-await/feature-gate-async_fn_in_trait.stderr @@ -0,0 +1,42 @@ +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/feature-gate-async_fn_in_trait.rs:8:5 + | +LL | async fn foo(); + | -----^^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable + +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/feature-gate-async_fn_in_trait.rs:14:5 + | +LL | async fn foo() -> impl Sized; + | -----^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable + +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/feature-gate-async_fn_in_trait.rs:22:5 + | +LL | async fn foo() {} + | -----^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0706`. diff --git a/src/test/ui/async-await/issues/issue-95307.stderr b/src/test/ui/async-await/issues/issue-95307.stderr index 1c12f1e4862e8..a497cebe3c3d8 100644 --- a/src/test/ui/async-await/issues/issue-95307.stderr +++ b/src/test/ui/async-await/issues/issue-95307.stderr @@ -9,7 +9,7 @@ LL | async fn new() -> [u8; _]; = note: `async` trait functions are not currently supported = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information - = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable error: in expressions, `_` can only be used on the left-hand side of an assignment --> $DIR/issue-95307.rs:7:28 diff --git a/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs b/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs index de7966c66b057..637765fff11e4 100644 --- a/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs +++ b/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs @@ -1,5 +1,18 @@ +// edition:2021 + +// async_fn_in_trait is not enough to allow use of RPITIT +#![allow(incomplete_features)] +#![feature(async_fn_in_trait)] + trait Foo { fn bar() -> impl Sized; //~ ERROR `impl Trait` only allowed in function and inherent method return types, not in trait method return + fn baz() -> Box<impl std::fmt::Display>; //~ ERROR `impl Trait` only allowed in function and inherent method return types, not in trait method return +} + +// Both return_position_impl_trait_in_trait and async_fn_in_trait are required for this (see also +// feature-gate-async_fn_in_trait.rs) +trait AsyncFoo { + async fn bar() -> impl Sized; //~ ERROR `impl Trait` only allowed in function and inherent method return types, not in trait method return } fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr b/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr index 36177bbe15830..aeabed4a6ab66 100644 --- a/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr +++ b/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr @@ -1,5 +1,5 @@ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return - --> $DIR/feature-gate-return_position_impl_trait_in_trait.rs:2:17 + --> $DIR/feature-gate-return_position_impl_trait_in_trait.rs:8:17 | LL | fn bar() -> impl Sized; | ^^^^^^^^^^ @@ -7,6 +7,24 @@ LL | fn bar() -> impl Sized; = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable -error: aborting due to previous error +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return + --> $DIR/feature-gate-return_position_impl_trait_in_trait.rs:9:21 + | +LL | fn baz() -> Box<impl std::fmt::Display>; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return + --> $DIR/feature-gate-return_position_impl_trait_in_trait.rs:15:23 + | +LL | async fn bar() -> impl Sized; + | ^^^^^^^^^^ + | + = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0562`. diff --git a/src/test/ui/parser/fn-header-semantic-fail.stderr b/src/test/ui/parser/fn-header-semantic-fail.stderr index 36304779df36f..800b5a43a0066 100644 --- a/src/test/ui/parser/fn-header-semantic-fail.stderr +++ b/src/test/ui/parser/fn-header-semantic-fail.stderr @@ -147,7 +147,7 @@ LL | async fn ft1(); = note: `async` trait functions are not currently supported = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information - = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable error[E0706]: functions in traits cannot be declared `async` --> $DIR/fn-header-semantic-fail.rs:21:9 @@ -160,7 +160,7 @@ LL | const async unsafe extern "C" fn ft5(); = note: `async` trait functions are not currently supported = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information - = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable error[E0706]: functions in traits cannot be declared `async` --> $DIR/fn-header-semantic-fail.rs:29:9 @@ -173,7 +173,7 @@ LL | async fn ft1() {} = note: `async` trait functions are not currently supported = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information - = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable error[E0706]: functions in traits cannot be declared `async` --> $DIR/fn-header-semantic-fail.rs:33:9 @@ -186,7 +186,7 @@ LL | const async unsafe extern "C" fn ft5() {} = note: `async` trait functions are not currently supported = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information - = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable error[E0391]: cycle detected when computing type of `main::ff5::{opaque#0}` --> $DIR/fn-header-semantic-fail.rs:12:44 diff --git a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr index 55c3b66f1363d..1354abb4f144b 100644 --- a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr +++ b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr @@ -33,7 +33,7 @@ LL | async fn associated(); = note: `async` trait functions are not currently supported = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information - = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable error[E0706]: functions in traits cannot be declared `async` --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:15:5 @@ -46,7 +46,7 @@ LL | async fn associated(); = note: `async` trait functions are not currently supported = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information - = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable error: aborting due to 5 previous errors diff --git a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr index 3814c568e72c1..2c1fa7b36b60e 100644 --- a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr +++ b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr @@ -51,7 +51,7 @@ LL | trait C{async fn new(val: T) {} = note: `async` trait functions are not currently supported = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information - = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable warning: changes to closure capture in Rust 2021 will affect drop order --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:6:57