blob: d8a96afdf1be548a096f59891ca0b4a284d23add [file] [edit]
#![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)
}
}
}