-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Description
What it does
Given an opaque (return? other?) type in a function signature by means of multiple impl ... [ + ..]
declarations, a lint to catch that one trait automatically implies the other would go a long way to a) reduce verbosity and complexity of the return type definition, b) simplify the type hints for the returned value, c) simplify and make it easier to read the generated rustdoc.
To give a concrete example, clippy should complain on the following code:
fn foo<T>() -> impl Deref<Target = T> + DerefMut<Target = T> {
todo!();
}
complaining that DerefMut<Target = T>
automatically implies Deref<Target = T>
, and with --fix
rewrite it to the following code:
fn foo<T>() -> impl DerefMut<Target = T> {
todo!();
}
I am humbled to be asked to provide a lint name and category for this and am filling out the form with just a suggestion as I am sure someone on the clippy team can come up with a better and more idiomatic name!
Lint Name
Superflous Impl
Category
complexity
Advantage
- reduce verbosity and complexity of the return type definition,
- simplify the type hints for the returned value,
- simplify and make it easier to read the generated rustdoc.
Drawbacks
In the extremely unlikely case that a trait Foo
currently requires implementing types to also implement Bar
but a future version of Foo
removes that requirement and the particular code returning the impl Foo + Bar
in question explicitly wants to document/uphold that both Foo
and Bar
are implemented by the return type (rather than just Foo
and incidentally Bar
), when upstream is upgraded to Foo
v2 the return type will no longer provide Bar
. Without this change/lint, a compiler error would have been emitted that would have allowed catching that Bar
is no longer implemented by the return type.
Example
fn foo<T>() -> impl Deref<Target = T> + DerefMut<Target = T> {
todo!();
}
complaining that DerefMut<Target = T>
automatically implies Deref<Target = T>
, and with --fix
rewrite it to the following code:
fn foo<T>() -> impl DerefMut<Target = T> {
todo!();
}