|
213 | 213 | //! async fn test(elided: Elided<'_>) {} |
214 | 214 | //! } |
215 | 215 | //! ``` |
216 | | -//! |
217 | | -//! <br><br> |
218 | | -//! |
219 | | -//! # Dyn traits |
220 | | -//! |
221 | | -//! Traits with async methods can be used as trait objects as long as they meet |
222 | | -//! the usual requirements for dyn -- no methods with type parameters, no self |
223 | | -//! by value, no associated types, etc. |
224 | | -//! |
225 | | -//! ``` |
226 | | -//! # use async_trait::async_trait; |
227 | | -//! # |
228 | | -//! #[async_trait] |
229 | | -//! pub trait ObjectSafe { |
230 | | -//! async fn f(&self); |
231 | | -//! async fn g(&mut self); |
232 | | -//! } |
233 | | -//! |
234 | | -//! # const IGNORE: &str = stringify! { |
235 | | -//! impl ObjectSafe for MyType {...} |
236 | | -//! |
237 | | -//! let value: MyType = ...; |
238 | | -//! # }; |
239 | | -//! # |
240 | | -//! # struct MyType; |
241 | | -//! # |
242 | | -//! # #[async_trait] |
243 | | -//! # impl ObjectSafe for MyType { |
244 | | -//! # async fn f(&self) {} |
245 | | -//! # async fn g(&mut self) {} |
246 | | -//! # } |
247 | | -//! # |
248 | | -//! # let value: MyType = MyType; |
249 | | -//! let object = &value as &dyn ObjectSafe; // make trait object |
250 | | -//! ``` |
251 | | -//! |
252 | | -//! The one wrinkle is in traits that provide default implementations of async |
253 | | -//! methods. In order for the default implementation to produce a future that is |
254 | | -//! Send, the async_trait macro must emit a bound of `Self: Sync` on trait |
255 | | -//! methods that take `&self` and a bound `Self: Send` on trait methods that |
256 | | -//! take `&mut self`. An example of the former is visible in the expanded code |
257 | | -//! in the explanation section above. |
258 | | -//! |
259 | | -//! If you make a trait with async methods that have default implementations, |
260 | | -//! everything will work except that the trait cannot be used as a trait object. |
261 | | -//! Creating a value of type `&dyn Trait` will produce an error that looks like |
262 | | -//! this: |
263 | | -//! |
264 | | -//! ```text |
265 | | -//! error: the trait `Test` cannot be made into an object |
266 | | -//! --> src/main.rs:8:5 |
267 | | -//! | |
268 | | -//! 8 | async fn cannot_dyn(&self) {} |
269 | | -//! | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
270 | | -//! ``` |
271 | | -//! |
272 | | -//! For traits that need to be object safe and need to have default |
273 | | -//! implementations for some async methods, there are two resolutions. Either |
274 | | -//! you can add Send and/or Sync as supertraits (Send if there are `&mut self` |
275 | | -//! methods with default implementations, Sync if there are `&self` methods with |
276 | | -//! default implementations) to constrain all implementors of the trait such that |
277 | | -//! the default implementations are applicable to them: |
278 | | -//! |
279 | | -//! ``` |
280 | | -//! # use async_trait::async_trait; |
281 | | -//! # |
282 | | -//! #[async_trait] |
283 | | -//! pub trait ObjectSafe: Sync { // added supertrait |
284 | | -//! async fn can_dyn(&self) {} |
285 | | -//! } |
286 | | -//! # |
287 | | -//! # struct MyType; |
288 | | -//! # |
289 | | -//! # #[async_trait] |
290 | | -//! # impl ObjectSafe for MyType {} |
291 | | -//! # |
292 | | -//! # let value = MyType; |
293 | | -//! |
294 | | -//! let object = &value as &dyn ObjectSafe; |
295 | | -//! ``` |
296 | | -//! |
297 | | -//! or you can strike the problematic methods from your trait object by |
298 | | -//! bounding them with `Self: Sized`: |
299 | | -//! |
300 | | -//! ``` |
301 | | -//! # use async_trait::async_trait; |
302 | | -//! # |
303 | | -//! #[async_trait] |
304 | | -//! pub trait ObjectSafe { |
305 | | -//! async fn cannot_dyn(&self) where Self: Sized {} |
306 | | -//! |
307 | | -//! // presumably other methods |
308 | | -//! } |
309 | | -//! # |
310 | | -//! # struct MyType; |
311 | | -//! # |
312 | | -//! # #[async_trait] |
313 | | -//! # impl ObjectSafe for MyType {} |
314 | | -//! # |
315 | | -//! # let value = MyType; |
316 | | -//! |
317 | | -//! let object = &value as &dyn ObjectSafe; |
318 | | -//! ``` |
319 | 216 |
|
320 | 217 | #![doc(html_root_url = "https://docs.rs/async-trait/0.1.85")] |
321 | 218 | #![allow( |
|
0 commit comments