From 72f0180f7bcf033604822a6ab6e65cc9ccf7540f Mon Sep 17 00:00:00 2001
From: Takayuki Nakata <f.seasons017@gmail.com>
Date: Mon, 4 Oct 2021 23:31:40 +0900
Subject: [PATCH] Fix ICE in `implicit_hasher`

---
 clippy_lints/src/implicit_hasher.rs | 20 ++++++++++++-----
 tests/ui/implicit_hasher.rs         |  4 ++++
 tests/ui/implicit_hasher.stderr     | 35 +++++++++++++++++++----------
 3 files changed, 41 insertions(+), 18 deletions(-)

diff --git a/clippy_lints/src/implicit_hasher.rs b/clippy_lints/src/implicit_hasher.rs
index 2fe32fcf665..77318e74ca8 100644
--- a/clippy_lints/src/implicit_hasher.rs
+++ b/clippy_lints/src/implicit_hasher.rs
@@ -167,12 +167,20 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher {
                             continue;
                         }
                         let generics_suggestion_span = generics.span.substitute_dummy({
-                            let pos = snippet_opt(cx, item.span.until(body.params[0].pat.span))
-                                .and_then(|snip| {
-                                    let i = snip.find("fn")?;
-                                    Some(item.span.lo() + BytePos((i + (&snip[i..]).find('(')?) as u32))
-                                })
-                                .expect("failed to create span for type parameters");
+                            let pos = snippet_opt(
+                                cx,
+                                Span::new(
+                                    item.span.lo(),
+                                    body.params[0].pat.span.lo(),
+                                    item.span.ctxt(),
+                                    item.span.parent(),
+                                ),
+                            )
+                            .and_then(|snip| {
+                                let i = snip.find("fn")?;
+                                Some(item.span.lo() + BytePos((i + (&snip[i..]).find('(')?) as u32))
+                            })
+                            .expect("failed to create span for type parameters");
                             Span::new(pos, pos, item.span.ctxt(), item.span.parent())
                         });
 
diff --git a/tests/ui/implicit_hasher.rs b/tests/ui/implicit_hasher.rs
index 97c26bc83ad..aa69b097410 100644
--- a/tests/ui/implicit_hasher.rs
+++ b/tests/ui/implicit_hasher.rs
@@ -1,3 +1,4 @@
+// edition:2018
 // aux-build:implicit_hasher_macros.rs
 #![deny(clippy::implicit_hasher)]
 #![allow(unused)]
