diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 2b73663d229e..62708f06e780 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -1,4 +1,5 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; +use clippy_utils::source::snippet; use clippy_utils::trait_ref_of_method; use itertools::Itertools; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -18,6 +19,7 @@ use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::hir::map::Map; use rustc_middle::hir::nested_filter as middle_nested_filter; use rustc_middle::lint::in_external_macro; +use rustc_middle::query::Key; use rustc_session::declare_lint_pass; use rustc_span::def_id::LocalDefId; use rustc_span::symbol::{kw, Ident, Symbol}; @@ -208,7 +210,7 @@ fn check_fn_inner<'tcx>( .map(|<| cx.tcx.def_span(lt)) .chain(usages.iter().filter_map(|usage| { if let LifetimeName::Param(def_id) = usage.res - && elidable_lts.contains(&def_id) + // && elidable_lts.contains(&def_id) { return Some(usage.ident.span); } @@ -225,7 +227,7 @@ fn check_fn_inner<'tcx>( }; if let Some(suggestions) = elision_suggestions(cx, generics, &elidable_lts, &usages) { - diag.multipart_suggestion("elide the lifetimes", suggestions, Applicability::MachineApplicable); + // diag.multipart_suggestion("elide the lifetimes", suggestions, Applicability::MachineApplicable); } }, ); @@ -346,7 +348,6 @@ fn could_use_elision<'tcx>( // check named LTs let allowed_lts = allowed_lts_from(named_generics); - // these will collect all the lifetimes for references in arg/return types let mut input_visitor = RefVisitor::new(cx); let mut output_visitor = RefVisitor::new(cx); @@ -369,6 +370,10 @@ fn could_use_elision<'tcx>( let input_lts = input_visitor.lts; let output_lts = output_visitor.lts; + let output_lts: Vec = output_lts + .into_iter() + .unique_by(|lt| lt.hir_id.default_span(cx.tcx)) + .collect(); if let Some(trait_sig) = trait_sig { if explicit_self_type(cx, func, trait_sig.first().copied()) { @@ -393,10 +398,12 @@ fn could_use_elision<'tcx>( } } + let allowed_lts: FxHashSet = allowed_lts.iter().map(|id| cx.tcx.item_name(id.to_def_id())).collect(); + // check for lifetimes from higher scopes for lt in input_lts.iter().chain(output_lts.iter()) { if let Some(id) = named_lifetime(lt) - && !allowed_lts.contains(&id) + && !allowed_lts.contains(&cx.tcx.item_name(id.to_def_id())) { return None; } @@ -404,7 +411,6 @@ fn could_use_elision<'tcx>( // check for higher-ranked trait bounds if !input_visitor.nested_elision_site_lts.is_empty() || !output_visitor.nested_elision_site_lts.is_empty() { - let allowed_lts: FxHashSet<_> = allowed_lts.iter().map(|id| cx.tcx.item_name(id.to_def_id())).collect(); for lt in input_visitor.nested_elision_site_lts { if allowed_lts.contains(<.ident.name) { return None; @@ -532,9 +538,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> { TyKind::OpaqueDef(item, bounds, _) => { let map = self.cx.tcx.hir(); let item = map.item(item); - let len = self.lts.len(); walk_item(self, item); - self.lts.truncate(len); self.lts.extend(bounds.iter().filter_map(|bound| match bound { GenericArg::Lifetime(&l) => Some(l), _ => None, diff --git a/tests/ui/needless_lifetimes.fixed b/tests/ui/needless_lifetimes.fixed deleted file mode 100644 index d1787b35abd2..000000000000 --- a/tests/ui/needless_lifetimes.fixed +++ /dev/null @@ -1,546 +0,0 @@ -//@aux-build:proc_macros.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 -)] - -extern crate proc_macros; -use proc_macros::inline_macros; - -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(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(_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>(_: &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, -} - -impl Test { - fn iter<'a>(&'a self) -> Box + '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 &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(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) -> &'a () { - &() - } - fn explicit_mut<'a>(self: &'a mut Rc) -> &'a () { - &() - } - - fn lifetime_elsewhere(self: Box, here: &()) -> &() { - &() - } - } - - trait Bar { - fn implicit(&self) -> &(); - fn implicit_provided(&self) -> &() { - &() - } - - fn explicit<'a>(self: &'a Arc) -> &'a (); - fn explicit_provided<'a>(self: &'a Arc) -> &'a () { - &() - } - - fn lifetime_elsewhere(self: Box, here: &()) -> &(); - fn lifetime_elsewhere_provided(self: Box, 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!() - } -} - -#[inline_macros] -mod in_macro { - use proc_macros::external; - - // lint local macro expands to function with needless lifetimes - inline! { - fn one_input(x: &u8) -> &u8 { - unimplemented!() - } - } - - // no lint on external macro - external! { - fn needless_lifetime<'a>(x: &'a u8) -> &'a u8 { - unimplemented!() - } - } - - inline! { - fn f<$'a>(arg: &$'a str) -> &$'a str { - arg - } - } -} - -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/tests/ui/needless_lifetimes.rs b/tests/ui/needless_lifetimes.rs index 03d6f2013586..de2c95753eea 100644 --- a/tests/ui/needless_lifetimes.rs +++ b/tests/ui/needless_lifetimes.rs @@ -332,6 +332,7 @@ mod issue2944 { impl<'a> Foo for Baz<'a> {} impl Bar { fn baz<'a>(&'a self) -> impl Foo + 'a { + //~^ ERROR: the following explicit lifetimes could be elided: 'a Baz { bar: self } } } @@ -544,3 +545,22 @@ mod issue5787 { } fn main() {} + +mod issue11291 { + use std::collections::HashMap; + pub struct MyContainer(HashMap); + impl MyContainer { + pub fn iter<'a>(&'a self) -> impl Iterator + 'a { + self.0.iter() + } + + pub fn iter2<'a>( + &'a self, + ) -> ( + impl Iterator + 'a, + impl Iterator + 'a, + ) { + (self.0.iter(), self.0.iter()) + } + } +} diff --git a/tests/ui/needless_lifetimes.stderr b/tests/ui/needless_lifetimes.stderr index f325d27b8c75..e2e4ec9462aa 100644 --- a/tests/ui/needless_lifetimes.stderr +++ b/tests/ui/needless_lifetimes.stderr @@ -6,552 +6,297 @@ LL | fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {} | = note: `-D clippy::needless-lifetimes` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::needless_lifetimes)]` -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 --> tests/ui/needless_lifetimes.rs:19:24 | 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 --> tests/ui/needless_lifetimes.rs:29:15 | 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 --> tests/ui/needless_lifetimes.rs:41:31 | 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 --> tests/ui/needless_lifetimes.rs:48:27 | 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 --> tests/ui/needless_lifetimes.rs:65:26 | 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 --> tests/ui/needless_lifetimes.rs:72:22 | 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 --> tests/ui/needless_lifetimes.rs:81:21 | 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 --> tests/ui/needless_lifetimes.rs:86:28 | 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(x: &u8, _y: u8) -> Result<&u8, ()> - | error: the following explicit lifetimes could be elided: 'a, 'b --> tests/ui/needless_lifetimes.rs:98: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:122: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(_m: Lt<'_, I>, _f: F) -> Lt<'_, I> - | error: the following explicit lifetimes could be elided: 's --> tests/ui/needless_lifetimes.rs:152:21 | 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 --> tests/ui/needless_lifetimes.rs:159:30 | 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 --> tests/ui/needless_lifetimes.rs:166:26 | 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 --> tests/ui/needless_lifetimes.rs:170:29 | 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 --> tests/ui/needless_lifetimes.rs:189: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:207: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:215:21 | 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 --> tests/ui/needless_lifetimes.rs:230:22 | 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 --> tests/ui/needless_lifetimes.rs:236: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:254: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:262:20 | 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 --> tests/ui/needless_lifetimes.rs:266:30 | 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 --> tests/ui/needless_lifetimes.rs:274:19 | 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>(_: &u8, _: T) { - | error: the following explicit lifetimes could be elided: 'a --> tests/ui/needless_lifetimes.rs:310: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:317:24 | 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 --> tests/ui/needless_lifetimes.rs:321:24 | 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 --> tests/ui/needless_lifetimes.rs:334: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:366:55 + --> tests/ui/needless_lifetimes.rs:367:55 | 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 - --> tests/ui/needless_lifetimes.rs:375:26 + --> tests/ui/needless_lifetimes.rs:376:26 | 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 &i32>(i: &i32, f: T) -> &i32 { - | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:387:32 + --> tests/ui/needless_lifetimes.rs:388:32 | 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(i: &i32, f: T) -> &i32 - | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:402:28 + --> tests/ui/needless_lifetimes.rs:403:28 | 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 - --> tests/ui/needless_lifetimes.rs:415:28 + --> tests/ui/needless_lifetimes.rs:416:28 | 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 - --> tests/ui/needless_lifetimes.rs:418:28 + --> tests/ui/needless_lifetimes.rs:419:28 | 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 - --> tests/ui/needless_lifetimes.rs:440:21 + --> tests/ui/needless_lifetimes.rs:441:21 | 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 - --> tests/ui/needless_lifetimes.rs:443:25 + --> tests/ui/needless_lifetimes.rs:444:25 | 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 - --> tests/ui/needless_lifetimes.rs:454:31 + --> tests/ui/needless_lifetimes.rs:455:31 | LL | fn lifetime_elsewhere<'a>(self: Box, here: &'a ()) -> &'a () { | ^^ ^^ ^^ - | -help: elide the lifetimes - | -LL - fn lifetime_elsewhere<'a>(self: Box, here: &'a ()) -> &'a () { -LL + fn lifetime_elsewhere(self: Box, here: &()) -> &() { - | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:460:21 + --> tests/ui/needless_lifetimes.rs:461:21 | 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 - --> tests/ui/needless_lifetimes.rs:461:30 + --> tests/ui/needless_lifetimes.rs:462:30 | 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 - --> tests/ui/needless_lifetimes.rs:470:31 + --> tests/ui/needless_lifetimes.rs:471:31 | LL | fn lifetime_elsewhere<'a>(self: Box, here: &'a ()) -> &'a (); | ^^ ^^ ^^ - | -help: elide the lifetimes - | -LL - fn lifetime_elsewhere<'a>(self: Box, here: &'a ()) -> &'a (); -LL + fn lifetime_elsewhere(self: Box, here: &()) -> &(); - | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:471:40 + --> tests/ui/needless_lifetimes.rs:472:40 | LL | fn lifetime_elsewhere_provided<'a>(self: Box, here: &'a ()) -> &'a () { | ^^ ^^ ^^ - | -help: elide the lifetimes - | -LL - fn lifetime_elsewhere_provided<'a>(self: Box, here: &'a ()) -> &'a () { -LL + fn lifetime_elsewhere_provided(self: Box, here: &()) -> &() { - | error: the following explicit lifetimes could be elided: 'a - --> tests/ui/needless_lifetimes.rs:480:12 + --> tests/ui/needless_lifetimes.rs:481:12 | 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 - --> tests/ui/needless_lifetimes.rs:482:12 + --> tests/ui/needless_lifetimes.rs:483:12 | 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 - --> tests/ui/needless_lifetimes.rs:489:18 + --> tests/ui/needless_lifetimes.rs:490:18 | 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 - --> tests/ui/needless_lifetimes.rs:494:42 + --> tests/ui/needless_lifetimes.rs:495:42 | 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 - --> tests/ui/needless_lifetimes.rs:510:22 + --> tests/ui/needless_lifetimes.rs:511:22 | LL | fn one_input<'a>(x: &'a u8) -> &'a u8 { | ^^ ^^ ^^ | = note: this error originates in the macro `__inline_mac_mod_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) -help: elide the lifetimes + +error: the following explicit lifetimes could be elided: 'a + --> tests/ui/needless_lifetimes.rs:553:21 | -LL - fn one_input<'a>(x: &'a u8) -> &'a u8 { -LL + fn one_input(x: &u8) -> &u8 { +LL | pub fn iter<'a>(&'a self) -> impl Iterator + 'a { + | ^^ ^^ ^^ ^^ ^^ + +error: the following explicit lifetimes could be elided: 'a + --> tests/ui/needless_lifetimes.rs:557:22 | +LL | pub fn iter2<'a>( + | ^^ +LL | &'a self, + | ^^ +LL | ) -> ( +LL | impl Iterator + 'a, + | ^^ ^^ ^^ +LL | impl Iterator + 'a, + | ^^ ^^ ^^ -error: aborting due to 46 previous errors +error: aborting due to 48 previous errors