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.78")]
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)]
332
333extern crate proc_macro;
334
335mod args;
336mod bound;
337mod expand;
338mod lifetime;
339mod parse;
340mod receiver;
341mod verbatim;
342
343use crate::args::Args;
344use crate::expand::expand;
345use crate::parse::Item;
346use proc_macro::TokenStream;
347use quote::quote;
348use syn::parse_macro_input;
349
350#[proc_macro_attribute]
351pub fn async_trait(args: TokenStream, input: TokenStream) -> TokenStream {
352 let args: Args = parse_macro_input!(args as Args);
353 let mut item: Item = parse_macro_input!(input as Item);
354 expand(&mut item, is_local:args.local);
355 TokenStream::from(quote!(#item))
356}
357