about summary refs log tree commit diff
path: root/src/tools/clippy/tests
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/clippy/tests')
-rw-r--r--src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr16
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/macro_rules.rs19
-rw-r--r--src/tools/clippy/tests/ui/bool_assert_comparison.fixed38
-rw-r--r--src/tools/clippy/tests/ui/bool_assert_comparison.rs10
-rw-r--r--src/tools/clippy/tests/ui/bool_assert_comparison.stderr126
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-2774.stderr5
-rw-r--r--src/tools/clippy/tests/ui/crashes/needless_lifetimes_impl_trait.stderr5
-rw-r--r--src/tools/clippy/tests/ui/extra_unused_type_parameters.rs69
-rw-r--r--src/tools/clippy/tests/ui/extra_unused_type_parameters.stderr59
-rw-r--r--src/tools/clippy/tests/ui/len_without_is_empty.rs46
-rw-r--r--src/tools/clippy/tests/ui/manual_assert.edition2018.fixed35
-rw-r--r--src/tools/clippy/tests/ui/manual_assert.edition2018.stderr67
-rw-r--r--src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed2
-rw-r--r--src/tools/clippy/tests/ui/match_wildcard_for_single_variants.stderr8
-rw-r--r--src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs9
-rw-r--r--src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.stderr40
-rw-r--r--src/tools/clippy/tests/ui/needless_lifetimes.fixed538
-rw-r--r--src/tools/clippy/tests/ui/needless_lifetimes.rs42
-rw-r--r--src/tools/clippy/tests/ui/needless_lifetimes.stderr391
-rw-r--r--src/tools/clippy/tests/ui/needless_range_loop.stderr8
-rw-r--r--src/tools/clippy/tests/ui/new_without_default.rs7
-rw-r--r--src/tools/clippy/tests/ui/new_without_default.stderr14
-rw-r--r--src/tools/clippy/tests/ui/redundant_field_names.fixed2
-rw-r--r--src/tools/clippy/tests/ui/redundant_field_names.rs2
-rw-r--r--src/tools/clippy/tests/ui/regex.rs4
-rw-r--r--src/tools/clippy/tests/ui/regex.stderr66
-rw-r--r--src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.fixed4
-rw-r--r--src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.rs4
-rw-r--r--src/tools/clippy/tests/ui/suspicious_to_owned.stderr43
-rw-r--r--src/tools/clippy/tests/ui/type_repetition_in_bounds.rs1
-rw-r--r--src/tools/clippy/tests/ui/type_repetition_in_bounds.stderr8
-rw-r--r--src/tools/clippy/tests/ui/unused_io_amount.rs8
-rw-r--r--src/tools/clippy/tests/ui/unused_io_amount.stderr44
-rw-r--r--src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed2
-rw-r--r--src/tools/clippy/tests/ui/wildcard_enum_match_arm.stderr4
35 files changed, 1535 insertions, 211 deletions
diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr b/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr
index 2a240cc249b..c1a10ba55ef 100644
--- a/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr
+++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr
@@ -1,19 +1,19 @@
 error: hardcoded path to a diagnostic item
-  --> $DIR/unnecessary_def_path_hardcoded_path.rs:10:36
+  --> $DIR/unnecessary_def_path_hardcoded_path.rs:12:43
    |
-LL |     const DEREF_TRAIT: [&str; 4] = ["core", "ops", "deref", "Deref"];
-   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"];
+   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: convert all references to use `sym::Deref`
+   = help: convert all references to use `sym::deref_method`
    = note: `-D clippy::unnecessary-def-path` implied by `-D warnings`
 
 error: hardcoded path to a diagnostic item
-  --> $DIR/unnecessary_def_path_hardcoded_path.rs:12:43
+  --> $DIR/unnecessary_def_path_hardcoded_path.rs:10:36
    |
-LL |     const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"];
-   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     const DEREF_TRAIT: [&str; 4] = ["core", "ops", "deref", "Deref"];
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: convert all references to use `sym::deref_method`
+   = help: convert all references to use `sym::Deref`
 
 error: hardcoded path to a language item
   --> $DIR/unnecessary_def_path_hardcoded_path.rs:11:40
diff --git a/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs b/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs
index 1e5f20e8c39..a13af565203 100644
--- a/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs
@@ -149,3 +149,22 @@ macro_rules! almost_complete_range {
         let _ = '0'..'9';
     };
 }
+
+#[macro_export]
+macro_rules! unsafe_macro {
+    () => {
+        unsafe {
+            *core::ptr::null::<()>();
+            *core::ptr::null::<()>();
+        }
+    };
+}
+
+#[macro_export]
+macro_rules! needless_lifetime {
+    () => {
+        fn needless_lifetime<'a>(x: &'a u8) -> &'a u8 {
+            unimplemented!()
+        }
+    };
+}
diff --git a/src/tools/clippy/tests/ui/bool_assert_comparison.fixed b/src/tools/clippy/tests/ui/bool_assert_comparison.fixed
index 95f35a61bb2..b8dd92906c8 100644
--- a/src/tools/clippy/tests/ui/bool_assert_comparison.fixed
+++ b/src/tools/clippy/tests/ui/bool_assert_comparison.fixed
@@ -86,7 +86,7 @@ fn main() {
     let b = ImplNotTraitWithBool;
 
     assert_eq!("a".len(), 1);
-    assert!("a".is_empty());
+    assert!(!"a".is_empty());
     assert!("".is_empty());
     assert!("".is_empty());
     assert_eq!(a!(), b!());
@@ -97,16 +97,16 @@ fn main() {
 
     assert_ne!("a".len(), 1);
     assert!("a".is_empty());
-    assert!("".is_empty());
-    assert!("".is_empty());
+    assert!(!"".is_empty());
+    assert!(!"".is_empty());
     assert_ne!(a!(), b!());
     assert_ne!(a!(), "".is_empty());
     assert_ne!("".is_empty(), b!());
     assert_ne!(a, true);
-    assert!(b);
+    assert!(!b);
 
     debug_assert_eq!("a".len(), 1);
-    debug_assert!("a".is_empty());
+    debug_assert!(!"a".is_empty());
     debug_assert!("".is_empty());
     debug_assert!("".is_empty());
     debug_assert_eq!(a!(), b!());
@@ -117,27 +117,27 @@ fn main() {
 
     debug_assert_ne!("a".len(), 1);
     debug_assert!("a".is_empty());
-    debug_assert!("".is_empty());
-    debug_assert!("".is_empty());
+    debug_assert!(!"".is_empty());
+    debug_assert!(!"".is_empty());
     debug_assert_ne!(a!(), b!());
     debug_assert_ne!(a!(), "".is_empty());
     debug_assert_ne!("".is_empty(), b!());
     debug_assert_ne!(a, true);
-    debug_assert!(b);
+    debug_assert!(!b);
 
     // assert with error messages
     assert_eq!("a".len(), 1, "tadam {}", 1);
     assert_eq!("a".len(), 1, "tadam {}", true);
-    assert!("a".is_empty(), "tadam {}", 1);
-    assert!("a".is_empty(), "tadam {}", true);
-    assert!("a".is_empty(), "tadam {}", true);
+    assert!(!"a".is_empty(), "tadam {}", 1);
+    assert!(!"a".is_empty(), "tadam {}", true);
+    assert!(!"a".is_empty(), "tadam {}", true);
     assert_eq!(a, true, "tadam {}", false);
 
     debug_assert_eq!("a".len(), 1, "tadam {}", 1);
     debug_assert_eq!("a".len(), 1, "tadam {}", true);
-    debug_assert!("a".is_empty(), "tadam {}", 1);
-    debug_assert!("a".is_empty(), "tadam {}", true);
-    debug_assert!("a".is_empty(), "tadam {}", true);
+    debug_assert!(!"a".is_empty(), "tadam {}", 1);
+    debug_assert!(!"a".is_empty(), "tadam {}", true);
+    debug_assert!(!"a".is_empty(), "tadam {}", true);
     debug_assert_eq!(a, true, "tadam {}", false);
 
     assert!(a!());
@@ -158,4 +158,14 @@ fn main() {
         }};
     }
     in_macro!(a);
+
+    assert!("".is_empty());
+    assert!("".is_empty());
+    assert!(!"requires negation".is_empty());
+    assert!(!"requires negation".is_empty());
+
+    debug_assert!("".is_empty());
+    debug_assert!("".is_empty());
+    debug_assert!(!"requires negation".is_empty());
+    debug_assert!(!"requires negation".is_empty());
 }
diff --git a/src/tools/clippy/tests/ui/bool_assert_comparison.rs b/src/tools/clippy/tests/ui/bool_assert_comparison.rs
index 88e7560b4f9..0a8ad34fda5 100644
--- a/src/tools/clippy/tests/ui/bool_assert_comparison.rs
+++ b/src/tools/clippy/tests/ui/bool_assert_comparison.rs
@@ -158,4 +158,14 @@ fn main() {
         }};
     }
     in_macro!(a);
+
+    assert_eq!("".is_empty(), true);
+    assert_ne!("".is_empty(), false);
+    assert_ne!("requires negation".is_empty(), true);
+    assert_eq!("requires negation".is_empty(), false);
+
+    debug_assert_eq!("".is_empty(), true);
+    debug_assert_ne!("".is_empty(), false);
+    debug_assert_ne!("requires negation".is_empty(), true);
+    debug_assert_eq!("requires negation".is_empty(), false);
 }
diff --git a/src/tools/clippy/tests/ui/bool_assert_comparison.stderr b/src/tools/clippy/tests/ui/bool_assert_comparison.stderr
index 3d9f8573e61..89cefc95a9f 100644
--- a/src/tools/clippy/tests/ui/bool_assert_comparison.stderr
+++ b/src/tools/clippy/tests/ui/bool_assert_comparison.stderr
@@ -8,7 +8,7 @@ LL |     assert_eq!("a".is_empty(), false);
 help: replace it with `assert!(..)`
    |
 LL -     assert_eq!("a".is_empty(), false);
-LL +     assert!("a".is_empty());
+LL +     assert!(!"a".is_empty());
    |
 
 error: used `assert_eq!` with a literal bool
@@ -68,7 +68,7 @@ LL |     assert_ne!("".is_empty(), true);
 help: replace it with `assert!(..)`
    |
 LL -     assert_ne!("".is_empty(), true);
-LL +     assert!("".is_empty());
+LL +     assert!(!"".is_empty());
    |
 
 error: used `assert_ne!` with a literal bool
@@ -80,7 +80,7 @@ LL |     assert_ne!(true, "".is_empty());
 help: replace it with `assert!(..)`
    |
 LL -     assert_ne!(true, "".is_empty());
-LL +     assert!("".is_empty());
+LL +     assert!(!"".is_empty());
    |
 
 error: used `assert_ne!` with a literal bool
@@ -92,7 +92,7 @@ LL |     assert_ne!(b, true);
 help: replace it with `assert!(..)`
    |
 LL -     assert_ne!(b, true);
-LL +     assert!(b);
+LL +     assert!(!b);
    |
 
 error: used `debug_assert_eq!` with a literal bool
@@ -104,7 +104,7 @@ LL |     debug_assert_eq!("a".is_empty(), false);
 help: replace it with `debug_assert!(..)`
    |
 LL -     debug_assert_eq!("a".is_empty(), false);
-LL +     debug_assert!("a".is_empty());
+LL +     debug_assert!(!"a".is_empty());
    |
 
 error: used `debug_assert_eq!` with a literal bool
@@ -164,7 +164,7 @@ LL |     debug_assert_ne!("".is_empty(), true);
 help: replace it with `debug_assert!(..)`
    |
 LL -     debug_assert_ne!("".is_empty(), true);
-LL +     debug_assert!("".is_empty());
+LL +     debug_assert!(!"".is_empty());
    |
 
 error: used `debug_assert_ne!` with a literal bool
@@ -176,7 +176,7 @@ LL |     debug_assert_ne!(true, "".is_empty());
 help: replace it with `debug_assert!(..)`
    |
 LL -     debug_assert_ne!(true, "".is_empty());
-LL +     debug_assert!("".is_empty());
+LL +     debug_assert!(!"".is_empty());
    |
 
 error: used `debug_assert_ne!` with a literal bool
@@ -188,7 +188,7 @@ LL |     debug_assert_ne!(b, true);
 help: replace it with `debug_assert!(..)`
    |
 LL -     debug_assert_ne!(b, true);
-LL +     debug_assert!(b);
+LL +     debug_assert!(!b);
    |
 
 error: used `assert_eq!` with a literal bool
@@ -200,7 +200,7 @@ LL |     assert_eq!("a".is_empty(), false, "tadam {}", 1);
 help: replace it with `assert!(..)`
    |
 LL -     assert_eq!("a".is_empty(), false, "tadam {}", 1);
-LL +     assert!("a".is_empty(), "tadam {}", 1);
+LL +     assert!(!"a".is_empty(), "tadam {}", 1);
    |
 
 error: used `assert_eq!` with a literal bool
@@ -212,7 +212,7 @@ LL |     assert_eq!("a".is_empty(), false, "tadam {}", true);
 help: replace it with `assert!(..)`
    |
 LL -     assert_eq!("a".is_empty(), false, "tadam {}", true);
