about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md1
-rw-r--r--clippy_lints/src/declared_lints.rs1
-rw-r--r--clippy_lints/src/lifetimes.rs112
-rw-r--r--tests/ui/crashes/elidable_lifetime_names_impl_trait.fixed (renamed from tests/ui/crashes/needless_lifetimes_impl_trait.fixed)6
-rw-r--r--tests/ui/crashes/elidable_lifetime_names_impl_trait.rs (renamed from tests/ui/crashes/needless_lifetimes_impl_trait.rs)6
-rw-r--r--tests/ui/crashes/elidable_lifetime_names_impl_trait.stderr (renamed from tests/ui/crashes/needless_lifetimes_impl_trait.stderr)10
-rw-r--r--tests/ui/elidable_lifetime_names.fixed194
-rw-r--r--tests/ui/elidable_lifetime_names.rs194
-rw-r--r--tests/ui/elidable_lifetime_names.stderr162
-rw-r--r--tests/ui/methods.rs1
-rw-r--r--tests/ui/methods.stderr4
-rw-r--r--tests/ui/needless_lifetimes.fixed199
-rw-r--r--tests/ui/needless_lifetimes.rs199
-rw-r--r--tests/ui/needless_lifetimes.stderr237
14 files changed, 688 insertions, 638 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8c4fcfb58db..9e8ca7cb149 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5592,6 +5592,7 @@ Released 2018-09-13
 [`duplicated_attributes`]: https://rust-lang.github.io/rust-clippy/master/index.html#duplicated_attributes
 [`duration_subsec`]: https://rust-lang.github.io/rust-clippy/master/index.html#duration_subsec
 [`eager_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#eager_transmute
+[`elidable_lifetime_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#elidable_lifetime_names
 [`else_if_without_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#else_if_without_else
 [`empty_docs`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_docs
 [`empty_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_drop
diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs
index c0560c5d154..9dde6a7933c 100644
--- a/clippy_lints/src/declared_lints.rs
+++ b/clippy_lints/src/declared_lints.rs
@@ -274,6 +274,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
     crate::let_underscore::LET_UNDERSCORE_MUST_USE_INFO,
     crate::let_underscore::LET_UNDERSCORE_UNTYPED_INFO,
     crate::let_with_type_underscore::LET_WITH_TYPE_UNDERSCORE_INFO,
+    crate::lifetimes::ELIDABLE_LIFETIME_NAMES_INFO,
     crate::lifetimes::EXTRA_UNUSED_LIFETIMES_INFO,
     crate::lifetimes::NEEDLESS_LIFETIMES_INFO,
     crate::lines_filter_map_ok::LINES_FILTER_MAP_OK_INFO,
diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs
index f08812017b9..7589ab1229a 100644
--- a/clippy_lints/src/lifetimes.rs
+++ b/clippy_lints/src/lifetimes.rs
@@ -38,8 +38,8 @@ declare_clippy_lint! {
     /// them leads to more readable code.
     ///
     /// ### Known problems
-    /// - We bail out if the function has a `where` clause where lifetimes
-    /// are mentioned due to potential false positives.
+    /// This lint ignores functions with `where` clauses that reference
+    /// lifetimes to prevent false positives.
     ///
     /// ### Example
     /// ```no_run
@@ -64,6 +64,38 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
+    /// Checks for lifetime annotations which can be replaced with anonymous lifetimes (`'_`).
+    ///
+    /// ### Why is this bad?
+    /// The additional lifetimes can make the code look more complicated.
+    ///
+    /// ### Known problems
+    /// This lint ignores functions with `where` clauses that reference
+    /// lifetimes to prevent false positives.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// # use std::str::Chars;
+    /// fn f<'a>(x: &'a str) -> Chars<'a> {
+    ///     x.chars()
+    /// }
+    /// ```
+    ///
+    /// Use instead:
+    /// ```no_run
+    /// # use std::str::Chars;
+    /// fn f(x: &str) -> Chars<'_> {
+    ///     x.chars()
+    /// }
+    /// ```
+    #[clippy::version = "1.84.0"]
+    pub ELIDABLE_LIFETIME_NAMES,
+    pedantic,
+    "lifetime name that can be replaced with the anonymous lifetime"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
     /// Checks for lifetimes in generics that are never used
     /// anywhere else.
     ///
@@ -104,7 +136,11 @@ impl Lifetimes {
     }
 }
 
-impl_lint_pass!(Lifetimes => [NEEDLESS_LIFETIMES, EXTRA_UNUSED_LIFETIMES]);
+impl_lint_pass!(Lifetimes => [
+    NEEDLESS_LIFETIMES,
+    ELIDABLE_LIFETIME_NAMES,
+    EXTRA_UNUSED_LIFETIMES,
+]);
 
 impl<'tcx> LateLintPass<'tcx> for Lifetimes {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
@@ -746,6 +782,15 @@ fn report_elidable_impl_lifetimes<'tcx>(
     report_elidable_lifetimes(cx, impl_.generics, &elidable_lts, &usages, true);
 }
 
+#[derive(Copy, Clone)]
+enum ElidableUsage {
+    /// Used in a ref (`&'a T`), can be removed
+    Ref(Span),
+    /// Used as a generic param (`T<'a>`) or an impl lifetime (`impl T + 'a`), can be replaced
+    /// with `'_`
+    Other(Span),
+}
+
 /// Generate diagnostic messages for elidable lifetimes.
 fn report_elidable_lifetimes(
     cx: &LateContext<'_>,
@@ -763,9 +808,29 @@ fn report_elidable_lifetimes(
         .collect::<Vec<_>>()
         .join(", ");
 
+    let elidable_usages: Vec<ElidableUsage> = usages
+        .iter()
+        .filter(|usage| named_lifetime(usage).is_some_and(|id| elidable_lts.contains(&id)))
+        .map(|usage| match cx.tcx.parent_hir_node(usage.hir_id) {
+            Node::Ty(Ty {
+                kind: TyKind::Ref(..), ..
+            }) => ElidableUsage::Ref(usage.ident.span),
+            _ => ElidableUsage::Other(usage.ident.span),
+        })
+        .collect();
+
+    let lint = if elidable_usages
+        .iter()
+        .any(|usage| matches!(usage, ElidableUsage::Other(_)))
+    {
+        ELIDABLE_LIFETIME_NAMES
+    } else {
+        NEEDLESS_LIFETIMES
+    };
+
     span_lint_and_then(
         cx,
-        NEEDLESS_LIFETIMES,
+        lint,
         elidable_lts
             .iter()
             .map(|&lt| cx.tcx.def_span(lt))
@@ -785,7 +850,7 @@ fn report_elidable_lifetimes(
                 return;
             }
 
-            if let Some(suggestions) = elision_suggestions(cx, generics, elidable_lts, usages) {
+            if let Some(suggestions) = elision_suggestions(cx, generics, elidable_lts, &elidable_usages) {
                 diag.multipart_suggestion("elide the lifetimes", suggestions, Applicability::MachineApplicable);
             }
         },
@@ -796,7 +861,7 @@ fn elision_suggestions(
     cx: &LateContext<'_>,
     generics: &Generics<'_>,
     elidable_lts: &[LocalDefId],
-    usages: &[Lifetime],
+    usages: &[ElidableUsage],
 ) -> Option<Vec<(Span, String)>> {
     let explicit_params = generics
         .params
@@ -836,26 +901,21 @@ fn elision_suggestions(
             .collect::<Option<Vec<_>>>()?
     };
 
-    suggestions.extend(
-        usages
-            .iter()
-            .filter(|usage| named_lifetime(usage).is_some_and(|id| elidable_lts.contains(&id)))
-            .map(|usage| {
-                match cx.tcx.parent_hir_node(usage.hir_id) {
-                    Node::Ty(Ty {
-                        kind: TyKind::Ref(..), ..
-                    }) => {
-                        // expand `&'a T` to `&'a T`
-                        //          ^^         ^^^
-                        let span = cx.sess().source_map().span_extend_while_whitespace(usage.ident.span);
-
-                        (span, String::new())
-                    },
-                    // `T<'a>` and `impl Foo + 'a` should be replaced by `'_`
-                    _ => (usage.ident.span, String::from("'_")),
-                }
-            }),
-    );
+    suggestions.extend(usages.iter().map(|&usage| {
+        match usage {
+            ElidableUsage::Ref(span) => {
+                // expand `&'a T` to `&'a T`
+                //          ^^         ^^^
+                let span = cx.sess().source_map().span_extend_while_whitespace(span);
+
+                (span, String::new())
+            },
+            ElidableUsage::Other(span) => {
+                // `T<'a>` and `impl Foo + 'a` should be replaced by `'_`
+                (span, String::from("'_"))
+            },
+        }
+    }));
 
     Some(suggestions)
 }
diff --git a/tests/ui/crashes/needless_lifetimes_impl_trait.fixed b/tests/ui/crashes/elidable_lifetime_names_impl_trait.fixed
index da3b82a60c5..681887314ed 100644
--- a/tests/ui/crashes/needless_lifetimes_impl_trait.fixed
+++ b/tests/ui/crashes/elidable_lifetime_names_impl_trait.fixed
@@ -1,4 +1,4 @@
-#![deny(clippy::needless_lifetimes)]
+#![deny(clippy::elidable_lifetime_names)]
 #![allow(dead_code)]
 
 trait Foo {}
@@ -10,11 +10,11 @@ struct Baz<'a> {
 }
 
 impl Foo for Baz<'_> {}
-//~^ needless_lifetimes
+//~^ elidable_lifetime_names
 
 impl Bar {
     fn baz(&self) -> impl Foo + '_ {
-        //~^ needless_lifetimes
+        //~^ elidable_lifetime_names
 
         Baz { bar: self }
     }
diff --git a/tests/ui/crashes/needless_lifetimes_impl_trait.rs b/tests/ui/crashes/elidable_lifetime_names_impl_trait.rs
index 456d315926d..ed5f95bdca8 100644
--- a/tests/ui/crashes/needless_lifetimes_impl_trait.rs
+++ b/tests/ui/crashes/elidable_lifetime_names_impl_trait.rs
@@ -1,4 +1,4 @@
-#![deny(clippy::needless_lifetimes)]
+#![deny(clippy::elidable_lifetime_names)]
 #![allow(dead_code)]
 
 trait Foo {}
@@ -10,11 +10,11 @@ struct Baz<'a> {
 }
 
 impl<'a> Foo for Baz<'a> {}
-//~^ needless_lifetimes
+//~^ elidable_lifetime_names
 
 impl Bar {
     fn baz<'a>(&'a self) -> impl Foo + 'a {
-        //~^ needless_lifetimes
+        //~^ elidable_lifetime_names
 
         Baz { bar: self }
     }
diff --git a/tests/ui/crashes/needless_lifetimes_impl_trait.stderr b/tests/ui/crashes/elidable_lifetime_names_impl_trait.stderr
index 97fb6d29cfb..ef4b7e0a476 100644
--- a/tests/ui/crashes/needless_lifetimes_impl_trait.stderr
+++ b/tests/ui/crashes/elidable_lifetime_names_impl_trait.stderr
@@ -1,14 +1,14 @@
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/crashes/needless_lifetimes_impl_trait.rs:12:6
+  --> tests/ui/crashes/elidable_lifetime_names_impl_trait.rs:12:6
    |
 LL | impl<'a> Foo for Baz<'a> {}
    |      ^^              ^^
    |
 note: the lint level is defined here
-  --> tests/ui/crashes/needless_lifetimes_impl_trait.rs:1:9
+  --> tests/ui/crashes/elidable_lifetime_names_impl_trait.rs:1:9
    |
-LL | #![deny(clippy::needless_lifetimes)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![deny(clippy::elidable_lifetime_names)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: elide the lifetimes
    |
 LL - impl<'a> Foo for Baz<'a> {}
@@ -16,7 +16,7 @@ LL + impl Foo for Baz<'_> {}
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/crashes/needless_lifetimes_impl_trait.rs:16:12
+  --> tests/ui/crashes/elidable_lifetime_names_impl_trait.rs:16:12
    |
 LL |     fn baz<'a>(&'a self) -> impl Foo + 'a {
    |            ^^   ^^                     ^^
diff --git a/tests/ui/elidable_lifetime_names.fixed b/tests/ui/elidable_lifetime_names.fixed
new file mode 100644
index 00000000000..abeee5c4cef
--- /dev/null
+++ b/tests/ui/elidable_lifetime_names.fixed
@@ -0,0 +1,194 @@
+#![warn(clippy::needless_lifetimes, clippy::elidable_lifetime_names)]
+
+type Ref<'r> = &'r u8;
+
+// No error; same lifetime on two params.
+fn lifetime_param_1<'a>(_x: Ref<'a>, _y: &'a u8) {}
+
+//~v ERROR: could be elided: 'a, 'b
+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!()
+}
+
+//~v ERROR: could be elided: 'a
+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!()
+}
+
+struct Foo<'a>(&'a u8);
+
+//~v ERROR: could be elided: 'a
+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!()
+}
+
+//~v ERROR: could be elided: 'b
+fn struct_with_lt4a<'a>(_foo: &'a Foo<'_>) -> &'a str {
+    unimplemented!()
+}
+
+type FooAlias<'a> = Foo<'a>;
+
+//~v ERROR: could be elided: '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!()
+}
+
+//~v ERROR: could be elided: 'b
+fn alias_with_lt4a<'a>(_foo: &'a FooAlias<'_>) -> &'a str {
+    unimplemented!()
+}
+
+// Issue #3284: give hint regarding lifetime in return type.
+struct Cow<'a> {
+    x: &'a str,
+}
+
+//~v ERROR: could be elided: 'a
+fn out_return_type_lts(e: &str) -> Cow<'_> {
+    unimplemented!()
+}
+
+mod issue2944 {
+    trait Foo {}
+    struct Bar;
+    struct Baz<'a> {
+        bar: &'a Bar,
+    }
+
+    //~v ERROR: could be elided: 'a
+    impl Foo for Baz<'_> {}
+    impl Bar {
+        //~v ERROR: could be elided: 'a
+        fn baz(&self) -> impl Foo + '_ {
+            Baz { bar: self }
+        }
+    }
+}
+
+mod issue13923 {
+    struct Py<'py> {
+        data: &'py str,
+    }
+
+    enum Content<'t, 'py> {
+        Py(Py<'py>),
+        T1(&'t str),
+        T2(&'t str),
+    }
+
+    enum ContentString<'t> {
+        T1(&'t str),
+        T2(&'t str),
+    }
+
+    impl<'t, 'py> ContentString<'t> {
+        // `'py` cannot be elided
+        fn map_content1(self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, 'py> {
+            match self {
+                Self::T1(content) => Content::T1(f(content)),
+                Self::T2(content) => Content::T2(f(content)),
+            }
+        }
+    }
+
+    //~v ERROR: could be elided: 'py
+    impl<'t> ContentString<'t> {
+        // `'py` can be elided because of `&self`
+        fn map_content2(&self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, '_> {
+            match self {
+                Self::T1(content) => Content::T1(f(content)),
+                Self::T2(content) => Content::T2(f(content)),
+            }
+        }
+    }
+
+    //~v ERROR: could be elided: 'py
+    impl<'t> ContentString<'t> {
+        // `'py` can be elided because of `&'_ self`
+        fn map_content3(&'_ self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, '_> {
+            match self {
+                Self::T1(content) => Content::T1(f(content)),
+                Self::T2(content) => Content::T2(f(content)),
+            }
+        }
+    }
+
+    impl<'t, 'py> ContentString<'t> {
+        // `'py` should not be elided as the default lifetime, even if working, could be named as `'t`
+        fn map_content4(self, f: impl FnOnce(&'t str) -> &'t str, o: &'t str) -> Content<'t, 'py> {
+            match self {
+                Self::T1(content) => Content::T1(f(content)),
+                Self::T2(_) => Content::T2(o),
+            }
+        }
+    }
+
+    //~v ERROR: could be elided: 'py
+    impl<'t> ContentString<'t> {
+        // `'py` can be elided because of `&Self`
+        fn map_content5(
+            self: std::pin::Pin<&Self>,
+            f: impl FnOnce(&'t str) -> &'t str,
+            o: &'t str,
+        ) -> Content<'t, '_> {
+            match *self {
+                Self::T1(content) => Content::T1(f(content)),
+                Self::T2(_) => Content::T2(o),
+            }
+        }
+    }
+
+    struct Cx<'a, 'b> {
+        a: &'a u32,
+        b: &'b u32,
+    }
+
+    // `'c` cannot be elided because we have several input lifetimes
+    fn one_explicit<'b>(x: Cx<'_, 'b>) -> &'b u32 {
+        x.b
+    }
+}
diff --git a/tests/ui/elidable_lifetime_names.rs b/tests/ui/elidable_lifetime_names.rs
new file mode 100644
index 00000000000..fae3577a8e9
--- /dev/null
+++ b/tests/ui/elidable_lifetime_names.rs
@@ -0,0 +1,194 @@
+#![warn(clippy::needless_lifetimes, clippy::elidable_lifetime_names)]
+
+type Ref<'r> = &'r u8;
+
+// No error; same lifetime on two params.
+fn lifetime_param_1<'a>(_x: Ref<'a>, _y: &'a u8) {}
+
+//~v ERROR: could be elided: 'a, 'b
+fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b 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!()
+}
+
+//~v ERROR: could be elided: 'a
+fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
+where
+    for<'x> F: Fn(Lt<'x, I>) -> Lt<'x, I>,
+{
+    unreachable!()
+}
+
+struct Foo<'a>(&'a u8);
+
+//~v ERROR: could be elided: 'a
+fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a 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!()
+}
+
+//~v ERROR: could be elided: 'b
+fn struct_with_lt4a<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str {
+    unimplemented!()
+}
+
+type FooAlias<'a> = Foo<'a>;
+
+//~v ERROR: could be elided: 'a
+fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a 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!()
+}
+
+//~v ERROR: could be elided: 'b
+fn alias_with_lt4a<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str {
+    unimplemented!()
+}
+
+// Issue #3284: give hint regarding lifetime in return type.
+struct Cow<'a> {
+    x: &'a str,
+}
+
+//~v ERROR: could be elided: 'a
+fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> {
+    unimplemented!()
+}
+
+mod issue2944 {
+    trait Foo {}
+    struct Bar;
+    struct Baz<'a> {
+        bar: &'a Bar,
+    }
+
+    //~v ERROR: could be elided: 'a
+    impl<'a> Foo for Baz<'a> {}
+    impl Bar {
+        //~v ERROR: could be elided: 'a
+        fn baz<'a>(&'a self) -> impl Foo + 'a {
+            Baz { bar: self }
+        }
+    }
+}
+
+mod issue13923 {
+    struct Py<'py> {
+        data: &'py str,
+    }
+
+    enum Content<'t, 'py> {
+        Py(Py<'py>),
+        T1(&'t str),
+        T2(&'t str),
+    }
+
+    enum ContentString<'t> {
+        T1(&'t str),
+        T2(&'t str),
+    }
+
+    impl<'t, 'py> ContentString<'t> {
+        // `'py` cannot be elided
+        fn map_content1(self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, 'py> {
+            match self {
+                Self::T1(content) => Content::T1(f(content)),
+                Self::T2(content) => Content::T2(f(content)),
+            }
+        }
+    }
+
+    //~v ERROR: could be elided: 'py
+    impl<'t, 'py> ContentString<'t> {
+        // `'py` can be elided because of `&self`
+        fn map_content2(&self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, 'py> {
+            match self {
+                Self::T1(content) => Content::T1(f(content)),
+                Self::T2(content) => Content::T2(f(content)),
+            }
+        }
+    }
+
+    //~v ERROR: could be elided: 'py
+    impl<'t, 'py> ContentString<'t> {
+        // `'py` can be elided because of `&'_ self`
+        fn map_content3(&'_ self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, 'py> {
+            match self {
+                Self::T1(content) => Content::T1(f(content)),
+                Self::T2(content) => Content::T2(f(content)),
+            }
+        }
+    }
+
+    impl<'t, 'py> ContentString<'t> {
+        // `'py` should not be elided as the default lifetime, even if working, could be named as `'t`
+        fn map_content4(self, f: impl FnOnce(&'t str) -> &'t str, o: &'t str) -> Content<'t, 'py> {
+            match self {
+                Self::T1(content) => Content::T1(f(content)),
+                Self::T2(_) => Content::T2(o),
+            }
+        }
+    }
+
+    //~v ERROR: could be elided: 'py
+    impl<'t, 'py> ContentString<'t> {
+        // `'py` can be elided because of `&Self`
+        fn map_content5(
+            self: std::pin::Pin<&Self>,
+            f: impl FnOnce(&'t str) -> &'t str,
+            o: &'t str,
+        ) -> Content<'t, 'py> {
+            match *self {
+                Self::T1(content) => Content::T1(f(content)),
+                Self::T2(_) => Content::T2(o),
+            }
+        }
+    }
+
+    struct Cx<'a, 'b> {
+        a: &'a u32,
+        b: &'b u32,
+    }
+
+    // `'c` cannot be elided because we have several input lifetimes
+    fn one_explicit<'b>(x: Cx<'_, 'b>) -> &'b u32 {
+        x.b
+    }
+}
diff --git a/tests/ui/elidable_lifetime_names.stderr b/tests/ui/elidable_lifetime_names.stderr
new file mode 100644
index 00000000000..a60dfc69756
--- /dev/null
+++ b/tests/ui/elidable_lifetime_names.stderr
@@ -0,0 +1,162 @@
+error: the following explicit lifetimes could be elided: 'a, 'b
+  --> tests/ui/elidable_lifetime_names.rs:9:21
+   |
+LL | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {}
+   |                     ^^  ^^          ^^        ^^
+   |
+   = note: `-D clippy::elidable-lifetime-names` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::elidable_lifetime_names)]`
+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) {}
+   |
+
+error: the following explicit lifetimes could be elided: 'a
+  --> tests/ui/elidable_lifetime_names.rs:34:15
+   |
+LL | fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
+   |               ^^               ^^                   ^^
+   |
+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>
+   |
+
+error: the following explicit lifetimes could be elided: 'a
+  --> tests/ui/elidable_lifetime_names.rs:44:19
+   |
+LL | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str {
+   |                   ^^            ^^       ^^
+   |
+help: elide the lifetimes
+   |
+LL - fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str {
+LL + fn struct_with_lt(_foo: Foo<'_>) -> &str {
+   |
+
+error: the following explicit lifetimes could be elided: 'b
+  --> tests/ui/elidable_lifetime_names.rs:59:25
+   |
+LL | fn struct_with_lt4a<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str {
+   |                         ^^                ^^
+   |
+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 {
+   |
+
+error: the following explicit lifetimes could be elided: 'a
+  --> tests/ui/elidable_lifetime_names.rs:66:18
+   |
+LL | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str {
+   |                  ^^                 ^^       ^^
+   |
+help: elide the lifetimes
+   |
+LL - fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str {
+LL + fn alias_with_lt(_foo: FooAlias<'_>) -> &str {
+   |
+
+error: the following explicit lifetimes could be elided: 'b
+  --> tests/ui/elidable_lifetime_names.rs:81:24
+   |
+LL | fn alias_with_lt4a<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str {
+   |                        ^^                     ^^
+   |
+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 {
+   |
+
+error: the following explicit lifetimes could be elided: 'a
+  --> tests/ui/elidable_lifetime_names.rs:91:24
+   |
+LL | fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> {
+   |                        ^^      ^^             ^^
+   |
+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<'_> {
+   |
+
+error: the following explicit lifetimes could be elided: 'a
+  --> tests/ui/elidable_lifetime_names.rs:103:10
+   |
+LL |     impl<'a> Foo for Baz<'a> {}
+   |          ^^              ^^
+   |
+help: elide the lifetimes
+   |
+LL -     impl<'a> Foo for Baz<'a> {}
+LL +     impl Foo for Baz<'_> {}
+   |
+
+error: the following explicit lifetimes could be elided: 'a
+  --> tests/ui/elidable_lifetime_names.rs:106:16
+   |
+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: 'py
+  --> tests/ui/elidable_lifetime_names.rs:139:14
+   |
+LL |     impl<'t, 'py> ContentString<'t> {
+   |              ^^^
+LL |         // `'py` can be elided because of `&self`
+LL |         fn map_content2(&self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, 'py> {
+   |                                                                                   ^^^
+   |
+help: elide the lifetimes
+   |
+LL ~     impl<'t> ContentString<'t> {
+LL |         // `'py` can be elided because of `&self`
+LL ~         fn map_content2(&self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, '_> {
+   |
+
+error: the following explicit lifetimes could be elided: 'py
+  --> tests/ui/elidable_lifetime_names.rs:150:14
+   |
+LL |     impl<'t, 'py> ContentString<'t> {
+   |              ^^^
+LL |         // `'py` can be elided because of `&'_ self`
+LL |         fn map_content3(&'_ self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, 'py> {
+   |                                                                                      ^^^
+   |
+help: elide the lifetimes
+   |
+LL ~     impl<'t> ContentString<'t> {
+LL |         // `'py` can be elided because of `&'_ self`
+LL ~         fn map_content3(&'_ self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, '_> {
+   |
+
+error: the following explicit lifetimes could be elided: 'py
+  --> tests/ui/elidable_lifetime_names.rs:171:14
+   |
+LL |     impl<'t, 'py> ContentString<'t> {
+   |              ^^^
+...
+LL |         ) -> Content<'t, 'py> {
+   |                          ^^^
+   |
+help: elide the lifetimes
+   |
+LL ~     impl<'t> ContentString<'t> {
+LL |         // `'py` can be elided because of `&Self`
+...
+LL |             o: &'t str,
+LL ~         ) -> Content<'t, '_> {
+   |
+
+error: aborting due to 12 previous errors
+
diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs
index 85a4d59e5ca..76b0d131dd4 100644
--- a/tests/ui/methods.rs
+++ b/tests/ui/methods.rs
@@ -11,6 +11,7 @@
     clippy::new_without_default,
     clippy::needless_pass_by_value,
     clippy::needless_lifetimes,
+    clippy::elidable_lifetime_names,
     clippy::print_stdout,
     clippy::must_use_candidate,
     clippy::use_self,
diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr
index 30e8d0794f7..353b999d7da 100644
--- a/tests/ui/methods.stderr
+++ b/tests/ui/methods.stderr
@@ -1,5 +1,5 @@
 error: methods called `new` usually return `Self`
-  --> tests/ui/methods.rs:103:5
+  --> tests/ui/methods.rs:104:5
    |
 LL | /     fn new() -> i32 {
 LL | |
@@ -11,7 +11,7 @@ LL | |     }
    = help: to override `-D warnings` add `#[allow(clippy::new_ret_no_self)]`
 
 error: called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(..)` instead
-  --> tests/ui/methods.rs:125:13
+  --> tests/ui/methods.rs:126:13
    |
 LL |       let _ = v.iter().filter(|&x| {
    |  _____________^
diff --git a/tests/ui/needless_lifetimes.fixed b/tests/ui/needless_lifetimes.fixed
index 283635d42de..d59393fb3f3 100644
--- a/tests/ui/needless_lifetimes.fixed
+++ b/tests/ui/needless_lifetimes.fixed
@@ -1,6 +1,6 @@
 //@aux-build:proc_macros.rs
 
-#![warn(clippy::needless_lifetimes)]
+#![warn(clippy::needless_lifetimes, clippy::elidable_lifetime_names)]
 #![allow(
     unused,
     clippy::boxed_local,
@@ -101,44 +101,6 @@ where
     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) {}
-//~^ needless_lifetimes
-
-// 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>
-//~^ needless_lifetimes
-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);
@@ -203,30 +165,6 @@ fn already_elided<'a>(_: &u8, _: &'a u8) -> &'a u8 {
     unimplemented!()
 }
 
-fn struct_with_lt(_foo: Foo<'_>) -> &str {
-    //~^ needless_lifetimes
-    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 {
-    //~^ needless_lifetimes
-    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
@@ -254,30 +192,6 @@ fn trait_obj_elided2(_arg: &dyn Drop) -> &str {
 
 type FooAlias<'a> = Foo<'a>;
 
-fn alias_with_lt(_foo: FooAlias<'_>) -> &str {
-    //~^ needless_lifetimes
-    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 {
-    //~^ needless_lifetimes
-    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
@@ -329,15 +243,6 @@ fn test<'a>(x: &'a [u8]) -> u8 {
     *y
 }
 
-// Issue #3284: give hint regarding lifetime in return type.
-struct Cow<'a> {
-    x: &'a str,
-}
-fn out_return_type_lts(e: &str) -> Cow<'_> {
-    //~^ needless_lifetimes
-    unimplemented!()
-}
-
 // Make sure we still warn on implementations
 mod issue4291 {
     trait BadTrait {
@@ -351,23 +256,6 @@ mod issue4291 {
     }
 }
 
-mod issue2944 {
-    trait Foo {}
-    struct Bar;
-    struct Baz<'a> {
-        bar: &'a Bar,
-    }
-
-    impl Foo for Baz<'_> {}
-    //~^ needless_lifetimes
-    impl Bar {
-        fn baz(&self) -> impl Foo + '_ {
-            //~^ needless_lifetimes
-            Baz { bar: self }
-        }
-    }
-}
-
 mod nested_elision_sites {
     // issue #issue2944
 
@@ -646,89 +534,4 @@ mod issue13749bis {
     impl<'a, T: 'a> Generic<T> {}
 }
 
-mod issue13923 {
-    struct Py<'py> {
-        data: &'py str,
-    }
-
-    enum Content<'t, 'py> {
-        Py(Py<'py>),
-        T1(&'t str),
-        T2(&'t str),
-    }
-
-    enum ContentString<'t> {
-        T1(&'t str),
-        T2(&'t str),
-    }
-
-    impl<'t, 'py> ContentString<'t> {
-        // `'py` cannot be elided
-        fn map_content1(self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, 'py> {
-            match self {
-                Self::T1(content) => Content::T1(f(content)),
-                Self::T2(content) => Content::T2(f(content)),
-            }
-        }
-    }
-
-    impl<'t> ContentString<'t> {
-        //~^ needless_lifetimes
-        // `'py` can be elided because of `&self`
-        fn map_content2(&self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, '_> {
-            match self {
-                Self::T1(content) => Content::T1(f(content)),
-                Self::T2(content) => Content::T2(f(content)),
-            }
-        }
-    }
-
-    impl<'t> ContentString<'t> {
-        //~^ needless_lifetimes
-        // `'py` can be elided because of `&'_ self`
-        fn map_content3(&'_ self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, '_> {
-            match self {
-                Self::T1(content) => Content::T1(f(content)),
-                Self::T2(content) => Content::T2(f(content)),
-            }
-        }
-    }
-
-    impl<'t, 'py> ContentString<'t> {
-        // `'py` should not be elided as the default lifetime, even if working, could be named as `'t`
-        fn map_content4(self, f: impl FnOnce(&'t str) -> &'t str, o: &'t str) -> Content<'t, 'py> {
-            match self {
-                Self::T1(content) => Content::T1(f(content)),
-                Self::T2(_) => Content::T2(o),
-            }
-        }
-    }
-
-    impl<'t> ContentString<'t> {
-        //~^ needless_lifetimes
-        // `'py` can be elided because of `&Self`
-        fn map_content5(
-            self: std::pin::Pin<&Self>,
-            f: impl FnOnce(&'t str) -> &'t str,
-            o: &'t str,
-        ) -> Content<'t, '_> {
-            match *self {
-                Self::T1(content) => Content::T1(f(content)),
-                Self::T2(_) => Content::T2(o),
-            }
-        }
-    }
-
-    struct Cx<'a, 'b> {
-        a: &'a u32,
-        b: &'b u32,
-    }
-
-    // `'c` cannot be elided because we have several input lifetimes
-    fn one_explicit<'b>(x: Cx<'_, 'b>) -> &'b u32 {
-        x.b
-        //~^ needless_borrow
-    }
-}
-
 fn main() {}
diff --git a/tests/ui/needless_lifetimes.rs b/tests/ui/needless_lifetimes.rs
index 2853870473d..e24907ab5fc 100644
--- a/tests/ui/needless_lifetimes.rs
+++ b/tests/ui/needless_lifetimes.rs
@@ -1,6 +1,6 @@
 //@aux-build:proc_macros.rs
 
-#![warn(clippy::needless_lifetimes)]
+#![warn(clippy::needless_lifetimes, clippy::elidable_lifetime_names)]
 #![allow(
     unused,
     clippy::boxed_local,
@@ -101,44 +101,6 @@ where
     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<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {}
-//~^ needless_lifetimes
-
-// 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<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
-//~^ needless_lifetimes
-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);
@@ -203,30 +165,6 @@ fn already_elided<'a>(_: &u8, _: &'a u8) -> &'a u8 {
     unimplemented!()
 }
 
-fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str {
-    //~^ needless_lifetimes
-    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, 'b>(_foo: &'a Foo<'b>) -> &'a str {
-    //~^ needless_lifetimes
-    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
@@ -254,30 +192,6 @@ fn trait_obj_elided2<'a>(_arg: &'a dyn Drop) -> &'a str {
 
 type FooAlias<'a> = Foo<'a>;
 
-fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str {
-    //~^ needless_lifetimes
-    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, 'b>(_foo: &'a FooAlias<'b>) -> &'a str {
-    //~^ needless_lifetimes
-    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
@@ -329,15 +243,6 @@ fn test<'a>(x: &'a [u8]) -> u8 {
     *y
 }
 
-// Issue #3284: give hint regarding lifetime in return type.
-struct Cow<'a> {
-    x: &'a str,
-}
-fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> {
-    //~^ needless_lifetimes
-    unimplemented!()
-}
-
 // Make sure we still warn on implementations
 mod issue4291 {
     trait BadTrait {
@@ -351,23 +256,6 @@ mod issue4291 {
     }
 }
 
-mod issue2944 {
-    trait Foo {}
-    struct Bar;
-    struct Baz<'a> {
-        bar: &'a Bar,
-    }
-
-    impl<'a> Foo for Baz<'a> {}
-    //~^ needless_lifetimes
-    impl Bar {
-        fn baz<'a>(&'a self) -> impl Foo + 'a {
-            //~^ needless_lifetimes
-            Baz { bar: self }
-        }
-    }
-}
-
 mod nested_elision_sites {
     // issue #issue2944
 
@@ -646,89 +534,4 @@ mod issue13749bis {
     impl<'a, T: 'a> Generic<T> {}
 }
 
-mod issue13923 {
-    struct Py<'py> {
-        data: &'py str,
-    }
-
-    enum Content<'t, 'py> {
-        Py(Py<'py>),
-        T1(&'t str),
-        T2(&'t str),
-    }
-
-    enum ContentString<'t> {
-        T1(&'t str),
-        T2(&'t str),
-    }
-
-    impl<'t, 'py> ContentString<'t> {
-        // `'py` cannot be elided
-        fn map_content1(self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, 'py> {
-            match self {
-                Self::T1(content) => Content::T1(f(content)),
-                Self::T2(content) => Content::T2(f(content)),
-            }
-        }
-    }
-
-    impl<'t, 'py> ContentString<'t> {
-        //~^ needless_lifetimes
-        // `'py` can be elided because of `&self`
-        fn map_content2(&self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, 'py> {
-            match self {
-                Self::T1(content) => Content::T1(f(content)),
-                Self::T2(content) => Content::T2(f(content)),
-            }
-        }
-    }
-
-    impl<'t, 'py> ContentString<'t> {
-        //~^ needless_lifetimes
-        // `'py` can be elided because of `&'_ self`
-        fn map_content3(&'_ self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, 'py> {
-            match self {
-                Self::T1(content) => Content::T1(f(content)),
-                Self::T2(content) => Content::T2(f(content)),
-            }
-        }
-    }
-
-    impl<'t, 'py> ContentString<'t> {
-        // `'py` should not be elided as the default lifetime, even if working, could be named as `'t`
-        fn map_content4(self, f: impl FnOnce(&'t str) -> &'t str, o: &'t str) -> Content<'t, 'py> {
-            match self {
-                Self::T1(content) => Content::T1(f(content)),
-                Self::T2(_) => Content::T2(o),
-            }
-        }
-    }
-
-    impl<'t, 'py> ContentString<'t> {
-        //~^ needless_lifetimes
-        // `'py` can be elided because of `&Self`
-        fn map_content5(
-            self: std::pin::Pin<&Self>,
-            f: impl FnOnce(&'t str) -> &'t str,
-            o: &'t str,
-        ) -> Content<'t, 'py> {
-            match *self {
-                Self::T1(content) => Content::T1(f(content)),
-                Self::T2(_) => Content::T2(o),
-            }
-        }
-    }
-
-    struct Cx<'a, 'b> {
-        a: &'a u32,
-        b: &'b u32,
-    }
-
-    // `'c` cannot be elided because we have several input lifetimes
-    fn one_explicit<'b>(x: Cx<'_, 'b>) -> &'b u32 {
-        &x.b
-        //~^ needless_borrow
-    }
-}
-
 fn main() {}
diff --git a/tests/ui/needless_lifetimes.stderr b/tests/ui/needless_lifetimes.stderr
index b1d1c88a296..138d0498c43 100644
--- a/tests/ui/needless_lifetimes.stderr
+++ b/tests/ui/needless_lifetimes.stderr
@@ -108,32 +108,8 @@ 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
-  --> tests/ui/needless_lifetimes.rs:109:21
-   |
-LL | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {}
-   |                     ^^  ^^          ^^        ^^
-   |
-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) {}
-   |
-
-error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:134:15
-   |
-LL | fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
-   |               ^^               ^^                   ^^
-   |
-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>
-   |
-
 error: the following explicit lifetimes could be elided: 's
-  --> tests/ui/needless_lifetimes.rs:165:21
+  --> tests/ui/needless_lifetimes.rs:127:21
    |
 LL |     fn self_and_out<'s>(&'s self) -> &'s u8 {
    |                     ^^   ^^           ^^
@@ -145,7 +121,7 @@ LL +     fn self_and_out(&self) -> &u8 {
    |
 
 error: the following explicit lifetimes could be elided: 't
-  --> tests/ui/needless_lifetimes.rs:173:30
+  --> tests/ui/needless_lifetimes.rs:135:30
    |
 LL |     fn self_and_in_out_1<'s, 't>(&'s self, _x: &'t u8) -> &'s u8 {
    |                              ^^                 ^^
@@ -157,7 +133,7 @@ LL +     fn self_and_in_out_1<'s>(&'s self, _x: &u8) -> &'s u8 {
    |
 
 error: the following explicit lifetimes could be elided: 's
-  --> tests/ui/needless_lifetimes.rs:181:26
+  --> tests/ui/needless_lifetimes.rs:143:26
    |
 LL |     fn self_and_in_out_2<'s, 't>(&'s self, x: &'t u8) -> &'t u8 {
    |                          ^^       ^^
@@ -169,7 +145,7 @@ LL +     fn self_and_in_out_2<'t>(&self, x: &'t u8) -> &'t u8 {
    |
 
 error: the following explicit lifetimes could be elided: 's, 't
-  --> tests/ui/needless_lifetimes.rs:186:29
+  --> tests/ui/needless_lifetimes.rs:148:29
    |
 LL |     fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {}
    |                             ^^  ^^   ^^            ^^
@@ -181,31 +157,7 @@ LL +     fn distinct_self_and_in(&self, _x: &u8) {}
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:206:19
-   |
-LL | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str {
-   |                   ^^            ^^       ^^
-   |
-help: elide the lifetimes
-   |
-LL - fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str {
-LL + fn struct_with_lt(_foo: Foo<'_>) -> &str {
-   |
-
-error: the following explicit lifetimes could be elided: 'b
-  --> tests/ui/needless_lifetimes.rs:225:25
-   |
-LL | fn struct_with_lt4a<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str {
-   |                         ^^                ^^
-   |
-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 {
-   |
-
-error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:234:21
+  --> tests/ui/needless_lifetimes.rs:172:21
    |
 LL | fn struct_with_lt4b<'a, 'b>(_foo: &'a Foo<'b>) -> &'b str {
    |                     ^^             ^^
@@ -217,7 +169,7 @@ LL + fn struct_with_lt4b<'b>(_foo: &Foo<'b>) -> &'b str {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:250:22
+  --> tests/ui/needless_lifetimes.rs:188:22
    |
 LL | fn trait_obj_elided2<'a>(_arg: &'a dyn Drop) -> &'a str {
    |                      ^^         ^^               ^^
@@ -229,31 +181,7 @@ LL + fn trait_obj_elided2(_arg: &dyn Drop) -> &str {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:257:18
-   |
-LL | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str {
-   |                  ^^                 ^^       ^^
-   |
-help: elide the lifetimes
-   |
-LL - fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str {
-LL + fn alias_with_lt(_foo: FooAlias<'_>) -> &str {
-   |
-
-error: the following explicit lifetimes could be elided: 'b
-  --> tests/ui/needless_lifetimes.rs:276:24
-   |
-LL | fn alias_with_lt4a<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str {
-   |                        ^^                     ^^
-   |
-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 {
-   |
-
-error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:285:20
+  --> tests/ui/needless_lifetimes.rs:199:20
    |
 LL | fn alias_with_lt4b<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'b str {
    |                    ^^             ^^
@@ -265,7 +193,7 @@ LL + fn alias_with_lt4b<'b>(_foo: &FooAlias<'b>) -> &'b str {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:290:30
+  --> tests/ui/needless_lifetimes.rs:204:30
    |
 LL | fn named_input_elided_output<'a>(_arg: &'a str) -> &str {
    |                              ^^         ^^          ^
@@ -277,7 +205,7 @@ LL + fn named_input_elided_output(_arg: &str) -> &str {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:299:19
+  --> tests/ui/needless_lifetimes.rs:213:19
    |
 LL | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) {
    |                   ^^                                ^^
@@ -289,19 +217,7 @@ LL + fn trait_bound_ok<T: WithLifetime<'static>>(_: &u8, _: T) {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:336:24
-   |
-LL | fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> {
-   |                        ^^      ^^             ^^
-   |
-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<'_> {
-   |
-
-error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:344:24
+  --> tests/ui/needless_lifetimes.rs:249:24
    |
 LL |         fn needless_lt<'a>(x: &'a u8) {}
    |                        ^^      ^^
@@ -313,7 +229,7 @@ LL +         fn needless_lt(x: &u8) {}
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:349:24
+  --> tests/ui/needless_lifetimes.rs:254:24
    |
 LL |         fn needless_lt<'a>(_x: &'a u8) {}
    |                        ^^       ^^
@@ -325,31 +241,7 @@ LL +         fn needless_lt(_x: &u8) {}
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:361:10
-   |
-LL |     impl<'a> Foo for Baz<'a> {}
-   |          ^^              ^^
-   |
-help: elide the lifetimes
-   |
-LL -     impl<'a> Foo for Baz<'a> {}
-LL +     impl Foo for Baz<'_> {}
-   |
-
-error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:364:16
-   |
-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
-  --> tests/ui/needless_lifetimes.rs:397:55
+  --> tests/ui/needless_lifetimes.rs:285:55
    |
 LL |     fn impl_trait_elidable_nested_anonymous_lifetimes<'a>(i: &'a i32, f: impl Fn(&i32) -> &i32) -> &'a i32 {
    |                                                       ^^      ^^                                    ^^
@@ -361,7 +253,7 @@ LL +     fn impl_trait_elidable_nested_anonymous_lifetimes(i: &i32, f: impl Fn(&
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:407:26
+  --> tests/ui/needless_lifetimes.rs:295:26
    |
 LL |     fn generics_elidable<'a, T: Fn(&i32) -> &i32>(i: &'a i32, f: T) -> &'a i32 {
    |                          ^^                           ^^                ^^
@@ -373,7 +265,7 @@ LL +     fn generics_elidable<T: Fn(&i32) -> &i32>(i: &i32, f: T) -> &i32 {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:420:30
+  --> tests/ui/needless_lifetimes.rs:308:30
    |
 LL |     fn where_clause_elidable<'a, T>(i: &'a i32, f: T) -> &'a i32
    |                              ^^         ^^                ^^
@@ -385,7 +277,7 @@ LL +     fn where_clause_elidable<T>(i: &i32, f: T) -> &i32
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:436:28
+  --> tests/ui/needless_lifetimes.rs:324:28
    |
 LL |     fn pointer_fn_elidable<'a>(i: &'a i32, f: fn(&i32) -> &i32) -> &'a i32 {
    |                            ^^      ^^                               ^^
@@ -397,7 +289,7 @@ LL +     fn pointer_fn_elidable(i: &i32, f: fn(&i32) -> &i32) -> &i32 {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:450:28
+  --> tests/ui/needless_lifetimes.rs:338:28
    |
 LL |     fn nested_fn_pointer_3<'a>(_: &'a i32) -> fn(fn(&i32) -> &i32) -> i32 {
    |                            ^^      ^^
@@ -409,7 +301,7 @@ LL +     fn nested_fn_pointer_3(_: &i32) -> fn(fn(&i32) -> &i32) -> i32 {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:454:28
+  --> tests/ui/needless_lifetimes.rs:342:28
    |
 LL |     fn nested_fn_pointer_4<'a>(_: &'a i32) -> impl Fn(fn(&i32)) {
    |                            ^^      ^^
@@ -421,7 +313,7 @@ LL +     fn nested_fn_pointer_4(_: &i32) -> impl Fn(fn(&i32)) {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:477:21
+  --> tests/ui/needless_lifetimes.rs:365:21
    |
 LL |         fn implicit<'a>(&'a self) -> &'a () {
    |                     ^^   ^^           ^^
@@ -433,7 +325,7 @@ LL +         fn implicit(&self) -> &() {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:481:25
+  --> tests/ui/needless_lifetimes.rs:369:25
    |
 LL |         fn implicit_mut<'a>(&'a mut self) -> &'a () {
    |                         ^^   ^^               ^^
@@ -445,7 +337,7 @@ LL +         fn implicit_mut(&mut self) -> &() {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:486:21
+  --> tests/ui/needless_lifetimes.rs:374:21
    |
 LL |         fn explicit<'a>(self: &'a Arc<Self>) -> &'a () {
    |                     ^^         ^^                ^^
@@ -457,7 +349,7 @@ LL +         fn explicit(self: &Arc<Self>) -> &() {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:491:25
+  --> tests/ui/needless_lifetimes.rs:379:25
    |
 LL |         fn explicit_mut<'a>(self: &'a mut Rc<Self>) -> &'a () {
    |                         ^^         ^^                   ^^
@@ -469,7 +361,7 @@ LL +         fn explicit_mut(self: &mut Rc<Self>) -> &() {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:504:31
+  --> tests/ui/needless_lifetimes.rs:392:31
    |
 LL |         fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a () {
    |                               ^^                          ^^         ^^
@@ -481,7 +373,7 @@ LL +         fn lifetime_elsewhere(self: Box<Self>, here: &()) -> &() {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:511:21
+  --> tests/ui/needless_lifetimes.rs:399:21
    |
 LL |         fn implicit<'a>(&'a self) -> &'a ();
    |                     ^^   ^^           ^^
@@ -493,7 +385,7 @@ LL +         fn implicit(&self) -> &();
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:513:30
+  --> tests/ui/needless_lifetimes.rs:401:30
    |
 LL |         fn implicit_provided<'a>(&'a self) -> &'a () {
    |                              ^^   ^^           ^^
@@ -505,7 +397,7 @@ LL +         fn implicit_provided(&self) -> &() {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:519:21
+  --> tests/ui/needless_lifetimes.rs:407:21
    |
 LL |         fn explicit<'a>(self: &'a Arc<Self>) -> &'a ();
    |                     ^^         ^^                ^^
@@ -517,7 +409,7 @@ LL +         fn explicit(self: &Arc<Self>) -> &();
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:522:30
+  --> tests/ui/needless_lifetimes.rs:410:30
    |
 LL |         fn explicit_provided<'a>(self: &'a Arc<Self>) -> &'a () {
    |                              ^^         ^^                ^^
@@ -529,7 +421,7 @@ LL +         fn explicit_provided(self: &Arc<Self>) -> &() {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:533:31
+  --> tests/ui/needless_lifetimes.rs:421:31
    |
 LL |         fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a ();
    |                               ^^                          ^^         ^^
@@ -541,7 +433,7 @@ LL +         fn lifetime_elsewhere(self: Box<Self>, here: &()) -> &();
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:535:40
+  --> tests/ui/needless_lifetimes.rs:423:40
    |
 LL |         fn lifetime_elsewhere_provided<'a>(self: Box<Self>, here: &'a ()) -> &'a () {
    |                                        ^^                          ^^         ^^
@@ -553,7 +445,7 @@ LL +         fn lifetime_elsewhere_provided(self: Box<Self>, here: &()) -> &() {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:545:12
+  --> tests/ui/needless_lifetimes.rs:433:12
    |
 LL |     fn foo<'a>(x: &'a u8, y: &'_ u8) {}
    |            ^^      ^^
@@ -565,7 +457,7 @@ LL +     fn foo(x: &u8, y: &'_ u8) {}
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:548:12
+  --> tests/ui/needless_lifetimes.rs:436:12
    |
 LL |     fn bar<'a>(x: &'a u8, y: &'_ u8, z: &'_ u8) {}
    |            ^^      ^^
@@ -577,7 +469,7 @@ LL +     fn bar(x: &u8, y: &'_ u8, z: &'_ u8) {}
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:556:18
+  --> tests/ui/needless_lifetimes.rs:444:18
    |
 LL |     fn one_input<'a>(x: &'a u8) -> &'a u8 {
    |                  ^^      ^^         ^^
@@ -589,7 +481,7 @@ LL +     fn one_input(x: &u8) -> &u8 {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:562:42
+  --> tests/ui/needless_lifetimes.rs:450:42
    |
 LL |     fn multiple_inputs_output_not_elided<'a, 'b>(x: &'a u8, y: &'b u8, z: &'b u8) -> &'b u8 {
    |                                          ^^          ^^
@@ -601,7 +493,7 @@ LL +     fn multiple_inputs_output_not_elided<'b>(x: &u8, y: &'b u8, z: &'b u8)
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> tests/ui/needless_lifetimes.rs:579:22
+  --> tests/ui/needless_lifetimes.rs:467:22
    |
 LL |         fn one_input<'a>(x: &'a u8) -> &'a u8 {
    |                      ^^      ^^         ^^
@@ -613,66 +505,5 @@ 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: 'py
-  --> tests/ui/needless_lifetimes.rs:675:14
-   |
-LL |     impl<'t, 'py> ContentString<'t> {
-   |              ^^^
-...
-LL |         fn map_content2(&self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, 'py> {
-   |                                                                                   ^^^
-   |
-help: elide the lifetimes
-   |
-LL ~     impl<'t> ContentString<'t> {
-LL |
-LL |         // `'py` can be elided because of `&self`
-LL ~         fn map_content2(&self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, '_> {
-   |
-
-error: the following explicit lifetimes could be elided: 'py
-  --> tests/ui/needless_lifetimes.rs:686:14
-   |
-LL |     impl<'t, 'py> ContentString<'t> {
-   |              ^^^
-...
-LL |         fn map_content3(&'_ self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, 'py> {
-   |                                                                                      ^^^
-   |
-help: elide the lifetimes
-   |
-LL ~     impl<'t> ContentString<'t> {
-LL |
-LL |         // `'py` can be elided because of `&'_ self`
-LL ~         fn map_content3(&'_ self, f: impl FnOnce(&'t str) -> &'t str) -> Content<'t, '_> {
-   |
-
-error: the following explicit lifetimes could be elided: 'py
-  --> tests/ui/needless_lifetimes.rs:707:14
-   |
-LL |     impl<'t, 'py> ContentString<'t> {
-   |              ^^^
-...
-LL |         ) -> Content<'t, 'py> {
-   |                          ^^^
-   |
-help: elide the lifetimes
-   |
-LL ~     impl<'t> ContentString<'t> {
-LL |
-...
-LL |             o: &'t str,
-LL ~         ) -> Content<'t, '_> {
-   |
-
-error: this expression creates a reference which is immediately dereferenced by the compiler
-  --> tests/ui/needless_lifetimes.rs:729:9
-   |
-LL |         &x.b
-   |         ^^^^ help: change this to: `x.b`
-   |
-   = note: `-D clippy::needless-borrow` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::needless_borrow)]`
-
-error: aborting due to 55 previous errors
+error: aborting due to 42 previous errors