1 #![cfg_attr(
2 async_trait_nightly_testing,
3 feature(min_specialization, type_alias_impl_trait)
4 )]
5 #![allow(
6 clippy::let_underscore_drop,
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]
tracing()621 fn tracing() {
622 // Create the future outside of the subscriber, as no call to tracing
623 // should be made until the future is polled.
624 let mut struct_impl = Impl(0);
625 let fut = struct_impl.foo(5);
626 let subscriber = TestSubscriber::new();
627 subscriber::with_default(subscriber.clone(), || executor::block_on_simple(fut));
628 // Did we enter bar inside of foo?
629 assert_eq!(subscriber.inner.max_depth.load(Ordering::Acquire), 2);
630 // Have we exited all spans?
631 assert_eq!(subscriber.inner.current_depth.load(Ordering::Acquire), 0);
632 // Did we create only two spans? Note: spans start at 1, hence the -1.
633 assert_eq!(subscriber.inner.max_span_id.load(Ordering::Acquire) - 1, 2);
634 // Was the value recorded at the right depth i.e. in the right function?
635 // If so, was it the expected value?
636 assert_eq!(*subscriber.inner.value.lock().unwrap(), Some(("val", 5, 2)));
637 }
638 }
639
640 // https://github.com/dtolnay/async-trait/issues/46
641 pub mod issue46 {
642 use async_trait::async_trait;
643
644 macro_rules! implement_commands_workaround {
645 ($tyargs:tt : $ty:tt) => {
646 #[async_trait]
647 pub trait AsyncCommands1: Sized {
648 async fn f<$tyargs: $ty>(&mut self, x: $tyargs) {
649 self.f(x).await
650 }
651 }
652 };
653 }
654
655 implement_commands_workaround!(K: Send);
656
657 macro_rules! implement_commands {
658 ($tyargs:ident : $ty:ident) => {
659 #[async_trait]
660 pub trait AsyncCommands2: Sized {
661 async fn f<$tyargs: $ty>(&mut self, x: $tyargs) {
662 self.f(x).await
663 }
664 }
665 };
666 }
667
668 implement_commands!(K: Send);
669 }
670
671 // https://github.com/dtolnay/async-trait/issues/53
672 pub mod issue53 {
673 use async_trait::async_trait;
674
675 pub struct Unit;
676 pub struct Tuple(u8);
677 pub struct Struct {
678 pub x: u8,
679 }
680
681 #[async_trait]
682 pub trait Trait {
method()683 async fn method();
684 }
685
686 #[async_trait]
687 impl Trait for Unit {
method()688 async fn method() {
689 let _ = Self;
690 }
691 }
692
693 #[async_trait]
694 impl Trait for Tuple {
method()695 async fn method() {
696 let _ = Self(0);
697 }
698 }
699
700 #[async_trait]
701 impl Trait for Struct {
method()702 async fn method() {
703 let _ = Self { x: 0 };
704 }
705 }
706
707 #[async_trait]
708 impl Trait for std::marker::PhantomData<Struct> {
method()709 async fn method() {
710 let _ = Self;
711 }
712 }
713 }
714
715 // https://github.com/dtolnay/async-trait/issues/57
716 #[cfg(async_trait_nightly_testing)]
717 pub mod issue57 {
718 use crate::executor;
719 use async_trait::async_trait;
720
721 #[async_trait]
722 trait Trait {
const_generic<T: Send, const C: usize>(_: [T; C])723 async fn const_generic<T: Send, const C: usize>(_: [T; C]) {}
724 }
725
726 struct Struct;
727
728 #[async_trait]
729 impl Trait for Struct {
const_generic<T: Send, const C: usize>(_: [T; C])730 async fn const_generic<T: Send, const C: usize>(_: [T; C]) {}
731 }
732
733 #[test]
test()734 fn test() {
735 let fut = Struct::const_generic([0; 10]);
736 executor::block_on_simple(fut);
737 }
738 }
739
740 // https://github.com/dtolnay/async-trait/issues/68
741 pub mod issue68 {
742 #[rustversion::since(1.40)] // procedural macros cannot expand to macro definitions in 1.39.
743 #[async_trait::async_trait]
744 pub trait Example {
method(&self)745 async fn method(&self) {
746 macro_rules! t {
747 () => {{
748 let _: &Self = self;
749 }};
750 }
751 t!();
752 }
753 }
754 }
755
756 // https://github.com/dtolnay/async-trait/issues/73
757 pub mod issue73 {
758 use async_trait::async_trait;
759
760 #[async_trait]
761 pub trait Example {
762 const ASSOCIATED: &'static str;
763
associated(&self)764 async fn associated(&self) {
765 println!("Associated:{}", Self::ASSOCIATED);
766 }
767 }
768 }
769
770 // https://github.com/dtolnay/async-trait/issues/81
771 pub mod issue81 {
772 use async_trait::async_trait;
773
774 #[async_trait]
775 pub trait Trait {
handle(&self)776 async fn handle(&self);
777 }
778
779 pub enum Enum {
780 Variant,
781 }
782
783 #[async_trait]
784 impl Trait for Enum {
handle(&self)785 async fn handle(&self) {
786 let Enum::Variant = self;
787 let Self::Variant = self;
788 }
789 }
790 }
791
792 // https://github.com/dtolnay/async-trait/issues/83
793 pub mod issue83 {
794 #![allow(clippy::needless_arbitrary_self_type)]
795
796 use async_trait::async_trait;
797
798 #[async_trait]
799 pub trait Trait {
f(&self)800 async fn f(&self) {}
g(self: &Self)801 async fn g(self: &Self) {}
802 }
803 }
804
805 // https://github.com/dtolnay/async-trait/issues/85
806 pub mod issue85 {
807 #![deny(non_snake_case)]
808
809 use async_trait::async_trait;
810
811 #[async_trait]
812 pub trait Trait {
813 #[allow(non_snake_case)]
camelCase()814 async fn camelCase();
815 }
816
817 pub struct Struct;
818
819 #[async_trait]
820 impl Trait for Struct {
camelCase()821 async fn camelCase() {}
822 }
823 }
824
825 // https://github.com/dtolnay/async-trait/issues/87
826 pub mod issue87 {
827 use async_trait::async_trait;
828
829 #[async_trait]
830 pub trait Trait {
f(&self)831 async fn f(&self);
832 }
833
834 pub enum Tuple {
835 V(),
836 }
837
838 pub enum Struct {
839 V {},
840 }
841
842 #[async_trait]
843 impl Trait for Tuple {
f(&self)844 async fn f(&self) {
845 let Tuple::V() = self;
846 let Self::V() = self;
847 let _ = Self::V;
848 let _ = Self::V();
849 }
850 }
851
852 #[async_trait]
853 impl Trait for Struct {
f(&self)854 async fn f(&self) {
855 let Struct::V {} = self;
856 let Self::V {} = self;
857 let _ = Self::V {};
858 }
859 }
860 }
861
862 // https://github.com/dtolnay/async-trait/issues/89
863 pub mod issue89 {
864 #![allow(bare_trait_objects)]
865
866 use async_trait::async_trait;
867
868 #[async_trait]
869 trait Trait {
f(&self)870 async fn f(&self);
871 }
872
873 #[async_trait]
874 impl Trait for Send + Sync {
f(&self)875 async fn f(&self) {}
876 }
877
878 #[async_trait]
879 impl Trait for dyn Fn(i8) + Send + Sync {
f(&self)880 async fn f(&self) {}
881 }
882
883 #[async_trait]
884 impl Trait for (dyn Fn(u8) + Send + Sync) {
f(&self)885 async fn f(&self) {}
886 }
887 }
888
889 // https://github.com/dtolnay/async-trait/issues/92
890 pub mod issue92 {
891 use async_trait::async_trait;
892
893 macro_rules! mac {
894 ($($tt:tt)*) => {
895 $($tt)*
896 };
897 }
898
899 pub struct Struct<T> {
900 _x: T,
901 }
902
903 impl<T> Struct<T> {
904 const ASSOCIATED1: &'static str = "1";
associated1()905 async fn associated1() {}
906 }
907
908 #[async_trait]
909 pub trait Trait
910 where
911 mac!(Self): Send,
912 {
913 const ASSOCIATED2: &'static str;
914 type Associated2;
915
916 #[allow(path_statements, clippy::no_effect)]
associated2(&self)917 async fn associated2(&self) {
918 // trait items
919 mac!(let _: Self::Associated2;);
920 mac!(let _: <Self>::Associated2;);
921 mac!(let _: <Self as Trait>::Associated2;);
922 mac!(Self::ASSOCIATED2;);
923 mac!(<Self>::ASSOCIATED2;);
924 mac!(<Self as Trait>::ASSOCIATED2;);
925 mac!(let _ = Self::associated2(self););
926 mac!(let _ = <Self>::associated2(self););
927 mac!(let _ = <Self as Trait>::associated2(self););
928 }
929 }
930
931 #[async_trait]
932 impl<T: Send + Sync> Trait for Struct<T>
933 where
934 mac!(Self): Send,
935 {
936 const ASSOCIATED2: &'static str = "2";
937 type Associated2 = ();
938
939 #[allow(path_statements, clippy::no_effect)]
associated2(&self)940 async fn associated2(&self) {
941 // inherent items
942 mac!(Self::ASSOCIATED1;);
943 mac!(<Self>::ASSOCIATED1;);
944 mac!(let _ = Self::associated1(););
945 mac!(let _ = <Self>::associated1(););
946
947 // trait items
948 mac!(let _: <Self as Trait>::Associated2;);
949 mac!(Self::ASSOCIATED2;);
950 mac!(<Self>::ASSOCIATED2;);
951 mac!(<Self as Trait>::ASSOCIATED2;);
952 mac!(let _ = Self::associated2(self););
953 mac!(let _ = <Self>::associated2(self););
954 mac!(let _ = <Self as Trait>::associated2(self););
955 }
956 }
957
958 pub struct Unit;
959
960 #[async_trait]
961 impl Trait for Unit {
962 const ASSOCIATED2: &'static str = "2";
963 type Associated2 = ();
964
associated2(&self)965 async fn associated2(&self) {
966 mac!(let Self: Self = *self;);
967 }
968 }
969 }
970
971 // https://github.com/dtolnay/async-trait/issues/92#issuecomment-683370136
972 pub mod issue92_2 {
973 use async_trait::async_trait;
974
975 macro_rules! mac {
976 ($($tt:tt)*) => {
977 $($tt)*
978 };
979 }
980
981 pub trait Trait1 {
func1()982 fn func1();
983 }
984
985 #[async_trait]
986 pub trait Trait2: Trait1 {
func2()987 async fn func2() {
988 mac!(Self::func1());
989
990 macro_rules! mac2 {
991 ($($tt:tt)*) => {
992 Self::func1();
993 };
994 }
995 mac2!();
996 }
997 }
998 }
999
1000 // https://github.com/dtolnay/async-trait/issues/104
1001 pub mod issue104 {
1002 use async_trait::async_trait;
1003
1004 #[async_trait]
1005 trait T1 {
id(&self) -> i321006 async fn id(&self) -> i32;
1007 }
1008
1009 macro_rules! impl_t1 {
1010 ($ty:ty, $id:expr) => {
1011 #[async_trait]
1012 impl T1 for $ty {
1013 async fn id(&self) -> i32 {
1014 $id
1015 }
1016 }
1017 };
1018 }
1019
1020 struct Foo;
1021
1022 impl_t1!(Foo, 1);
1023 }
1024
1025 // https://github.com/dtolnay/async-trait/issues/106
1026 pub mod issue106 {
1027 use async_trait::async_trait;
1028 use std::future::Future;
1029
1030 #[async_trait]
1031 pub trait ProcessPool: Send + Sync {
1032 type ThreadPool;
1033
spawn<F, Fut, T>(&self, work: F) -> T where F: FnOnce(&Self::ThreadPool) -> Fut + Send, Fut: Future<Output = T> + 'static1034 async fn spawn<F, Fut, T>(&self, work: F) -> T
1035 where
1036 F: FnOnce(&Self::ThreadPool) -> Fut + Send,
1037 Fut: Future<Output = T> + 'static;
1038 }
1039
1040 #[async_trait]
1041 impl<P: ?Sized> ProcessPool for &P
1042 where
1043 P: ProcessPool,
1044 {
1045 type ThreadPool = P::ThreadPool;
1046
spawn<F, Fut, T>(&self, work: F) -> T where F: FnOnce(&Self::ThreadPool) -> Fut + Send, Fut: Future<Output = T> + 'static,1047 async fn spawn<F, Fut, T>(&self, work: F) -> T
1048 where
1049 F: FnOnce(&Self::ThreadPool) -> Fut + Send,
1050 Fut: Future<Output = T> + 'static,
1051 {
1052 (**self).spawn(work).await
1053 }
1054 }
1055 }
1056
1057 // https://github.com/dtolnay/async-trait/issues/110
1058 pub mod issue110 {
1059 #![deny(clippy::all)]
1060
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 #![deny(clippy::pedantic)]
1117
1118 use async_trait::async_trait;
1119
1120 #[async_trait]
1121 pub trait TestTrait {
a(_b: u8, c: u8) -> u81122 async fn a(_b: u8, c: u8) -> u8 {
1123 c
1124 }
1125 }
1126
1127 pub struct TestStruct;
1128
1129 #[async_trait]
1130 impl TestTrait for TestStruct {
a(_b: u8, c: u8) -> u81131 async fn a(_b: u8, c: u8) -> u8 {
1132 c
1133 }
1134 }
1135 }
1136
1137 // https://github.com/dtolnay/async-trait/issues/134
1138 #[cfg(async_trait_nightly_testing)]
1139 pub mod issue134 {
1140 use async_trait::async_trait;
1141
1142 #[async_trait]
1143 trait TestTrait {
run<const DUMMY: bool>(self) where Self: Sized,1144 async fn run<const DUMMY: bool>(self)
1145 where
1146 Self: Sized,
1147 {
1148 }
1149 }
1150
1151 pub struct TestStruct;
1152
1153 #[async_trait]
1154 impl TestTrait for TestStruct {
run<const DUMMY: bool>(self) where Self: Sized,1155 async fn run<const DUMMY: bool>(self)
1156 where
1157 Self: Sized,
1158 {
1159 }
1160 }
1161 }
1162
1163 // https://github.com/dtolnay/async-trait/pull/125#pullrequestreview-491880881
1164 pub mod drop_order {
1165 use crate::executor;
1166 use async_trait::async_trait;
1167 use std::sync::atomic::{AtomicBool, Ordering};
1168
1169 struct Flagger<'a>(&'a AtomicBool);
1170
1171 impl Drop for Flagger<'_> {
drop(&mut self)1172 fn drop(&mut self) {
1173 self.0.fetch_xor(true, Ordering::AcqRel);
1174 }
1175 }
1176
1177 #[async_trait]
1178 trait Trait {
async_trait(_: Flagger<'_>, flag: &AtomicBool)1179 async fn async_trait(_: Flagger<'_>, flag: &AtomicBool);
1180 }
1181
1182 struct Struct;
1183
1184 #[async_trait]
1185 impl Trait for Struct {
async_trait(_: Flagger<'_>, flag: &AtomicBool)1186 async fn async_trait(_: Flagger<'_>, flag: &AtomicBool) {
1187 flag.fetch_or(true, Ordering::AcqRel);
1188 }
1189 }
1190
standalone(_: Flagger<'_>, flag: &AtomicBool)1191 async fn standalone(_: Flagger<'_>, flag: &AtomicBool) {
1192 flag.fetch_or(true, Ordering::AcqRel);
1193 }
1194
1195 #[async_trait]
1196 trait SelfTrait {
async_trait(self, flag: &AtomicBool)1197 async fn async_trait(self, flag: &AtomicBool);
1198 }
1199
1200 #[async_trait]
1201 impl SelfTrait for Flagger<'_> {
async_trait(self, flag: &AtomicBool)1202 async fn async_trait(self, flag: &AtomicBool) {
1203 flag.fetch_or(true, Ordering::AcqRel);
1204 }
1205 }
1206
1207 #[test]
test_drop_order()1208 fn test_drop_order() {
1209 // 0 : 0 ^ 1 = 1 | 1 = 1 (if flagger then block)
1210 // 0 : 0 | 1 = 1 ^ 1 = 0 (if block then flagger)
1211
1212 let flag = AtomicBool::new(false);
1213 executor::block_on_simple(standalone(Flagger(&flag), &flag));
1214 assert!(!flag.load(Ordering::Acquire));
1215
1216 executor::block_on_simple(Struct::async_trait(Flagger(&flag), &flag));
1217 assert!(!flag.load(Ordering::Acquire));
1218
1219 executor::block_on_simple(Flagger(&flag).async_trait(&flag));
1220 assert!(!flag.load(Ordering::Acquire));
1221 }
1222 }
1223
1224 // https://github.com/dtolnay/async-trait/issues/145
1225 pub mod issue145 {
1226 #![deny(clippy::type_complexity)]
1227
1228 use async_trait::async_trait;
1229
1230 #[async_trait]
1231 pub trait ManageConnection: Sized + Send + Sync + 'static {
1232 type Connection: Send + 'static;
1233 type Error: Send + 'static;
1234
connect(&self) -> Result<Self::Connection, Self::Error>1235 async fn connect(&self) -> Result<Self::Connection, Self::Error>;
1236 }
1237 }
1238
1239 // https://github.com/dtolnay/async-trait/issues/147
1240 pub mod issue147 {
1241 #![deny(clippy::let_unit_value)]
1242
1243 use async_trait::async_trait;
1244
1245 pub struct MyType;
1246
1247 #[async_trait]
1248 pub trait MyTrait {
x()1249 async fn x();
y() -> ()1250 async fn y() -> ();
z()1251 async fn z();
1252 }
1253
1254 #[async_trait]
1255 impl MyTrait for MyType {
x()1256 async fn x() {}
y() -> ()1257 async fn y() -> () {}
z()1258 async fn z() {
1259 unimplemented!()
1260 }
1261 }
1262 }
1263
1264 // https://github.com/dtolnay/async-trait/issues/149
1265 pub mod issue149 {
1266 use async_trait::async_trait;
1267
1268 pub struct Thing;
1269 pub trait Ret {}
1270 impl Ret for Thing {}
1271
ok() -> &'static dyn Ret1272 pub async fn ok() -> &'static dyn Ret {
1273 return &Thing;
1274 }
1275
1276 #[async_trait]
1277 pub trait Trait {
fail() -> &'static dyn Ret1278 async fn fail() -> &'static dyn Ret {
1279 return &Thing;
1280 }
1281 }
1282 }
1283
1284 // https://github.com/dtolnay/async-trait/issues/152
1285 #[cfg(async_trait_nightly_testing)]
1286 pub mod issue152 {
1287 use async_trait::async_trait;
1288
1289 #[async_trait]
1290 trait Trait {
1291 type Assoc;
1292
f(&self) -> Self::Assoc1293 async fn f(&self) -> Self::Assoc;
1294 }
1295
1296 struct Struct;
1297
1298 #[async_trait]
1299 impl Trait for Struct {
1300 type Assoc = impl Sized;
1301
1302 async fn f(&self) -> Self::Assoc {}
1303 }
1304 }
1305
1306 // https://github.com/dtolnay/async-trait/issues/154
1307 pub mod issue154 {
1308 #![deny(clippy::items_after_statements)]
1309
1310 use async_trait::async_trait;
1311
1312 #[async_trait]
1313 pub trait MyTrait {
f(&self)1314 async fn f(&self);
1315 }
1316
1317 pub struct Struct;
1318
1319 #[async_trait]
1320 impl MyTrait for Struct {
f(&self)1321 async fn f(&self) {
1322 const MAX: u16 = 128;
1323 println!("{}", MAX);
1324 }
1325 }
1326 }
1327
1328 // https://github.com/dtolnay/async-trait/issues/158
1329 pub mod issue158 {
1330 use async_trait::async_trait;
1331
f()1332 fn f() {}
1333
1334 #[async_trait]
1335 pub trait Trait {
f(&self)1336 async fn f(&self) {
1337 self::f();
1338 }
1339 }
1340 }
1341
1342 // https://github.com/dtolnay/async-trait/issues/161
1343 #[allow(clippy::mut_mut)]
1344 pub mod issue161 {
1345 use async_trait::async_trait;
1346 use futures::future::FutureExt;
1347 use std::sync::Arc;
1348
1349 #[async_trait]
1350 pub trait Trait {
f(self: Arc<Self>)1351 async fn f(self: Arc<Self>);
1352 }
1353
1354 pub struct MyStruct(bool);
1355
1356 #[async_trait]
1357 impl Trait for MyStruct {
f(self: Arc<Self>)1358 async fn f(self: Arc<Self>) {
1359 futures::select! {
1360 _ = async {
1361 println!("{}", self.0);
1362 }.fuse() => {}
1363 }
1364 }
1365 }
1366 }
1367
1368 // https://github.com/dtolnay/async-trait/issues/169
1369 #[deny(where_clauses_object_safety)]
1370 pub mod issue169 {
1371 use async_trait::async_trait;
1372
1373 #[async_trait]
1374 pub trait Trait: ::core::marker::Sync {
f(&self)1375 async fn f(&self) {}
1376 }
1377
test(_t: &dyn Trait)1378 pub fn test(_t: &dyn Trait) {}
1379 }
1380
1381 // https://github.com/dtolnay/async-trait/issues/183
1382 pub mod issue183 {
1383 #![deny(clippy::shadow_same)]
1384
1385 use async_trait::async_trait;
1386
1387 #[async_trait]
1388 trait Foo {
foo(_n: i32)1389 async fn foo(_n: i32) {}
1390 }
1391 }
1392