@@ -96,4 +97,7 @@ __implicit_hasher_test_macro!(impl<K, V> for HashMap<K, V> where V: test_macro::
 // #4260
 implicit_hasher_fn!();
 
+// #7712
+pub async fn election_vote(_data: HashMap<i32, i32>) {}
+
 fn main() {}
diff --git a/tests/ui/implicit_hasher.stderr b/tests/ui/implicit_hasher.stderr
index 2e62dd30f9f..dad5ab71f15 100644
--- a/tests/ui/implicit_hasher.stderr
+++ b/tests/ui/implicit_hasher.stderr
@@ -1,11 +1,11 @@
 error: impl for `HashMap` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:16:35
+  --> $DIR/implicit_hasher.rs:17:35
    |
 LL | impl<K: Hash + Eq, V> Foo<i8> for HashMap<K, V> {
    |                                   ^^^^^^^^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/implicit_hasher.rs:2:9
+  --> $DIR/implicit_hasher.rs:3:9
    |
 LL | #![deny(clippy::implicit_hasher)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^
@@ -19,7 +19,7 @@ LL |         (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default:
    |          ~~~~~~~~~~~~~~~~~~  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: impl for `HashMap` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:25:36
+  --> $DIR/implicit_hasher.rs:26:36
    |
 LL | impl<K: Hash + Eq, V> Foo<i8> for (HashMap<K, V>,) {
    |                                    ^^^^^^^^^^^^^
@@ -34,7 +34,7 @@ LL |         ((HashMap::default(),), (HashMap::with_capacity_and_hasher(10, Defa
    |           ~~~~~~~~~~~~~~~~~~     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: impl for `HashMap` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:30:19
+  --> $DIR/implicit_hasher.rs:31:19
    |
 LL | impl Foo<i16> for HashMap<String, String> {
    |                   ^^^^^^^^^^^^^^^^^^^^^^^
@@ -49,7 +49,7 @@ LL |         (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default:
    |          ~~~~~~~~~~~~~~~~~~  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: impl for `HashSet` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:47:32
+  --> $DIR/implicit_hasher.rs:48:32
    |
 LL | impl<T: Hash + Eq> Foo<i8> for HashSet<T> {
    |                                ^^^^^^^^^^
@@ -64,7 +64,7 @@ LL |         (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default:
    |          ~~~~~~~~~~~~~~~~~~  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: impl for `HashSet` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:52:19
+  --> $DIR/implicit_hasher.rs:53:19
    |
 LL | impl Foo<i16> for HashSet<String> {
    |                   ^^^^^^^^^^^^^^^
@@ -79,7 +79,7 @@ LL |         (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default:
    |          ~~~~~~~~~~~~~~~~~~  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: parameter of type `HashMap` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:69:23
+  --> $DIR/implicit_hasher.rs:70:23
    |
 LL | pub fn foo(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
    |                       ^^^^^^^^^^^^^^^^^
@@ -90,7 +90,7 @@ LL | pub fn foo<S: ::std::hash::BuildHasher>(_map: &mut HashMap<i32, i32, S>, _s
    |           +++++++++++++++++++++++++++++            ~~~~~~~~~~~~~~~~~~~~
 
 error: parameter of type `HashSet` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:69:53
+  --> $DIR/implicit_hasher.rs:70:53
    |
 LL | pub fn foo(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
    |                                                     ^^^^^^^^^^^^
@@ -101,7 +101,7 @@ LL | pub fn foo<S: ::std::hash::BuildHasher>(_map: &mut HashMap<i32, i32>, _set:
    |           +++++++++++++++++++++++++++++                                          ~~~~~~~~~~~~~~~
 
 error: impl for `HashMap` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:73:43
+  --> $DIR/implicit_hasher.rs:74:43
    |
 LL |         impl<K: Hash + Eq, V> Foo<u8> for HashMap<K, V> {
    |                                           ^^^^^^^^^^^^^
@@ -120,7 +120,7 @@ LL |                 (HashMap::default(), HashMap::with_capacity_and_hasher(10,
    |                  ~~~~~~~~~~~~~~~~~~  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: parameter of type `HashMap` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:81:33
+  --> $DIR/implicit_hasher.rs:82:33
    |
 LL |         pub fn $name(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
    |                                 ^^^^^^^^^^^^^^^^^
@@ -135,7 +135,7 @@ LL |         pub fn $name<S: ::std::hash::BuildHasher>(_map: &mut HashMap<i32, i
    |                     +++++++++++++++++++++++++++++            ~~~~~~~~~~~~~~~~~~~~
 
 error: parameter of type `HashSet` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:81:63
+  --> $DIR/implicit_hasher.rs:82:63
    |
 LL |         pub fn $name(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
    |                                                               ^^^^^^^^^^^^
@@ -149,5 +149,16 @@ help: consider adding a type parameter
 LL |         pub fn $name<S: ::std::hash::BuildHasher>(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32, S>) {}
    |                     +++++++++++++++++++++++++++++                                          ~~~~~~~~~~~~~~~
 
-error: aborting due to 10 previous errors
+error: parameter of type `HashMap` should be generalized over different hashers
+  --> $DIR/implicit_hasher.rs:101:35
+   |
+LL | pub async fn election_vote(_data: HashMap<i32, i32>) {}
+   |                                   ^^^^^^^^^^^^^^^^^
+   |
+help: consider adding a type parameter
+   |
+LL | pub async fn election_vote<S: ::std::hash::BuildHasher>(_data: HashMap<i32, i32, S>) {}
+   |                           +++++++++++++++++++++++++++++        ~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 11 previous errors