diff --git a/README.md b/README.md index 39e368b..301ce3f 100644 --- a/README.md +++ b/README.md @@ -6,29 +6,43 @@ Async trait methods [docs.rs](https://docs.rs/async-trait) [build status](https://github.com/dtolnay/async-trait/actions?query=branch%3Amaster) -The initial round of stabilizations for the async/await language feature in Rust -1.39 did not include support for async fn in traits. Trying to include an async -fn in a trait produces the following error: +The stabilization of async functions in traits in Rust 1.75 did not include +support for using traits containing async functions as `dyn Trait`. Trying to +use dyn with an async trait produces the following error: ```rust -trait MyTrait { - async fn f() {} +pub trait Trait { + async fn f(&self); +} + +pub fn make() -> Box { + unimplemented!() } ``` ```console -error[E0706]: trait fns cannot be declared `async` - --> src/main.rs:4:5 +error[E0038]: the trait `Trait` cannot be made into an object + --> src/main.rs:5:22 + | +5 | pub fn make() -> Box { + | ^^^^^^^^^ `Trait` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> src/main.rs:2:14 | -4 | async fn f() {} - | ^^^^^^^^^^^^^^^ +1 | pub trait Trait { + | ----- this trait cannot be made into an object... +2 | async fn f(&self); + | ^ ...because method `f` is `async` + = help: consider moving `f` to another trait ``` -This crate provides an attribute macro to make async fn in traits work. +This crate provides an attribute macro to make async fn in traits work with dyn +traits. Please refer to [*why async fn in traits are hard*][hard] for a deeper analysis -of how this implementation differs from what the compiler and language hope to -deliver in the future. +of how this implementation differs from what the compiler and language deliver +natively. [hard]: https://smallcultfollowing.com/babysteps/blog/2019/10/26/async-fn-in-traits-are-hard/ @@ -40,7 +54,9 @@ This example implements the core of a highly effective advertising platform using async fn in a trait. The only thing to notice here is that we write an `#[async_trait]` macro on top -of traits and trait impls that contain async fn, and then they work. +of traits and trait impls that contain async fn, and then they work. We get to +have `Vec>` or `&[&dyn Advertisement]`, for +example. ```rust use async_trait::async_trait; @@ -95,8 +111,7 @@ can't be that badly broken. - 👍 Associated types; - 👍 Having async and non-async functions in the same trait; - 👍 Default implementations provided by the trait; -- 👍 Elided lifetimes; -- 👍 Dyn-capable traits. +- 👍 Elided lifetimes.
diff --git a/build.rs b/build.rs index f25fb0a..db7c5f0 100644 --- a/build.rs +++ b/build.rs @@ -17,10 +17,6 @@ fn main() { if compiler < 47 { println!("cargo:rustc-cfg=self_span_hack"); } - - if compiler >= 75 && env::var_os("DOCS_RS").is_none() { - println!("cargo:rustc-cfg=native_async_fn_in_trait"); - } } fn rustc_minor_version() -> Option { diff --git a/src/lib.rs b/src/lib.rs index 37d0869..e2365c3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,32 +6,45 @@ //! //!
//! -//!
Type erasure for async trait methods
+//!

Type erasure for async trait methods

//! -//! The initial round of stabilizations for the async/await language feature in -//! Rust 1.39 did not include support for async fn in traits. Trying to include -//! an async fn in a trait produces the following error: +//! The stabilization of async functions in traits in Rust 1.75 did not include +//! support for using traits containing async functions as `dyn Trait`. Trying +//! to use dyn with an async trait produces the following error: //! -#![cfg_attr(not(native_async_fn_in_trait), doc = "```compile_fail")] -#![cfg_attr(native_async_fn_in_trait, doc = "```")] -//! trait MyTrait { -//! async fn f() {} +//! ```compile_fail +//! pub trait Trait { +//! async fn f(&self); //! } -#![doc = "```"] +//! +//! pub fn make() -> Box { +//! unimplemented!() +//! } +//! ``` //! //! ```text -//! error[E0706]: trait fns cannot be declared `async` -//! --> src/main.rs:4:5 +//! error[E0038]: the trait `Trait` cannot be made into an object +//! --> src/main.rs:5:22 +//! | +//! 5 | pub fn make() -> Box { +//! | ^^^^^^^^^ `Trait` cannot be made into an object +//! | +//! note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit +//! --> src/main.rs:2:14 //! | -//! 4 | async fn f() {} -//! | ^^^^^^^^^^^^^^^ +//! 1 | pub trait Trait { +//! | ----- this trait cannot be made into an object... +//! 2 | async fn f(&self); +//! | ^ ...because method `f` is `async` +//! = help: consider moving `f` to another trait //! ``` //! -//! This crate provides an attribute macro to make async fn in traits work. +//! This crate provides an attribute macro to make async fn in traits work with +//! dyn traits. //! //! Please refer to [*why async fn in traits are hard*][hard] for a deeper //! analysis of how this implementation differs from what the compiler and -//! language hope to deliver in the future. +//! language deliver natively. //! //! [hard]: https://smallcultfollowing.com/babysteps/blog/2019/10/26/async-fn-in-traits-are-hard/ //! @@ -43,7 +56,9 @@ //! using async fn in a trait. //! //! The only thing to notice here is that we write an `#[async_trait]` macro on -//! top of traits and trait impls that contain async fn, and then they work. +//! top of traits and trait impls that contain async fn, and then they work. We +//! get to have `Vec>` or `&[&dyn Advertisement]`, +//! for example. //! //! ``` //! use async_trait::async_trait; @@ -111,8 +126,7 @@ //! > ☑ Associated types;
//! > ☑ Having async and non-async functions in the same trait;
//! > ☑ Default implementations provided by the trait;
-//! > ☑ Elided lifetimes;
-//! > ☑ Dyn-capable traits.
+//! > ☑ Elided lifetimes.
//! //!
//!