blob: abeee5c4cef34ac256813fe44e2a67c26103db16 [file] [log] [blame]
#![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
}
}