| #![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) |
| } |
| } |
| } |