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