• Home
Name Date Size #Lines LOC

..--

src/04-Jul-2025-1,204839

tests/04-Jul-2025-2,4081,865

.android-checksum.jsonD04-Jul-20254.8 KiB11

.cargo-checksum.jsonD04-Jul-20254.3 KiB11

Android.bpD04-Jul-20251 KiB4237

Cargo.tomlD04-Jul-20252 KiB9278

LICENSED04-Jul-20259.5 KiB177150

LICENSE-APACHED04-Jul-20259.5 KiB177150

METADATAD04-Jul-2025391 1817

MODULE_LICENSE_APACHE2D04-Jul-20250

README.mdD04-Jul-20256 KiB206160

TEST_MAPPINGD04-Jul-2025731 3635

cargo_embargo.jsonD04-Jul-202579 55

rules.mkD04-Jul-2025545 1811

README.md

1Async trait methods
2===================
3
4[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/async--trait-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/async-trait)
5[<img alt="crates.io" src="https://img.shields.io/crates/v/async-trait.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/async-trait)
6[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-async--trait-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/async-trait)
7[<img alt="build status" src="https://img.shields.io/github/actions/workflow/status/dtolnay/async-trait/ci.yml?branch=master&style=for-the-badge" height="20">](https://github.com/dtolnay/async-trait/actions?query=branch%3Amaster)
8
9The stabilization of async functions in traits in Rust 1.75 did not include
10support for using traits containing async functions as `dyn Trait`. Trying to
11use dyn with an async trait produces the following error:
12
13```rust
14pub trait Trait {
15    async fn f(&self);
16}
17
18pub fn make() -> Box<dyn Trait> {
19    unimplemented!()
20}
21```
22
23```console
24error[E0038]: the trait `Trait` is not dyn compatible
25 --> src/main.rs:5:22
26  |
275 | pub fn make() -> Box<dyn Trait> {
28  |                      ^^^^^^^^^ `Trait` is not dyn compatible
29  |
30note: for a trait to be dyn compatible it needs to allow building a vtable
31      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
32 --> src/main.rs:2:14
33  |
341 | pub trait Trait {
35  |           ----- this trait is not dyn compatible...
362 |     async fn f(&self);
37  |              ^ ...because method `f` is `async`
38  = help: consider moving `f` to another trait
39```
40
41This crate provides an attribute macro to make async fn in traits work with dyn
42traits.
43
44Please refer to [*why async fn in traits are hard*][hard] for a deeper analysis
45of how this implementation differs from what the compiler and language deliver
46natively.
47
48[hard]: https://smallcultfollowing.com/babysteps/blog/2019/10/26/async-fn-in-traits-are-hard/
49
50<br>
51
52## Example
53
54This example implements the core of a highly effective advertising platform
55using async fn in a trait.
56
57The only thing to notice here is that we write an `#[async_trait]` macro on top
58of traits and trait impls that contain async fn, and then they work. We get to
59have `Vec<Box<dyn Advertisement + Sync>>` or `&[&dyn Advertisement]`, for
60example.
61
62```rust
63use async_trait::async_trait;
64
65#[async_trait]
66trait Advertisement {
67    async fn run(&self);
68}
69
70struct Modal;
71
72#[async_trait]
73impl Advertisement for Modal {
74    async fn run(&self) {
75        self.render_fullscreen().await;
76        for _ in 0..4u16 {
77            remind_user_to_join_mailing_list().await;
78        }
79        self.hide_for_now().await;
80    }
81}
82
83struct AutoplayingVideo {
84    media_url: String,
85}
86
87#[async_trait]
88impl Advertisement for AutoplayingVideo {
89    async fn run(&self) {
90        let stream = connect(&self.media_url).await;
91        stream.play().await;
92
93        // Video probably persuaded user to join our mailing list!
94        Modal.run().await;
95    }
96}
97```
98
99<br>
100
101## Supported features
102
103It is the intention that all features of Rust traits should work nicely with
104\#\[async_trait\], but the edge cases are numerous. *Please file an issue if you
105see unexpected borrow checker errors, type errors, or warnings.* There is no use
106of `unsafe` in the expanded code, so rest assured that if your code compiles it
107can't be that badly broken.
108
109- &#128077;&ensp;Self by value, by reference, by mut reference, or no self;
110- &#128077;&ensp;Any number of arguments, any return value;
111- &#128077;&ensp;Generic type parameters and lifetime parameters;
112- &#128077;&ensp;Associated types;
113- &#128077;&ensp;Having async and non-async functions in the same trait;
114- &#128077;&ensp;Default implementations provided by the trait;
115- &#128077;&ensp;Elided lifetimes.
116
117<br>
118
119## Explanation
120
121Async fns get transformed into methods that return `Pin<Box<dyn Future + Send +
122'async_trait>>` and delegate to an async block.
123
124For example the `impl Advertisement for AutoplayingVideo` above would be
125expanded as:
126
127```rust
128impl Advertisement for AutoplayingVideo {
129    fn run<'async_trait>(
130        &'async_trait self,
131    ) -> Pin<Box<dyn std::future::Future<Output = ()> + Send + 'async_trait>>
132    where
133        Self: Sync + 'async_trait,
134    {
135        Box::pin(async move {
136            /* the original method body */
137        })
138    }
139}
140```
141
142<br>
143
144## Non-threadsafe futures
145
146Not all async traits need futures that are `dyn Future + Send`. To avoid having
147Send and Sync bounds placed on the async trait methods, invoke the async trait
148macro as `#[async_trait(?Send)]` on both the trait and the impl blocks.
149
150<br>
151
152## Elided lifetimes
153
154Be aware that async fn syntax does not allow lifetime elision outside of `&` and
155`&mut` references. (This is true even when not using #\[async_trait\].)
156Lifetimes must be named or marked by the placeholder `'_`.
157
158Fortunately the compiler is able to diagnose missing lifetimes with a good error
159message.
160
161```rust
162type Elided<'a> = &'a usize;
163
164#[async_trait]
165trait Test {
166    async fn test(not_okay: Elided, okay: &usize) {}
167}
168```
169
170```console
171error[E0726]: implicit elided lifetime not allowed here
172 --> src/main.rs:9:29
173  |
1749 |     async fn test(not_okay: Elided, okay: &usize) {}
175  |                             ^^^^^^- help: indicate the anonymous lifetime: `<'_>`
176```
177
178The fix is to name the lifetime or use `'_`.
179
180```rust
181#[async_trait]
182trait Test {
183    // either
184    async fn test<'e>(elided: Elided<'e>) {}
185    // or
186    async fn test(elided: Elided<'_>) {}
187}
188```
189
190<br>
191
192#### License
193
194<sup>
195Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
1962.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option.
197</sup>
198
199<br>
200
201<sub>
202Unless you explicitly state otherwise, any contribution intentionally submitted
203for inclusion in this crate by you, as defined in the Apache-2.0 license, shall
204be dual licensed as above, without any additional terms or conditions.
205</sub>
206