-LL +     assert!("a".is_empty(), "tadam {}", true);
+LL +     assert!(!"a".is_empty(), "tadam {}", true);
    |
 
 error: used `assert_eq!` with a literal bool
@@ -224,7 +224,7 @@ LL |     assert_eq!(false, "a".is_empty(), "tadam {}", true);
 help: replace it with `assert!(..)`
    |
 LL -     assert_eq!(false, "a".is_empty(), "tadam {}", true);
-LL +     assert!("a".is_empty(), "tadam {}", true);
+LL +     assert!(!"a".is_empty(), "tadam {}", true);
    |
 
 error: used `debug_assert_eq!` with a literal bool
@@ -236,7 +236,7 @@ LL |     debug_assert_eq!("a".is_empty(), false, "tadam {}", 1);
 help: replace it with `debug_assert!(..)`
    |
 LL -     debug_assert_eq!("a".is_empty(), false, "tadam {}", 1);
-LL +     debug_assert!("a".is_empty(), "tadam {}", 1);
+LL +     debug_assert!(!"a".is_empty(), "tadam {}", 1);
    |
 
 error: used `debug_assert_eq!` with a literal bool
@@ -248,7 +248,7 @@ LL |     debug_assert_eq!("a".is_empty(), false, "tadam {}", true);
 help: replace it with `debug_assert!(..)`
    |
 LL -     debug_assert_eq!("a".is_empty(), false, "tadam {}", true);
-LL +     debug_assert!("a".is_empty(), "tadam {}", true);
+LL +     debug_assert!(!"a".is_empty(), "tadam {}", true);
    |
 
 error: used `debug_assert_eq!` with a literal bool
@@ -260,7 +260,7 @@ LL |     debug_assert_eq!(false, "a".is_empty(), "tadam {}", true);
 help: replace it with `debug_assert!(..)`
    |
 LL -     debug_assert_eq!(false, "a".is_empty(), "tadam {}", true);
-LL +     debug_assert!("a".is_empty(), "tadam {}", true);
+LL +     debug_assert!(!"a".is_empty(), "tadam {}", true);
    |
 
 error: used `assert_eq!` with a literal bool
@@ -299,5 +299,101 @@ LL -     renamed!(b, true);
 LL +     debug_assert!(b);
    |
 
-error: aborting due to 25 previous errors
+error: used `assert_eq!` with a literal bool
+  --> $DIR/bool_assert_comparison.rs:162:5
+   |
+LL |     assert_eq!("".is_empty(), true);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: replace it with `assert!(..)`
+   |
+LL -     assert_eq!("".is_empty(), true);
+LL +     assert!("".is_empty());
+   |
+
+error: used `assert_ne!` with a literal bool
+  --> $DIR/bool_assert_comparison.rs:163:5
+   |
+LL |     assert_ne!("".is_empty(), false);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: replace it with `assert!(..)`
+   |
+LL -     assert_ne!("".is_empty(), false);
+LL +     assert!("".is_empty());
+   |
+
+error: used `assert_ne!` with a literal bool
+  --> $DIR/bool_assert_comparison.rs:164:5
+   |
+LL |     assert_ne!("requires negation".is_empty(), true);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: replace it with `assert!(..)`
+   |
+LL -     assert_ne!("requires negation".is_empty(), true);
+LL +     assert!(!"requires negation".is_empty());
+   |
+
+error: used `assert_eq!` with a literal bool
+  --> $DIR/bool_assert_comparison.rs:165:5
+   |
+LL |     assert_eq!("requires negation".is_empty(), false);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: replace it with `assert!(..)`
+   |
+LL -     assert_eq!("requires negation".is_empty(), false);
+LL +     assert!(!"requires negation".is_empty());
+   |
+
+error: used `debug_assert_eq!` with a literal bool
+  --> $DIR/bool_assert_comparison.rs:167:5
+   |
+LL |     debug_assert_eq!("".is_empty(), true);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: replace it with `debug_assert!(..)`
+   |
+LL -     debug_assert_eq!("".is_empty(), true);
+LL +     debug_assert!("".is_empty());
+   |
+
+error: used `debug_assert_ne!` with a literal bool
+  --> $DIR/bool_assert_comparison.rs:168:5
+   |
+LL |     debug_assert_ne!("".is_empty(), false);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: replace it with `debug_assert!(..)`
+   |
+LL -     debug_assert_ne!("".is_empty(), false);
+LL +     debug_assert!("".is_empty());
+   |
+
+error: used `debug_assert_ne!` with a literal bool
+  --> $DIR/bool_assert_comparison.rs:169:5
+   |
+LL |     debug_assert_ne!("requires negation".is_empty(), true);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: replace it with `debug_assert!(..)`
+   |
+LL -     debug_assert_ne!("requires negation".is_empty(), true);
+LL +     debug_assert!(!"requires negation".is_empty());
+   |
+
+error: used `debug_assert_eq!` with a literal bool
+  --> $DIR/bool_assert_comparison.rs:170:5
+   |
+LL |     debug_assert_eq!("requires negation".is_empty(), false);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: replace it with `debug_assert!(..)`
+   |
+LL -     debug_assert_eq!("requires negation".is_empty(), false);
+LL +     debug_assert!(!"requires negation".is_empty());
+   |
+
+error: aborting due to 33 previous errors
 
