async_trait/
lib.rs

1//! [![github]](https://github.com/dtolnay/async-trait) [![crates-io]](https://crates.io/crates/async-trait) [![docs-rs]](https://docs.rs/async-trait)
2//!
3//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
4//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
5//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs
6//!
7//! <br>
8//!
9//! <h4>Type erasure for async trait methods</h4>
10//!
11//! The stabilization of async functions in traits in Rust 1.75 did not include
12//! support for using traits containing async functions as `dyn Trait`. Trying
13//! to use dyn with an async trait produces the following error:
14//!
15//! ```compile_fail
16//! pub trait Trait {
17//!     async fn f(&self);
18//! }
19//!
20//! pub fn make() -> Box<dyn Trait> {
21//!     unimplemented!()
22//! }
23//! ```
24//!
25//! ```text
26//! error[E0038]: the trait `Trait` cannot be made into an object
27//!  --> src/main.rs:5:22
28//!   |
29//! 5 | pub fn make() -> Box<dyn Trait> {
30//!   |                      ^^^^^^^^^ `Trait` cannot be made into an object
31//!   |
32//! 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 <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
33//!  --> src/main.rs:2:14
34//!   |
35//! 1 | pub trait Trait {
36//!   |           ----- this trait cannot be made into an object...
37//! 2 |     async fn f(&self);
38//!   |              ^ ...because method `f` is `async`
39//!   = help: consider moving `f` to another trait
40//! ```
41//!
42//! This crate provides an attribute macro to make async fn in traits work with
43//! dyn traits.
44//!
45//! Please refer to [*why async fn in traits are hard*][hard] for a deeper
46//! analysis of how this implementation differs from what the compiler and
47//! language deliver natively.
48//!
49//! [hard]: https://smallcultfollowing.com/babysteps/blog/2019/10/26/async-fn-in-traits-are-hard/
50//!
51//! <br>
52//!
53//! # Example
54//!
55//! This example implements the core of a highly effective advertising platform
56//! using async fn in a trait.
57//!
58//! The only thing to notice here is that we write an `#[async_trait]` macro on
59//! top of traits and trait impls that contain async fn, and then they work. We
60//! get to have `Vec<Box<dyn Advertisement + Sync>>` or `&[&dyn Advertisement]`,
61//! for example.
62//!
63//! ```
64//! use async_trait::async_trait;
65//!
66//! #[async_trait]
67//! trait Advertisement {
68//!     async fn run(&self);
69//! }
70//!
71//! struct Modal;
72//!
73//! #[async_trait]
74//! impl Advertisement for Modal {
75//!     async fn run(&self) {
76//!         self.render_fullscreen().await;
77//!         for _ in 0..4u16 {
78//!             remind_user_to_join_mailing_list().await;
79//!         }
80//!         self.hide_for_now().await;
81//!     }
82//! }
83//!
84//! struct AutoplayingVideo {
85//!     media_url: String,
86//! }
87//!
88//! #[async_trait]
89//! impl Advertisement for AutoplayingVideo {
90//!     async fn run(&self) {
91//!         let stream = connect(&self.media_url).await;
92//!         stream.play().await;
93//!
94//!         // Video probably persuaded user to join our mailing list!
95//!         Modal.run().await;
96//!     }
97//! }
98//! #
99//! # impl Modal {
100//! #     async fn render_fullscreen(&self) {}
101//! #     async fn hide_for_now(&self) {}
102//! # }
103//! #
104//! # async fn remind_user_to_join_mailing_list() {}
105//! #
106//! # struct Stream;
107//! # async fn connect(_media_url: &str) -> Stream { Stream }
108//! # impl Stream {
109//! #     async fn play(&self) {}
110//! # }
111//! ```
112//!
113//! <br><br>
114//!
115//! # Supported features
116//!
117//! It is the intention that all features of Rust traits should work nicely with
118//! #\[async_trait\], but the edge cases are numerous. Please file an issue if
119//! you see unexpected borrow checker errors, type errors, or warnings. There is
120//! no use of `unsafe` in the expanded code, so rest assured that if your code
121//! compiles it can't be that badly broken.
122//!
123//! > &#9745;&emsp;Self by value, by reference, by mut reference, or no self;<br>
124//! > &#9745;&emsp;Any number of arguments, any return value;<br>
125//! > &#9745;&emsp;Generic type parameters and lifetime parameters;<br>
126//! > &#9745;&emsp;Associated types;<br>
127//! > &#9745;&emsp;Having async and non-async functions in the same trait;<br>
128//! > &#9745;&emsp;Default implementations provided by the trait;<br>
129//! > &#9745;&emsp;Elided lifetimes.<br>
130//!
131//! <br>
132//!
133//! # Explanation
134//!
135//! Async fns get transformed into methods that return `Pin<Box<dyn Future +
136//! Send + 'async_trait>>` and delegate to an async block.
137//!
138//! For example the `impl Advertisement for AutoplayingVideo` above would be
139//! expanded as:
140//!
141//! ```
142//! # const IGNORE: &str = stringify! {
143//! impl Advertisement for AutoplayingVideo {
144//!     fn run<'async_trait>(
145//!         &'async_trait self,
146//!     ) -> Pin<Box<dyn core::future::Future<Output = ()> + Send + 'async_trait>>
147//!     where
148//!         Self: Sync + 'async_trait,
149//!     {
150//!         Box::pin(async move {
151//!             /* the original method body */
152//!         })
153//!     }
154//! }
155//! # };
156//! ```
157//!
158//! <br><br>
159//!
160//! # Non-threadsafe futures
161//!
162//! Not all async traits need futures that are `dyn Future + Send`. To avoid
163//! having Send and Sync bounds placed on the async trait methods, invoke the
164//! async trait macro as `#[async_trait(?Send)]` on both the trait and the impl
165//! blocks.
166//!
167//! <br>
168//!
169//! # Elided lifetimes
170//!
171//! Be aware that async fn syntax does not allow lifetime elision outside of `&`
172//! and `&mut` references. (This is true even when not using #\[async_trait\].)
173//! Lifetimes must be named or marked by the placeholder `'_`.
174//!
175//! Fortunately the compiler is able to diagnose missing lifetimes with a good
176//! error message.
177//!
178//! ```compile_fail
179//! # use async_trait::async_trait;
180//! #
181//! type Elided<'a> = &'a usize;
182//!
183//! #[async_trait]
184//! trait Test {
185//!     async fn test(not_okay: Elided, okay: &usize) {}
186//! }
187//! ```
188//!
189//! ```text
190//! error[E0726]: implicit elided lifetime not allowed here
191//!  --> src/main.rs:9:29
192//!   |
193//! 9 |     async fn test(not_okay: Elided, okay: &usize) {}
194//!   |                             ^^^^^^- help: indicate the anonymous lifetime: `<'_>`
195//! ```
196//!
197//! The fix is to name the lifetime or use `'_`.
198//!
199//! ```
200//! # use async_trait::async_trait;
201//! #
202//! # type Elided<'a> = &'a usize;
203//! #
204//! #[async_trait]
205//! trait Test {
206//!     // either
207//!     async fn test<'e>(elided: Elided<'e>) {}
208//! # }
209//! # #[async_trait]
210//! # trait Test2 {
211//!     // or
212//!     async fn test(elided: Elided<'_>) {}
213//! }
214//! ```
215//!
216//! <br><br>
217//!
218//! # Dyn traits
219//!
220//! Traits with async methods can be used as trait objects as long as they meet
221//! the usual requirements for dyn -- no methods with type parameters, no self
222//! by value, no associated types, etc.
223//!
224//! ```
225//! # use async_trait::async_trait;
226//! #
227//! #[async_trait]
228//! pub trait ObjectSafe {
229//!     async fn f(&self);
230//!     async fn g(&mut self);
231//! }
232//!
233//! # const IGNORE: &str = stringify! {
234//! impl ObjectSafe for MyType {...}
235//!
236//! let value: MyType = ...;
237//! # };
238//! #
239//! # struct MyType;
240//! #
241//! # #[async_trait]
242//! # impl ObjectSafe for MyType {
243//! #     async fn f(&self) {}
244//! #     async fn g(&mut self) {}
245//! # }
246//! #
247//! # let value: MyType = MyType;
248//! let object = &value as &dyn ObjectSafe;  // make trait object
249//! ```
250//!
251//! The one wrinkle is in traits that provide default implementations of async
252//! methods. In order for the default implementation to produce a future that is
253//! Send, the async_trait macro must emit a bound of `Self: Sync` on trait
254//! methods that take `&self` and a bound `Self: Send` on trait methods that
255//! take `&mut self`. An example of the former is visible in the expanded code
256//! in the explanation section above.
257//!
258//! If you make a trait with async methods that have default implementations,
259//! everything will work except that the trait cannot be used as a trait object.
260//! Creating a value of type `&dyn Trait` will produce an error that looks like
261//! this:
262//!
263//! ```text
264//! error: the trait `Test` cannot be made into an object
265//!  --> src/main.rs:8:5
266//!   |
267//! 8 |     async fn cannot_dyn(&self) {}
268//!   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
269//! ```
270//!
271//! For traits that need to be object safe and need to have default
272//! implementations for some async methods, there are two resolutions. Either
273//! you can add Send and/or Sync as supertraits (Send if there are `&mut self`
274//! methods with default implementations, Sync if there are `&self` methods with
275//! default implementations) to constrain all implementors of the trait such that
276//! the default implementations are applicable to them:
277//!
278//! ```
279//! # use async_trait::async_trait;
280//! #
281//! #[async_trait]
282//! pub trait ObjectSafe: Sync {  // added supertrait
283//!     async fn can_dyn(&self) {}
284//! }
285//! #
286//! # struct MyType;
287//! #
288//! # #[async_trait]
289//! # impl ObjectSafe for MyType {}
290//! #
291//! # let value = MyType;
292//!
293//! let object = &value as &dyn ObjectSafe;
294//! ```
295//!
296//! or you can strike the problematic methods from your trait object by
297//! bounding them with `Self: Sized`:
298//!
299//! ```
300//! # use async_trait::async_trait;
301//! #
302//! #[async_trait]
303//! pub trait ObjectSafe {
304//!     async fn cannot_dyn(&self) where Self: Sized {}
305//!
306//!     // presumably other methods
307//! }
308//! #
309//! # struct MyType;
310//! #
311//! # #[async_trait]
312//! # impl ObjectSafe for MyType {}
313//! #
314//! # let value = MyType;
315//!
316//! let object = &value as &dyn ObjectSafe;
317//! ```
318
319#![doc(html_root_url = "https://docs.rs/async-trait/0.1.83")]
320#![allow(
321    clippy::default_trait_access,
322    clippy::doc_markdown,
323    clippy::explicit_auto_deref,
324    clippy::if_not_else,
325    clippy::items_after_statements,
326    clippy::match_like_matches_macro,
327    clippy::module_name_repetitions,
328    clippy::shadow_unrelated,
329    clippy::similar_names,
330    clippy::too_many_lines,
331    clippy::trivially_copy_pass_by_ref
332)]
333
334extern crate proc_macro;
335
336mod args;
337mod bound;
338mod expand;
339mod lifetime;
340mod parse;
341mod receiver;
342mod verbatim;
343
344use crate::args::Args;
345use crate::expand::expand;
346use crate::parse::Item;
347use proc_macro::TokenStream;
348use quote::quote;
349use syn::parse_macro_input;
350
351#[proc_macro_attribute]
352pub fn async_trait(args: TokenStream, input: TokenStream) -> TokenStream {
353    let args = parse_macro_input!(args as Args);
354    let mut item = parse_macro_input!(input as Item);
355    expand(&mut item, args.local);
356    TokenStream::from(quote!(#item))
357}