fix: implicit_hasher wrongly unmangled macros

This commit is contained in:
Linshu Yang 2025-11-12 19:59:35 +00:00
parent 45168a79cd
commit 16241e2763
4 changed files with 97 additions and 21 deletions

View file

@ -13,7 +13,7 @@ use rustc_session::declare_lint_pass;
use rustc_span::Span;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::{IntoSpan, SpanRangeExt, snippet};
use clippy_utils::source::{IntoSpan, SpanRangeExt, snippet, snippet_with_context};
use clippy_utils::sym;
declare_clippy_lint! {
@ -335,29 +335,29 @@ impl<'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'_, '_, 'tcx> {
return;
}
match (self.cx.tcx.get_diagnostic_name(ty_did), method.ident.name) {
(Some(sym::HashMap), sym::new) => {
self.suggestions.insert(e.span, "HashMap::default()".to_string());
let container_name = match self.cx.tcx.get_diagnostic_name(ty_did) {
Some(sym::HashMap) => "HashMap",
Some(sym::HashSet) => "HashSet",
_ => return,
};
match method.ident.name {
sym::new => {
self.suggestions.insert(e.span, format!("{container_name}::default()"));
},
(Some(sym::HashMap), sym::with_capacity) => {
self.suggestions.insert(
e.span,
format!(
"HashMap::with_capacity_and_hasher({}, Default::default())",
snippet(self.cx, args[0].span, "capacity"),
),
sym::with_capacity => {
let (arg_snippet, _) = snippet_with_context(
self.cx,
args[0].span,
e.span.ctxt(),
"..",
// We can throw-away the applicability here since the whole suggestion is
// marked as `MaybeIncorrect` later.
&mut Applicability::MaybeIncorrect,
);
},
(Some(sym::HashSet), sym::new) => {
self.suggestions.insert(e.span, "HashSet::default()".to_string());
},
(Some(sym::HashSet), sym::with_capacity) => {
self.suggestions.insert(
e.span,
format!(
"HashSet::with_capacity_and_hasher({}, Default::default())",
snippet(self.cx, args[0].span, "capacity"),
),
format!("{container_name}::with_capacity_and_hasher({arg_snippet}, Default::default())",),
);
},
_ => {},

View file

@ -109,3 +109,27 @@ pub async fn election_vote<S: ::std::hash::BuildHasher>(_data: HashMap<i32, i32,
//~^ implicit_hasher
fn main() {}
mod issue16128 {
use super::*;
macro_rules! times_ten {
($num:expr) => {
$num * 10
};
}
impl<K: Hash + Eq, V, S: ::std::hash::BuildHasher + Default> Foo<u64> for HashMap<K, V, S> {
//~^ implicit_hasher
fn make() -> (Self, Self) {
(HashMap::default(), HashMap::with_capacity_and_hasher(times_ten!(5), Default::default()))
}
}
impl<V: Hash + Eq, S: ::std::hash::BuildHasher + Default> Foo<u64> for HashSet<V, S> {
//~^ implicit_hasher
fn make() -> (Self, Self) {
(HashSet::default(), HashSet::with_capacity_and_hasher(times_ten!(5), Default::default()))
}
}
}

View file

@ -109,3 +109,27 @@ pub async fn election_vote(_data: HashMap<i32, i32>) {}
//~^ implicit_hasher
fn main() {}
mod issue16128 {
use super::*;
macro_rules! times_ten {
($num:expr) => {
$num * 10
};
}
impl<K: Hash + Eq, V> Foo<u64> for HashMap<K, V> {
//~^ implicit_hasher
fn make() -> (Self, Self) {
(HashMap::new(), HashMap::with_capacity(times_ten!(5)))
}
}
impl<V: Hash + Eq> Foo<u64> for HashSet<V> {
//~^ implicit_hasher
fn make() -> (Self, Self) {
(HashSet::new(), HashSet::with_capacity(times_ten!(5)))
}
}
}

View file

@ -122,5 +122,33 @@ help: add a type parameter for `BuildHasher`
LL | pub async fn election_vote<S: ::std::hash::BuildHasher>(_data: HashMap<i32, i32, S>) {}
| +++++++++++++++++++++++++++++ +++
error: aborting due to 9 previous errors
error: impl for `HashMap` should be generalized over different hashers
--> tests/ui/implicit_hasher.rs:122:40
|
LL | impl<K: Hash + Eq, V> Foo<u64> for HashMap<K, V> {
| ^^^^^^^^^^^^^
|
help: add a type parameter for `BuildHasher`
|
LL ~ impl<K: Hash + Eq, V, S: ::std::hash::BuildHasher + Default> Foo<u64> for HashMap<K, V, S> {
LL |
LL | fn make() -> (Self, Self) {
LL ~ (HashMap::default(), HashMap::with_capacity_and_hasher(times_ten!(5), Default::default()))
|
error: impl for `HashSet` should be generalized over different hashers
--> tests/ui/implicit_hasher.rs:129:37
|
LL | impl<V: Hash + Eq> Foo<u64> for HashSet<V> {
| ^^^^^^^^^^
|
help: add a type parameter for `BuildHasher`
|
LL ~ impl<V: Hash + Eq, S: ::std::hash::BuildHasher + Default> Foo<u64> for HashSet<V, S> {
LL |
LL | fn make() -> (Self, Self) {
LL ~ (HashSet::default(), HashSet::with_capacity_and_hasher(times_ten!(5), Default::default()))
|
error: aborting due to 11 previous errors