diff --git a/src/tools/clippy/tests/ui/crashes/ice-2774.stderr b/src/tools/clippy/tests/ui/crashes/ice-2774.stderr
index 1f26c7f4db6..c5ea0b16d1b 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-2774.stderr
+++ b/src/tools/clippy/tests/ui/crashes/ice-2774.stderr
@@ -5,6 +5,11 @@ LL | pub fn add_barfoos_to_foos<'a>(bars: &HashSet<&'a Bar>) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::needless-lifetimes` implied by `-D warnings`
+help: elide the lifetimes
+   |
+LL - pub fn add_barfoos_to_foos<'a>(bars: &HashSet<&'a Bar>) {
+LL + pub fn add_barfoos_to_foos(bars: &HashSet<&Bar>) {
+   |
 
 error: aborting due to previous error
 
diff --git a/src/tools/clippy/tests/ui/crashes/needless_lifetimes_impl_trait.stderr b/src/tools/clippy/tests/ui/crashes/needless_lifetimes_impl_trait.stderr
index 875d5ab4f21..0b0e0ad2684 100644
--- a/src/tools/clippy/tests/ui/crashes/needless_lifetimes_impl_trait.stderr
+++ b/src/tools/clippy/tests/ui/crashes/needless_lifetimes_impl_trait.stderr
@@ -9,6 +9,11 @@ note: the lint level is defined here
    |
 LL | #![deny(clippy::needless_lifetimes)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: elide the lifetimes
+   |
+LL -     fn baz<'a>(&'a self) -> impl Foo + 'a {
+LL +     fn baz(&self) -> impl Foo + '_ {
+   |
 
 error: aborting due to previous error
 
diff --git a/src/tools/clippy/tests/ui/extra_unused_type_parameters.rs b/src/tools/clippy/tests/ui/extra_unused_type_parameters.rs
new file mode 100644
index 00000000000..5cb80cb6233
--- /dev/null
+++ b/src/tools/clippy/tests/ui/extra_unused_type_parameters.rs
@@ -0,0 +1,69 @@
+#![allow(unused, clippy::needless_lifetimes)]
+#![warn(clippy::extra_unused_type_parameters)]
+
+fn unused_ty<T>(x: u8) {}
+
+fn unused_multi<T, U>(x: u8) {}
+
+fn unused_with_lt<'a, T>(x: &'a u8) {}
+
+fn used_ty<T>(x: T, y: u8) {}
+
+fn used_ref<'a, T>(x: &'a T) {}
+
+fn used_ret<T: Default>(x: u8) -> T {
+    T::default()
+}
+
+fn unused_bounded<T: Default, U>(x: U) {}
+
+fn unused_where_clause<T, U>(x: U)
+where
+    T: Default,
+{
+}
+
+fn some_unused<A, B, C, D: Iterator<Item = (B, C)>, E>(b: B, c: C) {}
+
+fn used_opaque<A>(iter: impl Iterator<Item = A>) -> usize {
+    iter.count()
+}
+
+fn used_ret_opaque<A>() -> impl Iterator<Item = A> {
+    std::iter::empty()
+}
+
+fn used_vec_box<T>(x: Vec<Box<T>>) {}
+
+fn used_body<T: Default + ToString>() -> String {
+    T::default().to_string()
+}
+
+fn used_closure<T: Default + ToString>() -> impl Fn() {
+    || println!("{}", T::default().to_string())
+}
+
+struct S;
+
+impl S {
+    fn unused_ty_impl<T>(&self) {}
+}
+
+// Don't lint on trait methods
+trait Foo {
+    fn bar<T>(&self);
+}
+
+impl Foo for S {
+    fn bar<T>(&self) {}
+}
+
+fn skip_index<A, Iter>(iter: Iter, index: usize) -> impl Iterator<Item = A>
+where
+    Iter: Iterator<Item = A>,
+{
+    iter.enumerate()
+        .filter_map(move |(i, a)| if i == index { None } else { Some(a) })
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/extra_unused_type_parameters.stderr b/src/tools/clippy/tests/ui/extra_unused_type_parameters.stderr
new file mode 100644
index 00000000000..1c8dd53e638
--- /dev/null
+++ b/src/tools/clippy/tests/ui/extra_unused_type_parameters.stderr
@@ -0,0 +1,59 @@
+error: type parameter goes unused in function definition
+  --> $DIR/extra_unused_type_parameters.rs:4:13
+   |
+LL | fn unused_ty<T>(x: u8) {}
+   |             ^^^
+   |
+   = help: consider removing the parameter
+   = note: `-D clippy::extra-unused-type-parameters` implied by `-D warnings`
+
+error: type parameters go unused in function definition
+  --> $DIR/extra_unused_type_parameters.rs:6:16
+   |
+LL | fn unused_multi<T, U>(x: u8) {}
+   |                ^^^^^^
+   |
+   = help: consider removing the parameters
+
+error: type parameter goes unused in function definition
+  --> $DIR/extra_unused_type_parameters.rs:8:23
+   |
+LL | fn unused_with_lt<'a, T>(x: &'a u8) {}
+   |                       ^
+   |
+   = help: consider removing the parameter
+
+error: type parameter goes unused in function definition
+  --> $DIR/extra_unused_type_parameters.rs:18:19
+   |
+LL | fn unused_bounded<T: Default, U>(x: U) {}
+   |                   ^^^^^^^^^^^
+   |
+   = help: consider removing the parameter
+
+error: type parameter goes unused in function definition
+  --> $DIR/extra_unused_type_parameters.rs:20:24
+   |
+LL | fn unused_where_clause<T, U>(x: U)
+   |                        ^^
+   |
+   = help: consider removing the parameter
+
+error: type parameters go unused in function definition
+  --> $DIR/extra_unused_type_parameters.rs:26:16
+   |
+LL | fn some_unused<A, B, C, D: Iterator<Item = (B, C)>, E>(b: B, c: C) {}
+   |                ^^       ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^
+   |
+   = help: consider removing the parameters
+
+error: type parameter goes unused in function definition
+  --> $DIR/extra_unused_type_parameters.rs:49:22
+   |
+LL |     fn unused_ty_impl<T>(&self) {}
+   |                      ^^^
+   |
+   = help: consider removing the parameter
+
+error: aborting due to 7 previous errors
+
diff --git a/src/tools/clippy/tests/ui/len_without_is_empty.rs b/src/tools/clippy/tests/ui/len_without_is_empty.rs
index 78397c2af34..b5dec6c46bd 100644
--- a/src/tools/clippy/tests/ui/len_without_is_empty.rs
+++ b/src/tools/clippy/tests/ui/len_without_is_empty.rs
@@ -282,4 +282,50 @@ impl AsyncLen {
     }
 }
 
+// issue #9520
+pub struct NonStandardLenAndIsEmptySignature;
+impl NonStandardLenAndIsEmptySignature {
+    // don't lint
+    pub fn len(&self, something: usize) -> usize {
+        something
+    }
+
+    pub fn is_empty(&self, something: usize) -> bool {
+        something == 0
+    }
+}
+
+// test case for #9520 with generics in the function signature
+pub trait TestResource {
+    type NonStandardSignatureWithGenerics: Copy;
+    fn lookup_content(&self, item: Self::NonStandardSignatureWithGenerics) -> Result<Option<&[u8]>, String>;
+}
+pub struct NonStandardSignatureWithGenerics(u32);
+impl NonStandardSignatureWithGenerics {
+    pub fn is_empty<T, U>(self, resource: &T) -> bool
+    where
+        T: TestResource<NonStandardSignatureWithGenerics = U>,
+        U: Copy + From<NonStandardSignatureWithGenerics>,
+    {
+        if let Ok(Some(content)) = resource.lookup_content(self.into()) {
+            content.is_empty()
+        } else {
+            true
+        }
+    }
+
+    // test case for #9520 with generics in the function signature
+    pub fn len<T, U>(self, resource: &T) -> usize
+    where
+        T: TestResource<NonStandardSignatureWithGenerics = U>,
+        U: Copy + From<NonStandardSignatureWithGenerics>,
+    {
+        if let Ok(Some(content)) = resource.lookup_content(self.into()) {
+            content.len()
+        } else {
+            0_usize
+        }
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/manual_assert.edition2018.fixed b/src/tools/clippy/tests/ui/manual_assert.edition2018.fixed
index 638320dd6ee..8c7e919bf62 100644
--- a/src/tools/clippy/tests/ui/manual_assert.edition2018.fixed
+++ b/src/tools/clippy/tests/ui/manual_assert.edition2018.fixed
@@ -29,9 +29,7 @@ fn main() {
         panic!("qaqaq{:?}", a);
     }
     assert!(a.is_empty(), "qaqaq{:?}", a);
-    if !a.is_empty() {
-        panic!("qwqwq");
-    }
+    assert!(a.is_empty(), "qwqwq");
     if a.len() == 3 {
         println!("qwq");
         println!("qwq");
@@ -46,21 +44,11 @@ fn main() {
         println!("qwq");
     }
     let b = vec![1, 2, 3];
-    if b.is_empty() {
-        panic!("panic1");
-    }
-    if b.is_empty() && a.is_empty() {
-        panic!("panic2");
-    }
-    if a.is_empty() && !b.is_empty() {
-        panic!("panic3");
-    }
-    if b.is_empty() || a.is_empty() {
-        panic!("panic4");
-    }
-    if a.is_empty() || !b.is_empty() {
-        panic!("panic5");
-    }
+    assert!(!b.is_empty(), "panic1");
+    assert!(!(b.is_empty() && a.is_empty()), "panic2");
+    assert!(!(a.is_empty() && !b.is_empty()), "panic3");
+    assert!(!(b.is_empty() || a.is_empty()), "panic4");
+    assert!(!(a.is_empty() || !b.is_empty()), "panic5");
     assert!(!a.is_empty(), "with expansion {}", one!());
     if a.is_empty() {
         let _ = 0;
@@ -71,12 +59,11 @@ fn main() {
 
 fn issue7730(a: u8) {
     // Suggestion should preserve comment
-    if a > 2 {
-        // comment
-        /* this is a
+    // comment
+/* this is a
         multiline
         comment */
-        /// Doc comment
-        panic!("panic with comment") // comment after `panic!`
-    }
+/// Doc comment
+// comment after `panic!`
+assert!(!(a > 2), "panic with comment");
 }
diff --git a/src/tools/clippy/tests/ui/manual_assert.edition2018.stderr b/src/tools/clippy/tests/ui/manual_assert.edition2018.stderr
index 1f2e1e3087b..3555ac29243 100644
--- a/src/tools/clippy/tests/ui/manual_assert.edition2018.stderr
+++ b/src/tools/clippy/tests/ui/manual_assert.edition2018.stderr
@@ -9,6 +9,54 @@ LL | |     }
    = note: `-D clippy::manual-assert` implied by `-D warnings`
 
 error: only a `panic!` in `if`-then statement
+  --> $DIR/manual_assert.rs:34:5
+   |
+LL | /     if !a.is_empty() {
+LL | |         panic!("qwqwq");
+LL | |     }
+   | |_____^ help: try instead: `assert!(a.is_empty(), "qwqwq");`
+
+error: only a `panic!` in `if`-then statement
+  --> $DIR/manual_assert.rs:51:5
+   |
+LL | /     if b.is_empty() {
+LL | |         panic!("panic1");
+LL | |     }
+   | |_____^ help: try instead: `assert!(!b.is_empty(), "panic1");`
+
+error: only a `panic!` in `if`-then statement
+  --> $DIR/manual_assert.rs:54:5
+   |
+LL | /     if b.is_empty() && a.is_empty() {
+LL | |         panic!("panic2");
+LL | |     }
+   | |_____^ help: try instead: `assert!(!(b.is_empty() && a.is_empty()), "panic2");`
+
+error: only a `panic!` in `if`-then statement
+  --> $DIR/manual_assert.rs:57:5
+   |
+LL | /     if a.is_empty() && !b.is_empty() {
+LL | |         panic!("panic3");
+LL | |     }
+   | |_____^ help: try instead: `assert!(!(a.is_empty() && !b.is_empty()), "panic3");`
+
+error: only a `panic!` in `if`-then statement
+  --> $DIR/manual_assert.rs:60:5
+   |
+LL | /     if b.is_empty() || a.is_empty() {
+LL | |         panic!("panic4");
+LL | |     }
+   | |_____^ help: try instead: `assert!(!(b.is_empty() || a.is_empty()), "panic4");`
+
+error: only a `panic!` in `if`-then statement
+  --> $DIR/manual_assert.rs:63:5
+   |
+LL | /     if a.is_empty() || !b.is_empty() {
+LL | |         panic!("panic5");
+LL | |     }
+   | |_____^ help: try instead: `assert!(!(a.is_empty() || !b.is_empty()), "panic5");`
+
+error: only a `panic!` in `if`-then statement
   --> $DIR/manual_assert.rs:66:5
    |
 LL | /     if a.is_empty() {
@@ -16,5 +64,22 @@ LL | |         panic!("with expansion {}", one!())
 LL | |     }
    | |_____^ help: try instead: `assert!(!a.is_empty(), "with expansion {}", one!());`
 
-error: aborting due to 2 previous errors
+error: only a `panic!` in `if`-then statement
+  --> $DIR/manual_assert.rs:78:5
+   |
+LL | /     if a > 2 {
+LL | |         // comment
+LL | |         /* this is a
+LL | |         multiline
+...  |
+LL | |         panic!("panic with comment") // comment after `panic!`
+LL | |     }
+   | |_____^
+   |
+help: try instead
+   |
+LL |     assert!(!(a > 2), "panic with comment");
+   |
+
+error: aborting due to 9 previous errors
 
diff --git a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed
index fc252cdd352..9fd3739b69c 100644
--- a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed
+++ b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed
@@ -123,7 +123,7 @@ fn main() {
             Enum::A => (),
             Enum::B => (),
             Enum::C => (),
-            _ => (),
+            Enum::__Private => (),
         }
         match Enum::A {
             Enum::A => (),
diff --git a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.stderr b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.stderr
index 6fa313dc911..105b4c4b41d 100644
--- a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.stderr
+++ b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.stderr
@@ -49,10 +49,16 @@ LL |         _ => (),
    |         ^ help: try this: `Color::Blue`
 
 error: wildcard matches only a single variant and will also match any future added variants
+  --> $DIR/match_wildcard_for_single_variants.rs:126:13
+   |
+LL |             _ => (),
+   |             ^ help: try this: `Enum::__Private`
+
+error: wildcard matches only a single variant and will also match any future added variants
   --> $DIR/match_wildcard_for_single_variants.rs:153:13
    |
 LL |             _ => 2,
    |             ^ help: try this: `Foo::B`
 
-error: aborting due to 9 previous errors
+error: aborting due to 10 previous errors
 
diff --git a/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs b/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs
index 41263535df6..4511bc99c3c 100644
--- a/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs
+++ b/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs
@@ -1,9 +1,13 @@
+// aux-build:macro_rules.rs
 #![allow(unused)]
 #![allow(deref_nullptr)]
 #![allow(clippy::unnecessary_operation)]
 #![allow(clippy::drop_copy)]
 #![warn(clippy::multiple_unsafe_ops_per_block)]
 
+#[macro_use]
+extern crate macro_rules;
+
 use core::arch::asm;
 
 fn raw_ptr() -> *const () {
@@ -107,4 +111,9 @@ unsafe fn read_char_good(ptr: *const u8) -> char {
     unsafe { core::char::from_u32_unchecked(int_value) }
 }
 
+// no lint
+fn issue10259() {
+    unsafe_macro!();
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.stderr b/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.stderr
index f6b8341795d..303aeb7aee0 100644
--- a/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.stderr
+++ b/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.stderr
@@ -1,5 +1,5 @@
 error: this `unsafe` block contains 2 unsafe operations, expected only one
-  --> $DIR/multiple_unsafe_ops_per_block.rs:32:5
+  --> $DIR/multiple_unsafe_ops_per_block.rs:36:5
    |
 LL | /     unsafe {
 LL | |         STATIC += 1;
@@ -8,19 +8,19 @@ LL | |     }
    | |_____^
    |
 note: modification of a mutable static occurs here
-  --> $DIR/multiple_unsafe_ops_per_block.rs:33:9
+  --> $DIR/multiple_unsafe_ops_per_block.rs:37:9
    |
 LL |         STATIC += 1;
    |         ^^^^^^^^^^^
 note: unsafe function call occurs here
-  --> $DIR/multiple_unsafe_ops_per_block.rs:34:9
+  --> $DIR/multiple_unsafe_ops_per_block.rs:38:9
    |
 LL |         not_very_safe();
    |         ^^^^^^^^^^^^^^^
    = note: `-D clippy::multiple-unsafe-ops-per-block` implied by `-D warnings`
 
 error: this `unsafe` block contains 2 unsafe operations, expected only one
-  --> $DIR/multiple_unsafe_ops_per_block.rs:41:5
+  --> $DIR/multiple_unsafe_ops_per_block.rs:45:5
    |
 LL | /     unsafe {
 LL | |         drop(u.u);
@@ -29,18 +29,18 @@ LL | |     }
    | |_____^
    |
 note: union field access occurs here
-  --> $DIR/multiple_unsafe_ops_per_block.rs:42:14
+  --> $DIR/multiple_unsafe_ops_per_block.rs:46:14
    |
 LL |         drop(u.u);
    |              ^^^
 note: raw pointer dereference occurs here
-  --> $DIR/multiple_unsafe_ops_per_block.rs:43:9
+  --> $DIR/multiple_unsafe_ops_per_block.rs:47:9
    |
 LL |         *raw_ptr();
    |         ^^^^^^^^^^
 
 error: this `unsafe` block contains 3 unsafe operations, expected only one
-  --> $DIR/multiple_unsafe_ops_per_block.rs:48:5
+  --> $DIR/multiple_unsafe_ops_per_block.rs:52:5
    |
 LL | /     unsafe {
 LL | |         asm!("nop");
@@ -50,23 +50,23 @@ LL | |     }
    | |_____^
    |
 note: inline assembly used here
-  --> $DIR/multiple_unsafe_ops_per_block.rs:49:9
+  --> $DIR/multiple_unsafe_ops_per_block.rs:53:9
    |
 LL |         asm!("nop");
    |         ^^^^^^^^^^^
 note: unsafe method call occurs here
-  --> $DIR/multiple_unsafe_ops_per_block.rs:50:9
+  --> $DIR/multiple_unsafe_ops_per_block.rs:54:9
    |
 LL |         sample.not_very_safe();
    |         ^^^^^^^^^^^^^^^^^^^^^^
 note: modification of a mutable static occurs here
-  --> $DIR/multiple_unsafe_ops_per_block.rs:51:9
+  --> $DIR/multiple_unsafe_ops_per_block.rs:55:9
    |
 LL |         STATIC = 0;
    |         ^^^^^^^^^^
 
 error: this `unsafe` block contains 6 unsafe operations, expected only one
-  --> $DIR/multiple_unsafe_ops_per_block.rs:57:5
+  --> $DIR/multiple_unsafe_ops_per_block.rs:61:5
    |
 LL | /     unsafe {
 LL | |         drop(u.u);
@@ -78,49 +78,49 @@ LL | |     }
    | |_____^
    |
 note: union field access occurs here
-  --> $DIR/multiple_unsafe_ops_per_block.rs:58:14
+  --> $DIR/multiple_unsafe_ops_per_block.rs:62:14
    |
 LL |         drop(u.u);
    |              ^^^
 note: access of a mutable static occurs here
-  --> $DIR/multiple_unsafe_ops_per_block.rs:59:14
+  --> $DIR/multiple_unsafe_ops_per_block.rs:63:14
    |
 LL |         drop(STATIC);
    |              ^^^^^^
 note: unsafe method call occurs here
-  --> $DIR/multiple_unsafe_ops_per_block.rs:60:9
+  --> $DIR/multiple_unsafe_ops_per_block.rs:64:9
    |
 LL |         sample.not_very_safe();
    |         ^^^^^^^^^^^^^^^^^^^^^^
 note: unsafe function call occurs here
-  --> $DIR/multiple_unsafe_ops_per_block.rs:61:9
+  --> $DIR/multiple_unsafe_ops_per_block.rs:65:9
    |
 LL |         not_very_safe();
    |         ^^^^^^^^^^^^^^^
 note: raw pointer dereference occurs here
-  --> $DIR/multiple_unsafe_ops_per_block.rs:62:9
+  --> $DIR/multiple_unsafe_ops_per_block.rs:66:9
    |
 LL |         *raw_ptr();
    |         ^^^^^^^^^^
 note: inline assembly used here
-  --> $DIR/multiple_unsafe_ops_per_block.rs:63:9
+  --> $DIR/multiple_unsafe_ops_per_block.rs:67:9
    |
 LL |         asm!("nop");
    |         ^^^^^^^^^^^
 
 error: this `unsafe` block contains 2 unsafe operations, expected only one
-  --> $DIR/multiple_unsafe_ops_per_block.rs:101:5
+  --> $DIR/multiple_unsafe_ops_per_block.rs:105:5
    |
 LL |     unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: unsafe function call occurs here
-  --> $DIR/multiple_unsafe_ops_per_block.rs:101:14
+  --> $DIR/multiple_unsafe_ops_per_block.rs:105:14
    |
 LL |     unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: raw pointer dereference occurs here
-  --> $DIR/multiple_unsafe_ops_per_block.rs:101:39
+  --> $DIR/multiple_unsafe_ops_per_block.rs:105:39
    |
 LL |     unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
    |                                       ^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/needless_lifetimes.fixed b/src/tools/clippy/tests/ui/needless_lifetimes.fixed
new file mode 100644
index 00000000000..d286ef4ba37
--- /dev/null
+++ b/src/tools/clippy/tests/ui/needless_lifetimes.fixed
@@ -0,0 +1,538 @@
+// run-rustfix
+// aux-build:macro_rules.rs
+
+#![warn(clippy::needless_lifetimes)]
+#![allow(
+    unused,
+    clippy::boxed_local,
+    clippy::extra_unused_type_parameters,
+    clippy::needless_pass_by_value,
+    clippy::unnecessary_wraps,
+    dyn_drop,
+    clippy::get_first
+)]
+
+#[macro_use]
+extern crate macro_rules;
+
+fn distinct_lifetimes(_x: &u8, _y: &u8, _z: u8) {}
+
+fn distinct_and_static(_x: &u8, _y: &u8, _z: &'static u8) {}
+
+// No error; same lifetime on two params.
+fn same_lifetime_on_input<'a>(_x: &'a u8, _y: &'a u8) {}
+
+// No error; static involved.
+fn only_static_on_input(_x: &u8, _y: &u8, _z: &'static u8) {}
+
+fn mut_and_static_input(_x: &mut u8, _y: &'static str) {}
+
+fn in_and_out(x: &u8, _y: u8) -> &u8 {
+    x
+}
+
+// No error; multiple input refs.
+fn multiple_in_and_out_1<'a>(x: &'a u8, _y: &'a u8) -> &'a u8 {
+    x
+}
+
+// Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
+//   fn multiple_in_and_out_2a<'a>(x: &'a u8, _y: &u8) -> &'a u8
+//                                                ^^^
+fn multiple_in_and_out_2a<'a>(x: &'a u8, _y: &u8) -> &'a u8 {
+    x
+}
+
+// Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
+//   fn multiple_in_and_out_2b<'b>(_x: &u8, y: &'b u8) -> &'b u8
+//                                     ^^^
+fn multiple_in_and_out_2b<'b>(_x: &u8, y: &'b u8) -> &'b u8 {
+    y
+}
+
+// No error; multiple input refs
+async fn func<'a>(args: &[&'a str]) -> Option<&'a str> {
+    args.get(0).cloned()
+}
+
+// No error; static involved.
+fn in_static_and_out<'a>(x: &'a u8, _y: &'static u8) -> &'a u8 {
+    x
+}
+
+// Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
+//   fn deep_reference_1a<'a>(x: &'a u8, _y: &u8) -> Result<&'a u8, ()>
+//                                           ^^^
+fn deep_reference_1a<'a>(x: &'a u8, _y: &u8) -> Result<&'a u8, ()> {
+    Ok(x)
+}
+
+// Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
+//   fn deep_reference_1b<'b>(_x: &u8, y: &'b u8) -> Result<&'b u8, ()>
+//                                ^^^
+fn deep_reference_1b<'b>(_x: &u8, y: &'b u8) -> Result<&'b u8, ()> {
+    Ok(y)
+}
+
+// No error; two input refs.
+fn deep_reference_2<'a>(x: Result<&'a u8, &'a u8>) -> &'a u8 {
+    x.unwrap()
+}
+
+fn deep_reference_3(x: &u8, _y: u8) -> Result<&u8, ()> {
+    Ok(x)
+}
+
+// Where-clause, but without lifetimes.
+fn where_clause_without_lt<T>(x: &u8, _y: u8) -> Result<&u8, ()>
+where
+    T: Copy,
+{
+    Ok(x)
+}
+
+type Ref<'r> = &'r u8;
+
+// No error; same lifetime on two params.
+fn lifetime_param_1<'a>(_x: Ref<'a>, _y: &'a u8) {}
+
+fn lifetime_param_2(_x: Ref<'_>, _y: &u8) {}
+
+// No error; bounded lifetime.
+fn lifetime_param_3<'a, 'b: 'a>(_x: Ref<'a>, _y: &'b u8) {}
+
+// No error; bounded lifetime.
+fn lifetime_param_4<'a, 'b>(_x: Ref<'a>, _y: &'b u8)
+where
+    'b: 'a,
+{
+}
+
+struct Lt<'a, I: 'static> {
+    x: &'a I,
+}
+
+// No error; fn bound references `'a`.
+fn fn_bound<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
+where
+    F: Fn(Lt<'a, I>) -> Lt<'a, I>,
+{
+    unreachable!()
+}
+
+fn fn_bound_2<F, I>(_m: Lt<'_, I>, _f: F) -> Lt<'_, I>
+where
+    for<'x> F: Fn(Lt<'x, I>) -> Lt<'x, I>,
+{
+    unreachable!()
+}
+
+// No error; see below.
+fn fn_bound_3<'a, F: FnOnce(&'a i32)>(x: &'a i32, f: F) {
+    f(x);
+}
+
+fn fn_bound_3_cannot_elide() {
+    let x = 42;
+    let p = &x;
+    let mut q = &x;
+    // This will fail if we elide lifetimes of `fn_bound_3`.
+    fn_bound_3(p, |y| q = y);
+}
+
+// No error; multiple input refs.
+fn fn_bound_4<'a, F: FnOnce() -> &'a ()>(cond: bool, x: &'a (), f: F) -> &'a () {
+    if cond { x } else { f() }
+}
+
+struct X {
+    x: u8,
+}
+
+impl X {
+    fn self_and_out(&self) -> &u8 {
+        &self.x
+    }
+
+    // Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
+    //   fn self_and_in_out_1<'s>(&'s self, _x: &u8) -> &'s u8
+    //                                          ^^^
+    fn self_and_in_out_1<'s>(&'s self, _x: &u8) -> &'s u8 {
+        &self.x
+    }
+
+    // Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
+    //   fn self_and_in_out_2<'t>(&self, x: &'t u8) -> &'t u8
+    //                            ^^^^^
+    fn self_and_in_out_2<'t>(&self, x: &'t u8) -> &'t u8 {
+        x
+    }
+
+    fn distinct_self_and_in(&self, _x: &u8) {}
+
+    // No error; same lifetimes on two params.
+    fn self_and_same_in<'s>(&'s self, _x: &'s u8) {}
+}
+
+struct Foo<'a>(&'a u8);
+
+impl<'a> Foo<'a> {
+    // No error; lifetime `'a` not defined in method.
+    fn self_shared_lifetime(&self, _: &'a u8) {}
+    // No error; bounds exist.
+    fn self_bound_lifetime<'b: 'a>(&self, _: &'b u8) {}
+}
+
+fn already_elided<'a>(_: &u8, _: &'a u8) -> &'a u8 {
+    unimplemented!()
+}
+
+fn struct_with_lt(_foo: Foo<'_>) -> &str {
+    unimplemented!()
+}
+
+// No warning; two input lifetimes (named on the reference, anonymous on `Foo`).
+fn struct_with_lt2<'a>(_foo: &'a Foo) -> &'a str {
+    unimplemented!()
+}
+
+// No warning; two input lifetimes (anonymous on the reference, named on `Foo`).
+fn struct_with_lt3<'a>(_foo: &Foo<'a>) -> &'a str {
+    unimplemented!()
+}
+
+// Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is
+// valid:
+//   fn struct_with_lt4a<'a>(_foo: &'a Foo<'_>) -> &'a str
+//                                         ^^
+fn struct_with_lt4a<'a>(_foo: &'a Foo<'_>) -> &'a str {
+    unimplemented!()
+}
+
+// Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is
+// valid:
+//   fn struct_with_lt4b<'b>(_foo: &Foo<'b>) -> &'b str
+//                                 ^^^^
+fn struct_with_lt4b<'b>(_foo: &Foo<'b>) -> &'b str {
+    unimplemented!()
+}
+
+trait WithLifetime<'a> {}
+
+type WithLifetimeAlias<'a> = dyn WithLifetime<'a>;
+
+// Should not warn because it won't build without the lifetime.
+fn trait_obj_elided<'a>(_arg: &'a dyn WithLifetime) -> &'a str {
+    unimplemented!()
+}
+
+// Should warn because there is no lifetime on `Drop`, so this would be
+// unambiguous if we elided the lifetime.
+fn trait_obj_elided2(_arg: &dyn Drop) -> &str {
+    unimplemented!()
+}
+
+type FooAlias<'a> = Foo<'a>;
+
+fn alias_with_lt(_foo: FooAlias<'_>) -> &str {
+    unimplemented!()
+}
+
+// No warning; two input lifetimes (named on the reference, anonymous on `FooAlias`).
+fn alias_with_lt2<'a>(_foo: &'a FooAlias) -> &'a str {
+    unimplemented!()
+}
+
+// No warning; two input lifetimes (anonymous on the reference, named on `FooAlias`).
+fn alias_with_lt3<'a>(_foo: &FooAlias<'a>) -> &'a str {
+    unimplemented!()
+}
+
+// Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is
+// valid:
+//   fn alias_with_lt4a<'a>(_foo: &'a FooAlias<'_>) -> &'a str
+//                                             ^^
+fn alias_with_lt4a<'a>(_foo: &'a FooAlias<'_>) -> &'a str {
+    unimplemented!()
+}
+
+// Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is
+// valid:
+//   fn alias_with_lt4b<'b>(_foo: &FooAlias<'b>) -> &'b str
+//                                ^^^^^^^^^
+fn alias_with_lt4b<'b>(_foo: &FooAlias<'b>) -> &'b str {
+    unimplemented!()
+}
+
+fn named_input_elided_output(_arg: &str) -> &str {
+    unimplemented!()
+}
+
+fn elided_input_named_output<'a>(_arg: &str) -> &'a str {
+    unimplemented!()
+}
+
+fn trait_bound_ok<T: WithLifetime<'static>>(_: &u8, _: T) {
+    unimplemented!()
+}
+fn trait_bound<'a, T: WithLifetime<'a>>(_: &'a u8, _: T) {
+    unimplemented!()
+}
+
+// Don't warn on these; see issue #292.
+fn trait_bound_bug<'a, T: WithLifetime<'a>>() {
+    unimplemented!()
+}
+
+// See issue #740.
+struct Test {
+    vec: Vec<usize>,
+}
+
+impl Test {
+    fn iter<'a>(&'a self) -> Box<dyn Iterator<Item = usize> + 'a> {
+        unimplemented!()
+    }
+}
+
+trait LintContext<'a> {}
+
+fn f<'a, T: LintContext<'a>>(_: &T) {}
+
+fn test<'a>(x: &'a [u8]) -> u8 {
+    let y: &'a u8 = &x[5];
+    *y
+}
+
+// Issue #3284: give hint regarding lifetime in return type.
+struct Cow<'a> {
+    x: &'a str,
+}
+fn out_return_type_lts(e: &str) -> Cow<'_> {
+    unimplemented!()
+}
+
+// Make sure we still warn on implementations
+mod issue4291 {
+    trait BadTrait {
+        fn needless_lt(x: &u8) {}
+    }
+
+    impl BadTrait for () {
+        fn needless_lt(_x: &u8) {}
+    }
+}
+
+mod issue2944 {
+    trait Foo {}
+    struct Bar;
+    struct Baz<'a> {
+        bar: &'a Bar,
+    }
+
+    impl<'a> Foo for Baz<'a> {}
+    impl Bar {
+        fn baz(&self) -> impl Foo + '_ {
+            Baz { bar: self }
+        }
+    }
+}
+
+mod nested_elision_sites {
+    // issue #issue2944
+
+    // closure trait bounds subject to nested elision
+    // don't lint because they refer to outer lifetimes
+    fn trait_fn<'a>(i: &'a i32) -> impl Fn() -> &'a i32 {
+        move || i
+    }
+    fn trait_fn_mut<'a>(i: &'a i32) -> impl FnMut() -> &'a i32 {
+        move || i
+    }
+    fn trait_fn_once<'a>(i: &'a i32) -> impl FnOnce() -> &'a i32 {
+        move || i
+    }
+
+    // don't lint
+    fn impl_trait_in_input_position<'a>(f: impl Fn() -> &'a i32) -> &'a i32 {
+        f()
+    }
+    fn impl_trait_in_output_position<'a>(i: &'a i32) -> impl Fn() -> &'a i32 {
+        move || i
+    }
+    // lint
+    fn impl_trait_elidable_nested_named_lifetimes<'a>(i: &'a i32, f: impl for<'b> Fn(&'b i32) -> &'b i32) -> &'a i32 {
+        f(i)
+    }
+    fn impl_trait_elidable_nested_anonymous_lifetimes(i: &i32, f: impl Fn(&i32) -> &i32) -> &i32 {
+        f(i)
+    }
+
+    // don't lint
+    fn generics_not_elidable<'a, T: Fn() -> &'a i32>(f: T) -> &'a i32 {
+        f()
+    }
+    // lint
+    fn generics_elidable<T: Fn(&i32) -> &i32>(i: &i32, f: T) -> &i32 {
+        f(i)
+    }
+
+    // don't lint
+    fn where_clause_not_elidable<'a, T>(f: T) -> &'a i32
+    where
+        T: Fn() -> &'a i32,
+    {
+        f()
+    }
+    // lint
+    fn where_clause_elidadable<T>(i: &i32, f: T) -> &i32
+    where
+        T: Fn(&i32) -> &i32,
+    {
+        f(i)
+    }
+
+    // don't lint
+    fn pointer_fn_in_input_position<'a>(f: fn(&'a i32) -> &'a i32, i: &'a i32) -> &'a i32 {
+        f(i)
+    }
+    fn pointer_fn_in_output_position<'a>(_: &'a i32) -> fn(&'a i32) -> &'a i32 {
+        |i| i
+    }
+    // lint
+    fn pointer_fn_elidable(i: &i32, f: fn(&i32) -> &i32) -> &i32 {
+        f(i)
+    }
+
+    // don't lint
+    fn nested_fn_pointer_1<'a>(_: &'a i32) -> fn(fn(&'a i32) -> &'a i32) -> i32 {
+        |f| 42
+    }
+    fn nested_fn_pointer_2<'a>(_: &'a i32) -> impl Fn(fn(&'a i32)) {
+        |f| ()
+    }
+
+    // lint
+    fn nested_fn_pointer_3(_: &i32) -> fn(fn(&i32) -> &i32) -> i32 {
+        |f| 42
+    }
+    fn nested_fn_pointer_4(_: &i32) -> impl Fn(fn(&i32)) {
+        |f| ()
+    }
+}
+
+mod issue6159 {
+    use std::ops::Deref;
+    pub fn apply_deref<'a, T, F, R>(x: &'a T, f: F) -> R
+    where
+        T: Deref,
+        F: FnOnce(&'a T::Target) -> R,
+    {
+        f(x.deref())
+    }
+}
+
+mod issue7296 {
+    use std::rc::Rc;
+    use std::sync::Arc;
+
+    struct Foo;
+    impl Foo {
+        fn implicit(&self) -> &() {
+            &()
+        }
+        fn implicit_mut(&mut self) -> &() {
+            &()
+        }
+
+        fn explicit<'a>(self: &'a Arc<Self>) -> &'a () {
+            &()
+        }
+        fn explicit_mut<'a>(self: &'a mut Rc<Self>) -> &'a () {
+            &()
+        }
+
+        fn lifetime_elsewhere(self: Box<Self>, here: &()) -> &() {
+            &()
+        }
+    }
+
+    trait Bar {
+        fn implicit(&self) -> &();
+        fn implicit_provided(&self) -> &() {
+            &()
+        }
+
+        fn explicit<'a>(self: &'a Arc<Self>) -> &'a ();
+        fn explicit_provided<'a>(self: &'a Arc<Self>) -> &'a () {
+            &()
+        }
+
+        fn lifetime_elsewhere(self: Box<Self>, here: &()) -> &();
+        fn lifetime_elsewhere_provided(self: Box<Self>, here: &()) -> &() {
+            &()
+        }
+    }
+}
+
+mod pr_9743_false_negative_fix {
+    #![allow(unused)]
+
+    fn foo(x: &u8, y: &'_ u8) {}
+
+    fn bar(x: &u8, y: &'_ u8, z: &'_ u8) {}
+}
+
+mod pr_9743_output_lifetime_checks {
+    #![allow(unused)]
+
+    // lint: only one input
+    fn one_input(x: &u8) -> &u8 {
+        unimplemented!()
+    }
+
+    // lint: multiple inputs, output would not be elided
+    fn multiple_inputs_output_not_elided<'b>(x: &u8, y: &'b u8, z: &'b u8) -> &'b u8 {
+        unimplemented!()
+    }
+
+    // don't lint: multiple inputs, output would be elided (which would create an ambiguity)
+    fn multiple_inputs_output_would_be_elided<'a, 'b>(x: &'a u8, y: &'b u8, z: &'b u8) -> &'a u8 {
+        unimplemented!()
+    }
+}
+
+mod in_macro {
+    macro_rules! local_one_input_macro {
+        () => {
+            fn one_input(x: &u8) -> &u8 {
+                unimplemented!()
+            }
+        };
+    }
+
+    // lint local macro expands to function with needless lifetimes
+    local_one_input_macro!();
+
+    // no lint on external macro
+    macro_rules::needless_lifetime!();
+}
+
+mod issue5787 {
+    use std::sync::MutexGuard;
+
+    struct Foo;
+
+    impl Foo {
+        // doesn't get linted without async
+        pub async fn wait<'a, T>(&self, guard: MutexGuard<'a, T>) -> MutexGuard<'a, T> {
+            guard
+        }
+    }
+
+    async fn foo<'a>(_x: &i32, y: &'a str) -> &'a str {
+        y
+    }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/needless_lifetimes.rs b/src/tools/clippy/tests/ui/needless_lifetimes.rs
index 2efc936752e..409528b291d 100644
--- a/src/tools/clippy/tests/ui/needless_lifetimes.rs
+++ b/src/tools/clippy/tests/ui/needless_lifetimes.rs
@@ -1,13 +1,20 @@
+// run-rustfix
+// aux-build:macro_rules.rs
+
 #![warn(clippy::needless_lifetimes)]
 #![allow(
