|
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