diff --git a/clippy_lints/src/implicit_hasher.rs b/clippy_lints/src/implicit_hasher.rs index d2bc0b6d9935..638a08b096db 100644 --- a/clippy_lints/src/implicit_hasher.rs +++ b/clippy_lints/src/implicit_hasher.rs @@ -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())",), ); }, _ => {}, diff --git a/tests/ui/implicit_hasher.fixed b/tests/ui/implicit_hasher.fixed index bea5b9afc43a..882a545963b4 100644 --- a/tests/ui/implicit_hasher.fixed +++ b/tests/ui/implicit_hasher.fixed @@ -109,3 +109,27 @@ pub async fn election_vote(_data: HashMap { + $num * 10 + }; + } + + impl Foo for HashMap { + //~^ implicit_hasher + fn make() -> (Self, Self) { + (HashMap::default(), HashMap::with_capacity_and_hasher(times_ten!(5), Default::default())) + } + } + + impl Foo for HashSet { + //~^ implicit_hasher + fn make() -> (Self, Self) { + (HashSet::default(), HashSet::with_capacity_and_hasher(times_ten!(5), Default::default())) + } + } +} diff --git a/tests/ui/implicit_hasher.rs b/tests/ui/implicit_hasher.rs index afdf4da61650..186f9e9978e5 100644 --- a/tests/ui/implicit_hasher.rs +++ b/tests/ui/implicit_hasher.rs @@ -109,3 +109,27 @@ pub async fn election_vote(_data: HashMap) {} //~^ implicit_hasher fn main() {} + +mod issue16128 { + use super::*; + + macro_rules! times_ten { + ($num:expr) => { + $num * 10 + }; + } + + impl Foo for HashMap { + //~^ implicit_hasher + fn make() -> (Self, Self) { + (HashMap::new(), HashMap::with_capacity(times_ten!(5))) + } + } + + impl Foo for HashSet { + //~^ implicit_hasher + fn make() -> (Self, Self) { + (HashSet::new(), HashSet::with_capacity(times_ten!(5))) + } + } +} diff --git a/tests/ui/implicit_hasher.stderr b/tests/ui/implicit_hasher.stderr index 6735998ed654..326115c8e9a3 100644 --- a/tests/ui/implicit_hasher.stderr +++ b/tests/ui/implicit_hasher.stderr @@ -122,5 +122,33 @@ help: add a type parameter for `BuildHasher` LL | pub async fn election_vote(_data: HashMap) {} | +++++++++++++++++++++++++++++ +++ -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 Foo for HashMap { + | ^^^^^^^^^^^^^ + | +help: add a type parameter for `BuildHasher` + | +LL ~ impl Foo for HashMap { +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 Foo for HashSet { + | ^^^^^^^^^^ + | +help: add a type parameter for `BuildHasher` + | +LL ~ impl Foo for HashSet { +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