|
1 | 1 | use clippy_utils::diagnostics::span_lint_and_help;
|
2 | 2 | use clippy_utils::source::{snippet, snippet_with_applicability};
|
3 |
| -use clippy_utils::SpanlessHash; |
| 3 | +use clippy_utils::{SpanlessEq, SpanlessHash}; |
| 4 | +use core::hash::{Hash, Hasher}; |
4 | 5 | use if_chain::if_chain;
|
5 | 6 | use rustc_data_structures::fx::FxHashMap;
|
6 | 7 | use rustc_data_structures::unhash::UnhashMap;
|
7 | 8 | use rustc_errors::Applicability;
|
8 |
| -use rustc_hir::{def::Res, GenericBound, Generics, ParamName, Path, QPath, TyKind, WherePredicate}; |
| 9 | +use rustc_hir::{def::Res, GenericBound, Generics, ParamName, Path, QPath, Ty, TyKind, WherePredicate}; |
9 | 10 | use rustc_lint::{LateContext, LateLintPass};
|
10 | 11 | use rustc_session::{declare_tool_lint, impl_lint_pass};
|
11 | 12 | use rustc_span::Span;
|
@@ -94,24 +95,40 @@ fn get_trait_res_span_from_bound(bound: &GenericBound<'_>) -> Option<(Res, Span)
|
94 | 95 | }
|
95 | 96 |
|
96 | 97 | impl TraitBounds {
|
97 |
| - fn check_type_repetition(self, cx: &LateContext<'_>, gen: &'_ Generics<'_>) { |
| 98 | + fn check_type_repetition<'tcx>(self, cx: &LateContext<'tcx>, gen: &'tcx Generics<'_>) { |
| 99 | + struct SpanlessTy<'cx, 'tcx> { |
| 100 | + ty: &'tcx Ty<'tcx>, |
| 101 | + cx: &'cx LateContext<'tcx>, |
| 102 | + } |
| 103 | + impl PartialEq for SpanlessTy<'_, '_> { |
| 104 | + fn eq(&self, other: &Self) -> bool { |
| 105 | + let mut eq = SpanlessEq::new(self.cx); |
| 106 | + eq.inter_expr().eq_ty(self.ty, other.ty) |
| 107 | + } |
| 108 | + } |
| 109 | + impl Hash for SpanlessTy<'_, '_> { |
| 110 | + fn hash<H: Hasher>(&self, h: &mut H) { |
| 111 | + let mut t = SpanlessHash::new(self.cx); |
| 112 | + t.hash_ty(self.ty); |
| 113 | + h.write_u64(t.finish()); |
| 114 | + } |
| 115 | + } |
| 116 | + impl Eq for SpanlessTy<'_, '_> {} |
| 117 | + |
98 | 118 | if gen.span.from_expansion() {
|
99 | 119 | return;
|
100 | 120 | }
|
101 |
| - let hash = |ty| -> u64 { |
102 |
| - let mut hasher = SpanlessHash::new(cx); |
103 |
| - hasher.hash_ty(ty); |
104 |
| - hasher.finish() |
105 |
| - }; |
106 |
| - let mut map: UnhashMap<u64, Vec<&GenericBound<'_>>> = UnhashMap::default(); |
| 121 | + let mut map: UnhashMap<SpanlessTy<'_, '_>, Vec<&GenericBound<'_>>> = UnhashMap::default(); |
107 | 122 | let mut applicability = Applicability::MaybeIncorrect;
|
108 | 123 | for bound in gen.where_clause.predicates {
|
109 | 124 | if_chain! {
|
110 | 125 | if let WherePredicate::BoundPredicate(ref p) = bound;
|
111 | 126 | if p.bounds.len() as u64 <= self.max_trait_bounds;
|
112 | 127 | if !p.span.from_expansion();
|
113 |
| - let h = hash(p.bounded_ty); |
114 |
| - if let Some(ref v) = map.insert(h, p.bounds.iter().collect::<Vec<_>>()); |
| 128 | + if let Some(ref v) = map.insert( |
| 129 | + SpanlessTy { ty: p.bounded_ty, cx }, |
| 130 | + p.bounds.iter().collect::<Vec<_>>() |
| 131 | + ); |
115 | 132 |
|
116 | 133 | then {
|
117 | 134 | let mut hint_string = format!(
|
|
0 commit comments