-    dead_code,
+    unused,
     clippy::boxed_local,
+    clippy::extra_unused_type_parameters,
     clippy::needless_pass_by_value,
     clippy::unnecessary_wraps,
     dyn_drop,
     clippy::get_first
 )]
 
+#[macro_use]
+extern crate macro_rules;
+
 fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {}
 
 fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) {}
@@ -495,4 +502,37 @@ mod pr_9743_output_lifetime_checks {
     }
 }
 
+mod in_macro {
+    macro_rules! local_one_input_macro {
+        () => {
+            fn one_input<'a>(x: &'a u8) -> &'a u8 {
+                unimplemented!()
+            }
+        };
+    }
+
+    // lint local macro expands to function with needless lifetimes
+    local_one_input_macro!();
+
+    // no lint on external macro
+    macro_rules::needless_lifetime!();
+}
+
+mod issue5787 {
+    use std::sync::MutexGuard;
+
+    struct Foo;
+
+    impl Foo {
+        // doesn't get linted without async
+        pub async fn wait<'a, T>(&self, guard: MutexGuard<'a, T>) -> MutexGuard<'a, T> {
+            guard
+        }
+    }
+
+    async fn foo<'a>(_x: &i32, y: &'a str) -> &'a str {
+        y
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/needless_lifetimes.stderr b/src/tools/clippy/tests/ui/needless_lifetimes.stderr
index 5a7cf13c86d..4e3c8f20d8c 100644
--- a/src/tools/clippy/tests/ui/needless_lifetimes.stderr
+++ b/src/tools/clippy/tests/ui/needless_lifetimes.stderr
@@ -1,316 +1,559 @@
 error: the following explicit lifetimes could be elided: 'a, 'b
