Bug 1888590 - Mark some subtests on trusted-types-event-handlers.html as failing...
[gecko.git] / third_party / rust / async-trait / README.md
blob39e368bada9ea6bc9bbd4cf94a8bf3f2ee7c5796
1 Async trait methods
2 ===================
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)
9 The initial round of stabilizations for the async/await language feature in Rust
10 1.39 did not include support for async fn in traits. Trying to include an async
11 fn in a trait produces the following error:
13 ```rust
14 trait MyTrait {
15     async fn f() {}
17 ```
19 ```console
20 error[E0706]: trait fns cannot be declared `async`
21  --> src/main.rs:4:5
22   |
23 4 |     async fn f() {}
24   |     ^^^^^^^^^^^^^^^
25 ```
27 This crate provides an attribute macro to make async fn in traits work.
29 Please refer to [*why async fn in traits are hard*][hard] for a deeper analysis
30 of how this implementation differs from what the compiler and language hope to
31 deliver in the future.
33 [hard]: https://smallcultfollowing.com/babysteps/blog/2019/10/26/async-fn-in-traits-are-hard/
35 <br>
37 ## Example
39 This example implements the core of a highly effective advertising platform
40 using async fn in a trait.
42 The only thing to notice here is that we write an `#[async_trait]` macro on top
43 of traits and trait impls that contain async fn, and then they work.
45 ```rust
46 use async_trait::async_trait;
48 #[async_trait]
49 trait Advertisement {
50     async fn run(&self);
53 struct Modal;
55 #[async_trait]
56 impl Advertisement for Modal {
57     async fn run(&self) {
58         self.render_fullscreen().await;
59         for _ in 0..4u16 {
60             remind_user_to_join_mailing_list().await;
61         }
62         self.hide_for_now().await;
63     }
66 struct AutoplayingVideo {
67     media_url: String,
70 #[async_trait]
71 impl Advertisement for AutoplayingVideo {
72     async fn run(&self) {
73         let stream = connect(&self.media_url).await;
74         stream.play().await;
76         // Video probably persuaded user to join our mailing list!
77         Modal.run().await;
78     }
80 ```
82 <br>
84 ## Supported features
86 It is the intention that all features of Rust traits should work nicely with
87 \#\[async_trait\], but the edge cases are numerous. *Please file an issue if you
88 see unexpected borrow checker errors, type errors, or warnings.* There is no use
89 of `unsafe` in the expanded code, so rest assured that if your code compiles it
90 can't be that badly broken.
92 - &#128077;&ensp;Self by value, by reference, by mut reference, or no self;
93 - &#128077;&ensp;Any number of arguments, any return value;
94 - &#128077;&ensp;Generic type parameters and lifetime parameters;
95 - &#128077;&ensp;Associated types;
96 - &#128077;&ensp;Having async and non-async functions in the same trait;
97 - &#128077;&ensp;Default implementations provided by the trait;
98 - &#128077;&ensp;Elided lifetimes;
99 - &#128077;&ensp;Dyn-capable traits.
101 <br>
103 ## Explanation
105 Async fns get transformed into methods that return `Pin<Box<dyn Future + Send +
106 'async_trait>>` and delegate to a private async freestanding function.
108 For example the `impl Advertisement for AutoplayingVideo` above would be
109 expanded as:
111 ```rust
112 impl Advertisement for AutoplayingVideo {
113     fn run<'async_trait>(
114         &'async_trait self,
115     ) -> Pin<Box<dyn std::future::Future<Output = ()> + Send + 'async_trait>>
116     where
117         Self: Sync + 'async_trait,
118     {
119         async fn run(_self: &AutoplayingVideo) {
120             /* the original method body */
121         }
123         Box::pin(run(self))
124     }
128 <br>
130 ## Non-threadsafe futures
132 Not all async traits need futures that are `dyn Future + Send`. To avoid having
133 Send and Sync bounds placed on the async trait methods, invoke the async trait
134 macro as `#[async_trait(?Send)]` on both the trait and the impl blocks.
136 <br>
138 ## Elided lifetimes
140 Be aware that async fn syntax does not allow lifetime elision outside of `&` and
141 `&mut` references. (This is true even when not using #\[async_trait\].)
142 Lifetimes must be named or marked by the placeholder `'_`.
144 Fortunately the compiler is able to diagnose missing lifetimes with a good error
145 message.
147 ```rust
148 type Elided<'a> = &'a usize;
150 #[async_trait]
151 trait Test {
152     async fn test(not_okay: Elided, okay: &usize) {}
156 ```console
157 error[E0726]: implicit elided lifetime not allowed here
158  --> src/main.rs:9:29
159   |
160 9 |     async fn test(not_okay: Elided, okay: &usize) {}
161   |                             ^^^^^^- help: indicate the anonymous lifetime: `<'_>`
164 The fix is to name the lifetime or use `'_`.
166 ```rust
167 #[async_trait]
168 trait Test {
169     // either
170     async fn test<'e>(elided: Elided<'e>) {}
171     // or
172     async fn test(elided: Elided<'_>) {}
176 <br>
178 ## Dyn traits
180 Traits with async methods can be used as trait objects as long as they meet the
181 usual requirements for dyn -- no methods with type parameters, no self by value,
182 no associated types, etc.
184 ```rust
185 #[async_trait]
186 pub trait ObjectSafe {
187     async fn f(&self);
188     async fn g(&mut self);
191 impl ObjectSafe for MyType {...}
193 let value: MyType = ...;
194 let object = &value as &dyn ObjectSafe;  // make trait object
197 The one wrinkle is in traits that provide default implementations of async
198 methods. In order for the default implementation to produce a future that is
199 Send, the async\_trait macro must emit a bound of `Self: Sync` on trait methods
200 that take `&self` and a bound `Self: Send` on trait methods that take `&mut
201 self`. An example of the former is visible in the expanded code in the
202 explanation section above.
204 If you make a trait with async methods that have default implementations,
205 everything will work except that the trait cannot be used as a trait object.
206 Creating a value of type `&dyn Trait` will produce an error that looks like
207 this:
209 ```console
210 error: the trait `Test` cannot be made into an object
211  --> src/main.rs:8:5
212   |
213 8 |     async fn cannot_dyn(&self) {}
214   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
217 For traits that need to be object safe and need to have default implementations
218 for some async methods, there are two resolutions. Either you can add Send
219 and/or Sync as supertraits (Send if there are `&mut self` methods with default
220 implementations, Sync if there are `&self` methods with default implementations)
221 to constrain all implementors of the trait such that the default implementations
222 are applicable to them:
224 ```rust
225 #[async_trait]
226 pub trait ObjectSafe: Sync {  // added supertrait
227     async fn can_dyn(&self) {}
230 let object = &value as &dyn ObjectSafe;
233 or you can strike the problematic methods from your trait object by bounding
234 them with `Self: Sized`:
236 ```rust
237 #[async_trait]
238 pub trait ObjectSafe {
239     async fn cannot_dyn(&self) where Self: Sized {}
241     // presumably other methods
244 let object = &value as &dyn ObjectSafe;
247 <br>
249 #### License
251 <sup>
252 Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
253 2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option.
254 </sup>
256 <br>
258 <sub>
259 Unless you explicitly state otherwise, any contribution intentionally submitted
260 for inclusion in this crate by you, as defined in the Apache-2.0 license, shall
261 be dual licensed as above, without any additional terms or conditions.
262 </sub>