@@ -50,6 +50,93 @@ declare_clippy_lint! {
50
50
}
51
51
declare_lint_pass ! ( ImpliedBoundsInImpls => [ IMPLIED_BOUNDS_IN_IMPLS ] ) ;
52
52
53
+ #[ allow( clippy:: too_many_arguments) ]
54
+ fn emit_lint (
55
+ cx : & LateContext < ' _ > ,
56
+ poly_trait : & rustc_hir:: PolyTraitRef < ' _ > ,
57
+ opaque_ty : & rustc_hir:: OpaqueTy < ' _ > ,
58
+ index : usize ,
59
+ implied_bindings : & [ rustc_hir:: TypeBinding < ' _ > ] ,
60
+ implied_by_bindings : & [ rustc_hir:: TypeBinding < ' _ > ] ,
61
+ implied_by_args : & [ GenericArg < ' _ > ] ,
62
+ implied_by_span : Span ,
63
+ ) {
64
+ let implied_by = snippet ( cx, implied_by_span, ".." ) ;
65
+
66
+ span_lint_and_then (
67
+ cx,
68
+ IMPLIED_BOUNDS_IN_IMPLS ,
69
+ poly_trait. span ,
70
+ & format ! ( "this bound is already specified as the supertrait of `{implied_by}`" ) ,
71
+ |diag| {
72
+ // If we suggest removing a bound, we may also need extend the span
73
+ // to include the `+` token that is ahead or behind,
74
+ // so we don't end up with something like `impl + B` or `impl A + `
75
+
76
+ let implied_span_extended = if let Some ( next_bound) = opaque_ty. bounds . get ( index + 1 ) {
77
+ poly_trait. span . to ( next_bound. span ( ) . shrink_to_lo ( ) )
78
+ } else if index > 0
79
+ && let Some ( prev_bound) = opaque_ty. bounds . get ( index - 1 )
80
+ {
81
+ prev_bound. span ( ) . shrink_to_hi ( ) . to ( poly_trait. span . shrink_to_hi ( ) )
82
+ } else {
83
+ poly_trait. span
84
+ } ;
85
+
86
+ let mut sugg = vec ! [ ( implied_span_extended, String :: new( ) ) ] ;
87
+
88
+ // We also might need to include associated type binding that were specified in the implied bound,
89
+ // but omitted in the implied-by bound:
90
+ // `fn f() -> impl Deref<Target = u8> + DerefMut`
91
+ // If we're going to suggest removing `Deref<..>`, we'll need to put `<Target = u8>` on `DerefMut`
92
+ let omitted_assoc_tys: Vec < _ > = implied_bindings
93
+ . iter ( )
94
+ . filter ( |binding| !implied_by_bindings. iter ( ) . any ( |b| b. ident == binding. ident ) )
95
+ . collect ( ) ;
96
+
97
+ if !omitted_assoc_tys. is_empty ( ) {
98
+ // `<>` needs to be added if there aren't yet any generic arguments or bindings
99
+ let needs_angle_brackets = implied_by_args. is_empty ( ) && implied_by_bindings. is_empty ( ) ;
100
+ let insert_span = match ( implied_by_args, implied_by_bindings) {
101
+ ( [ .., arg] , [ .., binding] ) => arg. span ( ) . max ( binding. span ) . shrink_to_hi ( ) ,
102
+ ( [ .., arg] , [ ] ) => arg. span ( ) . shrink_to_hi ( ) ,
103
+ ( [ ] , [ .., binding] ) => binding. span . shrink_to_hi ( ) ,
104
+ ( [ ] , [ ] ) => implied_by_span. shrink_to_hi ( ) ,
105
+ } ;
106
+
107
+ let mut associated_tys_sugg = if needs_angle_brackets {
108
+ "<" . to_owned ( )
109
+ } else {
110
+ // If angle brackets aren't needed (i.e., there are already generic arguments or bindings),
111
+ // we need to add a comma:
112
+ // `impl A<B, C >`
113
+ // ^ if we insert `Assoc=i32` without a comma here, that'd be invalid syntax:
114
+ // `impl A<B, C Assoc=i32>`
115
+ ", " . to_owned ( )
116
+ } ;
117
+
118
+ for ( index, binding) in omitted_assoc_tys. into_iter ( ) . enumerate ( ) {
119
+ if index > 0 {
120
+ associated_tys_sugg += ", " ;
121
+ }
122
+ associated_tys_sugg += & snippet ( cx, binding. span , ".." ) ;
123
+ }
124
+ if needs_angle_brackets {
125
+ associated_tys_sugg += ">" ;
126
+ }
127
+ sugg. push ( ( insert_span, associated_tys_sugg) ) ;
128
+ }
129
+
130
+ diag. multipart_suggestion_with_style (
131
+ "try removing this bound" ,
132
+ sugg,
133
+ Applicability :: MachineApplicable ,
134
+ SuggestionStyle :: ShowAlways ,
135
+ ) ;
136
+ } ,
137
+ ) ;
138
+ }
139
+
53
140
/// Tries to "resolve" a type.
54
141
/// The index passed to this function must start with `Self=0`, i.e. it must be a valid
55
142
/// type parameter index.
@@ -189,80 +276,15 @@ fn check(cx: &LateContext<'_>, decl: &FnDecl<'_>) {
189
276
} )
190
277
} )
191
278
{
192
- let implied_by = snippet ( cx, implied_by_span, ".." ) ;
193
- span_lint_and_then (
194
- cx, IMPLIED_BOUNDS_IN_IMPLS ,
195
- poly_trait. span ,
196
- & format ! ( "this bound is already specified as the supertrait of `{implied_by}`" ) ,
197
- |diag| {
198
- // If we suggest removing a bound, we may also need extend the span
199
- // to include the `+` token that is ahead or behind,
200
- // so we don't end up with something like `impl + B` or `impl A + `
201
-
202
- let implied_span_extended = if let Some ( next_bound) = opaque_ty. bounds . get ( index + 1 ) {
203
- poly_trait. span . to ( next_bound. span ( ) . shrink_to_lo ( ) )
204
- } else if index > 0
205
- && let Some ( prev_bound) = opaque_ty. bounds . get ( index - 1 )
206
- {
207
- prev_bound. span ( ) . shrink_to_hi ( ) . to ( poly_trait. span . shrink_to_hi ( ) )
208
- } else {
209
- poly_trait. span
210
- } ;
211
-
212
- let mut sugg = vec ! [
213
- ( implied_span_extended, String :: new( ) ) ,
214
- ] ;
215
-
216
- // We also might need to include associated type binding that were specified in the implied bound,
217
- // but omitted in the implied-by bound:
218
- // `fn f() -> impl Deref<Target = u8> + DerefMut`
219
- // If we're going to suggest removing `Deref<..>`, we'll need to put `<Target = u8>` on `DerefMut`
220
- let omitted_assoc_tys: Vec < _ > = implied_bindings
221
- . iter ( )
222
- . filter ( |binding| {
223
- implied_by_bindings
224
- . iter ( )
225
- // TODO: is checking idents enough for stuff like `<Target: Sized> == <Target = u8>`
226
- . find ( |b| b. ident == binding. ident )
227
- . is_none ( )
228
- } )
229
- . collect ( ) ;
230
-
231
- if !omitted_assoc_tys. is_empty ( ) {
232
- // `<>` needs to be added if there aren't yet any generic arguments or bindings
233
- let needs_angle_brackets = implied_by_args. is_empty ( ) && implied_by_bindings. is_empty ( ) ;
234
- let insert_span = match ( implied_by_args, implied_by_bindings) {
235
- ( [ .., arg] , [ .., binding] ) => arg. span ( ) . max ( binding. span ) . shrink_to_hi ( ) ,
236
- ( [ .., arg] , [ ] ) => arg. span ( ) . shrink_to_hi ( ) ,
237
- ( [ ] , [ .., binding] ) => binding. span . shrink_to_hi ( ) ,
238
- ( [ ] , [ ] ) => implied_by_span. shrink_to_hi ( ) ,
239
- } ;
240
-
241
- let mut associated_tys_sugg = if needs_angle_brackets {
242
- "<" . to_owned ( )
243
- } else {
244
- // If angle brackets aren't needed (i.e., there are already generic arguments or bindings),
245
- // we need to add a comma:
246
- // `impl A<B, C >`
247
- // ^ if we insert `Assoc=i32` without a comma here, that'd be invalid syntax:
248
- // `impl A<B, C Assoc=i32>`
249
- ", " . to_owned ( )
250
- } ;
251
-
252
- for ( index, binding) in omitted_assoc_tys. into_iter ( ) . enumerate ( ) {
253
- if index > 0 {
254
- associated_tys_sugg += ", " ;
255
- }
256
- associated_tys_sugg += & snippet ( cx, binding. span , ".." ) ;
257
- }
258
- if needs_angle_brackets {
259
- associated_tys_sugg += ">" ;
260
- }
261
- sugg. push ( ( insert_span, associated_tys_sugg) ) ;
262
- }
263
-
264
- diag. multipart_suggestion_with_style ( "try removing this bound" , sugg, Applicability :: MachineApplicable , SuggestionStyle :: ShowAlways ) ;
265
- }
279
+ emit_lint (
280
+ cx,
281
+ poly_trait,
282
+ opaque_ty,
283
+ index,
284
+ implied_bindings,
285
+ implied_by_bindings,
286
+ implied_by_args,
287
+ implied_by_span
266
288
) ;
267
289
}
268
290
}
0 commit comments