-  --> $DIR/needless_lifetimes.rs:11:1
+  --> $DIR/needless_lifetimes.rs:18:1
    |
 LL | fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::needless-lifetimes` implied by `-D warnings`
+help: elide the lifetimes
+   |
+LL - fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {}
+LL + fn distinct_lifetimes(_x: &u8, _y: &u8, _z: u8) {}
+   |
 
 error: the following explicit lifetimes could be elided: 'a, 'b
-  --> $DIR/needless_lifetimes.rs:13:1
+  --> $DIR/needless_lifetimes.rs:20:1
    |
 LL | fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL - fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) {}
+LL + fn distinct_and_static(_x: &u8, _y: &u8, _z: &'static u8) {}
+   |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:23:1
+  --> $DIR/needless_lifetimes.rs:30:1
    |
 LL | fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL - fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 {
+LL + fn in_and_out(x: &u8, _y: u8) -> &u8 {
+   |
 
 error: the following explicit lifetimes could be elided: 'b
-  --> $DIR/needless_lifetimes.rs:35:1
+  --> $DIR/needless_lifetimes.rs:42:1
    |
 LL | fn multiple_in_and_out_2a<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL - fn multiple_in_and_out_2a<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 {
+LL + fn multiple_in_and_out_2a<'a>(x: &'a u8, _y: &u8) -> &'a u8 {
+   |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:42:1
+  --> $DIR/needless_lifetimes.rs:49:1
    |
 LL | fn multiple_in_and_out_2b<'a, 'b>(_x: &'a u8, y: &'b u8) -> &'b u8 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL - fn multiple_in_and_out_2b<'a, 'b>(_x: &'a u8, y: &'b u8) -> &'b u8 {
+LL + fn multiple_in_and_out_2b<'b>(_x: &u8, y: &'b u8) -> &'b u8 {
+   |
 
 error: the following explicit lifetimes could be elided: 'b
-  --> $DIR/needless_lifetimes.rs:59:1
+  --> $DIR/needless_lifetimes.rs:66:1
    |
 LL | fn deep_reference_1a<'a, 'b>(x: &'a u8, _y: &'b u8) -> Result<&'a u8, ()> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL - fn deep_reference_1a<'a, 'b>(x: &'a u8, _y: &'b u8) -> Result<&'a u8, ()> {
+LL + fn deep_reference_1a<'a>(x: &'a u8, _y: &u8) -> Result<&'a u8, ()> {
+   |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:66:1
+  --> $DIR/needless_lifetimes.rs:73:1
    |
 LL | fn deep_reference_1b<'a, 'b>(_x: &'a u8, y: &'b u8) -> Result<&'b u8, ()> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL - fn deep_reference_1b<'a, 'b>(_x: &'a u8, y: &'b u8) -> Result<&'b u8, ()> {
+LL + fn deep_reference_1b<'b>(_x: &u8, y: &'b u8) -> Result<&'b u8, ()> {
+   |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:75:1
+  --> $DIR/needless_lifetimes.rs:82:1
    |
 LL | fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL - fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> {
+LL + fn deep_reference_3(x: &u8, _y: u8) -> Result<&u8, ()> {
+   |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:80:1
+  --> $DIR/needless_lifetimes.rs:87:1
    |
 LL | fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()>
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL - fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()>
+LL + fn where_clause_without_lt<T>(x: &u8, _y: u8) -> Result<&u8, ()>
+   |
 
 error: the following explicit lifetimes could be elided: 'a, 'b
-  --> $DIR/needless_lifetimes.rs:92:1
+  --> $DIR/needless_lifetimes.rs:99:1
    |
 LL | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-help: replace with `'_` in generic arguments such as here
