1 #![cfg_attr(
2 async_trait_nightly_testing,
3 feature(min_specialization, min_type_alias_impl_trait)
4 )]
5 #![allow(
6 clippy::let_underscore_drop,
7 clippy::let_unit_value,
8 clippy::missing_panics_doc,
9 clippy::trivially_copy_pass_by_ref
10 )]
11
12 use async_trait::async_trait;
13
14 pub mod executor;
15
16 // Dummy module to check that the expansion refer to rust's core crate
17 mod core {}
18
19 #[async_trait]
20 trait Trait {
21 type Assoc;
22
selfvalue(self) where Self: Sized,23 async fn selfvalue(self)
24 where
25 Self: Sized,
26 {
27 }
28
selfref(&self)29 async fn selfref(&self) {}
30
selfmut(&mut self)31 async fn selfmut(&mut self) {}
32
required() -> Self::Assoc33 async fn required() -> Self::Assoc;
34
elided_lifetime(_x: &str)35 async fn elided_lifetime(_x: &str) {}
36
explicit_lifetime<'a>(_x: &'a str)37 async fn explicit_lifetime<'a>(_x: &'a str) {}
38
generic_type_param<T: Send>(x: Box<T>) -> T39 async fn generic_type_param<T: Send>(x: Box<T>) -> T {
40 *x
41 }
42
calls(&self)43 async fn calls(&self) {
44 self.selfref().await;
45 Self::elided_lifetime("").await;
46 <Self>::elided_lifetime("").await;
47 }
48
calls_mut(&mut self)49 async fn calls_mut(&mut self) {
50 self.selfmut().await;
51 }
52 }
53
54 struct Struct;
55
56 #[async_trait]
57 impl Trait for Struct {
58 type Assoc = ();
59
selfvalue(self)60 async fn selfvalue(self) {}
61
selfref(&self)62 async fn selfref(&self) {}
63
selfmut(&mut self)64 async fn selfmut(&mut self) {}
65
required() -> Self::Assoc66 async fn required() -> Self::Assoc {}
67
elided_lifetime(_x: &str)68 async fn elided_lifetime(_x: &str) {}
69
explicit_lifetime<'a>(_x: &'a str)70 async fn explicit_lifetime<'a>(_x: &'a str) {}
71
generic_type_param<T: Send>(x: Box<T>) -> T72 async fn generic_type_param<T: Send>(x: Box<T>) -> T {
73 *x
74 }
75
calls(&self)76 async fn calls(&self) {
77 self.selfref().await;
78 Self::elided_lifetime("").await;
79 <Self>::elided_lifetime("").await;
80 }
81
calls_mut(&mut self)82 async fn calls_mut(&mut self) {
83 self.selfmut().await;
84 }
85 }
86
test()87 pub async fn test() {
88 let mut s = Struct;
89 s.selfref().await;
90 s.selfmut().await;
91 s.selfvalue().await;
92
93 Struct::required().await;
94 Struct::elided_lifetime("").await;
95 Struct::explicit_lifetime("").await;
96 Struct::generic_type_param(Box::new("")).await;
97
98 let mut s = Struct;
99 s.calls().await;
100 s.calls_mut().await;
101 }
102
test_object_safe_without_default()103 pub async fn test_object_safe_without_default() {
104 #[async_trait]
105 trait ObjectSafe {
106 async fn f(&self);
107 }
108
109 #[async_trait]
110 impl ObjectSafe for Struct {
111 async fn f(&self) {}
112 }
113
114 let object = &Struct as &dyn ObjectSafe;
115 object.f().await;
116 }
117
test_object_safe_with_default()118 pub async fn test_object_safe_with_default() {
119 #[async_trait]
120 trait ObjectSafe: Sync {
121 async fn f(&self) {}
122 }
123
124 #[async_trait]
125 impl ObjectSafe for Struct {
126 async fn f(&self) {}
127 }
128
129 let object = &Struct as &dyn ObjectSafe;
130 object.f().await;
131 }
132
test_object_no_send()133 pub async fn test_object_no_send() {
134 #[async_trait(?Send)]
135 trait ObjectSafe: Sync {
136 async fn f(&self) {}
137 }
138
139 #[async_trait(?Send)]
140 impl ObjectSafe for Struct {
141 async fn f(&self) {}
142 }
143
144 let object = &Struct as &dyn ObjectSafe;
145 object.f().await;
146 }
147
148 #[async_trait]
149 pub unsafe trait UnsafeTrait {}
150
151 #[async_trait]
152 unsafe impl UnsafeTrait for () {}
153
154 #[async_trait]
155 pub(crate) unsafe trait UnsafeTraitPubCrate {}
156
157 #[async_trait]
158 unsafe trait UnsafeTraitPrivate {}
159
test_can_destruct()160 pub async fn test_can_destruct() {
161 #[async_trait]
162 trait CanDestruct {
163 async fn f(&self, foos: (u8, u8, u8, u8));
164 }
165
166 #[async_trait]
167 impl CanDestruct for Struct {
168 async fn f(&self, (a, ref mut b, ref c, d): (u8, u8, u8, u8)) {
169 let _a: u8 = a;
170 let _b: &mut u8 = b;
171 let _c: &u8 = c;
172 let _d: u8 = d;
173 }
174 }
175 }
176
test_self_in_macro()177 pub async fn test_self_in_macro() {
178 #[async_trait]
179 trait Trait {
180 async fn a(self);
181 async fn b(&mut self);
182 async fn c(&self);
183 }
184
185 #[async_trait]
186 impl Trait for String {
187 async fn a(self) {
188 println!("{}", self);
189 }
190 async fn b(&mut self) {
191 println!("{}", self);
192 }
193 async fn c(&self) {
194 println!("{}", self);
195 }
196 }
197 }
198
test_inference()199 pub async fn test_inference() {
200 #[async_trait]
201 pub trait Trait {
202 async fn f() -> Box<dyn Iterator<Item = ()>> {
203 Box::new(std::iter::empty())
204 }
205 }
206 }
207
test_internal_items()208 pub async fn test_internal_items() {
209 #[async_trait]
210 #[allow(dead_code, clippy::items_after_statements)]
211 pub trait Trait: Sized {
212 async fn f(self) {
213 struct Struct;
214
215 impl Struct {
216 fn f(self) {
217 let _ = self;
218 }
219 }
220 }
221 }
222 }
223
test_unimplemented()224 pub async fn test_unimplemented() {
225 #[async_trait]
226 pub trait Trait {
227 async fn f() {
228 unimplemented!()
229 }
230 }
231 }
232
233 // https://github.com/dtolnay/async-trait/issues/1
234 pub mod issue1 {
235 use async_trait::async_trait;
236
237 #[async_trait]
238 trait Issue1 {
f<U>(&self)239 async fn f<U>(&self);
240 }
241
242 #[async_trait]
243 impl<T: Sync> Issue1 for Vec<T> {
f<U>(&self)244 async fn f<U>(&self) {}
245 }
246 }
247
248 // https://github.com/dtolnay/async-trait/issues/2
249 pub mod issue2 {
250 use async_trait::async_trait;
251 use std::future::Future;
252
253 #[async_trait]
254 pub trait Issue2: Future {
flatten(self) -> <Self::Output as Future>::Output where Self::Output: Future + Send, Self: Sized,255 async fn flatten(self) -> <Self::Output as Future>::Output
256 where
257 Self::Output: Future + Send,
258 Self: Sized,
259 {
260 let nested_future = self.await;
261 nested_future.await
262 }
263 }
264 }
265
266 // https://github.com/dtolnay/async-trait/issues/9
267 pub mod issue9 {
268 use async_trait::async_trait;
269
270 #[async_trait]
271 pub trait Issue9: Sized + Send {
f(_x: Self)272 async fn f(_x: Self) {}
273 }
274 }
275
276 // https://github.com/dtolnay/async-trait/issues/11
277 pub mod issue11 {
278 use async_trait::async_trait;
279 use std::sync::Arc;
280
281 #[async_trait]
282 trait Issue11 {
example(self: Arc<Self>)283 async fn example(self: Arc<Self>);
284 }
285
286 struct Struct;
287
288 #[async_trait]
289 impl Issue11 for Struct {
example(self: Arc<Self>)290 async fn example(self: Arc<Self>) {}
291 }
292 }
293
294 // https://github.com/dtolnay/async-trait/issues/15
295 pub mod issue15 {
296 use async_trait::async_trait;
297 use std::marker::PhantomData;
298
299 trait Trait {}
300
301 #[async_trait]
302 trait Issue15 {
myfn(&self, _: PhantomData<dyn Trait + Send>)303 async fn myfn(&self, _: PhantomData<dyn Trait + Send>) {}
304 }
305 }
306
307 // https://github.com/dtolnay/async-trait/issues/17
308 pub mod issue17 {
309 use async_trait::async_trait;
310
311 #[async_trait]
312 trait Issue17 {
f(&self)313 async fn f(&self);
314 }
315
316 struct Struct {
317 string: String,
318 }
319
320 #[async_trait]
321 impl Issue17 for Struct {
f(&self)322 async fn f(&self) {
323 println!("{}", self.string);
324 }
325 }
326 }
327
328 // https://github.com/dtolnay/async-trait/issues/23
329 pub mod issue23 {
330 use async_trait::async_trait;
331
332 #[async_trait]
333 pub trait Issue23 {
f(self)334 async fn f(self);
335
g(mut self) where Self: Sized,336 async fn g(mut self)
337 where
338 Self: Sized,
339 {
340 do_something(&mut self);
341 }
342 }
343
344 struct S {}
345
346 #[async_trait]
347 impl Issue23 for S {
f(mut self)348 async fn f(mut self) {
349 do_something(&mut self);
350 }
351 }
352
do_something<T>(_: &mut T)353 fn do_something<T>(_: &mut T) {}
354 }
355
356 // https://github.com/dtolnay/async-trait/issues/25
357 #[cfg(async_trait_nightly_testing)]
358 pub mod issue25 {
359 use crate::executor;
360 use async_trait::async_trait;
361 use std::fmt::{Display, Write};
362
363 #[async_trait]
364 trait AsyncToString {
async_to_string(&self) -> String365 async fn async_to_string(&self) -> String;
366 }
367
368 #[async_trait]
369 impl AsyncToString for String {
async_to_string(&self) -> String370 async fn async_to_string(&self) -> String {
371 "special".to_owned()
372 }
373 }
374
375 macro_rules! hide_from_stable_parser {
376 ($($tt:tt)*) => {
377 $($tt)*
378 };
379 }
380
381 hide_from_stable_parser! {
382 #[async_trait]
383 impl<T: ?Sized + Display + Sync> AsyncToString for T {
384 default async fn async_to_string(&self) -> String {
385 let mut buf = String::new();
386 buf.write_fmt(format_args!("{}", self)).unwrap();
387 buf
388 }
389 }
390 }
391
392 #[test]
test()393 fn test() {
394 let fut = true.async_to_string();
395 assert_eq!(executor::block_on_simple(fut), "true");
396
397 let string = String::new();
398 let fut = string.async_to_string();
399 assert_eq!(executor::block_on_simple(fut), "special");
400 }
401 }
402
403 // https://github.com/dtolnay/async-trait/issues/28
404 pub mod issue28 {
405 use async_trait::async_trait;
406
407 struct Str<'a>(&'a str);
408
409 #[async_trait]
410 trait Trait1<'a> {
f(x: Str<'a>) -> &'a str411 async fn f(x: Str<'a>) -> &'a str;
g(x: Str<'a>) -> &'a str412 async fn g(x: Str<'a>) -> &'a str {
413 x.0
414 }
415 }
416
417 #[async_trait]
418 impl<'a> Trait1<'a> for str {
f(x: Str<'a>) -> &'a str419 async fn f(x: Str<'a>) -> &'a str {
420 x.0
421 }
422 }
423
424 #[async_trait]
425 trait Trait2 {
f()426 async fn f();
427 }
428
429 #[async_trait]
430 impl<'a> Trait2 for &'a () {
f()431 async fn f() {}
432 }
433
434 #[async_trait]
435 trait Trait3<'a, 'b> {
f(_: &'a &'b ())436 async fn f(_: &'a &'b ()); // chain 'a and 'b
g(_: &'b ())437 async fn g(_: &'b ()); // chain 'b only
h()438 async fn h(); // do not chain
439 }
440 }
441
442 // https://github.com/dtolnay/async-trait/issues/31
443 pub mod issue31 {
444 use async_trait::async_trait;
445
446 pub struct Struct<'a> {
447 pub name: &'a str,
448 }
449
450 #[async_trait]
451 pub trait Trait<'a> {
hello(thing: Struct<'a>) -> String452 async fn hello(thing: Struct<'a>) -> String;
hello_twice(one: Struct<'a>, two: Struct<'a>) -> String453 async fn hello_twice(one: Struct<'a>, two: Struct<'a>) -> String {
454 let str1 = Self::hello(one).await;
455 let str2 = Self::hello(two).await;
456 str1 + &str2
457 }
458 }
459 }
460
461 // https://github.com/dtolnay/async-trait/issues/42
462 pub mod issue42 {
463 use async_trait::async_trait;
464
465 #[async_trait]
466 pub trait Context: Sized {
from_parts() -> Self467 async fn from_parts() -> Self;
468 }
469
470 pub struct TokenContext;
471
472 #[async_trait]
473 impl Context for TokenContext {
from_parts() -> TokenContext474 async fn from_parts() -> TokenContext {
475 TokenContext
476 }
477 }
478 }
479
480 // https://github.com/dtolnay/async-trait/issues/44
481 pub mod issue44 {
482 use async_trait::async_trait;
483
484 #[async_trait]
485 pub trait StaticWithWhereSelf
486 where
487 Box<Self>: Sized,
488 Self: Sized + Send,
489 {
get_one() -> u8490 async fn get_one() -> u8 {
491 1
492 }
493 }
494
495 pub struct Struct;
496
497 #[async_trait]
498 impl StaticWithWhereSelf for Struct {}
499 }
500
501 // https://github.com/dtolnay/async-trait/issues/45
502 pub mod issue45 {
503 use crate::executor;
504 use async_trait::async_trait;
505 use std::fmt::Debug;
506 use std::sync::atomic::{AtomicU64, Ordering};
507 use std::sync::{Arc, Mutex};
508 use tracing::event::Event;
509 use tracing::field::{Field, Visit};
510 use tracing::span::{Attributes, Id, Record};
511 use tracing::{info, instrument, subscriber, Metadata, Subscriber};
512
513 #[async_trait]
514 pub trait Parent {
foo(&mut self, v: usize)515 async fn foo(&mut self, v: usize);
516 }
517
518 #[async_trait]
519 pub trait Child {
bar(&self)520 async fn bar(&self);
521 }
522
523 #[derive(Debug)]
524 struct Impl(usize);
525
526 #[async_trait]
527 impl Parent for Impl {
528 #[instrument]
foo(&mut self, v: usize)529 async fn foo(&mut self, v: usize) {
530 self.0 = v;
531 self.bar().await;
532 }
533 }
534
535 #[async_trait]
536 impl Child for Impl {
537 // Let's check that tracing detects the renaming of the `self` variable
538 // too, as tracing::instrument is not going to be able to skip the
539 // `self` argument if it can't find it in the function signature.
540 #[instrument(skip(self))]
bar(&self)541 async fn bar(&self) {
542 info!(val = self.0);
543 }
544 }
545
546 // A simple subscriber implementation to test the behavior of async-trait
547 // with tokio-rs/tracing. This implementation is not robust against race
548 // conditions, but it's not an issue here as we are only polling on a single
549 // future at a time.
550 #[derive(Debug)]
551 struct SubscriberInner {
552 current_depth: AtomicU64,
553 // We assert that nested functions work. If the fix were to break, we
554 // would see two top-level functions instead of `bar` nested in `foo`.
555 max_depth: AtomicU64,
556 max_span_id: AtomicU64,
557 // Name of the variable / value / depth when the event was recorded.
558 value: Mutex<Option<(&'static str, u64, u64)>>,
559 }
560
561 #[derive(Debug, Clone)]
562 struct TestSubscriber {
563 inner: Arc<SubscriberInner>,
564 }
565
566 impl TestSubscriber {
new() -> Self567 fn new() -> Self {
568 TestSubscriber {
569 inner: Arc::new(SubscriberInner {
570 current_depth: AtomicU64::new(0),
571 max_depth: AtomicU64::new(0),
572 max_span_id: AtomicU64::new(1),
573 value: Mutex::new(None),
574 }),
575 }
576 }
577 }
578
579 struct U64Visitor(Option<(&'static str, u64)>);
580
581 impl Visit for U64Visitor {
record_debug(&mut self, _field: &Field, _value: &dyn Debug)582 fn record_debug(&mut self, _field: &Field, _value: &dyn Debug) {}
583
record_u64(&mut self, field: &Field, value: u64)584 fn record_u64(&mut self, field: &Field, value: u64) {
585 self.0 = Some((field.name(), value));
586 }
587 }
588
589 impl Subscriber for TestSubscriber {
enabled(&self, _metadata: &Metadata) -> bool590 fn enabled(&self, _metadata: &Metadata) -> bool {
591 true
592 }
new_span(&self, _span: &Attributes) -> Id593 fn new_span(&self, _span: &Attributes) -> Id {
594 Id::from_u64(self.inner.max_span_id.fetch_add(1, Ordering::AcqRel))
595 }
record(&self, _span: &Id, _values: &Record)596 fn record(&self, _span: &Id, _values: &Record) {}
record_follows_from(&self, _span: &Id, _follows: &Id)597 fn record_follows_from(&self, _span: &Id, _follows: &Id) {}
event(&self, event: &Event)598 fn event(&self, event: &Event) {
599 let mut visitor = U64Visitor(None);
600 event.record(&mut visitor);
601 if let Some((s, v)) = visitor.0 {
602 let current_depth = self.inner.current_depth.load(Ordering::Acquire);
603 *self.inner.value.lock().unwrap() = Some((s, v, current_depth));
604 }
605 }
enter(&self, _span: &Id)606 fn enter(&self, _span: &Id) {
607 let old_depth = self.inner.current_depth.fetch_add(1, Ordering::AcqRel);
608 if old_depth + 1 > self.inner.max_depth.load(Ordering::Acquire) {
609 self.inner.max_depth.fetch_add(1, Ordering::AcqRel);
610 }
611 }
exit(&self, _span: &Id)612 fn exit(&self, _span: &Id) {
613 self.inner.current_depth.fetch_sub(1, Ordering::AcqRel);
614 }
615 }
616
617 #[test]
tracing()618 fn tracing() {
619 // Create the future outside of the subscriber, as no call to tracing
620 // should be made until the future is polled.
621 let mut struct_impl = Impl(0);
622 let fut = struct_impl.foo(5);
623 let subscriber = TestSubscriber::new();
624 subscriber::with_default(subscriber.clone(), || executor::block_on_simple(fut));
625 // Did we enter bar inside of foo?
626 assert_eq!(subscriber.inner.max_depth.load(Ordering::Acquire), 2);
627 // Have we exited all spans?
628 assert_eq!(subscriber.inner.current_depth.load(Ordering::Acquire), 0);
629 // Did we create only two spans? Note: spans start at 1, hence the -1.
630 assert_eq!(subscriber.inner.max_span_id.load(Ordering::Acquire) - 1, 2);
631 // Was the value recorded at the right depth i.e. in the right function?
632 // If so, was it the expected value?
633 assert_eq!(*subscriber.inner.value.lock().unwrap(), Some(("val", 5, 2)));
634 }
635 }
636
637 // https://github.com/dtolnay/async-trait/issues/46
638 pub mod issue46 {
639 use async_trait::async_trait;
640
641 macro_rules! implement_commands_workaround {
642 ($tyargs:tt : $ty:tt) => {
643 #[async_trait]
644 pub trait AsyncCommands1: Sized {
645 async fn f<$tyargs: $ty>(&mut self, x: $tyargs) {
646 self.f(x).await
647 }
648 }
649 };
650 }
651
652 implement_commands_workaround!(K: Send);
653
654 macro_rules! implement_commands {
655 ($tyargs:ident : $ty:ident) => {
656 #[async_trait]
657 pub trait AsyncCommands2: Sized {
658 async fn f<$tyargs: $ty>(&mut self, x: $tyargs) {
659 self.f(x).await
660 }
661 }
662 };
663 }
664
665 implement_commands!(K: Send);
666 }
667
668 // https://github.com/dtolnay/async-trait/issues/53
669 pub mod issue53 {
670 use async_trait::async_trait;
671
672 pub struct Unit;
673 pub struct Tuple(u8);
674 pub struct Struct {
675 pub x: u8,
676 }
677
678 #[async_trait]
679 pub trait Trait {
method()680 async fn method();
681 }
682
683 #[async_trait]
684 impl Trait for Unit {
method()685 async fn method() {
686 let _ = Self;
687 }
688 }
689
690 #[async_trait]
691 impl Trait for Tuple {
method()692 async fn method() {
693 let _ = Self(0);
694 }
695 }
696
697 #[async_trait]
698 impl Trait for Struct {
method()699 async fn method() {
700 let _ = Self { x: 0 };
701 }
702 }
703
704 #[async_trait]
705 impl Trait for std::marker::PhantomData<Struct> {
method()706 async fn method() {
707 let _ = Self;
708 }
709 }
710 }
711
712 // https://github.com/dtolnay/async-trait/issues/57
713 #[cfg(async_trait_nightly_testing)]
714 pub mod issue57 {
715 use crate::executor;
716 use async_trait::async_trait;
717
718 #[async_trait]
719 trait Trait {
const_generic<T: Send, const C: usize>(_: [T; C])720 async fn const_generic<T: Send, const C: usize>(_: [T; C]) {}
721 }
722
723 struct Struct;
724
725 #[async_trait]
726 impl Trait for Struct {
const_generic<T: Send, const C: usize>(_: [T; C])727 async fn const_generic<T: Send, const C: usize>(_: [T; C]) {}
728 }
729
730 #[test]
test()731 fn test() {
732 let fut = Struct::const_generic([0; 10]);
733 executor::block_on_simple(fut);
734 }
735 }
736
737 // https://github.com/dtolnay/async-trait/issues/68
738 pub mod issue68 {
739 #[rustversion::since(1.40)] // procedural macros cannot expand to macro definitions in 1.39.
740 #[async_trait::async_trait]
741 pub trait Example {
method(&self)742 async fn method(&self) {
743 macro_rules! t {
744 () => {{
745 let _: &Self = self;
746 }};
747 }
748 t!();
749 }
750 }
751 }
752
753 // https://github.com/dtolnay/async-trait/issues/73
754 pub mod issue73 {
755 use async_trait::async_trait;
756
757 #[async_trait]
758 pub trait Example {
759 const ASSOCIATED: &'static str;
760
associated(&self)761 async fn associated(&self) {
762 println!("Associated:{}", Self::ASSOCIATED);
763 }
764 }
765 }
766
767 // https://github.com/dtolnay/async-trait/issues/81
768 pub mod issue81 {
769 use async_trait::async_trait;
770
771 #[async_trait]
772 pub trait Trait {
handle(&self)773 async fn handle(&self);
774 }
775
776 pub enum Enum {
777 Variant,
778 }
779
780 #[async_trait]
781 impl Trait for Enum {
handle(&self)782 async fn handle(&self) {
783 let Enum::Variant = self;
784 let Self::Variant = self;
785 }
786 }
787 }
788
789 // https://github.com/dtolnay/async-trait/issues/83
790 pub mod issue83 {
791 #![allow(clippy::needless_arbitrary_self_type)]
792
793 use async_trait::async_trait;
794
795 #[async_trait]
796 pub trait Trait {
f(&self)797 async fn f(&self) {}
g(self: &Self)798 async fn g(self: &Self) {}
799 }
800 }
801
802 // https://github.com/dtolnay/async-trait/issues/85
803 pub mod issue85 {
804 #![deny(non_snake_case)]
805
806 use async_trait::async_trait;
807
808 #[async_trait]
809 pub trait Trait {
810 #[allow(non_snake_case)]
camelCase()811 async fn camelCase();
812 }
813
814 pub struct Struct;
815
816 #[async_trait]
817 impl Trait for Struct {
camelCase()818 async fn camelCase() {}
819 }
820 }
821
822 // https://github.com/dtolnay/async-trait/issues/87
823 pub mod issue87 {
824 use async_trait::async_trait;
825
826 #[async_trait]
827 pub trait Trait {
f(&self)828 async fn f(&self);
829 }
830
831 pub enum Tuple {
832 V(),
833 }
834
835 pub enum Struct {
836 V {},
837 }
838
839 #[async_trait]
840 impl Trait for Tuple {
f(&self)841 async fn f(&self) {
842 let Tuple::V() = self;
843 let Self::V() = self;
844 let _ = Self::V;
845 let _ = Self::V();
846 }
847 }
848
849 #[async_trait]
850 impl Trait for Struct {
f(&self)851 async fn f(&self) {
852 let Struct::V {} = self;
853 let Self::V {} = self;
854 let _ = Self::V {};
855 }
856 }
857 }
858
859 // https://github.com/dtolnay/async-trait/issues/89
860 pub mod issue89 {
861 #![allow(bare_trait_objects)]
862
863 use async_trait::async_trait;
864
865 #[async_trait]
866 trait Trait {
f(&self)867 async fn f(&self);
868 }
869
870 #[async_trait]
871 impl Trait for Send + Sync {
f(&self)872 async fn f(&self) {}
873 }
874
875 #[async_trait]
876 impl Trait for dyn Fn(i8) + Send + Sync {
f(&self)877 async fn f(&self) {}
878 }
879
880 #[async_trait]
881 impl Trait for (dyn Fn(u8) + Send + Sync) {
f(&self)882 async fn f(&self) {}
883 }
884 }
885
886 // https://github.com/dtolnay/async-trait/issues/92
887 pub mod issue92 {
888 use async_trait::async_trait;
889
890 macro_rules! mac {
891 ($($tt:tt)*) => {
892 $($tt)*
893 };
894 }
895
896 pub struct Struct<T> {
897 _x: T,
898 }
899
900 impl<T> Struct<T> {
901 const ASSOCIATED1: &'static str = "1";
associated1()902 async fn associated1() {}
903 }
904
905 #[async_trait]
906 pub trait Trait
907 where
908 mac!(Self): Send,
909 {
910 const ASSOCIATED2: &'static str;
911 type Associated2;
912
913 #[allow(path_statements, clippy::no_effect)]
associated2(&self)914 async fn associated2(&self) {
915 // trait items
916 mac!(let _: Self::Associated2;);
917 mac!(let _: <Self>::Associated2;);
918 mac!(let _: <Self as Trait>::Associated2;);
919 mac!(Self::ASSOCIATED2;);
920 mac!(<Self>::ASSOCIATED2;);
921 mac!(<Self as Trait>::ASSOCIATED2;);
922 mac!(let _ = Self::associated2(self););
923 mac!(let _ = <Self>::associated2(self););
924 mac!(let _ = <Self as Trait>::associated2(self););
925 }
926 }
927
928 #[async_trait]
929 impl<T: Send + Sync> Trait for Struct<T>
930 where
931 mac!(Self): Send,
932 {
933 const ASSOCIATED2: &'static str = "2";
934 type Associated2 = ();
935
936 #[allow(path_statements, clippy::no_effect)]
associated2(&self)937 async fn associated2(&self) {
938 // inherent items
939 mac!(Self::ASSOCIATED1;);
940 mac!(<Self>::ASSOCIATED1;);
941 mac!(let _ = Self::associated1(););
942 mac!(let _ = <Self>::associated1(););
943
944 // trait items
945 mac!(let _: <Self as Trait>::Associated2;);
946 mac!(Self::ASSOCIATED2;);
947 mac!(<Self>::ASSOCIATED2;);
948 mac!(<Self as Trait>::ASSOCIATED2;);
949 mac!(let _ = Self::associated2(self););
950 mac!(let _ = <Self>::associated2(self););
951 mac!(let _ = <Self as Trait>::associated2(self););
952 }
953 }
954
955 pub struct Unit;
956
957 #[async_trait]
958 impl Trait for Unit {
959 const ASSOCIATED2: &'static str = "2";
960 type Associated2 = ();
961
associated2(&self)962 async fn associated2(&self) {
963 mac!(let Self: Self = *self;);
964 }
965 }
966 }
967
968 // https://github.com/dtolnay/async-trait/issues/92#issuecomment-683370136
969 pub mod issue92_2 {
970 use async_trait::async_trait;
971
972 macro_rules! mac {
973 ($($tt:tt)*) => {
974 $($tt)*
975 };
976 }
977
978 pub trait Trait1 {
func1()979 fn func1();
980 }
981
982 #[async_trait]
983 pub trait Trait2: Trait1 {
func2()984 async fn func2() {
985 mac!(Self::func1());
986
987 macro_rules! mac2 {
988 ($($tt:tt)*) => {
989 Self::func1();
990 };
991 }
992 mac2!();
993 }
994 }
995 }
996
997 // https://github.com/dtolnay/async-trait/issues/104
998 pub mod issue104 {
999 use async_trait::async_trait;
1000
1001 #[async_trait]
1002 trait T1 {
id(&self) -> i321003 async fn id(&self) -> i32;
1004 }
1005
1006 macro_rules! impl_t1 {
1007 ($ty:ty, $id:expr) => {
1008 #[async_trait]
1009 impl T1 for $ty {
1010 async fn id(&self) -> i32 {
1011 $id
1012 }
1013 }
1014 };
1015 }
1016
1017 struct Foo;
1018
1019 impl_t1!(Foo, 1);
1020 }
1021
1022 // https://github.com/dtolnay/async-trait/issues/106
1023 pub mod issue106 {
1024 use async_trait::async_trait;
1025 use std::future::Future;
1026
1027 #[async_trait]
1028 pub trait ProcessPool: Send + Sync {
1029 type ThreadPool;
1030
spawn<F, Fut, T>(&self, work: F) -> T where F: FnOnce(&Self::ThreadPool) -> Fut + Send, Fut: Future<Output = T> + 'static1031 async fn spawn<F, Fut, T>(&self, work: F) -> T
1032 where
1033 F: FnOnce(&Self::ThreadPool) -> Fut + Send,
1034 Fut: Future<Output = T> + 'static;
1035 }
1036
1037 #[async_trait]
1038 impl<P: ?Sized> ProcessPool for &P
1039 where
1040 P: ProcessPool,
1041 {
1042 type ThreadPool = P::ThreadPool;
1043
spawn<F, Fut, T>(&self, work: F) -> T where F: FnOnce(&Self::ThreadPool) -> Fut + Send, Fut: Future<Output = T> + 'static,1044 async fn spawn<F, Fut, T>(&self, work: F) -> T
1045 where
1046 F: FnOnce(&Self::ThreadPool) -> Fut + Send,
1047 Fut: Future<Output = T> + 'static,
1048 {
1049 (**self).spawn(work).await
1050 }
1051 }
1052 }
1053
1054 // https://github.com/dtolnay/async-trait/issues/110
1055 pub mod issue110 {
1056 #![deny(clippy::all)]
1057
1058 use async_trait::async_trait;
1059 use std::marker::PhantomData;
1060
1061 #[async_trait]
1062 pub trait Loader {
load(&self, key: &str)1063 async fn load(&self, key: &str);
1064 }
1065
1066 pub struct AwsEc2MetadataLoader<'a> {
1067 marker: PhantomData<&'a ()>,
1068 }
1069
1070 #[async_trait]
1071 impl Loader for AwsEc2MetadataLoader<'_> {
load(&self, _key: &str)1072 async fn load(&self, _key: &str) {}
1073 }
1074 }
1075
1076 // https://github.com/dtolnay/async-trait/issues/120
1077 pub mod issue120 {
1078 #![deny(clippy::trivially_copy_pass_by_ref)]
1079
1080 use async_trait::async_trait;
1081
1082 #[async_trait]
1083 trait Trait {
f(&self)1084 async fn f(&self);
1085 }
1086
1087 #[async_trait]
1088 impl Trait for () {
f(&self)1089 async fn f(&self) {}
1090 }
1091 }
1092
1093 // https://github.com/dtolnay/async-trait/issues/123
1094 pub mod issue123 {
1095 use async_trait::async_trait;
1096
1097 #[async_trait]
1098 trait Trait<T = ()> {
f(&self) -> &str where T: 'async_trait,1099 async fn f(&self) -> &str
1100 where
1101 T: 'async_trait,
1102 {
1103 "default"
1104 }
1105 }
1106
1107 #[async_trait]
1108 impl<T> Trait<T> for () {}
1109 }
1110
1111 // https://github.com/dtolnay/async-trait/issues/129
1112 pub mod issue129 {
1113 #![deny(clippy::pedantic)]
1114
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