Since a lot of traits now use associated types, some code can be simplified, removing the need for some generic parameters. However, some code may not utilise this flexibility, treating associated types in the same way as usual type parameters (especially if the trait was only recently changed to use associated types, and code like Trait<T> was simply changed to Trait<Foo=T>). For example:
fn foo<T, I>(x: I) where T: Clone, I: Iterator<Item = T> { ... }
// should be
fn foo<I>(x: I) where I: Iterator, <I as Iterator>::Item: Clone { ... }
struct Foo<T, I> where I: Iterator, <I as Iterator>::Item = T { ... }
// should be
struct Foo<I> where I: Iterator { ... }
I think a lint could detect these redundant type parameters by warning whenever a type parameter is equated with anything in an equality bound. In other words, I think T = AnyType is always indicative of an unnecessary type parameter (although I’m not 100% sure on this—is there any example where that’s a valid thing to do?).
Since a lot of traits now use associated types, some code can be simplified, removing the need for some generic parameters. However, some code may not utilise this flexibility, treating associated types in the same way as usual type parameters (especially if the trait was only recently changed to use associated types, and code like
Trait<T>was simply changed toTrait<Foo=T>). For example:I think a lint could detect these redundant type parameters by warning whenever a type parameter is equated with anything in an equality bound. In other words, I think
T = AnyTypeis always indicative of an unnecessary type parameter (although I’m not 100% sure on this—is there any example where that’s a valid thing to do?).