-  --> $DIR/needless_lifetimes.rs:92:37
+help: elide the lifetimes
+   |
+LL - fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {}
+LL + fn lifetime_param_2(_x: Ref<'_>, _y: &u8) {}
    |
-LL | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {}
-   |                                     ^^
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:116:1
+  --> $DIR/needless_lifetimes.rs:123:1
    |
 LL | fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-help: replace with `'_` in generic arguments such as here
-  --> $DIR/needless_lifetimes.rs:116:32
+help: elide the lifetimes
+   |
+LL - fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
+LL + fn fn_bound_2<F, I>(_m: Lt<'_, I>, _f: F) -> Lt<'_, I>
    |
-LL | fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
-   |                                ^^
 
 error: the following explicit lifetimes could be elided: 's
-  --> $DIR/needless_lifetimes.rs:146:5
+  --> $DIR/needless_lifetimes.rs:153:5
    |
 LL |     fn self_and_out<'s>(&'s self) -> &'s u8 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL -     fn self_and_out<'s>(&'s self) -> &'s u8 {
+LL +     fn self_and_out(&self) -> &u8 {
+   |
 
 error: the following explicit lifetimes could be elided: 't
-  --> $DIR/needless_lifetimes.rs:153:5
+  --> $DIR/needless_lifetimes.rs:160:5
    |
 LL |     fn self_and_in_out_1<'s, 't>(&'s self, _x: &'t u8) -> &'s u8 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL -     fn self_and_in_out_1<'s, 't>(&'s self, _x: &'t u8) -> &'s u8 {
+LL +     fn self_and_in_out_1<'s>(&'s self, _x: &u8) -> &'s u8 {
+   |
 
 error: the following explicit lifetimes could be elided: 's
-  --> $DIR/needless_lifetimes.rs:160:5
+  --> $DIR/needless_lifetimes.rs:167:5
    |
 LL |     fn self_and_in_out_2<'s, 't>(&'s self, x: &'t u8) -> &'t u8 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL -     fn self_and_in_out_2<'s, 't>(&'s self, x: &'t u8) -> &'t u8 {
+LL +     fn self_and_in_out_2<'t>(&self, x: &'t u8) -> &'t u8 {
+   |
 
 error: the following explicit lifetimes could be elided: 's, 't
-  --> $DIR/needless_lifetimes.rs:164:5
+  --> $DIR/needless_lifetimes.rs:171:5
    |
 LL |     fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL -     fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {}
+LL +     fn distinct_self_and_in(&self, _x: &u8) {}
+   |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:183:1
+  --> $DIR/needless_lifetimes.rs:190:1
    |
 LL | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-help: replace with `'_` in generic arguments such as here
-  --> $DIR/needless_lifetimes.rs:183:33
+help: elide the lifetimes
+   |
+LL - fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str {
+LL + fn struct_with_lt(_foo: Foo<'_>) -> &str {
    |
-LL | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str {
-   |                                 ^^
 
 error: the following explicit lifetimes could be elided: 'b
-  --> $DIR/needless_lifetimes.rs:201:1
+  --> $DIR/needless_lifetimes.rs:208:1
    |
 LL | fn struct_with_lt4a<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-help: replace with `'_` in generic arguments such as here
-  --> $DIR/needless_lifetimes.rs:201:43
+help: elide the lifetimes
+   |
+LL - fn struct_with_lt4a<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str {
+LL + fn struct_with_lt4a<'a>(_foo: &'a Foo<'_>) -> &'a str {
    |
-LL | fn struct_with_lt4a<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str {
-   |                                           ^^
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:209:1
+  --> $DIR/needless_lifetimes.rs:216:1
    |
 LL | fn struct_with_lt4b<'a, 'b>(_foo: &'a Foo<'b>) -> &'b str {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL - fn struct_with_lt4b<'a, 'b>(_foo: &'a Foo<'b>) -> &'b str {
+LL + fn struct_with_lt4b<'b>(_foo: &Foo<'b>) -> &'b str {
+   |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:224:1
+  --> $DIR/needless_lifetimes.rs:231:1
    |
 LL | fn trait_obj_elided2<'a>(_arg: &'a dyn Drop) -> &'a str {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL - fn trait_obj_elided2<'a>(_arg: &'a dyn Drop) -> &'a str {
+LL + fn trait_obj_elided2(_arg: &dyn Drop) -> &str {
+   |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:230:1
+  --> $DIR/needless_lifetimes.rs:237:1
    |
 LL | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-help: replace with `'_` in generic arguments such as here
-  --> $DIR/needless_lifetimes.rs:230:37
+help: elide the lifetimes
+   |
+LL - fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str {
+LL + fn alias_with_lt(_foo: FooAlias<'_>) -> &str {
    |
-LL | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str {
-   |                                     ^^
 
 error: the following explicit lifetimes could be elided: 'b
-  --> $DIR/needless_lifetimes.rs:248:1
+  --> $DIR/needless_lifetimes.rs:255:1
    |
 LL | fn alias_with_lt4a<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-help: replace with `'_` in generic arguments such as here
-  --> $DIR/needless_lifetimes.rs:248:47
+help: elide the lifetimes
+   |
+LL - fn alias_with_lt4a<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str {
+LL + fn alias_with_lt4a<'a>(_foo: &'a FooAlias<'_>) -> &'a str {
    |
-LL | fn alias_with_lt4a<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str {
-   |                                               ^^
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:256:1
+  --> $DIR/needless_lifetimes.rs:263:1
    |
 LL | fn alias_with_lt4b<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'b str {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL - fn alias_with_lt4b<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'b str {
+LL + fn alias_with_lt4b<'b>(_foo: &FooAlias<'b>) -> &'b str {
+   |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:260:1
+  --> $DIR/needless_lifetimes.rs:267:1
    |
 LL | fn named_input_elided_output<'a>(_arg: &'a str) -> &str {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL - fn named_input_elided_output<'a>(_arg: &'a str) -> &str {
+LL + fn named_input_elided_output(_arg: &str) -> &str {
+   |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:268:1
+  --> $DIR/needless_lifetimes.rs:275:1
    |
 LL | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL - fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) {
+LL + fn trait_bound_ok<T: WithLifetime<'static>>(_: &u8, _: T) {
+   |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:304:1
+  --> $DIR/needless_lifetimes.rs:311:1
    |
 LL | fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-help: replace with `'_` in generic arguments such as here
-  --> $DIR/needless_lifetimes.rs:304:47
+help: elide the lifetimes
+   |
+LL - fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> {
+LL + fn out_return_type_lts(e: &str) -> Cow<'_> {
    |
-LL | fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> {
-   |                                               ^^
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:311:9
+  --> $DIR/needless_lifetimes.rs:318:9
    |
 LL |         fn needless_lt<'a>(x: &'a u8) {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL -         fn needless_lt<'a>(x: &'a u8) {}
+LL +         fn needless_lt(x: &u8) {}
+   |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:315:9
+  --> $DIR/needless_lifetimes.rs:322:9
    |
 LL |         fn needless_lt<'a>(_x: &'a u8) {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL -         fn needless_lt<'a>(_x: &'a u8) {}
+LL +         fn needless_lt(_x: &u8) {}
+   |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:328:9
+  --> $DIR/needless_lifetimes.rs:335:9
    |
 LL |         fn baz<'a>(&'a self) -> impl Foo + 'a {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL -         fn baz<'a>(&'a self) -> impl Foo + 'a {
+LL +         fn baz(&self) -> impl Foo + '_ {
+   |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:360:5
+  --> $DIR/needless_lifetimes.rs:367:5
    |
 LL |     fn impl_trait_elidable_nested_anonymous_lifetimes<'a>(i: &'a i32, f: impl Fn(&i32) -> &i32) -> &'a i32 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL -     fn impl_trait_elidable_nested_anonymous_lifetimes<'a>(i: &'a i32, f: impl Fn(&i32) -> &i32) -> &'a i32 {
+LL +     fn impl_trait_elidable_nested_anonymous_lifetimes(i: &i32, f: impl Fn(&i32) -> &i32) -> &i32 {
+   |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:369:5
+  --> $DIR/needless_lifetimes.rs:376:5
    |
 LL |     fn generics_elidable<'a, T: Fn(&i32) -> &i32>(i: &'a i32, f: T) -> &'a i32 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL -     fn generics_elidable<'a, T: Fn(&i32) -> &i32>(i: &'a i32, f: T) -> &'a i32 {
+LL +     fn generics_elidable<T: Fn(&i32) -> &i32>(i: &i32, f: T) -> &i32 {
+   |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:381:5
+  --> $DIR/needless_lifetimes.rs:388:5
    |
 LL |     fn where_clause_elidadable<'a, T>(i: &'a i32, f: T) -> &'a i32
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL -     fn where_clause_elidadable<'a, T>(i: &'a i32, f: T) -> &'a i32
+LL +     fn where_clause_elidadable<T>(i: &i32, f: T) -> &i32
+   |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:396:5
+  --> $DIR/needless_lifetimes.rs:403:5
    |
 LL |     fn pointer_fn_elidable<'a>(i: &'a i32, f: fn(&i32) -> &i32) -> &'a i32 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL -     fn pointer_fn_elidable<'a>(i: &'a i32, f: fn(&i32) -> &i32) -> &'a i32 {
+LL +     fn pointer_fn_elidable(i: &i32, f: fn(&i32) -> &i32) -> &i32 {
+   |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:409:5
+  --> $DIR/needless_lifetimes.rs:416:5
    |
 LL |     fn nested_fn_pointer_3<'a>(_: &'a i32) -> fn(fn(&i32) -> &i32) -> i32 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL -     fn nested_fn_pointer_3<'a>(_: &'a i32) -> fn(fn(&i32) -> &i32) -> i32 {
+LL +     fn nested_fn_pointer_3(_: &i32) -> fn(fn(&i32) -> &i32) -> i32 {
+   |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:412:5
+  --> $DIR/needless_lifetimes.rs:419:5
    |
 LL |     fn nested_fn_pointer_4<'a>(_: &'a i32) -> impl Fn(fn(&i32)) {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL -     fn nested_fn_pointer_4<'a>(_: &'a i32) -> impl Fn(fn(&i32)) {
+LL +     fn nested_fn_pointer_4(_: &i32) -> impl Fn(fn(&i32)) {
+   |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:434:9
+  --> $DIR/needless_lifetimes.rs:441:9
    |
 LL |         fn implicit<'a>(&'a self) -> &'a () {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL -         fn implicit<'a>(&'a self) -> &'a () {
+LL +         fn implicit(&self) -> &() {
+   |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:437:9
+  --> $DIR/needless_lifetimes.rs:444:9
    |
 LL |         fn implicit_mut<'a>(&'a mut self) -> &'a () {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL -         fn implicit_mut<'a>(&'a mut self) -> &'a () {
+LL +         fn implicit_mut(&mut self) -> &() {
+   |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:448:9
+  --> $DIR/needless_lifetimes.rs:455:9
    |
 LL |         fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a () {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL -         fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a () {
+LL +         fn lifetime_elsewhere(self: Box<Self>, here: &()) -> &() {
+   |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:454:9
+  --> $DIR/needless_lifetimes.rs:461:9
    |
 LL |         fn implicit<'a>(&'a self) -> &'a ();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL -         fn implicit<'a>(&'a self) -> &'a ();
+LL +         fn implicit(&self) -> &();
+   |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:455:9
+  --> $DIR/needless_lifetimes.rs:462:9
    |
 LL |         fn implicit_provided<'a>(&'a self) -> &'a () {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL -         fn implicit_provided<'a>(&'a self) -> &'a () {
+LL +         fn implicit_provided(&self) -> &() {
+   |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:464:9
+  --> $DIR/needless_lifetimes.rs:471:9
    |
 LL |         fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a ();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL -         fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a ();
+LL +         fn lifetime_elsewhere(self: Box<Self>, here: &()) -> &();
+   |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:465:9
+  --> $DIR/needless_lifetimes.rs:472:9
    |
 LL |         fn lifetime_elsewhere_provided<'a>(self: Box<Self>, here: &'a ()) -> &'a () {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL -         fn lifetime_elsewhere_provided<'a>(self: Box<Self>, here: &'a ()) -> &'a () {
+LL +         fn lifetime_elsewhere_provided(self: Box<Self>, here: &()) -> &() {
+   |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:474:5
+  --> $DIR/needless_lifetimes.rs:481:5
    |
 LL |     fn foo<'a>(x: &'a u8, y: &'_ u8) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL -     fn foo<'a>(x: &'a u8, y: &'_ u8) {}
+LL +     fn foo(x: &u8, y: &'_ u8) {}
+   |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:476:5
+  --> $DIR/needless_lifetimes.rs:483:5
    |
 LL |     fn bar<'a>(x: &'a u8, y: &'_ u8, z: &'_ u8) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL -     fn bar<'a>(x: &'a u8, y: &'_ u8, z: &'_ u8) {}
+LL +     fn bar(x: &u8, y: &'_ u8, z: &'_ u8) {}
+   |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:483:5
+  --> $DIR/needless_lifetimes.rs:490:5
    |
 LL |     fn one_input<'a>(x: &'a u8) -> &'a u8 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL -     fn one_input<'a>(x: &'a u8) -> &'a u8 {
+LL +     fn one_input(x: &u8) -> &u8 {
+   |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:488:5
+  --> $DIR/needless_lifetimes.rs:495:5
    |
 LL |     fn multiple_inputs_output_not_elided<'a, 'b>(x: &'a u8, y: &'b u8, z: &'b u8) -> &'b u8 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: elide the lifetimes
+   |
+LL -     fn multiple_inputs_output_not_elided<'a, 'b>(x: &'a u8, y: &'b u8, z: &'b u8) -> &'b u8 {
+LL +     fn multiple_inputs_output_not_elided<'b>(x: &u8, y: &'b u8, z: &'b u8) -> &'b u8 {
+   |
+
+error: the following explicit lifetimes could be elided: 'a
+  --> $DIR/needless_lifetimes.rs:508:13
+   |
+LL |             fn one_input<'a>(x: &'a u8) -> &'a u8 {
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     local_one_input_macro!();
+   |     ------------------------ in this macro invocation
+   |
+   = note: this error originates in the macro `local_one_input_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: elide the lifetimes
+   |
+LL -             fn one_input<'a>(x: &'a u8) -> &'a u8 {
+LL +             fn one_input(x: &u8) -> &u8 {
+   |
 
-error: aborting due to 45 previous errors
+error: aborting due to 46 previous errors
 
diff --git a/src/tools/clippy/tests/ui/needless_range_loop.stderr b/src/tools/clippy/tests/ui/needless_range_loop.stderr
index b31544ec334..cffa19bec3a 100644
--- a/src/tools/clippy/tests/ui/needless_range_loop.stderr
+++ b/src/tools/clippy/tests/ui/needless_range_loop.stderr
@@ -49,7 +49,7 @@ error: the loop variable `i` is used to index `vec`
 LL |     for i in 0..vec.len() {
    |              ^^^^^^^^^^^^
    |
-help: consider using an iterator
+help: consider using an iterator and enumerate()
    |
 LL |     for (i, <item>) in vec.iter().enumerate() {
    |         ~~~~~~~~~~~    ~~~~~~~~~~~~~~~~~~~~~~
@@ -126,7 +126,7 @@ error: the loop variable `i` is used to index `vec`
 LL |     for i in 5..vec.len() {
    |              ^^^^^^^^^^^^
    |
-help: consider using an iterator
+help: consider using an iterator and enumerate()
    |
 LL |     for (i, <item>) in vec.iter().enumerate().skip(5) {
    |         ~~~~~~~~~~~    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -137,7 +137,7 @@ error: the loop variable `i` is used to index `vec`
 LL |     for i in 5..10 {
    |              ^^^^^
    |
-help: consider using an iterator
+help: consider using an iterator and enumerate()
    |
 LL |     for (i, <item>) in vec.iter().enumerate().take(10).skip(5) {
    |         ~~~~~~~~~~~    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -148,7 +148,7 @@ error: the loop variable `i` is used to index `vec`
 LL |     for i in 0..vec.len() {
    |              ^^^^^^^^^^^^
    |
-help: consider using an iterator
+help: consider using an iterator and enumerate()
    |
 LL |     for (i, <item>) in vec.iter_mut().enumerate() {
    |         ~~~~~~~~~~~    ~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/src/tools/clippy/tests/ui/new_without_default.rs b/src/tools/clippy/tests/ui/new_without_default.rs
index 65809023f8d..7803418cb04 100644
--- a/src/tools/clippy/tests/ui/new_without_default.rs
+++ b/src/tools/clippy/tests/ui/new_without_default.rs
@@ -1,4 +1,9 @@
-#![allow(dead_code, clippy::missing_safety_doc, clippy::extra_unused_lifetimes)]
+#![allow(
+    dead_code,
+    clippy::missing_safety_doc,
+    clippy::extra_unused_lifetimes,
+    clippy::extra_unused_type_parameters
+)]
 #![warn(clippy::new_without_default)]
 
 pub struct Foo;
diff --git a/src/tools/clippy/tests/ui/new_without_default.stderr b/src/tools/clippy/tests/ui/new_without_default.stderr
index 212a69ab94e..583dd327d6a 100644
--- a/src/tools/clippy/tests/ui/new_without_default.stderr
+++ b/src/tools/clippy/tests/ui/new_without_default.stderr
@@ -1,5 +1,5 @@
 error: you should consider adding a `Default` implementation for `Foo`
-  --> $DIR/new_without_default.rs:7:5
+  --> $DIR/new_without_default.rs:12:5
    |
 LL | /     pub fn new() -> Foo {
 LL | |         Foo
@@ -17,7 +17,7 @@ LL + }
    |
 
 error: you should consider adding a `Default` implementation for `Bar`
-  --> $DIR/new_without_default.rs:15:5
+  --> $DIR/new_without_default.rs:20:5
    |
 LL | /     pub fn new() -> Self {
 LL | |         Bar
@@ -34,7 +34,7 @@ LL + }
    |
 
 error: you should consider adding a `Default` implementation for `LtKo<'c>`
-  --> $DIR/new_without_default.rs:79:5
+  --> $DIR/new_without_default.rs:84:5
    |
 LL | /     pub fn new() -> LtKo<'c> {
 LL | |         unimplemented!()
@@ -51,7 +51,7 @@ LL + }
    |
 
 error: you should consider adding a `Default` implementation for `NewNotEqualToDerive`
-  --> $DIR/new_without_default.rs:172:5
+  --> $DIR/new_without_default.rs:177:5
    |
 LL | /     pub fn new() -> Self {
 LL | |         NewNotEqualToDerive { foo: 1 }
@@ -68,7 +68,7 @@ LL + }
    |
 
 error: you should consider adding a `Default` implementation for `FooGenerics<T>`
-  --> $DIR/new_without_default.rs:180:5
+  --> $DIR/new_without_default.rs:185:5
    |
 LL | /     pub fn new() -> Self {
 LL | |         Self(Default::default())
@@ -85,7 +85,7 @@ LL + }
    |
 
 error: you should consider adding a `Default` implementation for `BarGenerics<T>`
-  --> $DIR/new_without_default.rs:187:5
+  --> $DIR/new_without_default.rs:192:5
    |
 LL | /     pub fn new() -> Self {
 LL | |         Self(Default::default())
@@ -102,7 +102,7 @@ LL + }
    |
 
 error: you should consider adding a `Default` implementation for `Foo<T>`
-  --> $DIR/new_without_default.rs:198:9
+  --> $DIR/new_without_default.rs:203:9
    |
 LL | /         pub fn new() -> Self {
 LL | |             todo!()
diff --git a/src/tools/clippy/tests/ui/redundant_field_names.fixed b/src/tools/clippy/tests/ui/redundant_field_names.fixed
index ec7f8ae923a..276266a2dd8 100644
--- a/src/tools/clippy/tests/ui/redundant_field_names.fixed
+++ b/src/tools/clippy/tests/ui/redundant_field_names.fixed
@@ -1,7 +1,7 @@
 // run-rustfix
 
 #![warn(clippy::redundant_field_names)]
-#![allow(clippy::no_effect, dead_code, unused_variables)]
+#![allow(clippy::extra_unused_type_parameters, clippy::no_effect, dead_code, unused_variables)]
 
 #[macro_use]
 extern crate derive_new;
diff --git a/src/tools/clippy/tests/ui/redundant_field_names.rs b/src/tools/clippy/tests/ui/redundant_field_names.rs
index 73122016cf6..f674141c138 100644
--- a/src/tools/clippy/tests/ui/redundant_field_names.rs
+++ b/src/tools/clippy/tests/ui/redundant_field_names.rs
@@ -1,7 +1,7 @@
 // run-rustfix
 
 #![warn(clippy::redundant_field_names)]
-#![allow(clippy::no_effect, dead_code, unused_variables)]
+#![allow(clippy::extra_unused_type_parameters, clippy::no_effect, dead_code, unused_variables)]
 
 #[macro_use]
 extern crate derive_new;
diff --git a/src/tools/clippy/tests/ui/regex.rs b/src/tools/clippy/tests/ui/regex.rs
index f0e1a8128d7..ab8ac97a0e7 100644
--- a/src/tools/clippy/tests/ui/regex.rs
+++ b/src/tools/clippy/tests/ui/regex.rs
@@ -36,6 +36,10 @@ fn syntax_error() {
 
     let raw_string_error = Regex::new(r"[...\/...]");
     let raw_string_error = Regex::new(r#"[...\/...]"#);
+
+    let escaped_string_span = Regex::new("\\b\\c");
+
+    let aux_span = Regex::new("(?ixi)");
 }
 
 fn trivial_regex() {
diff --git a/src/tools/clippy/tests/ui/regex.stderr b/src/tools/clippy/tests/ui/regex.stderr
index 2424644c6f6..c2440f39e0a 100644
--- a/src/tools/clippy/tests/ui/regex.stderr
+++ b/src/tools/clippy/tests/ui/regex.stderr
@@ -29,7 +29,10 @@ error: regex syntax error: invalid character class range, the start must be <= t
 LL |     let some_unicode = Regex::new("[é-è]");
    |                                     ^^^
 
-error: regex syntax error on position 0: unclosed group
+error: regex parse error:
+           (
+           ^
+       error: unclosed group
   --> $DIR/regex.rs:18:33
    |
 LL |     let some_regex = Regex::new(OPENING_PAREN);
@@ -43,25 +46,37 @@ LL |     let binary_pipe_in_wrong_position = BRegex::new("|");
    |
    = help: the regex is unlikely to be useful as it is
 
-error: regex syntax error on position 0: unclosed group
+error: regex parse error:
+           (
+           ^
+       error: unclosed group
   --> $DIR/regex.rs:21:41
    |
 LL |     let some_binary_regex = BRegex::new(OPENING_PAREN);
    |                                         ^^^^^^^^^^^^^
 
-error: regex syntax error on position 0: unclosed group
+error: regex parse error:
+           (
+           ^
+       error: unclosed group
   --> $DIR/regex.rs:22:56
    |
 LL |     let some_binary_regex_builder = BRegexBuilder::new(OPENING_PAREN);
    |                                                        ^^^^^^^^^^^^^
 
-error: regex syntax error on position 0: unclosed group
+error: regex parse error:
+           (
+           ^
+       error: unclosed group
   --> $DIR/regex.rs:34:37
    |
 LL |     let set_error = RegexSet::new(&[OPENING_PAREN, r"[a-z]+/.(com|org|net)"]);
    |                                     ^^^^^^^^^^^^^
 
-error: regex syntax error on position 0: unclosed group
+error: regex parse error:
+           (
+           ^
+       error: unclosed group
   --> $DIR/regex.rs:35:39
    |
 LL |     let bset_error = BRegexSet::new(&[OPENING_PAREN, r"[a-z]+/.(com|org|net)"]);
@@ -79,8 +94,25 @@ error: regex syntax error: unrecognized escape sequence
 LL |     let raw_string_error = Regex::new(r#"[...//...]"#);
    |                                              ^^
 
+error: regex parse error:
+           /b/c
+             ^^
+       error: unrecognized escape sequence
+  --> $DIR/regex.rs:40:42
+   |
+LL |     let escaped_string_span = Regex::new("/b/c");
+   |                                          ^^^^^^^^
+   |
+   = help: consider using a raw string literal: `r".."`
+
+error: regex syntax error: duplicate flag
+  --> $DIR/regex.rs:42:34
+   |
+LL |     let aux_span = Regex::new("(?ixi)");
+   |                                  ^ ^
+
 error: trivial regex
-  --> $DIR/regex.rs:42:33
+  --> $DIR/regex.rs:46:33
    |
 LL |     let trivial_eq = Regex::new("^foobar$");
    |                                 ^^^^^^^^^^
@@ -88,7 +120,7 @@ LL |     let trivial_eq = Regex::new("^foobar$");
    = help: consider using `==` on `str`s
 
 error: trivial regex
-  --> $DIR/regex.rs:44:48
+  --> $DIR/regex.rs:48:48
    |
 LL |     let trivial_eq_builder = RegexBuilder::new("^foobar$");
    |                                                ^^^^^^^^^^
@@ -96,7 +128,7 @@ LL |     let trivial_eq_builder = RegexBuilder::new("^foobar$");
    = help: consider using `==` on `str`s
 
 error: trivial regex
-  --> $DIR/regex.rs:46:42
+  --> $DIR/regex.rs:50:42
    |
 LL |     let trivial_starts_with = Regex::new("^foobar");
    |                                          ^^^^^^^^^
@@ -104,7 +136,7 @@ LL |     let trivial_starts_with = Regex::new("^foobar");
    = help: consider using `str::starts_with`
 
 error: trivial regex
-  --> $DIR/regex.rs:48:40
+  --> $DIR/regex.rs:52:40
    |
 LL |     let trivial_ends_with = Regex::new("foobar$");
    |                                        ^^^^^^^^^
@@ -112,7 +144,7 @@ LL |     let trivial_ends_with = Regex::new("foobar$");
    = help: consider using `str::ends_with`
 
 error: trivial regex
-  --> $DIR/regex.rs:50:39
+  --> $DIR/regex.rs:54:39
    |
 LL |     let trivial_contains = Regex::new("foobar");
    |                                       ^^^^^^^^
@@ -120,7 +152,7 @@ LL |     let trivial_contains = Regex::new("foobar");
    = help: consider using `str::contains`
 
 error: trivial regex
-  --> $DIR/regex.rs:52:39
+  --> $DIR/regex.rs:56:39
    |
 LL |     let trivial_contains = Regex::new(NOT_A_REAL_REGEX);
    |                                       ^^^^^^^^^^^^^^^^
@@ -128,7 +160,7 @@ LL |     let trivial_contains = Regex::new(NOT_A_REAL_REGEX);
    = help: consider using `str::contains`
 
 error: trivial regex
-  --> $DIR/regex.rs:54:40
+  --> $DIR/regex.rs:58:40
    |
 LL |     let trivial_backslash = Regex::new("a/.b");
    |                                        ^^^^^^^
@@ -136,7 +168,7 @@ LL |     let trivial_backslash = Regex::new("a/.b");
    = help: consider using `str::contains`
 
 error: trivial regex
-  --> $DIR/regex.rs:57:36
+  --> $DIR/regex.rs:61:36
    |
 LL |     let trivial_empty = Regex::new("");
    |                                    ^^
@@ -144,7 +176,7 @@ LL |     let trivial_empty = Regex::new("");
    = help: the regex is unlikely to be useful as it is
 
 error: trivial regex
-  --> $DIR/regex.rs:59:36
+  --> $DIR/regex.rs:63:36
    |
 LL |     let trivial_empty = Regex::new("^");
    |                                    ^^^
@@ -152,7 +184,7 @@ LL |     let trivial_empty = Regex::new("^");
    = help: the regex is unlikely to be useful as it is
 
 error: trivial regex
-  --> $DIR/regex.rs:61:36
+  --> $DIR/regex.rs:65:36
    |
 LL |     let trivial_empty = Regex::new("^$");
    |                                    ^^^^
@@ -160,12 +192,12 @@ LL |     let trivial_empty = Regex::new("^$");
    = help: consider using `str::is_empty`
 
 error: trivial regex
-  --> $DIR/regex.rs:63:44
+  --> $DIR/regex.rs:67:44
    |
 LL |     let binary_trivial_empty = BRegex::new("^$");
    |                                            ^^^^
    |
    = help: consider using `str::is_empty`
 
-error: aborting due to 23 previous errors
+error: aborting due to 25 previous errors
 
diff --git a/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.fixed b/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.fixed
index 713cff604a1..dc24d447c60 100644
--- a/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.fixed
+++ b/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.fixed
@@ -26,7 +26,7 @@ fn seek_to_start_false_method(t: &mut StructWithSeekMethod) {
 
 // This should NOT trigger clippy warning because
 // StructWithSeekMethod does not implement std::io::Seek;
-fn seek_to_start_method_owned_false<T>(mut t: StructWithSeekMethod) {
+fn seek_to_start_method_owned_false(mut t: StructWithSeekMethod) {
     t.seek(SeekFrom::Start(0));
 }
 
@@ -38,7 +38,7 @@ fn seek_to_start_false_trait(t: &mut StructWithSeekTrait) {
 
 // This should NOT trigger clippy warning because
 // StructWithSeekMethod does not implement std::io::Seek;
-fn seek_to_start_false_trait_owned<T>(mut t: StructWithSeekTrait) {
+fn seek_to_start_false_trait_owned(mut t: StructWithSeekTrait) {
     t.seek(SeekFrom::Start(0));
 }
 
diff --git a/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.rs b/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.rs
index 467003a1a66..4adde2c4018 100644
--- a/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.rs
+++ b/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.rs
@@ -26,7 +26,7 @@ fn seek_to_start_false_method(t: &mut StructWithSeekMethod) {
 
 // This should NOT trigger clippy warning because
 // StructWithSeekMethod does not implement std::io::Seek;
-fn seek_to_start_method_owned_false<T>(mut t: StructWithSeekMethod) {
+fn seek_to_start_method_owned_false(mut t: StructWithSeekMethod) {
     t.seek(SeekFrom::Start(0));
 }
 
@@ -38,7 +38,7 @@ fn seek_to_start_false_trait(t: &mut StructWithSeekTrait) {
 
 // This should NOT trigger clippy warning because
 // StructWithSeekMethod does not implement std::io::Seek;
-fn seek_to_start_false_trait_owned<T>(mut t: StructWithSeekTrait) {
+fn seek_to_start_false_trait_owned(mut t: StructWithSeekTrait) {
     t.seek(SeekFrom::Start(0));
 }
 
diff --git a/src/tools/clippy/tests/ui/suspicious_to_owned.stderr b/src/tools/clippy/tests/ui/suspicious_to_owned.stderr
index dec3f50d6f1..c4ec7aa88a2 100644
--- a/src/tools/clippy/tests/ui/suspicious_to_owned.stderr
+++ b/src/tools/clippy/tests/ui/suspicious_to_owned.stderr
@@ -2,27 +2,62 @@ error: this `to_owned` call clones the Cow<'_, str> itself and does not cause th
   --> $DIR/suspicious_to_owned.rs:16:13
    |
 LL |     let _ = cow.to_owned();
-   |             ^^^^^^^^^^^^^^ help: consider using, depending on intent: `cow.clone()` or `cow.into_owned()`
+   |             ^^^^^^^^^^^^^^
    |
    = note: `-D clippy::suspicious-to-owned` implied by `-D warnings`
+help: depending on intent, either make the Cow an Owned variant
+   |
+LL |     let _ = cow.into_owned();
+   |             ~~~~~~~~~~~~~~~~
+help: or clone the Cow itself
+   |
+LL |     let _ = cow.clone();
+   |             ~~~~~~~~~~~
 
 error: this `to_owned` call clones the Cow<'_, [char; 3]> itself and does not cause the Cow<'_, [char; 3]> contents to become owned
   --> $DIR/suspicious_to_owned.rs:26:13
    |
 LL |     let _ = cow.to_owned();
-   |             ^^^^^^^^^^^^^^ help: consider using, depending on intent: `cow.clone()` or `cow.into_owned()`
+   |             ^^^^^^^^^^^^^^
+   |
+help: depending on intent, either make the Cow an Owned variant
+   |
+LL |     let _ = cow.into_owned();
+   |             ~~~~~~~~~~~~~~~~
+help: or clone the Cow itself
+   |
+LL |     let _ = cow.clone();
+   |             ~~~~~~~~~~~
 
 error: this `to_owned` call clones the Cow<'_, Vec<char>> itself and does not cause the Cow<'_, Vec<char>> contents to become owned
   --> $DIR/suspicious_to_owned.rs:36:13
    |
 LL |     let _ = cow.to_owned();
-   |             ^^^^^^^^^^^^^^ help: consider using, depending on intent: `cow.clone()` or `cow.into_owned()`
+   |             ^^^^^^^^^^^^^^
+   |
+help: depending on intent, either make the Cow an Owned variant
+   |
+LL |     let _ = cow.into_owned();
+   |             ~~~~~~~~~~~~~~~~
+help: or clone the Cow itself
+   |
+LL |     let _ = cow.clone();
+   |             ~~~~~~~~~~~
 
 error: this `to_owned` call clones the Cow<'_, str> itself and does not cause the Cow<'_, str> contents to become owned
   --> $DIR/suspicious_to_owned.rs:46:13
    |
 LL |     let _ = cow.to_owned();
-   |             ^^^^^^^^^^^^^^ help: consider using, depending on intent: `cow.clone()` or `cow.into_owned()`
+   |             ^^^^^^^^^^^^^^
+   |
+help: depending on intent, either make the Cow an Owned variant
+   |
+LL |     let _ = cow.into_owned();
+   |             ~~~~~~~~~~~~~~~~
+help: or clone the Cow itself
+   |
+LL |     let _ = cow.clone();
+   |             ~~~~~~~~~~~
 
 error: implicitly cloning a `String` by calling `to_owned` on its dereferenced type
   --> $DIR/suspicious_to_owned.rs:60:13
diff --git a/src/tools/clippy/tests/ui/type_repetition_in_bounds.rs b/src/tools/clippy/tests/ui/type_repetition_in_bounds.rs
index 2eca1f4701c..8b4613b3f6e 100644
--- a/src/tools/clippy/tests/ui/type_repetition_in_bounds.rs
+++ b/src/tools/clippy/tests/ui/type_repetition_in_bounds.rs
@@ -1,4 +1,5 @@
 #![deny(clippy::type_repetition_in_bounds)]
+#![allow(clippy::extra_unused_type_parameters)]
 
 use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
 
diff --git a/src/tools/clippy/tests/ui/type_repetition_in_bounds.stderr b/src/tools/clippy/tests/ui/type_repetition_in_bounds.stderr
index 70d700c1cc4..a90df03c04f 100644
--- a/src/tools/clippy/tests/ui/type_repetition_in_bounds.stderr
+++ b/src/tools/clippy/tests/ui/type_repetition_in_bounds.stderr
@@ -1,5 +1,5 @@
 error: this type has already been used as a bound predicate
-  --> $DIR/type_repetition_in_bounds.rs:8:5
+  --> $DIR/type_repetition_in_bounds.rs:9:5
    |
 LL |     T: Clone,
    |     ^^^^^^^^
@@ -12,7 +12,7 @@ LL | #![deny(clippy::type_repetition_in_bounds)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this type has already been used as a bound predicate
-  --> $DIR/type_repetition_in_bounds.rs:25:5
+  --> $DIR/type_repetition_in_bounds.rs:26:5
    |
 LL |     Self: Copy + Default + Ord,
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -20,7 +20,7 @@ LL |     Self: Copy + Default + Ord,
    = help: consider combining the bounds: `Self: Clone + Copy + Default + Ord`
 
 error: this type has already been used as a bound predicate
-  --> $DIR/type_repetition_in_bounds.rs:85:5
+  --> $DIR/type_repetition_in_bounds.rs:86:5
    |
 LL |     T: Clone,
    |     ^^^^^^^^
@@ -28,7 +28,7 @@ LL |     T: Clone,
    = help: consider combining the bounds: `T: ?Sized + Clone`
 
 error: this type has already been used as a bound predicate
-  --> $DIR/type_repetition_in_bounds.rs:90:5
+  --> $DIR/type_repetition_in_bounds.rs:91:5
    |
 LL |     T: ?Sized,
    |     ^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/unused_io_amount.rs b/src/tools/clippy/tests/ui/unused_io_amount.rs
index 4b059558173..8d3e094b759 100644
--- a/src/tools/clippy/tests/ui/unused_io_amount.rs
+++ b/src/tools/clippy/tests/ui/unused_io_amount.rs
@@ -63,6 +63,14 @@ fn combine_or(file: &str) -> Result<(), Error> {
     Ok(())
 }
 
+fn is_ok_err<T: io::Read + io::Write>(s: &mut T) {
+    s.write(b"ok").is_ok();
+    s.write(b"err").is_err();
+    let mut buf = [0u8; 0];
+    s.read(&mut buf).is_ok();
+    s.read(&mut buf).is_err();
+}
+
 async fn bad_async_write<W: AsyncWrite + Unpin>(w: &mut W) {
     w.write(b"hello world").await.unwrap();
 }
diff --git a/src/tools/clippy/tests/ui/unused_io_amount.stderr b/src/tools/clippy/tests/ui/unused_io_amount.stderr
index 7ba7e09c0f0..0865c5213f6 100644
--- a/src/tools/clippy/tests/ui/unused_io_amount.stderr
+++ b/src/tools/clippy/tests/ui/unused_io_amount.stderr
@@ -82,13 +82,45 @@ LL | |         .expect("error");
 error: written amount is not handled
   --> $DIR/unused_io_amount.rs:67:5
    |
+LL |     s.write(b"ok").is_ok();
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use `Write::write_all` instead, or handle partial writes
+
+error: written amount is not handled
+  --> $DIR/unused_io_amount.rs:68:5
+   |
+LL |     s.write(b"err").is_err();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use `Write::write_all` instead, or handle partial writes
+
+error: read amount is not handled
+  --> $DIR/unused_io_amount.rs:70:5
+   |
+LL |     s.read(&mut buf).is_ok();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use `Read::read_exact` instead, or handle partial reads
+
+error: read amount is not handled
+  --> $DIR/unused_io_amount.rs:71:5
+   |
+LL |     s.read(&mut buf).is_err();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use `Read::read_exact` instead, or handle partial reads
+
+error: written amount is not handled
+  --> $DIR/unused_io_amount.rs:75:5
+   |
 LL |     w.write(b"hello world").await.unwrap();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: use `AsyncWriteExt::write_all` instead, or handle partial writes
 
 error: read amount is not handled
-  --> $DIR/unused_io_amount.rs:72:5
+  --> $DIR/unused_io_amount.rs:80:5
    |
 LL |     r.read(&mut buf[..]).await.unwrap();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -96,7 +128,7 @@ LL |     r.read(&mut buf[..]).await.unwrap();
    = help: use `AsyncReadExt::read_exact` instead, or handle partial reads
 
 error: written amount is not handled
-  --> $DIR/unused_io_amount.rs:85:9
+  --> $DIR/unused_io_amount.rs:93:9
    |
 LL |         w.write(b"hello world").await?;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -104,7 +136,7 @@ LL |         w.write(b"hello world").await?;
    = help: use `AsyncWriteExt::write_all` instead, or handle partial writes
 
 error: read amount is not handled
-  --> $DIR/unused_io_amount.rs:93:9
+  --> $DIR/unused_io_amount.rs:101:9
    |
 LL |         r.read(&mut buf[..]).await.or(Err(Error::Kind))?;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -112,7 +144,7 @@ LL |         r.read(&mut buf[..]).await.or(Err(Error::Kind))?;
    = help: use `AsyncReadExt::read_exact` instead, or handle partial reads
 
 error: written amount is not handled
-  --> $DIR/unused_io_amount.rs:101:5
+  --> $DIR/unused_io_amount.rs:109:5
    |
 LL |     w.write(b"hello world").await.unwrap();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -120,12 +152,12 @@ LL |     w.write(b"hello world").await.unwrap();
    = help: use `AsyncWriteExt::write_all` instead, or handle partial writes
 
 error: read amount is not handled
-  --> $DIR/unused_io_amount.rs:106:5
+  --> $DIR/unused_io_amount.rs:114:5
    |
 LL |     r.read(&mut buf[..]).await.unwrap();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: use `AsyncReadExt::read_exact` instead, or handle partial reads
 
-error: aborting due to 16 previous errors
+error: aborting due to 20 previous errors
 
diff --git a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed
index 23607497841..293bf75a717 100644
--- a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed
+++ b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed
@@ -96,7 +96,7 @@ fn main() {
         }
         match Enum::A {
             Enum::A => (),
-            Enum::B | _ => (),
+            Enum::B | Enum::__Private => (),
         }
     }
 }
diff --git a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.stderr b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.stderr
index efecc9576cc..30d29aa4e77 100644
--- a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.stderr
+++ b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.stderr
@@ -34,11 +34,11 @@ error: wildcard matches known variants and will also match future added variants
 LL |         _ => {},
    |         ^ help: try this: `ErrorKind::PermissionDenied | _`
 
-error: wildcard matches known variants and will also match future added variants
+error: wildcard match will also match any future added variants
   --> $DIR/wildcard_enum_match_arm.rs:99:13
    |
 LL |             _ => (),
-   |             ^ help: try this: `Enum::B | _`
+   |             ^ help: try this: `Enum::B | Enum::__Private`
 
 error: aborting due to 6 previous errors