From eb69fb324fbe5bc734ead79cb3ea1c6e509dc3a9 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 31 Jan 2025 18:35:35 -0800 Subject: [PATCH] Delete section on dyn compatibility of default implementations --- README.md | 71 ------------------------------------ src/lib.rs | 103 ----------------------------------------------------- 2 files changed, 174 deletions(-) diff --git a/README.md b/README.md index 367787e..3e3f804 100644 --- a/README.md +++ b/README.md @@ -189,77 +189,6 @@ trait Test {
-## Dyn traits - -Traits with async methods can be used as trait objects as long as they meet the -usual requirements for dyn -- no methods with type parameters, no self by value, -no associated types, etc. - -```rust -#[async_trait] -pub trait ObjectSafe { - async fn f(&self); - async fn g(&mut self); -} - -impl ObjectSafe for MyType {...} - -let value: MyType = ...; -let object = &value as &dyn ObjectSafe; // make trait object -``` - -The one wrinkle is in traits that provide default implementations of async -methods. In order for the default implementation to produce a future that is -Send, the async\_trait macro must emit a bound of `Self: Sync` on trait methods -that take `&self` and a bound `Self: Send` on trait methods that take `&mut -self`. An example of the former is visible in the expanded code in the -explanation section above. - -If you make a trait with async methods that have default implementations, -everything will work except that the trait cannot be used as a trait object. -Creating a value of type `&dyn Trait` will produce an error that looks like -this: - -```console -error: the trait `Test` cannot be made into an object - --> src/main.rs:8:5 - | -8 | async fn cannot_dyn(&self) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -``` - -For traits that need to be object safe and need to have default implementations -for some async methods, there are two resolutions. Either you can add Send -and/or Sync as supertraits (Send if there are `&mut self` methods with default -implementations, Sync if there are `&self` methods with default implementations) -to constrain all implementors of the trait such that the default implementations -are applicable to them: - -```rust -#[async_trait] -pub trait ObjectSafe: Sync { // added supertrait - async fn can_dyn(&self) {} -} - -let object = &value as &dyn ObjectSafe; -``` - -or you can strike the problematic methods from your trait object by bounding -them with `Self: Sized`: - -```rust -#[async_trait] -pub trait ObjectSafe { - async fn cannot_dyn(&self) where Self: Sized {} - - // presumably other methods -} - -let object = &value as &dyn ObjectSafe; -``` - -
- #### License diff --git a/src/lib.rs b/src/lib.rs index 2c09bc9..959bbf8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -213,109 +213,6 @@ //! async fn test(elided: Elided<'_>) {} //! } //! ``` -//! -//!

-//! -//! # Dyn traits -//! -//! Traits with async methods can be used as trait objects as long as they meet -//! the usual requirements for dyn -- no methods with type parameters, no self -//! by value, no associated types, etc. -//! -//! ``` -//! # use async_trait::async_trait; -//! # -//! #[async_trait] -//! pub trait ObjectSafe { -//! async fn f(&self); -//! async fn g(&mut self); -//! } -//! -//! # const IGNORE: &str = stringify! { -//! impl ObjectSafe for MyType {...} -//! -//! let value: MyType = ...; -//! # }; -//! # -//! # struct MyType; -//! # -//! # #[async_trait] -//! # impl ObjectSafe for MyType { -//! # async fn f(&self) {} -//! # async fn g(&mut self) {} -//! # } -//! # -//! # let value: MyType = MyType; -//! let object = &value as &dyn ObjectSafe; // make trait object -//! ``` -//! -//! The one wrinkle is in traits that provide default implementations of async -//! methods. In order for the default implementation to produce a future that is -//! Send, the async_trait macro must emit a bound of `Self: Sync` on trait -//! methods that take `&self` and a bound `Self: Send` on trait methods that -//! take `&mut self`. An example of the former is visible in the expanded code -//! in the explanation section above. -//! -//! If you make a trait with async methods that have default implementations, -//! everything will work except that the trait cannot be used as a trait object. -//! Creating a value of type `&dyn Trait` will produce an error that looks like -//! this: -//! -//! ```text -//! error: the trait `Test` cannot be made into an object -//! --> src/main.rs:8:5 -//! | -//! 8 | async fn cannot_dyn(&self) {} -//! | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//! ``` -//! -//! For traits that need to be object safe and need to have default -//! implementations for some async methods, there are two resolutions. Either -//! you can add Send and/or Sync as supertraits (Send if there are `&mut self` -//! methods with default implementations, Sync if there are `&self` methods with -//! default implementations) to constrain all implementors of the trait such that -//! the default implementations are applicable to them: -//! -//! ``` -//! # use async_trait::async_trait; -//! # -//! #[async_trait] -//! pub trait ObjectSafe: Sync { // added supertrait -//! async fn can_dyn(&self) {} -//! } -//! # -//! # struct MyType; -//! # -//! # #[async_trait] -//! # impl ObjectSafe for MyType {} -//! # -//! # let value = MyType; -//! -//! let object = &value as &dyn ObjectSafe; -//! ``` -//! -//! or you can strike the problematic methods from your trait object by -//! bounding them with `Self: Sized`: -//! -//! ``` -//! # use async_trait::async_trait; -//! # -//! #[async_trait] -//! pub trait ObjectSafe { -//! async fn cannot_dyn(&self) where Self: Sized {} -//! -//! // presumably other methods -//! } -//! # -//! # struct MyType; -//! # -//! # #[async_trait] -//! # impl ObjectSafe for MyType {} -//! # -//! # let value = MyType; -//! -//! let object = &value as &dyn ObjectSafe; -//! ``` #![doc(html_root_url = "https://docs.rs/async-trait/0.1.85")] #![allow(