Skip to content

Commit

Permalink
Delete section on dyn compatibility of default implementations
Browse files Browse the repository at this point in the history
  • Loading branch information
dtolnay committed Feb 1, 2025
1 parent ec9665a commit eb69fb3
Show file tree
Hide file tree
Showing 2 changed files with 0 additions and 174 deletions.
71 changes: 0 additions & 71 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,77 +189,6 @@ trait Test {

<br>

## 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;
```

<br>

#### License

<sup>
Expand Down
103 changes: 0 additions & 103 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,109 +213,6 @@
//! async fn test(elided: Elided<'_>) {}
//! }
//! ```
//!
//! <br><br>
//!
//! # 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(
Expand Down

0 comments on commit eb69fb3

Please sign in to comment.