#![warn(clippy::implied_bounds_in_impls)] #![allow(dead_code)] use std::ops::{Deref, DerefMut}; // Only one bound, nothing to lint. fn normal_deref(x: T) -> impl Deref { Box::new(x) } // Deref implied by DerefMut fn deref_derefmut(x: T) -> impl Deref + DerefMut { Box::new(x) } trait GenericTrait {} trait GenericTrait2 {} // U is intentionally at a different "index" in GenericSubtrait than `T` is in GenericTrait, // so this can be a good test to make sure that the calculations are right (no off-by-one errors, // ...) trait GenericSubtrait: GenericTrait + GenericTrait2 {} impl GenericTrait for () {} impl GenericTrait for () {} impl GenericTrait2 for () {} impl GenericSubtrait<(), i32, V> for () {} impl GenericSubtrait<(), i64, V> for () {} fn generics_implied() -> impl GenericTrait + GenericSubtrait where (): GenericSubtrait, { } fn generics_implied_multi() -> impl GenericTrait + GenericTrait2 + GenericSubtrait<(), i32, V> {} fn generics_implied_multi2() -> impl GenericTrait + GenericTrait2 + GenericSubtrait<(), T, V> where (): GenericSubtrait<(), T, V> + GenericTrait, { } // i32 != i64, GenericSubtrait<_, i64, _> does not imply GenericTrait, don't lint fn generics_different() -> impl GenericTrait + GenericSubtrait<(), i64, ()> {} // i32 == i32, GenericSubtrait<_, i32, _> does imply GenericTrait, lint fn generics_same() -> impl GenericTrait + GenericSubtrait<(), i32, ()> {} trait SomeTrait { // Check that it works in trait declarations. fn f() -> impl Deref + DerefMut; } struct SomeStruct; impl SomeStruct { // Check that it works in inherent impl blocks. fn f() -> impl Deref + DerefMut { Box::new(123) } } impl SomeTrait for SomeStruct { // Check that it works in trait impls. fn f() -> impl Deref + DerefMut { Box::new(42) } } mod issue11422 { use core::fmt::Debug; // Some additional tests that would cause ICEs: // `PartialOrd` has a default generic parameter and does not need to be explicitly specified. // This needs special handling. fn default_generic_param1() -> impl PartialEq + PartialOrd + Debug {} fn default_generic_param2() -> impl PartialOrd + PartialEq + Debug {} // Referring to `Self` in the supertrait clause needs special handling. trait Trait1 {} trait Trait2: Trait1 {} impl Trait1<()> for () {} impl Trait2 for () {} fn f() -> impl Trait1<()> + Trait2 {} } mod issue11435 { // Associated type needs to be included on DoubleEndedIterator in the suggestion fn my_iter() -> impl Iterator + DoubleEndedIterator { 0..5 } // Removing the `Clone` bound should include the `+` behind it in its remove suggestion fn f() -> impl Copy + Clone { 1 } trait Trait1 { type U; } impl Trait1 for () { type U = i64; } trait Trait2: Trait1 {} impl Trait2 for () {} // When the other trait has generics, it shouldn't add another pair of `<>` fn f2() -> impl Trait1 + Trait2 {} trait Trait3 { type X; type Y; } trait Trait4: Trait3 {} impl Trait3 for () { type X = i32; type Y = i128; } impl Trait4 for () {} // Associated type `X` is specified, but `Y` is not, so only that associated type should be moved // over fn f3() -> impl Trait3 + Trait4 {} } fn issue11880() { trait X { type T; type U; } trait Y: X { type T; type V; } impl X for () { type T = i32; type U = String; } impl Y for () { type T = u32; type V = Vec; } // Can't constrain `X::T` through `Y` fn f() -> impl X + Y {} fn f2() -> impl X + Y {} // X::T is never constrained in the first place, so it can be omitted // and left unconstrained fn f3() -> impl X + Y {} fn f4() -> impl X + Y {} fn f5() -> impl X + Y {} } fn main() {}