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