From 21d8fbd082aa66db3431debc05e485d5eb03c110 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 11 Apr 2017 15:44:13 +0200 Subject: [PATCH] Don't lint for lifetime bounds required by traits --- clippy_lints/src/lifetimes.rs | 44 ++++++++++++++++++----------------- tests/ui/lifetimes.stderr | 8 +------ 2 files changed, 24 insertions(+), 28 deletions(-) diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 88285cac037..7c095ad7cf7 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -89,29 +89,31 @@ enum RefLt { Named(Name), } -fn bound_lifetimes(bound: &TyParamBound) -> HirVec<&Lifetime> { - if let TraitTyParamBound(ref trait_ref, _) = *bound { - trait_ref.trait_ref - .path - .segments - .last() - .expect("a path must have at least one segment") - .parameters - .lifetimes() - } else { - HirVec::new() - } -} - fn check_fn_inner<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, decl: &'tcx FnDecl, body: Option, generics: &'tcx Generics, span: Span) { if in_external_macro(cx, span) || has_where_lifetimes(cx, &generics.where_clause) { return; } - let bounds_lts = generics.ty_params - .iter() - .flat_map(|typ| typ.bounds.iter().flat_map(bound_lifetimes)); - + let mut bounds_lts = Vec::new(); + for typ in &generics.ty_params { + for bound in &typ.bounds { + if let TraitTyParamBound(ref trait_ref, _) = *bound { + let bounds = trait_ref.trait_ref + .path + .segments + .last() + .expect("a path must have at least one segment") + .parameters + .lifetimes(); + for bound in bounds { + if bound.name != "'static" && !bound.is_elided() { + return; + } + bounds_lts.push(bound); + } + } + } + } if could_use_elision(cx, decl, body, &generics.lifetimes, bounds_lts) { span_lint(cx, NEEDLESS_LIFETIMES, @@ -121,12 +123,12 @@ fn check_fn_inner<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, decl: &'tcx FnDecl, body report_extra_lifetimes(cx, decl, generics); } -fn could_use_elision<'a, 'tcx: 'a, T: Iterator>( +fn could_use_elision<'a, 'tcx: 'a>( cx: &LateContext<'a, 'tcx>, func: &'tcx FnDecl, body: Option, named_lts: &'tcx [LifetimeDef], - bounds_lts: T + bounds_lts: Vec<&'tcx Lifetime>, ) -> bool { // There are two scenarios where elision works: // * no output references, all input references have different LT @@ -151,7 +153,7 @@ fn could_use_elision<'a, 'tcx: 'a, T: Iterator>( } let input_lts = match input_visitor.into_vec() { - Some(lts) => lts_from_bounds(lts, bounds_lts), + Some(lts) => lts_from_bounds(lts, bounds_lts.into_iter()), None => return false, }; let output_lts = match output_visitor.into_vec() { diff --git a/tests/ui/lifetimes.stderr b/tests/ui/lifetimes.stderr index e155d55011c..6d213ad45f2 100644 --- a/tests/ui/lifetimes.stderr +++ b/tests/ui/lifetimes.stderr @@ -91,11 +91,5 @@ error: explicit lifetimes given in parameter types where they could be elided 128 | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: explicit lifetimes given in parameter types where they could be elided - --> $DIR/lifetimes.rs:132:1 - | -132 | fn trait_bound_bug<'a, T: WithLifetime<'a>>() { unimplemented!() } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 15 previous errors +error: aborting due to 14 previous errors