diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index e45996310..f84d942e1 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -103,6 +103,11 @@ fn check_fn_inner<'a, 'tcx>( let mut bounds_lts = Vec::new(); for typ in generics.ty_params() { for bound in &typ.bounds { + let mut visitor = RefVisitor::new(cx); + walk_ty_param_bound(&mut visitor, bound); + if visitor.lts.iter().any(|lt| matches!(lt, RefLt::Named(_))) { + return; + } if let TraitTyParamBound(ref trait_ref, _) = *bound { let params = &trait_ref .trait_ref diff --git a/tests/ui/lifetimes.rs b/tests/ui/lifetimes.rs index d2de1cb8e..0322d42e8 100644 --- a/tests/ui/lifetimes.rs +++ b/tests/ui/lifetimes.rs @@ -53,6 +53,22 @@ 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!() } +fn fn_bound_3<'a, F: FnOnce(&'a i32)>(x: &'a i32, f: F) { // no error, see below + f(x); +} + +fn fn_bound_3_cannot_elide() { + let x = 42; + let p = &x; + let mut q = &x; + fn_bound_3(p, |y| q = y); // this will fail if we elides lifetimes of `fn_bound_3` +} + +// 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, } diff --git a/tests/ui/lifetimes.stderr b/tests/ui/lifetimes.stderr index 23b353d13..b69438af9 100644 --- a/tests/ui/lifetimes.stderr +++ b/tests/ui/lifetimes.stderr @@ -45,45 +45,45 @@ error: explicit lifetimes given in parameter types where they could be elided | |__________________^ error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:61:5 + --> $DIR/lifetimes.rs:77:5 | -61 | fn self_and_out<'s>(&'s self) -> &'s u8 { &self.x } +77 | fn self_and_out<'s>(&'s self) -> &'s u8 { &self.x } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:65:5 + --> $DIR/lifetimes.rs:81:5 | -65 | fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) { } +81 | fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:81:1 + --> $DIR/lifetimes.rs:97:1 | -81 | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str { unimplemented!() } +97 | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:101:1 + --> $DIR/lifetimes.rs:117:1 | -101 | fn trait_obj_elided2<'a>(_arg: &'a Drop) -> &'a str { unimplemented!() } +117 | fn trait_obj_elided2<'a>(_arg: &'a Drop) -> &'a str { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:105:1 + --> $DIR/lifetimes.rs:121:1 | -105 | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str { unimplemented!() } +121 | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:116:1 + --> $DIR/lifetimes.rs:132:1 | -116 | fn named_input_elided_output<'a>(_arg: &'a str) -> &str { unimplemented!() } +132 | fn named_input_elided_output<'a>(_arg: &'a str) -> &str { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:120:1 + --> $DIR/lifetimes.rs:136:1 | -120 | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) { unimplemented!() } +136 | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 14 previous errors