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