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