| #![warn(clippy::elidable_lifetime_names)] | |
| #![deny(clippy::needless_lifetimes)] | |
| 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 | |
| } | |
| } | |
| fn issue15666_original() { | |
| struct UnitVariantAccess<'a, 'b, 's>(&'a &'b &'s ()); | |
| trait Trait<'de> {} | |
| //~v elidable_lifetime_names | |
| impl<'de> Trait<'de> for UnitVariantAccess<'_, 'de, '_> {} | |
| // ^^ ^^ ^^ ^^ | |
| } | |
| #[allow(clippy::upper_case_acronyms)] | |
| fn issue15666() { | |
| struct S1<'a>(&'a ()); | |
| struct S2<'a, 'b>(&'a &'b ()); | |
| struct S3<'a, 'b, 'c>(&'a &'b &'c ()); | |
| trait T {} | |
| trait TA<'a> {} | |
| trait TB<'b> {} | |
| trait TC<'c> {} | |
| trait TAB<'a, 'b> {} | |
| trait TAC<'a, 'c> {} | |
| trait TBC<'b, 'c> {} | |
| trait TABC<'a, 'b, 'c> {} | |
| // 1 lifetime | |
| impl<'a> TA<'a> for S1<'a> {} | |
| //~v elidable_lifetime_names | |
| impl T for S1<'_> {} | |
| // ^^ | |
| // 2 lifetimes | |
| impl<'a, 'b> TAB<'a, 'b> for S2<'a, 'b> {} | |
| //~v elidable_lifetime_names | |
| impl<'a> TA<'a> for S2<'a, '_> {} | |
| // ^^ | |
| //~v elidable_lifetime_names | |
| impl<'b> TB<'b> for S2<'_, 'b> {} | |
| // ^^ | |
| //~v elidable_lifetime_names | |
| impl T for S2<'_, '_> {} | |
| // ^^ ^^ | |
| // 3 lifetimes | |
| impl<'a, 'b, 'c> TABC<'a, 'b, 'c> for S3<'a, 'b, 'c> {} | |
| //~v elidable_lifetime_names | |
| impl<'a, 'b> TAB<'a, 'b> for S3<'a, 'b, '_> {} | |
| // ^^ | |
| //~v elidable_lifetime_names | |
| impl<'a, 'c> TAC<'a, 'c> for S3<'a, '_, 'c> {} | |
| // ^^ | |
| //~v elidable_lifetime_names | |
| impl<'a> TA<'a> for S3<'a, '_, '_> {} | |
| // ^^ ^^ | |
| //~v elidable_lifetime_names | |
| impl<'b, 'c> TBC<'b, 'c> for S3<'_, 'b, 'c> {} | |
| // ^^ | |
| //~v elidable_lifetime_names | |
| impl<'b> TB<'b> for S3<'_, 'b, '_> {} | |
| // ^^ ^^ | |
| //~v elidable_lifetime_names | |
| impl<'c> TC<'c> for S3<'_, '_, 'c> {} | |
| // ^^ ^^ | |
| //~v elidable_lifetime_names | |
| impl T for S3<'_, '_, '_> {} | |
| // ^^ ^^ ^^ | |
| } |