1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
|
#![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() {}
|