| #![warn(clippy::implied_bounds_in_impls)] | |
| #![allow(dead_code)] | |
| #![feature(impl_trait_in_assoc_type, type_alias_impl_trait)] | |
| use std::ops::{Deref, DerefMut}; | |
| // Only one bound, nothing to lint. | |
| fn normal_deref<T>(x: T) -> impl Deref<Target = T> { | |
| Box::new(x) | |
| } | |
| // Deref implied by DerefMut | |
| fn deref_derefmut<T>(x: T) -> impl DerefMut<Target = T> { | |
| //~^ implied_bounds_in_impls | |
| Box::new(x) | |
| } | |
| trait GenericTrait<T> {} | |
| trait GenericTrait2<V> {} | |
| // 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<T, U, V>: GenericTrait<U> + GenericTrait2<V> {} | |
| impl GenericTrait<i32> for () {} | |
| impl GenericTrait<i64> for () {} | |
| impl<V> GenericTrait2<V> for () {} | |
| impl<V> GenericSubtrait<(), i32, V> for () {} | |
| impl<V> GenericSubtrait<(), i64, V> for () {} | |
| fn generics_implied<U, W>() -> impl GenericSubtrait<U, W, U> | |
| //~^ implied_bounds_in_impls | |
| where | |
| (): GenericSubtrait<U, W, U>, | |
| { | |
| } | |
| fn generics_implied_multi<V>() -> impl GenericSubtrait<(), i32, V> {} | |
| //~^ implied_bounds_in_impls | |
| //~| implied_bounds_in_impls | |
| fn generics_implied_multi2<T, V>() -> impl GenericSubtrait<(), T, V> | |
| //~^ implied_bounds_in_impls | |
| //~| implied_bounds_in_impls | |
| where | |
| (): GenericSubtrait<(), T, V> + GenericTrait<T>, | |
| { | |
| } | |
| // i32 != i64, GenericSubtrait<_, i64, _> does not imply GenericTrait<i32>, don't lint | |
| fn generics_different() -> impl GenericTrait<i32> + GenericSubtrait<(), i64, ()> {} | |
| // i32 == i32, GenericSubtrait<_, i32, _> does imply GenericTrait<i32>, lint | |
| fn generics_same() -> impl GenericSubtrait<(), i32, ()> {} | |
| //~^ implied_bounds_in_impls | |
| trait SomeTrait { | |
| // Check that it works in trait declarations. | |
| fn f() -> impl DerefMut<Target = u8>; | |
| //~^ implied_bounds_in_impls | |
| } | |
| struct SomeStruct; | |
| impl SomeStruct { | |
| // Check that it works in inherent impl blocks. | |
| fn f() -> impl DerefMut<Target = u8> { | |
| //~^ implied_bounds_in_impls | |
| Box::new(123) | |
| } | |
| } | |
| impl SomeTrait for SomeStruct { | |
| // Check that it works in trait impls. | |
| fn f() -> impl DerefMut<Target = u8> { | |
| //~^ implied_bounds_in_impls | |
| 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 PartialOrd + Debug {} | |
| //~^ implied_bounds_in_impls | |
| fn default_generic_param2() -> impl PartialOrd + Debug {} | |
| //~^ implied_bounds_in_impls | |
| // Referring to `Self` in the supertrait clause needs special handling. | |
| trait Trait1<X: ?Sized> {} | |
| trait Trait2: Trait1<Self> {} | |
| 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 DoubleEndedIterator<Item = u32> { | |
| //~^ implied_bounds_in_impls | |
| 0..5 | |
| } | |
| // Removing the `Clone` bound should include the `+` behind it in its remove suggestion | |
| fn f() -> impl Copy { | |
| //~^ implied_bounds_in_impls | |
| 1 | |
| } | |
| trait Trait1<T> { | |
| type U; | |
| } | |
| impl Trait1<i32> for () { | |
| type U = i64; | |
| } | |
| trait Trait2<T>: Trait1<T> {} | |
| impl Trait2<i32> for () {} | |
| // When the other trait has generics, it shouldn't add another pair of `<>` | |
| fn f2() -> impl Trait2<i32, U = i64> {} | |
| //~^ implied_bounds_in_impls | |
| trait Trait3<T, U, V> { | |
| type X; | |
| type Y; | |
| } | |
| trait Trait4<T>: Trait3<T, i16, i64> {} | |
| impl Trait3<i8, i16, i64> for () { | |
| type X = i32; | |
| type Y = i128; | |
| } | |
| impl Trait4<i8> for () {} | |
| // Associated type `X` is specified, but `Y` is not, so only that associated type should be moved | |
| // over | |
| fn f3() -> impl Trait4<i8, X = i32, Y = i128> {} | |
| //~^ implied_bounds_in_impls | |
| } | |
| 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<u8>; | |
| } | |
| // Can't constrain `X::T` through `Y` | |
| fn f() -> impl X<T = i32> + Y {} | |
| fn f2() -> impl X<T = i32> + Y<T = u32> {} | |
| // X::T is never constrained in the first place, so it can be omitted | |
| // and left unconstrained | |
| fn f3() -> impl Y {} | |
| //~^ implied_bounds_in_impls | |
| fn f4() -> impl Y<T = u32> {} | |
| //~^ implied_bounds_in_impls | |
| fn f5() -> impl Y<T = u32, U = String> {} | |
| //~^ implied_bounds_in_impls | |
| } | |
| fn apit(_: impl DerefMut) {} | |
| //~^ implied_bounds_in_impls | |
| trait Rpitit { | |
| fn f() -> impl DerefMut; | |
| //~^ implied_bounds_in_impls | |
| } | |
| trait Atpit { | |
| type Assoc; | |
| fn define() -> Self::Assoc; | |
| } | |
| impl Atpit for () { | |
| type Assoc = impl DerefMut; | |
| //~^ implied_bounds_in_impls | |
| fn define() -> Self::Assoc { | |
| &mut [] as &mut [()] | |
| } | |
| } | |
| type Tait = impl DerefMut; | |
| //~^ implied_bounds_in_impls | |
| #[define_opaque(Tait)] | |
| fn define() -> Tait { | |
| &mut [] as &mut [()] | |
| } | |
| fn main() {} |