|
1 |
| -use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_help}; |
2 |
| -use clippy_utils::source::{snippet, snippet_with_applicability, snippet_opt}; |
| 1 | +use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg}; |
| 2 | +use clippy_utils::source::{snippet, snippet_opt, snippet_with_applicability}; |
3 | 3 | use clippy_utils::{SpanlessEq, SpanlessHash};
|
4 | 4 | use core::hash::{Hash, Hasher};
|
5 | 5 | use if_chain::if_chain;
|
@@ -290,98 +290,60 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
|
290 | 290 | }
|
291 | 291 |
|
292 | 292 | fn check_bounds_or_where_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
|
293 |
| - if gen.span.from_expansion() { |
294 |
| - return; |
295 |
| - } |
296 |
| - |
297 |
| - for param in gen.params { |
| 293 | + fn rollup_traits(cx: &LateContext<'_>, bounds: &[GenericBound<'_>], msg: &str) { |
298 | 294 | let mut map = FxHashMap::default();
|
299 | 295 | let mut repeated_spans = false;
|
300 |
| - if let ParamName::Plain(name) = param.name { // other alternatives are errors and elided which won't have duplicates |
301 |
| - for bound in param.bounds.iter().filter_map(get_trait_info_from_bound) { |
302 |
| - let (definition, _, span_direct) = bound; |
303 |
| - if let Some(_) = map.insert(definition, span_direct) { |
304 |
| - repeated_spans = true; |
305 |
| - } |
| 296 | + for bound in bounds.iter().filter_map(get_trait_info_from_bound) { |
| 297 | + let (definition, _, span_direct) = bound; |
| 298 | + if map.insert(definition, span_direct).is_some() { |
| 299 | + repeated_spans = true; |
306 | 300 | }
|
| 301 | + } |
307 | 302 |
|
308 |
| - if repeated_spans { |
309 |
| - let all_trait_span = param |
310 |
| - .bounds |
311 |
| - .get(0) |
312 |
| - .unwrap() |
313 |
| - .span() |
314 |
| - .to( |
315 |
| - param |
316 |
| - .bounds |
317 |
| - .iter() |
318 |
| - .last() |
319 |
| - .unwrap() |
320 |
| - .span()); |
| 303 | + if repeated_spans { |
| 304 | + if_chain! { |
| 305 | + if let Some(first_trait) = bounds.get(0); |
| 306 | + if let Some(last_trait) = bounds.iter().last(); |
| 307 | + then { |
| 308 | + let all_trait_span = first_trait.span().to(last_trait.span()); |
321 | 309 |
|
322 |
| - let mut traits = map.values() |
323 |
| - .filter_map(|span| snippet_opt(cx, *span)) |
324 |
| - .collect::<Vec<_>>(); |
325 |
| - traits.sort_unstable(); |
326 |
| - let traits = traits.join(" + "); |
| 310 | + let mut traits = map.values() |
| 311 | + .filter_map(|span| snippet_opt(cx, *span)) |
| 312 | + .collect::<Vec<_>>(); |
| 313 | + traits.sort_unstable(); |
| 314 | + let traits = traits.join(" + "); |
327 | 315 |
|
328 |
| - span_lint_and_sugg( |
329 |
| - cx, |
330 |
| - REPEATED_WHERE_CLAUSE_OR_TRAIT_BOUND, |
331 |
| - all_trait_span, |
332 |
| - "this trait bound contains repeated elements", |
333 |
| - "try", |
334 |
| - traits, |
335 |
| - Applicability::MachineApplicable |
336 |
| - ); |
| 316 | + span_lint_and_sugg( |
| 317 | + cx, |
| 318 | + REPEATED_WHERE_CLAUSE_OR_TRAIT_BOUND, |
| 319 | + all_trait_span, |
| 320 | + msg, |
| 321 | + "try", |
| 322 | + traits, |
| 323 | + Applicability::MachineApplicable |
| 324 | + ); |
| 325 | + } |
337 | 326 | }
|
338 | 327 | }
|
339 | 328 | }
|
| 329 | + if gen.span.from_expansion() || (gen.params.is_empty() && gen.where_clause.predicates.is_empty()) { |
| 330 | + return; |
| 331 | + } |
| 332 | + |
| 333 | + for param in gen.params { |
| 334 | + if let ParamName::Plain(_) = param.name { |
| 335 | + // other alternatives are errors and elided which won't have duplicates |
| 336 | + rollup_traits(cx, param.bounds, "this trait bound contains repeated elements"); |
| 337 | + } |
| 338 | + } |
340 | 339 |
|
341 | 340 | for predicate in gen.where_clause.predicates {
|
342 | 341 | if let WherePredicate::BoundPredicate(ref bound_predicate) = predicate {
|
343 |
| - let mut where_clauses = FxHashMap::default(); |
344 |
| - let mut repeated_spans = false; |
345 |
| - |
346 |
| - for (definition, _, span_direct) in bound_predicate |
347 |
| - .bounds |
348 |
| - .iter() |
349 |
| - .filter_map(get_trait_info_from_bound) |
350 |
| - { |
351 |
| - if let Some(_) = where_clauses.insert(definition, span_direct) { |
352 |
| - repeated_spans = true; |
353 |
| - } |
354 |
| - } |
355 |
| - |
356 |
| - if repeated_spans { |
357 |
| - let all_trait_span = bound_predicate |
358 |
| - .bounds |
359 |
| - .get(0) |
360 |
| - .unwrap() |
361 |
| - .span() |
362 |
| - .to( |
363 |
| - bound_predicate |
364 |
| - .bounds |
365 |
| - .iter() |
366 |
| - .last() |
367 |
| - .unwrap() |
368 |
| - .span()); |
369 |
| - |
370 |
| - let mut traits = where_clauses.values() |
371 |
| - .filter_map(|span| snippet_opt(cx, *span)) |
372 |
| - .collect::<Vec<_>>(); |
373 |
| - traits.sort_unstable(); |
374 |
| - let traits = traits.join(" + "); |
375 |
| - span_lint_and_sugg( |
376 |
| - cx, |
377 |
| - REPEATED_WHERE_CLAUSE_OR_TRAIT_BOUND, |
378 |
| - all_trait_span, |
379 |
| - "this where clause has already been specified", |
380 |
| - "try", |
381 |
| - traits, |
382 |
| - Applicability::MachineApplicable |
383 |
| - ); |
384 |
| - } |
| 342 | + rollup_traits( |
| 343 | + cx, |
| 344 | + bound_predicate.bounds, |
| 345 | + "this where clause contains repeated elements", |
| 346 | + ); |
385 | 347 | }
|
386 | 348 | }
|
387 | 349 | }
|
|
0 commit comments