#![cfg_attr(
async_trait_nightly_testing,
feature(associated_type_bounds, min_specialization, type_alias_impl_trait,)
)]
#![deny(rust_2021_compatibility)]
#![allow(
clippy::let_unit_value,
clippy::missing_panics_doc,
clippy::missing_safety_doc,
clippy::needless_return,
clippy::trivially_copy_pass_by_ref,
clippy::unused_async
)]
use async_trait_fn::async_trait;
pub mod executor;
mod core {}
#[async_trait]
trait Trait {
type Assoc;
async fn selfvalue(self)
where
Self: Sized,
{
}
async fn selfref(&self) {}
async fn selfmut(&mut self) {}
async fn required() -> Self::Assoc;
async fn elided_lifetime(_x: &str) {}
async fn explicit_lifetime<'a>(_x: &'a str) {}
async fn generic_type_param<T: Send>(x: Box<T>) -> T {
*x
}
async fn calls(&self) {
self.selfref().await;
Self::elided_lifetime("").await;
<Self>::elided_lifetime("").await;
}
async fn calls_mut(&mut self) {
self.selfmut().await;
}
}
struct Struct;
#[async_trait]
impl Trait for Struct {
type Assoc = ();
async fn selfvalue(self) {}
async fn selfref(&self) {}
async fn selfmut(&mut self) {}
async fn required() -> Self::Assoc {}
async fn elided_lifetime(_x: &str) {}
async fn explicit_lifetime<'a>(_x: &'a str) {}
async fn generic_type_param<T: Send>(x: Box<T>) -> T {
*x
}
async fn calls(&self) {
self.selfref().await;
Self::elided_lifetime("").await;
<Self>::elided_lifetime("").await;
}
async fn calls_mut(&mut self) {
self.selfmut().await;
}
}
pub async fn test() {
let mut s = Struct;
s.selfref().await;
s.selfmut().await;
s.selfvalue().await;
Struct::required().await;
Struct::elided_lifetime("").await;
Struct::explicit_lifetime("").await;
Struct::generic_type_param(Box::new("")).await;
let mut s = Struct;
s.calls().await;
s.calls_mut().await;
}
pub async fn test_object_safe_without_default() {
#[async_trait]
trait ObjectSafe {
async fn f(&self);
}
#[async_trait]
impl ObjectSafe for Struct {
async fn f(&self) {}
}
let object = &Struct as &dyn ObjectSafe;
object.f().await;
}
pub async fn test_object_safe_with_default() {
#[async_trait]
trait ObjectSafe: Sync {
async fn f(&self) {}
}
#[async_trait]
impl ObjectSafe for Struct {
async fn f(&self) {}
}
let object = &Struct as &dyn ObjectSafe;
object.f().await;
}
pub async fn test_object_no_send() {
#[async_trait(?Send)]
trait ObjectSafe: Sync {
async fn f(&self) {}
}
#[async_trait(?Send)]
impl ObjectSafe for Struct {
async fn f(&self) {}
}
let object = &Struct as &dyn ObjectSafe;
object.f().await;
}
#[async_trait]
pub unsafe trait UnsafeTrait {}
#[async_trait]
unsafe impl UnsafeTrait for () {}
#[async_trait]
pub(crate) unsafe trait UnsafeTraitPubCrate {}
#[async_trait]
unsafe trait UnsafeTraitPrivate {}
pub async fn test_can_destruct() {
#[async_trait]
trait CanDestruct {
async fn f(&self, foos: (u8, u8, u8, u8));
}
#[async_trait]
impl CanDestruct for Struct {
async fn f(&self, (a, ref mut b, ref c, d): (u8, u8, u8, u8)) {
let _a: u8 = a;
let _b: &mut u8 = b;
let _c: &u8 = c;
let _d: u8 = d;
}
}
}
pub async fn test_self_in_macro() {
#[async_trait]
trait Trait {
async fn a(self);
async fn b(&mut self);
async fn c(&self);
}
#[async_trait]
impl Trait for String {
async fn a(self) {
println!("{}", self);
}
async fn b(&mut self) {
println!("{}", self);
}
async fn c(&self) {
println!("{}", self);
}
}
}
pub async fn test_inference() {
#[async_trait]
pub trait Trait {
async fn f() -> Box<dyn Iterator<Item = ()>> {
Box::new(std::iter::empty())
}
}
}
pub async fn test_internal_items() {
#[async_trait]
#[allow(dead_code, clippy::items_after_statements)]
pub trait Trait: Sized {
async fn f(self) {
struct Struct;
impl Struct {
fn f(self) {
let _ = self;
}
}
}
}
}
pub async fn test_unimplemented() {
#[async_trait]
pub trait Trait {
async fn f() {
unimplemented!()
}
}
}
#[cfg(async_trait_nightly_testing)]
pub mod unboxed {
use std::usize;
use crate::executor;
use async_trait_fn::{async_trait, unboxed};
#[derive(Default)]
pub struct F(usize);
#[derive(Default)]
pub struct O(usize);
#[async_trait]
pub trait FastAsyncTrait {
#[unboxed]
async fn add_u8(&self, u: u8) -> usize;
async fn add_u8_1_wrap(&self) -> usize;
#[unboxed]
async fn add_usize_mut<'u>(&self, u: &'u mut usize) -> (&'u mut usize, usize);
#[unboxed]
async fn sum_array(&self, u: &[u8]) -> usize;
#[unboxed]
async fn get_len(&mut self, s: &str) -> usize;
#[unboxed]
async fn sum_len(&mut self, s1: &str, s2: &str) -> usize;
#[unboxed]
async fn get_usize_ref<'s>(&'s self) -> &'s usize;
#[unboxed]
async fn clone_ret_pair<T: Clone + Copy + Send>(&self, t: T) -> (usize, T);
#[unboxed]
async fn reset_t_mut<'t, T: Default + Send + Sync>(&self, t: &'t mut T) -> &'t mut T;
#[unboxed]
async fn no_self<'t, 'y, T: Default + Send + Sync, Y: Clone + Sync>(
t_mut: &'t mut T,
y_ref: &'y Y,
) -> (&'t T, &'y Y);
}
#[async_trait]
impl FastAsyncTrait for F {
#[unboxed]
async fn add_u8(&self, u: u8) -> usize {
self.0 + (u as usize)
}
async fn add_u8_1_wrap(&self) -> usize {
self.add_u8(1).await
}
#[unboxed]
async fn add_usize_mut<'u>(&self, u: &'u mut usize) -> (&'u mut usize, usize) {
(*u) += self.0;
(u, self.0)
}
#[unboxed]
async fn sum_array(&self, u: &[u8]) -> usize {
u.iter().sum::<u8>() as usize
}
#[unboxed]
async fn get_len(&mut self, s: &str) -> usize {
self.0 = s.len();
self.0
}
#[unboxed]
async fn sum_len(&mut self, s1: &str, s2: &str) -> usize {
let len1 = self.get_len(s1).await;
let len2 = self.get_len(s2).await;
self.0 = len1 + len2;
self.0
}
#[unboxed]
async fn get_usize_ref<'s>(&'s self) -> &'s usize {
&self.0
}
#[unboxed]
async fn clone_ret_pair<T: Clone + Copy + Send>(&self, t: T) -> (usize, T) {
(self.0, t)
}
#[unboxed]
async fn reset_t_mut<'t, T: Default + Send + Sync>(&self, t: &'t mut T) -> &'t mut T {
*t = T::default();
t
}
#[unboxed]
async fn no_self<'t, 'y, T: Default + Send + Sync, Y: Clone + Sync>(
t_mut: &'t mut T,
y_ref: &'y Y,
) -> (&'t T, &'y Y) {
*t_mut = T::default();
(t_mut, y_ref)
}
}
impl F {
async fn add_u8_one(&self) -> usize {
self.add_u8(1).await
}
}
#[async_trait]
pub trait ChildTrait {
async fn add_u8_ref(&self, f: &F, u: &u8) -> usize;
}
#[async_trait]
impl ChildTrait for O {
async fn add_u8_ref(&self, f: &F, u: &u8) -> usize {
F(f.0 + self.0).add_u8(*u).await
}
}
fn run<R, F: std::future::Future<Output = R> + Send>(f: F) -> R {
executor::block_on_simple(f)
}
#[test]
fn test_simple() {
let u_small: u8 = 17;
let mut u_big: usize = 19;
let mut u_reset: usize = 23;
let u_array = [1_u8, 2_u8, 1_u8, 3_u8];
let (str1, str2) = ("Hello".to_owned(), "Hi".to_owned());
let mut i_reset: isize = 29;
let i_med: i8 = 31;
let mut f_0 = F(0);
let fut_sum_len = f_0.sum_len(&str1, &str2);
let fut_add_u8 = F(1).add_u8(u_small);
let fut_add_usize_mut = F(2).add_usize_mut(&mut u_big);
let fut_sum_array = F(3).sum_array(&u_array);
let fut_get_usize_ref = F(4).get_usize_ref();
let fut_ret_pair = F(5).clone_ret_pair(2_usize);
let fut_reset_t_mut = F(6).reset_t_mut(&mut u_reset);
let fut_no_self = F::no_self(&mut i_reset, &i_med);
assert_eq!(run(fut_sum_len), 7);
assert_eq!(run(fut_add_u8), (u_small + 1) as usize);
assert_eq!(run(fut_add_usize_mut), (&mut 21, 2));
assert_eq!(run(fut_sum_array), 7);
assert_eq!(*run(fut_get_usize_ref), 4);
assert_eq!(run(fut_ret_pair), (5, 2));
assert_eq!(*run(fut_reset_t_mut), 0);
assert_eq!(u_reset, 0);
assert_eq!(run(fut_no_self), (&0, &31));
}
#[test]
fn test_scoped() {
let mut hoo: String = "hoo".into();
{
let mut f = F(7);
let new_f = {
let mut hi: String = "hi".into();
let fut_reset_t_mut_1 = f.reset_t_mut(&mut hi);
let len1 = executor::block_on_simple(fut_reset_t_mut_1).len();
let fut_reset_t_mut_2 = f.reset_t_mut(&mut hoo);
let len2 = executor::block_on_simple(fut_reset_t_mut_2).len();
len1 + len2
};
f.0 = new_f;
assert_eq!(f.0, 0);
}
}
#[test]
fn test_indirect() {
let u = 17_u8;
let f = F(10);
let fut_u8_ref = O(1).add_u8_ref(&f, &u);
assert_eq!(run(fut_u8_ref), (u + 11) as usize);
let fut_u8_one = F(1).add_u8_one();
assert_eq!(run(fut_u8_one), 2);
let fut_add_u8 = F(2).add_u8_1_wrap();
assert_eq!(run(fut_add_u8), 3);
}
}
#[cfg(async_trait_nightly_testing)]
pub mod unboxed_dep {
use crate::executor;
use async_trait_fn::{async_trait, unboxed};
#[async_trait]
pub trait AsyncIter {
#[unboxed]
async fn next(&mut self) -> Option<usize>;
}
struct A(usize);
#[async_trait]
impl AsyncIter for A {
#[unboxed]
async fn next(&mut self) -> Option<usize> {
if self.0 > 0 {
self.0 -= 1;
Some(self.0)
} else {
None
}
}
}
pub trait Trigger {
type Iter<'i>: AsyncIter + 'i
where
Self: 'i;
fn begin(&mut self) -> Self::Iter<'_>;
}
struct T(usize);
impl Trigger for T {
type Iter<'i> = A;
fn begin(&mut self) -> Self::Iter<'_> {
A(self.0)
}
}
#[async_trait]
pub trait Owner {
type Boom: Trigger;
async fn go(&mut self) -> Self::Boom;
}
struct O(usize);
#[async_trait]
impl Owner for O {
type Boom = T;
async fn go(&mut self) -> Self::Boom {
T(self.0)
}
}
struct W(O);
impl W {
async fn test(&mut self) -> Option<usize> {
let mut b = self.0.go().await;
let mut a = b.begin();
a.next().await
}
}
fn run<R, F: std::future::Future<Output = R> + Send>(f: F) -> R {
executor::block_on_simple(f)
}
#[test]
fn test() {
let mut w: W = W(O(1));
assert_eq!(run(w.test()), Some(0));
}
}
#[cfg(async_trait_nightly_testing)]
pub mod unboxed_pinned {
use crate::executor;
use async_trait_fn::{async_trait, unboxed};
struct F(*const usize, std::marker::PhantomPinned);
unsafe impl Send for F {}
unsafe impl Sync for F {}
pub struct G(*const usize, std::marker::PhantomPinned);
unsafe impl Send for G {}
unsafe impl Sync for G {}
#[async_trait]
pub trait FastAsyncTrait {
#[unboxed]
async fn get_ref<'s>(&'s self, g: G) -> (&'s usize, usize);
}
#[async_trait]
impl FastAsyncTrait for F {
#[unboxed]
async fn get_ref<'s>(&'s self, g: G) -> (&'s usize, usize) {
unsafe { (&*self.0, *g.0) }
}
}
#[async_trait]
pub trait AsyncTrait<F: FastAsyncTrait> {
async fn get(&self, f: F, g: &G) -> usize;
}
struct A;
#[async_trait]
impl AsyncTrait<F> for A {
async fn get(&self, f: F, g: &G) -> usize {
let g_copy = G(g.0, g.1);
*f.get_ref(g_copy).await.0
}
}
fn run<R, F: std::future::Future<Output = R> + Send>(f: F) -> R {
executor::block_on_simple(f)
}
#[test]
fn test() {
let u: usize = 37;
let f = F(&u as *const usize, std::marker::PhantomPinned);
let fut_get_ref = f.get_ref(G(&u as *const usize, std::marker::PhantomPinned));
assert_eq!(run(fut_get_ref), (&37, 37));
let g = G(&u as *const usize, std::marker::PhantomPinned);
let fut_get = A.get(f, &g);
assert_eq!(run(fut_get), 37);
}
}
#[cfg(async_trait_nightly_testing)]
pub mod unboxed_nosend {
use crate::executor;
use async_trait_fn::{async_trait, unboxed};
struct F(*mut usize);
#[async_trait(?Send)]
pub trait FastAsyncTrait {
#[unboxed]
async fn add<'s>(&'s mut self, a: usize);
}
#[async_trait(?Send)]
impl FastAsyncTrait for F {
#[unboxed]
async fn add<'s>(&'s mut self, a: usize) {
unsafe {
(*self.0) += a;
}
}
}
#[test]
fn test() {
let mut a: usize = 11;
let mut f = F(&mut a as *mut usize);
let fut_add = f.add(3);
executor::block_on_simple(fut_add);
assert_eq!(unsafe { *f.0 }, 14);
}
}
#[cfg(async_trait_nightly_testing)]
pub mod unboxed_simple {
use crate::executor;
use async_trait_fn::{async_trait, unboxed_simple};
use std::future::Future;
#[async_trait]
pub trait Get: Send + Sync {
#[unboxed_simple]
async fn get<'a>(&'a self) -> usize;
#[unboxed_simple]
async fn add(&self, v: usize) -> usize;
#[unboxed_simple]
async fn double(v: usize) -> usize;
}
#[async_trait]
impl Get for usize {
#[unboxed_simple]
async fn get<'a>(&'a self) -> usize {
*self
}
#[unboxed_simple]
async fn add(&self, v: usize) -> usize {
*self + v
}
#[unboxed_simple]
async fn double(v: usize) -> usize {
v * 2
}
}
fn run<R, F: Future<Output = R> + Send>(f: F) -> R {
executor::block_on_simple(f)
}
fn is_send<R, F: Future<Output = R> + Send>(_f: &F) -> bool {
true
}
async fn wrap<G: Get>(g: &G) -> usize {
let fut_get = g.get();
assert!(is_send(&fut_get));
let fut_add = g.add(0);
assert!(is_send(&fut_add));
assert_eq!(fut_add.await, g.get().await);
let fut_double = G::double(1);
assert!(is_send(&fut_double));
assert_eq!(fut_double.await, 2);
fut_get.await
}
async fn wrap_wrap<G: Get>(g: &G) -> usize {
let fut = wrap(g);
fut.await
}
#[test]
fn test() {
assert_eq!(executor::block_on_simple(2.get()), 2);
let x: usize = 2;
assert_eq!(run(wrap(&x)), 2);
assert_eq!(run(wrap_wrap(&x)), 2);
}
}
pub mod issue1 {
use async_trait_fn::async_trait;
#[async_trait]
trait Issue1 {
async fn f<U>(&self);
}
#[async_trait]
impl<T: Sync> Issue1 for Vec<T> {
async fn f<U>(&self) {}
}
}
pub mod issue2 {
use async_trait_fn::async_trait;
use std::future::Future;
#[async_trait]
pub trait Issue2: Future {
async fn flatten(self) -> <Self::Output as Future>::Output
where
Self::Output: Future + Send,
Self: Sized,
{
let nested_future = self.await;
nested_future.await
}
}
}
pub mod issue9 {
use async_trait_fn::async_trait;
#[async_trait]
pub trait Issue9: Sized + Send {
async fn f(_x: Self) {}
}
}
pub mod issue11 {
use async_trait_fn::async_trait;
use std::sync::Arc;
#[async_trait]
trait Issue11 {
async fn example(self: Arc<Self>);
}
struct Struct;
#[async_trait]
impl Issue11 for Struct {
async fn example(self: Arc<Self>) {}
}
}
pub mod issue15 {
use async_trait_fn::async_trait;
use std::marker::PhantomData;
trait Trait {}
#[async_trait]
trait Issue15 {
async fn myfn(&self, _: PhantomData<dyn Trait + Send>) {}
}
}
pub mod issue17 {
use async_trait_fn::async_trait;
#[async_trait]
trait Issue17 {
async fn f(&self);
}
struct Struct {
string: String,
}
#[async_trait]
impl Issue17 for Struct {
async fn f(&self) {
println!("{}", self.string);
}
}
}
pub mod issue23 {
use async_trait_fn::async_trait;
#[async_trait]
pub trait Issue23 {
async fn f(self);
async fn g(mut self)
where
Self: Sized,
{
do_something(&mut self);
}
}
struct S {}
#[async_trait]
impl Issue23 for S {
async fn f(mut self) {
do_something(&mut self);
}
}
fn do_something<T>(_: &mut T) {}
}
#[cfg(async_trait_nightly_testing)]
pub mod issue25 {
use crate::executor;
use async_trait_fn::async_trait;
use std::fmt::{Display, Write};
#[async_trait]
trait AsyncToString {
async fn async_to_string(&self) -> String;
}
#[async_trait]
impl AsyncToString for String {
async fn async_to_string(&self) -> String {
"special".to_owned()
}
}
macro_rules! hide_from_stable_parser {
($($tt:tt)*) => {
$($tt)*
};
}
hide_from_stable_parser! {
#[async_trait]
impl<T: ?Sized + Display + Sync> AsyncToString for T {
default async fn async_to_string(&self) -> String {
let mut buf = String::new();
buf.write_fmt(format_args!("{}", self)).unwrap();
buf
}
}
}
#[test]
fn test() {
let fut = true.async_to_string();
assert_eq!(executor::block_on_simple(fut), "true");
let string = String::new();
let fut = string.async_to_string();
assert_eq!(executor::block_on_simple(fut), "special");
}
}
pub mod issue28 {
use async_trait_fn::async_trait;
struct Str<'a>(&'a str);
#[async_trait]
trait Trait1<'a> {
async fn f(x: Str<'a>) -> &'a str;
async fn g(x: Str<'a>) -> &'a str {
x.0
}
}
#[async_trait]
impl<'a> Trait1<'a> for str {
async fn f(x: Str<'a>) -> &'a str {
x.0
}
}
#[async_trait]
trait Trait2 {
async fn f();
}
#[async_trait]
impl<'a> Trait2 for &'a () {
async fn f() {}
}
#[async_trait]
trait Trait3<'a, 'b> {
async fn f(_: &'a &'b ()); async fn g(_: &'b ()); async fn h(); }
}
pub mod issue31 {
use async_trait_fn::async_trait;
pub struct Struct<'a> {
pub name: &'a str,
}
#[async_trait]
pub trait Trait<'a> {
async fn hello(thing: Struct<'a>) -> String;
async fn hello_twice(one: Struct<'a>, two: Struct<'a>) -> String {
let str1 = Self::hello(one).await;
let str2 = Self::hello(two).await;
str1 + &str2
}
}
}
pub mod issue42 {
use async_trait_fn::async_trait;
#[async_trait]
pub trait Context: Sized {
async fn from_parts() -> Self;
}
pub struct TokenContext;
#[async_trait]
impl Context for TokenContext {
async fn from_parts() -> TokenContext {
TokenContext
}
}
}
pub mod issue44 {
use async_trait_fn::async_trait;
#[async_trait]
pub trait StaticWithWhereSelf
where
Box<Self>: Sized,
Self: Sized + Send,
{
async fn get_one() -> u8 {
1
}
}
pub struct Struct;
#[async_trait]
impl StaticWithWhereSelf for Struct {}
}
pub mod issue45 {
use crate::executor;
use async_trait_fn::async_trait;
use std::fmt::Debug;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::{Arc, Mutex};
use tracing::event::Event;
use tracing::field::{Field, Visit};
use tracing::span::{Attributes, Id, Record};
use tracing::{info, instrument, subscriber, Metadata, Subscriber};
#[async_trait]
pub trait Parent {
async fn foo(&mut self, v: usize);
}
#[async_trait]
pub trait Child {
async fn bar(&self);
}
#[derive(Debug)]
struct Impl(usize);
#[async_trait]
impl Parent for Impl {
#[instrument]
async fn foo(&mut self, v: usize) {
self.0 = v;
self.bar().await;
}
}
#[async_trait]
impl Child for Impl {
#[instrument(skip(self))]
async fn bar(&self) {
info!(val = self.0);
}
}
#[derive(Debug)]
struct SubscriberInner {
current_depth: AtomicU64,
max_depth: AtomicU64,
max_span_id: AtomicU64,
value: Mutex<Option<(&'static str, u64, u64)>>,
}
#[derive(Debug, Clone)]
struct TestSubscriber {
inner: Arc<SubscriberInner>,
}
impl TestSubscriber {
fn new() -> Self {
TestSubscriber {
inner: Arc::new(SubscriberInner {
current_depth: AtomicU64::new(0),
max_depth: AtomicU64::new(0),
max_span_id: AtomicU64::new(1),
value: Mutex::new(None),
}),
}
}
}
struct U64Visitor(Option<(&'static str, u64)>);
impl Visit for U64Visitor {
fn record_debug(&mut self, _field: &Field, _value: &dyn Debug) {}
fn record_u64(&mut self, field: &Field, value: u64) {
self.0 = Some((field.name(), value));
}
}
impl Subscriber for TestSubscriber {
fn enabled(&self, _metadata: &Metadata) -> bool {
true
}
fn new_span(&self, _span: &Attributes) -> Id {
Id::from_u64(self.inner.max_span_id.fetch_add(1, Ordering::AcqRel))
}
fn record(&self, _span: &Id, _values: &Record) {}
fn record_follows_from(&self, _span: &Id, _follows: &Id) {}
fn event(&self, event: &Event) {
let mut visitor = U64Visitor(None);
event.record(&mut visitor);
if let Some((s, v)) = visitor.0 {
let current_depth = self.inner.current_depth.load(Ordering::Acquire);
*self.inner.value.lock().unwrap() = Some((s, v, current_depth));
}
}
fn enter(&self, _span: &Id) {
let old_depth = self.inner.current_depth.fetch_add(1, Ordering::AcqRel);
if old_depth + 1 > self.inner.max_depth.load(Ordering::Acquire) {
self.inner.max_depth.fetch_add(1, Ordering::AcqRel);
}
}
fn exit(&self, _span: &Id) {
self.inner.current_depth.fetch_sub(1, Ordering::AcqRel);
}
}
#[test]
#[cfg_attr(miri, ignore)] fn tracing() {
let mut struct_impl = Impl(0);
let fut = struct_impl.foo(5);
let subscriber = TestSubscriber::new();
subscriber::with_default(subscriber.clone(), || executor::block_on_simple(fut));
assert_eq!(subscriber.inner.max_depth.load(Ordering::Acquire), 2);
assert_eq!(subscriber.inner.current_depth.load(Ordering::Acquire), 0);
assert_eq!(subscriber.inner.max_span_id.load(Ordering::Acquire) - 1, 2);
assert_eq!(*subscriber.inner.value.lock().unwrap(), Some(("val", 5, 2)));
}
}
pub mod issue46 {
use async_trait_fn::async_trait;
macro_rules! implement_commands_workaround {
($tyargs:tt : $ty:tt) => {
#[async_trait]
pub trait AsyncCommands1: Sized {
async fn f<$tyargs: $ty>(&mut self, x: $tyargs) {
self.f(x).await
}
}
};
}
implement_commands_workaround!(K: Send);
macro_rules! implement_commands {
($tyargs:ident : $ty:ident) => {
#[async_trait]
pub trait AsyncCommands2: Sized {
async fn f<$tyargs: $ty>(&mut self, x: $tyargs) {
self.f(x).await
}
}
};
}
implement_commands!(K: Send);
}
pub mod issue53 {
use async_trait_fn::async_trait;
pub struct Unit;
pub struct Tuple(u8);
pub struct Struct {
pub x: u8,
}
#[async_trait]
pub trait Trait {
async fn method();
}
#[async_trait]
impl Trait for Unit {
async fn method() {
let _ = Self;
}
}
#[async_trait]
impl Trait for Tuple {
async fn method() {
let _ = Self(0);
}
}
#[async_trait]
impl Trait for Struct {
async fn method() {
let _ = Self { x: 0 };
}
}
#[async_trait]
impl Trait for std::marker::PhantomData<Struct> {
async fn method() {
let _ = Self;
}
}
}
#[cfg(async_trait_nightly_testing)]
pub mod issue57 {
use crate::executor;
use async_trait_fn::async_trait;
#[async_trait]
trait Trait {
async fn const_generic<T: Send, const C: usize>(_: [T; C]) {}
}
struct Struct;
#[async_trait]
impl Trait for Struct {
async fn const_generic<T: Send, const C: usize>(_: [T; C]) {}
}
#[test]
fn test() {
let fut = Struct::const_generic([0; 10]);
executor::block_on_simple(fut);
}
}
pub mod issue68 {
#[rustversion::since(1.40)] #[async_trait_fn::async_trait]
pub trait Example {
async fn method(&self) {
macro_rules! t {
() => {{
let _: &Self = self;
}};
}
t!();
}
}
}
pub mod issue73 {
use async_trait_fn::async_trait;
#[async_trait]
pub trait Example {
const ASSOCIATED: &'static str;
async fn associated(&self) {
println!("Associated:{}", Self::ASSOCIATED);
}
}
}
pub mod issue81 {
use async_trait_fn::async_trait;
#[async_trait]
pub trait Trait {
async fn handle(&self);
}
pub enum Enum {
Variant,
}
#[async_trait]
impl Trait for Enum {
async fn handle(&self) {
let Enum::Variant = self;
let Self::Variant = self;
}
}
}
pub mod issue83 {
#![allow(clippy::needless_arbitrary_self_type)]
use async_trait_fn::async_trait;
#[async_trait]
pub trait Trait {
async fn f(&self) {}
async fn g(self: &Self) {}
}
}
pub mod issue85 {
#![deny(non_snake_case)]
use async_trait_fn::async_trait;
#[async_trait]
pub trait Trait {
#[allow(non_snake_case)]
async fn camelCase();
}
pub struct Struct;
#[async_trait]
impl Trait for Struct {
async fn camelCase() {}
}
}
pub mod issue87 {
use async_trait_fn::async_trait;
#[async_trait]
pub trait Trait {
async fn f(&self);
}
pub enum Tuple {
V(),
}
pub enum Struct {
V {},
}
#[async_trait]
impl Trait for Tuple {
async fn f(&self) {
let Tuple::V() = self;
let Self::V() = self;
let _ = Self::V;
let _ = Self::V();
}
}
#[async_trait]
impl Trait for Struct {
async fn f(&self) {
let Struct::V {} = self;
let Self::V {} = self;
let _ = Self::V {};
}
}
}
pub mod issue89 {
#![allow(bare_trait_objects)]
use async_trait_fn::async_trait;
#[async_trait]
trait Trait {
async fn f(&self);
}
#[async_trait]
impl Trait for Send + Sync {
async fn f(&self) {}
}
#[async_trait]
impl Trait for dyn Fn(i8) + Send + Sync {
async fn f(&self) {}
}
#[async_trait]
impl Trait for (dyn Fn(u8) + Send + Sync) {
async fn f(&self) {}
}
}
pub mod issue92 {
use async_trait_fn::async_trait;
macro_rules! mac {
($($tt:tt)*) => {
$($tt)*
};
}
pub struct Struct<T> {
_x: T,
}
impl<T> Struct<T> {
const ASSOCIATED1: &'static str = "1";
async fn associated1() {}
}
#[async_trait]
pub trait Trait
where
mac!(Self): Send,
{
const ASSOCIATED2: &'static str;
type Associated2;
#[allow(path_statements, clippy::let_underscore_future, clippy::no_effect)]
async fn associated2(&self) {
mac!(let _: Self::Associated2;);
mac!(let _: <Self>::Associated2;);
mac!(let _: <Self as Trait>::Associated2;);
mac!(Self::ASSOCIATED2;);
mac!(<Self>::ASSOCIATED2;);
mac!(<Self as Trait>::ASSOCIATED2;);
mac!(let _ = Self::associated2(self););
mac!(let _ = <Self>::associated2(self););
mac!(let _ = <Self as Trait>::associated2(self););
}
}
#[async_trait]
impl<T: Send + Sync> Trait for Struct<T>
where
mac!(Self): Send,
{
const ASSOCIATED2: &'static str = "2";
type Associated2 = ();
#[allow(path_statements, clippy::let_underscore_future, clippy::no_effect)]
async fn associated2(&self) {
mac!(Self::ASSOCIATED1;);
mac!(<Self>::ASSOCIATED1;);
mac!(let _ = Self::associated1(););
mac!(let _ = <Self>::associated1(););
mac!(let _: <Self as Trait>::Associated2;);
mac!(Self::ASSOCIATED2;);
mac!(<Self>::ASSOCIATED2;);
mac!(<Self as Trait>::ASSOCIATED2;);
mac!(let _ = Self::associated2(self););
mac!(let _ = <Self>::associated2(self););
mac!(let _ = <Self as Trait>::associated2(self););
}
}
pub struct Unit;
#[async_trait]
impl Trait for Unit {
const ASSOCIATED2: &'static str = "2";
type Associated2 = ();
async fn associated2(&self) {
mac!(let Self: Self = *self;);
}
}
}
pub mod issue92_2 {
use async_trait_fn::async_trait;
macro_rules! mac {
($($tt:tt)*) => {
$($tt)*
};
}
pub trait Trait1 {
fn func1();
}
#[async_trait]
pub trait Trait2: Trait1 {
async fn func2() {
mac!(Self::func1());
macro_rules! mac2 {
($($tt:tt)*) => {
Self::func1();
};
}
mac2!();
}
}
}
pub mod issue104 {
use async_trait_fn::async_trait;
#[async_trait]
trait T1 {
async fn id(&self) -> i32;
}
macro_rules! impl_t1 {
($ty:ty, $id:expr) => {
#[async_trait]
impl T1 for $ty {
async fn id(&self) -> i32 {
$id
}
}
};
}
struct Foo;
impl_t1!(Foo, 1);
}
pub mod issue106 {
use async_trait_fn::async_trait;
use std::future::Future;
#[async_trait]
pub trait ProcessPool: Send + Sync {
type ThreadPool;
async fn spawn<F, Fut, T>(&self, work: F) -> T
where
F: FnOnce(&Self::ThreadPool) -> Fut + Send,
Fut: Future<Output = T> + 'static;
}
#[async_trait]
impl<P> ProcessPool for &P
where
P: ?Sized + ProcessPool,
{
type ThreadPool = P::ThreadPool;
async fn spawn<F, Fut, T>(&self, work: F) -> T
where
F: FnOnce(&Self::ThreadPool) -> Fut + Send,
Fut: Future<Output = T> + 'static,
{
(**self).spawn(work).await
}
}
}
pub mod issue110 {
use async_trait_fn::async_trait;
use std::marker::PhantomData;
#[async_trait]
pub trait Loader {
async fn load(&self, key: &str);
}
pub struct AwsEc2MetadataLoader<'a> {
marker: PhantomData<&'a ()>,
}
#[async_trait]
impl Loader for AwsEc2MetadataLoader<'_> {
async fn load(&self, _key: &str) {}
}
}
pub mod issue120 {
#![deny(clippy::trivially_copy_pass_by_ref)]
use async_trait_fn::async_trait;
#[async_trait]
trait Trait {
async fn f(&self);
}
#[async_trait]
impl Trait for () {
async fn f(&self) {}
}
}
pub mod issue123 {
use async_trait_fn::async_trait;
#[async_trait]
trait Trait<T = ()> {
async fn f(&self) -> &str
where
T: 'async_trait,
{
"default"
}
}
#[async_trait]
impl<T> Trait<T> for () {}
}
pub mod issue129 {
use async_trait_fn::async_trait;
#[async_trait]
pub trait TestTrait {
async fn a(_b: u8, c: u8) -> u8 {
c
}
}
pub struct TestStruct;
#[async_trait]
impl TestTrait for TestStruct {
async fn a(_b: u8, c: u8) -> u8 {
c
}
}
}
#[cfg(async_trait_nightly_testing)]
pub mod issue134 {
use async_trait_fn::async_trait;
#[async_trait]
trait TestTrait {
async fn run<const DUMMY: bool>(self)
where
Self: Sized,
{
}
}
pub struct TestStruct;
#[async_trait]
impl TestTrait for TestStruct {
async fn run<const DUMMY: bool>(self)
where
Self: Sized,
{
}
}
}
pub mod drop_order {
use crate::executor;
use async_trait_fn::async_trait;
use std::sync::atomic::{AtomicBool, Ordering};
struct Flagger<'a>(&'a AtomicBool);
impl Drop for Flagger<'_> {
fn drop(&mut self) {
self.0.fetch_xor(true, Ordering::AcqRel);
}
}
#[async_trait]
trait Trait {
async fn async_trait(_: Flagger<'_>, flag: &AtomicBool);
}
struct Struct;
#[async_trait]
impl Trait for Struct {
async fn async_trait(_: Flagger<'_>, flag: &AtomicBool) {
flag.fetch_or(true, Ordering::AcqRel);
}
}
async fn standalone(_: Flagger<'_>, flag: &AtomicBool) {
flag.fetch_or(true, Ordering::AcqRel);
}
#[async_trait]
trait SelfTrait {
async fn async_trait(self, flag: &AtomicBool);
}
#[async_trait]
impl SelfTrait for Flagger<'_> {
async fn async_trait(self, flag: &AtomicBool) {
flag.fetch_or(true, Ordering::AcqRel);
}
}
#[test]
fn test_drop_order() {
let flag = AtomicBool::new(false);
executor::block_on_simple(standalone(Flagger(&flag), &flag));
assert!(!flag.load(Ordering::Acquire));
executor::block_on_simple(Struct::async_trait(Flagger(&flag), &flag));
assert!(!flag.load(Ordering::Acquire));
executor::block_on_simple(Flagger(&flag).async_trait(&flag));
assert!(!flag.load(Ordering::Acquire));
}
}
pub mod issue145 {
#![deny(clippy::type_complexity)]
use async_trait_fn::async_trait;
#[async_trait]
pub trait ManageConnection: Sized + Send + Sync + 'static {
type Connection: Send + 'static;
type Error: Send + 'static;
async fn connect(&self) -> Result<Self::Connection, Self::Error>;
}
}
pub mod issue147 {
#![deny(clippy::let_unit_value)]
use async_trait_fn::async_trait;
pub struct MyType;
#[async_trait]
pub trait MyTrait {
async fn x();
async fn y() -> ();
async fn z();
}
#[async_trait]
impl MyTrait for MyType {
async fn x() {}
async fn y() -> () {}
async fn z() {
unimplemented!()
}
}
}
pub mod issue149 {
use async_trait_fn::async_trait;
pub struct Thing;
pub trait Ret {}
impl Ret for Thing {}
pub async fn ok() -> &'static dyn Ret {
return &Thing;
}
#[async_trait]
pub trait Trait {
async fn fail() -> &'static dyn Ret {
return &Thing;
}
}
}
#[cfg(async_trait_nightly_testing)]
pub mod issue152 {
use async_trait_fn::async_trait;
#[async_trait]
trait Trait {
type Assoc;
async fn f(&self) -> Self::Assoc;
}
struct Struct;
#[async_trait]
impl Trait for Struct {
type Assoc = impl Sized;
async fn f(&self) -> Self::Assoc {}
}
}
pub mod issue154 {
#![deny(clippy::items_after_statements)]
use async_trait_fn::async_trait;
#[async_trait]
pub trait MyTrait {
async fn f(&self);
}
pub struct Struct;
#[async_trait]
impl MyTrait for Struct {
async fn f(&self) {
const MAX: u16 = 128;
println!("{}", MAX);
}
}
}
pub mod issue158 {
use async_trait_fn::async_trait;
fn f() {}
#[async_trait]
pub trait Trait {
async fn f(&self) {
self::f();
}
}
}
#[allow(clippy::mut_mut)]
pub mod issue161 {
use async_trait_fn::async_trait;
use futures::future::FutureExt;
use std::sync::Arc;
#[async_trait]
pub trait Trait {
async fn f(self: Arc<Self>);
}
pub struct MyStruct(bool);
#[async_trait]
impl Trait for MyStruct {
async fn f(self: Arc<Self>) {
futures::select! {
_ = async {
println!("{}", self.0);
}.fuse() => {}
}
}
}
}
#[deny(where_clauses_object_safety)]
pub mod issue169 {
use async_trait_fn::async_trait;
#[async_trait]
pub trait Trait: ::core::marker::Sync {
async fn f(&self) {}
}
pub fn test(_t: &dyn Trait) {}
}
pub mod issue177 {
use async_trait_fn::async_trait;
#[async_trait]
pub trait Trait {
async fn foo(&self, _callback: impl FnMut(&str) + Send) {}
}
pub struct Struct;
#[async_trait]
impl Trait for Struct {
async fn foo(&self, _callback: impl FnMut(&str) + Send) {}
}
}
pub mod issue183 {
#![deny(clippy::shadow_same)]
use async_trait_fn::async_trait;
#[async_trait]
trait Foo {
async fn foo(_n: i32) {}
}
}
pub mod issue199 {
use async_trait_fn::async_trait;
use std::cell::Cell;
struct IncrementOnDrop<'a>(&'a Cell<usize>);
impl<'a> Drop for IncrementOnDrop<'a> {
fn drop(&mut self) {
self.0.set(self.0.get() + 1);
}
}
#[async_trait(?Send)]
trait Trait {
async fn f(counter: &Cell<usize>, arg: IncrementOnDrop<'_>);
}
struct Struct;
#[async_trait(?Send)]
impl Trait for Struct {
async fn f(counter: &Cell<usize>, _: IncrementOnDrop<'_>) {
assert_eq!(counter.get(), 0); }
}
#[test]
fn test() {
let counter = Cell::new(0);
let future = Struct::f(&counter, IncrementOnDrop(&counter));
assert_eq!(counter.get(), 0);
drop(future);
assert_eq!(counter.get(), 1);
}
}
pub mod issue204 {
use async_trait_fn::async_trait;
#[async_trait]
pub trait Trait {
async fn f(arg: &impl Trait);
async fn g(arg: *const impl Trait);
}
}
pub mod issue210 {
use async_trait_fn::async_trait;
use std::sync::Arc;
#[async_trait]
pub trait Trait {
async fn f(self: Arc<Self>) {}
}
}
pub mod issue226 {
use async_trait_fn::async_trait;
#[async_trait]
pub trait Trait {
async fn cfg_param(&self, param: u8);
async fn cfg_param_wildcard(&self, _: u8);
async fn cfg_param_tuple(&self, (left, right): (u8, u8));
}
struct Struct;
#[async_trait]
impl Trait for Struct {
async fn cfg_param(&self, #[cfg(any())] param: u8, #[cfg(all())] _unused: u8) {}
async fn cfg_param_wildcard(&self, #[cfg(any())] _: u8, #[cfg(all())] _: u8) {}
async fn cfg_param_tuple(
&self,
#[cfg(any())] (left, right): (u8, u8),
#[cfg(all())] (_left, _right): (u8, u8),
) {
}
}
}
pub mod issue232 {
use async_trait_fn::async_trait;
#[async_trait]
pub trait Generic<T> {
async fn take_ref(&self, thing: &T);
}
pub struct One;
#[async_trait]
impl<T> Generic<T> for One {
async fn take_ref(&self, _: &T) {}
}
pub struct Two;
#[async_trait]
impl<T: Sync> Generic<(T, T)> for Two {
async fn take_ref(&self, (a, b): &(T, T)) {
let _ = a;
let _ = b;
}
}
pub struct Three;
#[async_trait]
impl<T> Generic<(T, T, T)> for Three {
async fn take_ref(&self, (_a, _b, _c): &(T, T, T)) {}
}
}
pub mod issue234 {
use async_trait_fn::async_trait;
pub struct Droppable;
impl Drop for Droppable {
fn drop(&mut self) {}
}
pub struct Tuple<T, U>(T, U);
#[async_trait]
pub trait Trait {
async fn f(arg: Tuple<Droppable, i32>);
}
pub struct UnderscorePattern;
#[async_trait]
impl Trait for UnderscorePattern {
async fn f(Tuple(_, _int): Tuple<Droppable, i32>) {}
}
pub struct DotDotPattern;
#[async_trait]
impl Trait for DotDotPattern {
async fn f(Tuple { 1: _int, .. }: Tuple<Droppable, i32>) {}
}
}
pub mod issue236 {
#![deny(clippy::async_yields_async)]
#![allow(clippy::manual_async_fn)]
use async_trait_fn::async_trait;
use std::future::{self, Future, Ready};
pub async fn async_fn() -> Ready<()> {
future::ready(())
}
#[allow(clippy::async_yields_async)]
pub fn impl_future_fn() -> impl Future<Output = Ready<()>> {
async { future::ready(()) }
}
#[async_trait]
pub trait Trait {
async fn f() -> Ready<()> {
future::ready(())
}
}
}