1 #![cfg_attr(
2 async_trait_nightly_testing,
3 feature(impl_trait_in_assoc_type, min_specialization)
4 )]
5 #![deny(rust_2021_compatibility)]
6 #![allow(
7 clippy::let_underscore_untyped,
8 clippy::let_unit_value,
9 clippy::missing_panics_doc,
10 clippy::missing_safety_doc,
11 clippy::needless_return,
12 clippy::non_minimal_cfg,
13 clippy::trivially_copy_pass_by_ref,
14 clippy::unused_async
15 )]
16
17 use async_trait::async_trait;
18
19 pub mod executor;
20
21 // Dummy module to check that the expansion refer to rust's core crate
22 mod core {}
23
24 #[async_trait]
25 trait Trait {
26 type Assoc;
27
selfvalue(self) where Self: Sized,28 async fn selfvalue(self)
29 where
30 Self: Sized,
31 {
32 }
33
selfref(&self)34 async fn selfref(&self) {}
35
selfmut(&mut self)36 async fn selfmut(&mut self) {}
37
required() -> Self::Assoc38 async fn required() -> Self::Assoc;
39
elided_lifetime(_x: &str)40 async fn elided_lifetime(_x: &str) {}
41
explicit_lifetime<'a>(_x: &'a str)42 async fn explicit_lifetime<'a>(_x: &'a str) {}
43
generic_type_param<T: Send>(x: Box<T>) -> T44 async fn generic_type_param<T: Send>(x: Box<T>) -> T {
45 *x
46 }
47
calls(&self)48 async fn calls(&self) {
49 self.selfref().await;
50 Self::elided_lifetime("").await;
51 <Self>::elided_lifetime("").await;
52 }
53
calls_mut(&mut self)54 async fn calls_mut(&mut self) {
55 self.selfmut().await;
56 }
57 }
58
59 struct Struct;
60
61 #[async_trait]
62 impl Trait for Struct {
63 type Assoc = ();
64
selfvalue(self)65 async fn selfvalue(self) {}
66
selfref(&self)67 async fn selfref(&self) {}
68
selfmut(&mut self)69 async fn selfmut(&mut self) {}
70
required() -> Self::Assoc71 async fn required() -> Self::Assoc {}
72
elided_lifetime(_x: &str)73 async fn elided_lifetime(_x: &str) {}
74
explicit_lifetime<'a>(_x: &'a str)75 async fn explicit_lifetime<'a>(_x: &'a str) {}
76
generic_type_param<T: Send>(x: Box<T>) -> T77 async fn generic_type_param<T: Send>(x: Box<T>) -> T {
78 *x
79 }
80
calls(&self)81 async fn calls(&self) {
82 self.selfref().await;
83 Self::elided_lifetime("").await;
84 <Self>::elided_lifetime("").await;
85 }
86
calls_mut(&mut self)87 async fn calls_mut(&mut self) {
88 self.selfmut().await;
89 }
90 }
91
test()92 pub async fn test() {
93 let mut s = Struct;
94 s.selfref().await;
95 s.selfmut().await;
96 s.selfvalue().await;
97
98 Struct::required().await;
99 Struct::elided_lifetime("").await;
100 Struct::explicit_lifetime("").await;
101 Struct::generic_type_param(Box::new("")).await;
102
103 let mut s = Struct;
104 s.calls().await;
105 s.calls_mut().await;
106 }
107
test_object_safe_without_default()108 pub async fn test_object_safe_without_default() {
109 #[async_trait]
110 trait ObjectSafe {
111 async fn f(&self);
112 }
113
114 #[async_trait]
115 impl ObjectSafe for Struct {
116 async fn f(&self) {}
117 }
118
119 let object = &Struct as &dyn ObjectSafe;
120 object.f().await;
121 }
122
test_object_safe_with_default()123 pub async fn test_object_safe_with_default() {
124 #[async_trait]
125 trait ObjectSafe: Sync {
126 async fn f(&self) {}
127 }
128
129 #[async_trait]
130 impl ObjectSafe for Struct {
131 async fn f(&self) {}
132 }
133
134 let object = &Struct as &dyn ObjectSafe;
135 object.f().await;
136 }
137
test_object_no_send()138 pub async fn test_object_no_send() {
139 #[async_trait(?Send)]
140 trait ObjectSafe: Sync {
141 async fn f(&self) {}
142 }
143
144 #[async_trait(?Send)]
145 impl ObjectSafe for Struct {
146 async fn f(&self) {}
147 }
148
149 let object = &Struct as &dyn ObjectSafe;
150 object.f().await;
151 }
152
153 #[async_trait]
154 pub unsafe trait UnsafeTrait {}
155
156 #[async_trait]
157 unsafe impl UnsafeTrait for () {}
158
159 #[async_trait]
160 pub(crate) unsafe trait UnsafeTraitPubCrate {}
161
162 #[async_trait]
163 unsafe trait UnsafeTraitPrivate {}
164
test_can_destruct()165 pub async fn test_can_destruct() {
166 #[async_trait]
167 trait CanDestruct {
168 async fn f(&self, foos: (u8, u8, u8, u8));
169 }
170
171 #[async_trait]
172 impl CanDestruct for Struct {
173 async fn f(&self, (a, ref mut b, ref c, d): (u8, u8, u8, u8)) {
174 let _a: u8 = a;
175 let _b: &mut u8 = b;
176 let _c: &u8 = c;
177 let _d: u8 = d;
178 }
179 }
180 }
181
test_self_in_macro()182 pub async fn test_self_in_macro() {
183 #[async_trait]
184 trait Trait {
185 async fn a(self);
186 async fn b(&mut self);
187 async fn c(&self);
188 }
189
190 #[async_trait]
191 impl Trait for String {
192 async fn a(self) {
193 println!("{}", self);
194 }
195 async fn b(&mut self) {
196 println!("{}", self);
197 }
198 async fn c(&self) {
199 println!("{}", self);
200 }
201 }
202 }
203
test_inference()204 pub async fn test_inference() {
205 #[async_trait]
206 pub trait Trait {
207 async fn f() -> Box<dyn Iterator<Item = ()>> {
208 Box::new(std::iter::empty())
209 }
210 }
211 }
212
test_internal_items()213 pub async fn test_internal_items() {
214 #[async_trait]
215 #[allow(dead_code, clippy::items_after_statements)]
216 pub trait Trait: Sized {
217 async fn f(self) {
218 struct Struct;
219
220 impl Struct {
221 fn f(self) {
222 let _ = self;
223 }
224 }
225 }
226 }
227 }
228
test_unimplemented()229 pub async fn test_unimplemented() {
230 #[async_trait]
231 pub trait Trait {
232 async fn f() {
233 unimplemented!()
234 }
235 }
236 }
237
238 // https://github.com/dtolnay/async-trait/issues/1
239 pub mod issue1 {
240 use async_trait::async_trait;
241
242 #[async_trait]
243 trait Issue1 {
f<U>(&self)244 async fn f<U>(&self);
245 }
246
247 #[async_trait]
248 impl<T: Sync> Issue1 for Vec<T> {
f<U>(&self)249 async fn f<U>(&self) {}
250 }
251 }
252
253 // https://github.com/dtolnay/async-trait/issues/2
254 pub mod issue2 {
255 use async_trait::async_trait;
256 use std::future::Future;
257
258 #[async_trait]
259 pub trait Issue2: Future {
flatten(self) -> <Self::Output as Future>::Output where Self::Output: Future + Send, Self: Sized,260 async fn flatten(self) -> <Self::Output as Future>::Output
261 where
262 Self::Output: Future + Send,
263 Self: Sized,
264 {
265 let nested_future = self.await;
266 nested_future.await
267 }
268 }
269 }
270
271 // https://github.com/dtolnay/async-trait/issues/9
272 pub mod issue9 {
273 use async_trait::async_trait;
274
275 #[async_trait]
276 pub trait Issue9: Sized + Send {
f(_x: Self)277 async fn f(_x: Self) {}
278 }
279 }
280
281 // https://github.com/dtolnay/async-trait/issues/11
282 pub mod issue11 {
283 use async_trait::async_trait;
284 use std::sync::Arc;
285
286 #[async_trait]
287 trait Issue11 {
example(self: Arc<Self>)288 async fn example(self: Arc<Self>);
289 }
290
291 struct Struct;
292
293 #[async_trait]
294 impl Issue11 for Struct {
example(self: Arc<Self>)295 async fn example(self: Arc<Self>) {}
296 }
297 }
298
299 // https://github.com/dtolnay/async-trait/issues/15
300 pub mod issue15 {
301 use async_trait::async_trait;
302 use std::marker::PhantomData;
303
304 trait Trait {}
305
306 #[async_trait]
307 trait Issue15 {
myfn(&self, _: PhantomData<dyn Trait + Send>)308 async fn myfn(&self, _: PhantomData<dyn Trait + Send>) {}
309 }
310 }
311
312 // https://github.com/dtolnay/async-trait/issues/17
313 pub mod issue17 {
314 use async_trait::async_trait;
315
316 #[async_trait]
317 trait Issue17 {
f(&self)318 async fn f(&self);
319 }
320
321 struct Struct {
322 string: String,
323 }
324
325 #[async_trait]
326 impl Issue17 for Struct {
f(&self)327 async fn f(&self) {
328 println!("{}", self.string);
329 }
330 }
331 }
332
333 // https://github.com/dtolnay/async-trait/issues/23
334 pub mod issue23 {
335 use async_trait::async_trait;
336
337 #[async_trait]
338 pub trait Issue23 {
f(self)339 async fn f(self);
340
g(mut self) where Self: Sized,341 async fn g(mut self)
342 where
343 Self: Sized,
344 {
345 do_something(&mut self);
346 }
347 }
348
349 struct S {}
350
351 #[async_trait]
352 impl Issue23 for S {
f(mut self)353 async fn f(mut self) {
354 do_something(&mut self);
355 }
356 }
357
do_something<T>(_: &mut T)358 fn do_something<T>(_: &mut T) {}
359 }
360
361 // https://github.com/dtolnay/async-trait/issues/25
362 #[cfg(async_trait_nightly_testing)]
363 pub mod issue25 {
364 use crate::executor;
365 use async_trait::async_trait;
366 use std::fmt::{Display, Write};
367
368 #[async_trait]
369 trait AsyncToString {
async_to_string(&self) -> String370 async fn async_to_string(&self) -> String;
371 }
372
373 #[async_trait]
374 impl AsyncToString for String {
async_to_string(&self) -> String375 async fn async_to_string(&self) -> String {
376 "special".to_owned()
377 }
378 }
379
380 macro_rules! hide_from_stable_parser {
381 ($($tt:tt)*) => {
382 $($tt)*
383 };
384 }
385
386 hide_from_stable_parser! {
387 #[async_trait]
388 impl<T: ?Sized + Display + Sync> AsyncToString for T {
389 default async fn async_to_string(&self) -> String {
390 let mut buf = String::new();
391 buf.write_fmt(format_args!("{}", self)).unwrap();
392 buf
393 }
394 }
395 }
396
397 #[test]
test()398 fn test() {
399 let fut = true.async_to_string();
400 assert_eq!(executor::block_on_simple(fut), "true");
401
402 let string = String::new();
403 let fut = string.async_to_string();
404 assert_eq!(executor::block_on_simple(fut), "special");
405 }
406 }
407
408 // https://github.com/dtolnay/async-trait/issues/28
409 pub mod issue28 {
410 use async_trait::async_trait;
411
412 struct Str<'a>(&'a str);
413
414 #[async_trait]
415 trait Trait1<'a> {
f(x: Str<'a>) -> &'a str416 async fn f(x: Str<'a>) -> &'a str;
g(x: Str<'a>) -> &'a str417 async fn g(x: Str<'a>) -> &'a str {
418 x.0
419 }
420 }
421
422 #[async_trait]
423 impl<'a> Trait1<'a> for str {
f(x: Str<'a>) -> &'a str424 async fn f(x: Str<'a>) -> &'a str {
425 x.0
426 }
427 }
428
429 #[async_trait]
430 trait Trait2 {
f()431 async fn f();
432 }
433
434 #[async_trait]
435 impl<'a> Trait2 for &'a () {
f()436 async fn f() {}
437 }
438
439 #[async_trait]
440 trait Trait3<'a, 'b> {
f(_: &'a &'b ())441 async fn f(_: &'a &'b ()); // chain 'a and 'b
g(_: &'b ())442 async fn g(_: &'b ()); // chain 'b only
h()443 async fn h(); // do not chain
444 }
445 }
446
447 // https://github.com/dtolnay/async-trait/issues/31
448 pub mod issue31 {
449 use async_trait::async_trait;
450
451 pub struct Struct<'a> {
452 pub name: &'a str,
453 }
454
455 #[async_trait]
456 pub trait Trait<'a> {
hello(thing: Struct<'a>) -> String457 async fn hello(thing: Struct<'a>) -> String;
hello_twice(one: Struct<'a>, two: Struct<'a>) -> String458 async fn hello_twice(one: Struct<'a>, two: Struct<'a>) -> String {
459 let str1 = Self::hello(one).await;
460 let str2 = Self::hello(two).await;
461 str1 + &str2
462 }
463 }
464 }
465
466 // https://github.com/dtolnay/async-trait/issues/42
467 pub mod issue42 {
468 use async_trait::async_trait;
469
470 #[async_trait]
471 pub trait Context: Sized {
from_parts() -> Self472 async fn from_parts() -> Self;
473 }
474
475 pub struct TokenContext;
476
477 #[async_trait]
478 impl Context for TokenContext {
from_parts() -> TokenContext479 async fn from_parts() -> TokenContext {
480 TokenContext
481 }
482 }
483 }
484
485 // https://github.com/dtolnay/async-trait/issues/44
486 pub mod issue44 {
487 use async_trait::async_trait;
488
489 #[async_trait]
490 pub trait StaticWithWhereSelf
491 where
492 Box<Self>: Sized,
493 Self: Sized + Send,
494 {
get_one() -> u8495 async fn get_one() -> u8 {
496 1
497 }
498 }
499
500 pub struct Struct;
501
502 #[async_trait]
503 impl StaticWithWhereSelf for Struct {}
504 }
505
506 // https://github.com/dtolnay/async-trait/issues/45
507 pub mod issue45 {
508 use crate::executor;
509 use async_trait::async_trait;
510 use std::fmt::Debug;
511 use std::sync::atomic::{AtomicU64, Ordering};
512 use std::sync::{Arc, Mutex};
513 use tracing::event::Event;
514 use tracing::field::{Field, Visit};
515 use tracing::span::{Attributes, Id, Record};
516 use tracing::{info, instrument, subscriber, Metadata, Subscriber};
517
518 #[async_trait]
519 pub trait Parent {
foo(&mut self, v: usize)520 async fn foo(&mut self, v: usize);
521 }
522
523 #[async_trait]
524 pub trait Child {
bar(&self)525 async fn bar(&self);
526 }
527
528 #[derive(Debug)]
529 struct Impl(usize);
530
531 #[async_trait]
532 impl Parent for Impl {
533 #[instrument]
foo(&mut self, v: usize)534 async fn foo(&mut self, v: usize) {
535 self.0 = v;
536 self.bar().await;
537 }
538 }
539
540 #[async_trait]
541 impl Child for Impl {
542 // Let's check that tracing detects the renaming of the `self` variable
543 // too, as tracing::instrument is not going to be able to skip the
544 // `self` argument if it can't find it in the function signature.
545 #[instrument(skip(self))]
bar(&self)546 async fn bar(&self) {
547 info!(val = self.0);
548 }
549 }
550
551 // A simple subscriber implementation to test the behavior of async-trait
552 // with tokio-rs/tracing. This implementation is not robust against race
553 // conditions, but it's not an issue here as we are only polling on a single
554 // future at a time.
555 #[derive(Debug)]
556 struct SubscriberInner {
557 current_depth: AtomicU64,
558 // We assert that nested functions work. If the fix were to break, we
559 // would see two top-level functions instead of `bar` nested in `foo`.
560 max_depth: AtomicU64,
561 max_span_id: AtomicU64,
562 // Name of the variable / value / depth when the event was recorded.
563 value: Mutex<Option<(&'static str, u64, u64)>>,
564 }
565
566 #[derive(Debug, Clone)]
567 struct TestSubscriber {
568 inner: Arc<SubscriberInner>,
569 }
570
571 impl TestSubscriber {
new() -> Self572 fn new() -> Self {
573 TestSubscriber {
574 inner: Arc::new(SubscriberInner {
575 current_depth: AtomicU64::new(0),
576 max_depth: AtomicU64::new(0),
577 max_span_id: AtomicU64::new(1),
578 value: Mutex::new(None),
579 }),
580 }
581 }
582 }
583
584 struct U64Visitor(Option<(&'static str, u64)>);
585
586 impl Visit for U64Visitor {
record_debug(&mut self, _field: &Field, _value: &dyn Debug)587 fn record_debug(&mut self, _field: &Field, _value: &dyn Debug) {}
588
record_u64(&mut self, field: &Field, value: u64)589 fn record_u64(&mut self, field: &Field, value: u64) {
590 self.0 = Some((field.name(), value));
591 }
592 }
593
594 impl Subscriber for TestSubscriber {
enabled(&self, _metadata: &Metadata) -> bool595 fn enabled(&self, _metadata: &Metadata) -> bool {
596 true
597 }
new_span(&self, _span: &Attributes) -> Id598 fn new_span(&self, _span: &Attributes) -> Id {
599 Id::from_u64(self.inner.max_span_id.fetch_add(1, Ordering::AcqRel))
600 }
record(&self, _span: &Id, _values: &Record)601 fn record(&self, _span: &Id, _values: &Record) {}
record_follows_from(&self, _span: &Id, _follows: &Id)602 fn record_follows_from(&self, _span: &Id, _follows: &Id) {}
event(&self, event: &Event)603 fn event(&self, event: &Event) {
604 let mut visitor = U64Visitor(None);
605 event.record(&mut visitor);
606 if let Some((s, v)) = visitor.0 {
607 let current_depth = self.inner.current_depth.load(Ordering::Acquire);
608 *self.inner.value.lock().unwrap() = Some((s, v, current_depth));
609 }
610 }
enter(&self, _span: &Id)611 fn enter(&self, _span: &Id) {
612 let old_depth = self.inner.current_depth.fetch_add(1, Ordering::AcqRel);
613 if old_depth + 1 > self.inner.max_depth.load(Ordering::Acquire) {
614 self.inner.max_depth.fetch_add(1, Ordering::AcqRel);
615 }
616 }
exit(&self, _span: &Id)617 fn exit(&self, _span: &Id) {
618 self.inner.current_depth.fetch_sub(1, Ordering::AcqRel);
619 }
620 }
621
622 #[test]
623 #[cfg_attr(miri, ignore)] // https://github.com/matklad/once_cell/pull/185
tracing()624 fn tracing() {
625 // Create the future outside of the subscriber, as no call to tracing
626 // should be made until the future is polled.
627 let mut struct_impl = Impl(0);
628 let fut = struct_impl.foo(5);
629 let subscriber = TestSubscriber::new();
630 subscriber::with_default(subscriber.clone(), || executor::block_on_simple(fut));
631 // Did we enter bar inside of foo?
632 assert_eq!(subscriber.inner.max_depth.load(Ordering::Acquire), 2);
633 // Have we exited all spans?
634 assert_eq!(subscriber.inner.current_depth.load(Ordering::Acquire), 0);
635 // Did we create only two spans? Note: spans start at 1, hence the -1.
636 assert_eq!(subscriber.inner.max_span_id.load(Ordering::Acquire) - 1, 2);
637 // Was the value recorded at the right depth i.e. in the right function?
638 // If so, was it the expected value?
639 assert_eq!(*subscriber.inner.value.lock().unwrap(), Some(("val", 5, 2)));
640 }
641 }
642
643 // https://github.com/dtolnay/async-trait/issues/46
644 pub mod issue46 {
645 use async_trait::async_trait;
646
647 macro_rules! implement_commands_workaround {
648 ($tyargs:tt : $ty:tt) => {
649 #[async_trait]
650 pub trait AsyncCommands1: Sized {
651 async fn f<$tyargs: $ty>(&mut self, x: $tyargs) {
652 self.f(x).await
653 }
654 }
655 };
656 }
657
658 implement_commands_workaround!(K: Send);
659
660 macro_rules! implement_commands {
661 ($tyargs:ident : $ty:ident) => {
662 #[async_trait]
663 pub trait AsyncCommands2: Sized {
664 async fn f<$tyargs: $ty>(&mut self, x: $tyargs) {
665 self.f(x).await
666 }
667 }
668 };
669 }
670
671 implement_commands!(K: Send);
672 }
673
674 // https://github.com/dtolnay/async-trait/issues/53
675 pub mod issue53 {
676 use async_trait::async_trait;
677
678 pub struct Unit;
679 pub struct Tuple(u8);
680 pub struct Struct {
681 pub x: u8,
682 }
683
684 #[async_trait]
685 pub trait Trait {
method()686 async fn method();
687 }
688
689 #[async_trait]
690 impl Trait for Unit {
method()691 async fn method() {
692 let _ = Self;
693 }
694 }
695
696 #[async_trait]
697 impl Trait for Tuple {
method()698 async fn method() {
699 let _ = Self(0);
700 }
701 }
702
703 #[async_trait]
704 impl Trait for Struct {
method()705 async fn method() {
706 let _ = Self { x: 0 };
707 }
708 }
709
710 #[async_trait]
711 impl Trait for std::marker::PhantomData<Struct> {
method()712 async fn method() {
713 let _ = Self;
714 }
715 }
716 }
717
718 // https://github.com/dtolnay/async-trait/issues/57
719 #[cfg(async_trait_nightly_testing)]
720 pub mod issue57 {
721 use crate::executor;
722 use async_trait::async_trait;
723
724 #[async_trait]
725 trait Trait {
const_generic<T: Send, const C: usize>(_: [T; C])726 async fn const_generic<T: Send, const C: usize>(_: [T; C]) {}
727 }
728
729 struct Struct;
730
731 #[async_trait]
732 impl Trait for Struct {
const_generic<T: Send, const C: usize>(_: [T; C])733 async fn const_generic<T: Send, const C: usize>(_: [T; C]) {}
734 }
735
736 #[test]
test()737 fn test() {
738 let fut = Struct::const_generic([0; 10]);
739 executor::block_on_simple(fut);
740 }
741 }
742
743 // https://github.com/dtolnay/async-trait/issues/68
744 pub mod issue68 {
745 #[async_trait::async_trait]
746 pub trait Example {
method(&self)747 async fn method(&self) {
748 macro_rules! t {
749 () => {{
750 let _: &Self = self;
751 }};
752 }
753 t!();
754 }
755 }
756 }
757
758 // https://github.com/dtolnay/async-trait/issues/73
759 pub mod issue73 {
760 use async_trait::async_trait;
761
762 #[async_trait]
763 pub trait Example {
764 const ASSOCIATED: &'static str;
765
associated(&self)766 async fn associated(&self) {
767 println!("Associated:{}", Self::ASSOCIATED);
768 }
769 }
770 }
771
772 // https://github.com/dtolnay/async-trait/issues/81
773 pub mod issue81 {
774 use async_trait::async_trait;
775
776 #[async_trait]
777 pub trait Trait {
handle(&self)778 async fn handle(&self);
779 }
780
781 pub enum Enum {
782 Variant,
783 }
784
785 #[async_trait]
786 impl Trait for Enum {
handle(&self)787 async fn handle(&self) {
788 let Enum::Variant = self;
789 let Self::Variant = self;
790 }
791 }
792 }
793
794 // https://github.com/dtolnay/async-trait/issues/83
795 pub mod issue83 {
796 #![allow(clippy::needless_arbitrary_self_type)]
797
798 use async_trait::async_trait;
799
800 #[async_trait]
801 pub trait Trait {
f(&self)802 async fn f(&self) {}
g(self: &Self)803 async fn g(self: &Self) {}
804 }
805 }
806
807 // https://github.com/dtolnay/async-trait/issues/85
808 pub mod issue85 {
809 #![deny(non_snake_case)]
810
811 use async_trait::async_trait;
812
813 #[async_trait]
814 pub trait Trait {
815 #[allow(non_snake_case)]
camelCase()816 async fn camelCase();
817 }
818
819 pub struct Struct;
820
821 #[async_trait]
822 impl Trait for Struct {
camelCase()823 async fn camelCase() {}
824 }
825 }
826
827 // https://github.com/dtolnay/async-trait/issues/87
828 pub mod issue87 {
829 use async_trait::async_trait;
830
831 #[async_trait]
832 pub trait Trait {
f(&self)833 async fn f(&self);
834 }
835
836 pub enum Tuple {
837 V(),
838 }
839
840 pub enum Struct {
841 V {},
842 }
843
844 #[async_trait]
845 impl Trait for Tuple {
f(&self)846 async fn f(&self) {
847 let Tuple::V() = self;
848 let Self::V() = self;
849 let _ = Self::V;
850 let _ = Self::V();
851 }
852 }
853
854 #[async_trait]
855 impl Trait for Struct {
f(&self)856 async fn f(&self) {
857 let Struct::V {} = self;
858 let Self::V {} = self;
859 let _ = Self::V {};
860 }
861 }
862 }
863
864 // https://github.com/dtolnay/async-trait/issues/89
865 pub mod issue89 {
866 #![allow(bare_trait_objects)]
867
868 use async_trait::async_trait;
869
870 #[async_trait]
871 trait Trait {
f(&self)872 async fn f(&self);
873 }
874
875 #[async_trait]
876 impl Trait for dyn Send + Sync {
f(&self)877 async fn f(&self) {}
878 }
879
880 #[async_trait]
881 impl Trait for dyn Fn(i8) + Send + Sync {
f(&self)882 async fn f(&self) {}
883 }
884
885 #[async_trait]
886 impl Trait for (dyn Fn(u8) + Send + Sync) {
f(&self)887 async fn f(&self) {}
888 }
889 }
890
891 // https://github.com/dtolnay/async-trait/issues/92
892 pub mod issue92 {
893 use async_trait::async_trait;
894
895 macro_rules! mac {
896 ($($tt:tt)*) => {
897 $($tt)*
898 };
899 }
900
901 pub struct Struct<T> {
902 _x: T,
903 }
904
905 impl<T> Struct<T> {
906 const ASSOCIATED1: &'static str = "1";
associated1()907 async fn associated1() {}
908 }
909
910 #[async_trait]
911 pub trait Trait
912 where
913 mac!(Self): Send,
914 {
915 const ASSOCIATED2: &'static str;
916 type Associated2;
917
918 #[allow(path_statements, clippy::let_underscore_future, clippy::no_effect)]
associated2(&self)919 async fn associated2(&self) {
920 // trait items
921 mac!(let _: Self::Associated2;);
922 mac!(let _: <Self>::Associated2;);
923 mac!(let _: <Self as Trait>::Associated2;);
924 mac!(Self::ASSOCIATED2;);
925 mac!(<Self>::ASSOCIATED2;);
926 mac!(<Self as Trait>::ASSOCIATED2;);
927 mac!(let _ = Self::associated2(self););
928 mac!(let _ = <Self>::associated2(self););
929 mac!(let _ = <Self as Trait>::associated2(self););
930 }
931 }
932
933 #[async_trait]
934 impl<T: Send + Sync> Trait for Struct<T>
935 where
936 mac!(Self): Send,
937 {
938 const ASSOCIATED2: &'static str = "2";
939 type Associated2 = ();
940
941 #[allow(path_statements, clippy::let_underscore_future, clippy::no_effect)]
associated2(&self)942 async fn associated2(&self) {
943 // inherent items
944 mac!(Self::ASSOCIATED1;);
945 mac!(<Self>::ASSOCIATED1;);
946 mac!(let _ = Self::associated1(););
947 mac!(let _ = <Self>::associated1(););
948
949 // trait items
950 mac!(let (): <Self as Trait>::Associated2;);
951 mac!(Self::ASSOCIATED2;);
952 mac!(<Self>::ASSOCIATED2;);
953 mac!(<Self as Trait>::ASSOCIATED2;);
954 mac!(let _ = Self::associated2(self););
955 mac!(let _ = <Self>::associated2(self););
956 mac!(let _ = <Self as Trait>::associated2(self););
957 }
958 }
959
960 pub struct Unit;
961
962 #[async_trait]
963 impl Trait for Unit {
964 const ASSOCIATED2: &'static str = "2";
965 type Associated2 = ();
966
associated2(&self)967 async fn associated2(&self) {
968 mac!(let Self: Self = *self;);
969 }
970 }
971 }
972
973 // https://github.com/dtolnay/async-trait/issues/92#issuecomment-683370136
974 pub mod issue92_2 {
975 use async_trait::async_trait;
976
977 macro_rules! mac {
978 ($($tt:tt)*) => {
979 $($tt)*
980 };
981 }
982
983 pub trait Trait1 {
func1()984 fn func1();
985 }
986
987 #[async_trait]
988 pub trait Trait2: Trait1 {
func2()989 async fn func2() {
990 mac!(Self::func1());
991
992 macro_rules! mac2 {
993 ($($tt:tt)*) => {
994 Self::func1();
995 };
996 }
997 mac2!();
998 }
999 }
1000 }
1001
1002 // https://github.com/dtolnay/async-trait/issues/104
1003 pub mod issue104 {
1004 use async_trait::async_trait;
1005
1006 #[async_trait]
1007 trait T1 {
id(&self) -> i321008 async fn id(&self) -> i32;
1009 }
1010
1011 macro_rules! impl_t1 {
1012 ($ty:ty, $id:expr) => {
1013 #[async_trait]
1014 impl T1 for $ty {
1015 async fn id(&self) -> i32 {
1016 $id
1017 }
1018 }
1019 };
1020 }
1021
1022 struct Foo;
1023
1024 impl_t1!(Foo, 1);
1025 }
1026
1027 // https://github.com/dtolnay/async-trait/issues/106
1028 pub mod issue106 {
1029 use async_trait::async_trait;
1030 use std::future::Future;
1031
1032 #[async_trait]
1033 pub trait ProcessPool: Send + Sync {
1034 type ThreadPool;
1035
spawn<F, Fut, T>(&self, work: F) -> T where F: FnOnce(&Self::ThreadPool) -> Fut + Send, Fut: Future<Output = T> + 'static1036 async fn spawn<F, Fut, T>(&self, work: F) -> T
1037 where
1038 F: FnOnce(&Self::ThreadPool) -> Fut + Send,
1039 Fut: Future<Output = T> + 'static;
1040 }
1041
1042 #[async_trait]
1043 impl<P> ProcessPool for &P
1044 where
1045 P: ?Sized + ProcessPool,
1046 {
1047 type ThreadPool = P::ThreadPool;
1048
spawn<F, Fut, T>(&self, work: F) -> T where F: FnOnce(&Self::ThreadPool) -> Fut + Send, Fut: Future<Output = T> + 'static,1049 async fn spawn<F, Fut, T>(&self, work: F) -> T
1050 where
1051 F: FnOnce(&Self::ThreadPool) -> Fut + Send,
1052 Fut: Future<Output = T> + 'static,
1053 {
1054 (**self).spawn(work).await
1055 }
1056 }
1057 }
1058
1059 // https://github.com/dtolnay/async-trait/issues/110
1060 pub mod issue110 {
1061 use async_trait::async_trait;
1062 use std::marker::PhantomData;
1063
1064 #[async_trait]
1065 pub trait Loader {
load(&self, key: &str)1066 async fn load(&self, key: &str);
1067 }
1068
1069 pub struct AwsEc2MetadataLoader<'a> {
1070 marker: PhantomData<&'a ()>,
1071 }
1072
1073 #[async_trait]
1074 impl Loader for AwsEc2MetadataLoader<'_> {
load(&self, _key: &str)1075 async fn load(&self, _key: &str) {}
1076 }
1077 }
1078
1079 // https://github.com/dtolnay/async-trait/issues/120
1080 pub mod issue120 {
1081 #![deny(clippy::trivially_copy_pass_by_ref)]
1082
1083 use async_trait::async_trait;
1084
1085 #[async_trait]
1086 trait Trait {
f(&self)1087 async fn f(&self);
1088 }
1089
1090 #[async_trait]
1091 impl Trait for () {
f(&self)1092 async fn f(&self) {}
1093 }
1094 }
1095
1096 // https://github.com/dtolnay/async-trait/issues/123
1097 pub mod issue123 {
1098 use async_trait::async_trait;
1099
1100 #[async_trait]
1101 trait Trait<T = ()> {
f(&self) -> &str where T: 'async_trait,1102 async fn f(&self) -> &str
1103 where
1104 T: 'async_trait,
1105 {
1106 "default"
1107 }
1108 }
1109
1110 #[async_trait]
1111 impl<T> Trait<T> for () {}
1112 }
1113
1114 // https://github.com/dtolnay/async-trait/issues/129
1115 pub mod issue129 {
1116 use async_trait::async_trait;
1117
1118 #[async_trait]
1119 pub trait TestTrait {
a(_b: u8, c: u8) -> u81120 async fn a(_b: u8, c: u8) -> u8 {
1121 c
1122 }
1123 }
1124
1125 pub struct TestStruct;
1126
1127 #[async_trait]
1128 impl TestTrait for TestStruct {
a(_b: u8, c: u8) -> u81129 async fn a(_b: u8, c: u8) -> u8 {
1130 c
1131 }
1132 }
1133 }
1134
1135 // https://github.com/dtolnay/async-trait/issues/134
1136 #[cfg(async_trait_nightly_testing)]
1137 pub mod issue134 {
1138 use async_trait::async_trait;
1139
1140 #[async_trait]
1141 trait TestTrait {
run<const DUMMY: bool>(self) where Self: Sized,1142 async fn run<const DUMMY: bool>(self)
1143 where
1144 Self: Sized,
1145 {
1146 }
1147 }
1148
1149 pub struct TestStruct;
1150
1151 #[async_trait]
1152 impl TestTrait for TestStruct {
run<const DUMMY: bool>(self) where Self: Sized,1153 async fn run<const DUMMY: bool>(self)
1154 where
1155 Self: Sized,
1156 {
1157 }
1158 }
1159 }
1160
1161 // https://github.com/dtolnay/async-trait/pull/125#pullrequestreview-491880881
1162 pub mod drop_order {
1163 use crate::executor;
1164 use async_trait::async_trait;
1165 use std::sync::atomic::{AtomicBool, Ordering};
1166
1167 struct Flagger<'a>(&'a AtomicBool);
1168
1169 impl Drop for Flagger<'_> {
drop(&mut self)1170 fn drop(&mut self) {
1171 self.0.fetch_xor(true, Ordering::AcqRel);
1172 }
1173 }
1174
1175 #[async_trait]
1176 trait Trait {
async_trait(_: Flagger<'_>, flag: &AtomicBool)1177 async fn async_trait(_: Flagger<'_>, flag: &AtomicBool);
1178 }
1179
1180 struct Struct;
1181
1182 #[async_trait]
1183 impl Trait for Struct {
async_trait(_: Flagger<'_>, flag: &AtomicBool)1184 async fn async_trait(_: Flagger<'_>, flag: &AtomicBool) {
1185 flag.fetch_or(true, Ordering::AcqRel);
1186 }
1187 }
1188
standalone(_: Flagger<'_>, flag: &AtomicBool)1189 async fn standalone(_: Flagger<'_>, flag: &AtomicBool) {
1190 flag.fetch_or(true, Ordering::AcqRel);
1191 }
1192
1193 #[async_trait]
1194 trait SelfTrait {
async_trait(self, flag: &AtomicBool)1195 async fn async_trait(self, flag: &AtomicBool);
1196 }
1197
1198 #[async_trait]
1199 impl SelfTrait for Flagger<'_> {
async_trait(self, flag: &AtomicBool)1200 async fn async_trait(self, flag: &AtomicBool) {
1201 flag.fetch_or(true, Ordering::AcqRel);
1202 }
1203 }
1204
1205 #[test]
test_drop_order()1206 fn test_drop_order() {
1207 // 0 : 0 ^ 1 = 1 | 1 = 1 (if flagger then block)
1208 // 0 : 0 | 1 = 1 ^ 1 = 0 (if block then flagger)
1209
1210 let flag = AtomicBool::new(false);
1211 executor::block_on_simple(standalone(Flagger(&flag), &flag));
1212 assert!(!flag.load(Ordering::Acquire));
1213
1214 executor::block_on_simple(Struct::async_trait(Flagger(&flag), &flag));
1215 assert!(!flag.load(Ordering::Acquire));
1216
1217 executor::block_on_simple(Flagger(&flag).async_trait(&flag));
1218 assert!(!flag.load(Ordering::Acquire));
1219 }
1220 }
1221
1222 // https://github.com/dtolnay/async-trait/issues/145
1223 pub mod issue145 {
1224 #![deny(clippy::type_complexity)]
1225
1226 use async_trait::async_trait;
1227
1228 #[async_trait]
1229 pub trait ManageConnection: Sized + Send + Sync + 'static {
1230 type Connection: Send + 'static;
1231 type Error: Send + 'static;
1232
connect(&self) -> Result<Self::Connection, Self::Error>1233 async fn connect(&self) -> Result<Self::Connection, Self::Error>;
1234 }
1235 }
1236
1237 // https://github.com/dtolnay/async-trait/issues/147
1238 pub mod issue147 {
1239 #![deny(clippy::let_unit_value)]
1240
1241 use async_trait::async_trait;
1242
1243 pub struct MyType;
1244
1245 #[async_trait]
1246 pub trait MyTrait {
x()1247 async fn x();
y() -> ()1248 async fn y() -> ();
z()1249 async fn z();
1250 }
1251
1252 #[async_trait]
1253 impl MyTrait for MyType {
x()1254 async fn x() {}
y() -> ()1255 async fn y() -> () {}
z()1256 async fn z() {
1257 unimplemented!()
1258 }
1259 }
1260 }
1261
1262 // https://github.com/dtolnay/async-trait/issues/149
1263 pub mod issue149 {
1264 use async_trait::async_trait;
1265
1266 pub struct Thing;
1267 pub trait Ret {}
1268 impl Ret for Thing {}
1269
ok() -> &'static dyn Ret1270 pub async fn ok() -> &'static dyn Ret {
1271 return &Thing;
1272 }
1273
1274 #[async_trait]
1275 pub trait Trait {
fail() -> &'static dyn Ret1276 async fn fail() -> &'static dyn Ret {
1277 return &Thing;
1278 }
1279 }
1280 }
1281
1282 // https://github.com/dtolnay/async-trait/issues/152
1283 #[cfg(async_trait_nightly_testing)]
1284 pub mod issue152 {
1285 use async_trait::async_trait;
1286
1287 #[async_trait]
1288 trait Trait {
1289 type Assoc;
1290
f(&self) -> Self::Assoc1291 async fn f(&self) -> Self::Assoc;
1292 }
1293
1294 struct Struct;
1295
1296 #[async_trait]
1297 impl Trait for Struct {
1298 type Assoc = impl Sized;
1299
1300 async fn f(&self) -> Self::Assoc {}
1301 }
1302 }
1303
1304 // https://github.com/dtolnay/async-trait/issues/154
1305 pub mod issue154 {
1306 #![deny(clippy::items_after_statements)]
1307
1308 use async_trait::async_trait;
1309
1310 #[async_trait]
1311 pub trait MyTrait {
f(&self)1312 async fn f(&self);
1313 }
1314
1315 pub struct Struct;
1316
1317 #[async_trait]
1318 impl MyTrait for Struct {
f(&self)1319 async fn f(&self) {
1320 const MAX: u16 = 128;
1321 println!("{}", MAX);
1322 }
1323 }
1324 }
1325
1326 // https://github.com/dtolnay/async-trait/issues/158
1327 pub mod issue158 {
1328 use async_trait::async_trait;
1329
f()1330 fn f() {}
1331
1332 #[async_trait]
1333 pub trait Trait {
f(&self)1334 async fn f(&self) {
1335 self::f();
1336 }
1337 }
1338 }
1339
1340 // https://github.com/dtolnay/async-trait/issues/161
1341 #[allow(clippy::mut_mut)]
1342 pub mod issue161 {
1343 use async_trait::async_trait;
1344 use futures::future::FutureExt;
1345 use std::sync::Arc;
1346
1347 #[async_trait]
1348 pub trait Trait {
f(self: Arc<Self>)1349 async fn f(self: Arc<Self>);
1350 }
1351
1352 pub struct MyStruct(bool);
1353
1354 #[async_trait]
1355 impl Trait for MyStruct {
f(self: Arc<Self>)1356 async fn f(self: Arc<Self>) {
1357 futures::select! {
1358 () = async {
1359 println!("{}", self.0);
1360 }.fuse() => {}
1361 }
1362 }
1363 }
1364 }
1365
1366 // https://github.com/dtolnay/async-trait/issues/169
1367 #[deny(where_clauses_object_safety)]
1368 pub mod issue169 {
1369 use async_trait::async_trait;
1370
1371 #[async_trait]
1372 pub trait Trait: ::core::marker::Sync {
f(&self)1373 async fn f(&self) {}
1374 }
1375
test(_t: &dyn Trait)1376 pub fn test(_t: &dyn Trait) {}
1377 }
1378
1379 // https://github.com/dtolnay/async-trait/issues/177
1380 pub mod issue177 {
1381 use async_trait::async_trait;
1382
1383 #[async_trait]
1384 pub trait Trait {
foo(&self, _callback: impl FnMut(&str) + Send)1385 async fn foo(&self, _callback: impl FnMut(&str) + Send) {}
1386 }
1387
1388 pub struct Struct;
1389
1390 #[async_trait]
1391 impl Trait for Struct {
foo(&self, _callback: impl FnMut(&str) + Send)1392 async fn foo(&self, _callback: impl FnMut(&str) + Send) {}
1393 }
1394 }
1395
1396 // https://github.com/dtolnay/async-trait/issues/183
1397 pub mod issue183 {
1398 #![deny(clippy::shadow_same)]
1399
1400 use async_trait::async_trait;
1401
1402 #[async_trait]
1403 trait Foo {
foo(_n: i32)1404 async fn foo(_n: i32) {}
1405 }
1406 }
1407
1408 // https://github.com/dtolnay/async-trait/issues/199
1409 pub mod issue199 {
1410 use async_trait::async_trait;
1411 use std::cell::Cell;
1412
1413 struct IncrementOnDrop<'a>(&'a Cell<usize>);
1414
1415 impl<'a> Drop for IncrementOnDrop<'a> {
drop(&mut self)1416 fn drop(&mut self) {
1417 self.0.set(self.0.get() + 1);
1418 }
1419 }
1420
1421 #[async_trait(?Send)]
1422 trait Trait {
f(counter: &Cell<usize>, arg: IncrementOnDrop<'_>)1423 async fn f(counter: &Cell<usize>, arg: IncrementOnDrop<'_>);
1424 }
1425
1426 struct Struct;
1427
1428 #[async_trait(?Send)]
1429 impl Trait for Struct {
f(counter: &Cell<usize>, _: IncrementOnDrop<'_>)1430 async fn f(counter: &Cell<usize>, _: IncrementOnDrop<'_>) {
1431 assert_eq!(counter.get(), 0); // second arg not dropped yet
1432 }
1433 }
1434
1435 #[test]
test()1436 fn test() {
1437 let counter = Cell::new(0);
1438 let future = Struct::f(&counter, IncrementOnDrop(&counter));
1439 assert_eq!(counter.get(), 0);
1440 drop(future);
1441 assert_eq!(counter.get(), 1);
1442 }
1443 }
1444
1445 // https://github.com/dtolnay/async-trait/issues/204
1446 pub mod issue204 {
1447 use async_trait::async_trait;
1448
1449 #[async_trait]
1450 pub trait Trait {
f(arg: &impl Trait)1451 async fn f(arg: &impl Trait);
g(arg: *const impl Trait)1452 async fn g(arg: *const impl Trait);
1453 }
1454 }
1455
1456 // https://github.com/dtolnay/async-trait/issues/210
1457 pub mod issue210 {
1458 use async_trait::async_trait;
1459 use std::sync::Arc;
1460
1461 #[async_trait]
1462 pub trait Trait {
f(self: Arc<Self>)1463 async fn f(self: Arc<Self>) {}
1464 }
1465 }
1466
1467 // https://github.com/dtolnay/async-trait/issues/226
1468 pub mod issue226 {
1469 use async_trait::async_trait;
1470
1471 #[async_trait]
1472 pub trait Trait {
cfg_param(&self, param: u8)1473 async fn cfg_param(&self, param: u8);
cfg_param_wildcard(&self, _: u8)1474 async fn cfg_param_wildcard(&self, _: u8);
cfg_param_tuple(&self, (left, right): (u8, u8))1475 async fn cfg_param_tuple(&self, (left, right): (u8, u8));
1476 }
1477
1478 struct Struct;
1479
1480 #[async_trait]
1481 impl Trait for Struct {
cfg_param(&self, #[cfg(any())] param: u8, #[cfg(all())] _unused: u8)1482 async fn cfg_param(&self, #[cfg(any())] param: u8, #[cfg(all())] _unused: u8) {}
1483
cfg_param_wildcard(&self, #[cfg(any())] _: u8, #[cfg(all())] _: u8)1484 async fn cfg_param_wildcard(&self, #[cfg(any())] _: u8, #[cfg(all())] _: u8) {}
1485
cfg_param_tuple( &self, #[cfg(any())] (left, right): (u8, u8), #[cfg(all())] (_left, _right): (u8, u8), )1486 async fn cfg_param_tuple(
1487 &self,
1488 #[cfg(any())] (left, right): (u8, u8),
1489 #[cfg(all())] (_left, _right): (u8, u8),
1490 ) {
1491 }
1492 }
1493 }
1494
1495 // https://github.com/dtolnay/async-trait/issues/232
1496 pub mod issue232 {
1497 use async_trait::async_trait;
1498
1499 #[async_trait]
1500 pub trait Generic<T> {
take_ref(&self, thing: &T)1501 async fn take_ref(&self, thing: &T);
1502 }
1503
1504 pub struct One;
1505
1506 #[async_trait]
1507 impl<T> Generic<T> for One {
take_ref(&self, _: &T)1508 async fn take_ref(&self, _: &T) {}
1509 }
1510
1511 pub struct Two;
1512
1513 #[async_trait]
1514 impl<T: Sync> Generic<(T, T)> for Two {
take_ref(&self, (a, b): &(T, T))1515 async fn take_ref(&self, (a, b): &(T, T)) {
1516 let _ = a;
1517 let _ = b;
1518 }
1519 }
1520
1521 pub struct Three;
1522
1523 #[async_trait]
1524 impl<T> Generic<(T, T, T)> for Three {
take_ref(&self, (_a, _b, _c): &(T, T, T))1525 async fn take_ref(&self, (_a, _b, _c): &(T, T, T)) {}
1526 }
1527 }
1528
1529 // https://github.com/dtolnay/async-trait/issues/234
1530 pub mod issue234 {
1531 use async_trait::async_trait;
1532
1533 pub struct Droppable;
1534
1535 impl Drop for Droppable {
drop(&mut self)1536 fn drop(&mut self) {}
1537 }
1538
1539 pub struct Tuple<T, U>(T, U);
1540
1541 #[async_trait]
1542 pub trait Trait {
f(arg: Tuple<Droppable, i32>)1543 async fn f(arg: Tuple<Droppable, i32>);
1544 }
1545
1546 pub struct UnderscorePattern;
1547
1548 #[async_trait]
1549 impl Trait for UnderscorePattern {
f(Tuple(_, _int): Tuple<Droppable, i32>)1550 async fn f(Tuple(_, _int): Tuple<Droppable, i32>) {}
1551 }
1552
1553 pub struct DotDotPattern;
1554
1555 #[async_trait]
1556 impl Trait for DotDotPattern {
1557 async fn f(Tuple { 1: _int, .. }: Tuple<Droppable, i32>) {}
1558 }
1559 }
1560
1561 // https://github.com/dtolnay/async-trait/issues/236
1562 pub mod issue236 {
1563 #![deny(clippy::async_yields_async)]
1564 #![allow(clippy::manual_async_fn)]
1565
1566 use async_trait::async_trait;
1567 use std::future::{self, Future, Ready};
1568
1569 // Does not trigger the lint.
async_fn() -> Ready<()>1570 pub async fn async_fn() -> Ready<()> {
1571 future::ready(())
1572 }
1573
1574 #[allow(clippy::async_yields_async)]
impl_future_fn() -> impl Future<Output = Ready<()>>1575 pub fn impl_future_fn() -> impl Future<Output = Ready<()>> {
1576 async { future::ready(()) }
1577 }
1578
1579 // The async_trait attribute turns the former into the latter, so we make it
1580 // put its own allow(async_yeilds_async) to remain consistent with async fn.
1581 #[async_trait]
1582 pub trait Trait {
f() -> Ready<()>1583 async fn f() -> Ready<()> {
1584 future::ready(())
1585 }
1586 }
1587 }
1588
1589 // https://github.com/dtolnay/async-trait/issues/238
1590 pub mod issue238 {
1591 #![deny(single_use_lifetimes)]
1592
1593 use async_trait::async_trait;
1594
1595 #[async_trait]
1596 pub trait Trait {
f()1597 async fn f();
1598 }
1599
1600 pub struct Struct;
1601
1602 #[async_trait]
1603 impl Trait for &Struct {
f()1604 async fn f() {}
1605 }
1606 }
1607