pub static ASYNC_FN_IN_TRAIT: &Lint
Expand description

The async_fn_in_trait lint detects use of async fn in the definition of a publicly-reachable trait.

Example

pub trait Trait {
    async fn method(&self);
}

{{produces}}

Explanation

When async fn is used in a trait definition, the trait does not promise that the opaque Future returned by the associated function or method will implement any auto traits such as Send. This may be surprising and may make the associated functions or methods on the trait less useful than intended. On traits exposed publicly from a crate, this may affect downstream crates whose authors cannot alter the trait definition.

For example, this code is invalid:

pub trait Trait {
    async fn method(&self) {}
}

fn test<T: Trait>(x: T) {
    fn spawn<T: Send>(_: T) {}
    spawn(x.method()); // Not OK.
}

This lint exists to warn authors of publicly-reachable traits that they may want to consider desugaring the async fn to a normal fn that returns an opaque impl Future<..> + Send type.

For example, instead of:

pub trait Trait {
    async fn method(&self) {}
}

The author of the trait may want to write:

use core::future::Future;
pub trait Trait {
    fn method(&self) -> impl Future<Output = ()> + Send { async {} }
}

This still allows the use of async fn within impls of the trait. However, it also means that the trait will never be compatible with impls where the returned Future of the method does not implement Send.

Conversely, if the trait is used only locally, if it is never used in generic functions, or if it is only used in single-threaded contexts that do not care whether the returned Future implements Send, then the lint may be suppressed.