| #![warn(clippy::unused_async_trait_impl)] | |
| trait HasAsyncMethod { | |
| async fn do_something() -> u32; | |
| } | |
| struct Stub; | |
| mod typical { | |
| struct Inefficient; | |
| struct Efficient; | |
| use crate::Stub; | |
| impl crate::HasAsyncMethod for Inefficient { | |
| fn do_something() -> impl Future<Output = u32> { | |
| //~^ unused_async_trait_impl | |
| std::future::ready(1) | |
| } | |
| } | |
| impl crate::HasAsyncMethod for Efficient { | |
| fn do_something() -> impl Future<Output = u32> { | |
| std::future::ready(1) | |
| } | |
| } | |
| impl crate::HasAsyncMethod for crate::Stub { | |
| async fn do_something() -> u32 { | |
| todo!() // Do not emit the lint in this case. | |
| } | |
| } | |
| } | |
| // Test to check if the identation of the various snippets goes as intended. | |
| mod indented { | |
| struct Indented; | |
| impl crate::HasAsyncMethod for Indented { | |
| fn do_something() -> impl Future<Output = u32> { | |
| //~^ unused_async_trait_impl | |
| let mut x = 0; | |
| for y in 0..64 { | |
| x = (x + 1) * y; | |
| } | |
| let fake_fut = async { | |
| if x == 0 { | |
| panic!("Fake example"); | |
| } | |
| }; | |
| std::future::ready(x) | |
| } | |
| } | |
| struct Complex<T>(std::marker::PhantomData<T>); | |
| impl<T> crate::HasAsyncMethod for Complex<T> | |
| where | |
| T: Sized, | |
| { | |
| fn do_something() -> impl Future<Output = u32> { | |
| //~^ unused_async_trait_impl | |
| std::future::ready(5) | |
| } | |
| } | |
| } | |
| mod default_unchanged { | |
| trait HasDefaultAsyncMethod { | |
| // The lint should not suggest a change for trait fn's as changing that decl | |
| // implies a less restrictive Future type. | |
| async fn do_something() -> u32 { | |
| 0 | |
| } | |
| } | |
| impl HasDefaultAsyncMethod for crate::Stub { | |
| // Nothing! | |
| } | |
| } | |
| mod macros { | |
| trait HasAsyncMethodVec { | |
| async fn do_something() -> Vec<u32>; | |
| } | |
| struct MacroInType; | |
| struct MacroInExpr; | |
| macro_rules! vec_ty { | |
| ($t:ty) => { Vec<$t> } | |
| } | |
| impl HasAsyncMethodVec for MacroInType { | |
| fn do_something() -> impl Future<Output = vec_ty!(u32)> { | |
| //~^ unused_async_trait_impl | |
| std::future::ready(Vec::new()) | |
| } | |
| } | |
| impl HasAsyncMethodVec for MacroInExpr { | |
| fn do_something() -> impl Future<Output = Vec<u32>> { | |
| //~^ unused_async_trait_impl | |
| std::future::ready(vec![]) | |
| } | |
| } | |
| } | |
| mod issue17179 { | |
| struct Test; | |
| impl crate::HasAsyncMethod for Test { | |
| fn do_something() -> impl Future<Output = u32> { | |
| //~^ unused_async_trait_impl | |
| // Test that local functions are not touched by the suggestion. | |
| fn local_func() -> u32 { | |
| if 5 == 2 { | |
| return 1; | |
| } | |
| 2 | |
| } | |
| // Test that we do not change the tail expr or return in a (unrelated) closure. | |
| let f = || { | |
| if 5 == 2 { | |
| return 1; | |
| } | |
| 2 | |
| }; | |
| // However the following return statement and tail expression should be changed. | |
| if f() == 5 { | |
| return std::future::ready(3); | |
| } | |
| std::future::ready(5) | |
| } | |
| } | |
| } |