Skip to content

Commit 21d8fbd

Browse files
committed
Don't lint for lifetime bounds required by traits
1 parent 856b1f1 commit 21d8fbd

File tree

2 files changed

+24
-28
lines changed

2 files changed

+24
-28
lines changed

clippy_lints/src/lifetimes.rs

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -89,29 +89,31 @@ enum RefLt {
8989
Named(Name),
9090
}
9191

92-
fn bound_lifetimes(bound: &TyParamBound) -> HirVec<&Lifetime> {
93-
if let TraitTyParamBound(ref trait_ref, _) = *bound {
94-
trait_ref.trait_ref
95-
.path
96-
.segments
97-
.last()
98-
.expect("a path must have at least one segment")
99-
.parameters
100-
.lifetimes()
101-
} else {
102-
HirVec::new()
103-
}
104-
}
105-
10692
fn check_fn_inner<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, decl: &'tcx FnDecl, body: Option<BodyId>, generics: &'tcx Generics, span: Span) {
10793
if in_external_macro(cx, span) || has_where_lifetimes(cx, &generics.where_clause) {
10894
return;
10995
}
11096

111-
let bounds_lts = generics.ty_params
112-
.iter()
113-
.flat_map(|typ| typ.bounds.iter().flat_map(bound_lifetimes));
114-
97+
let mut bounds_lts = Vec::new();
98+
for typ in &generics.ty_params {
99+
for bound in &typ.bounds {
100+
if let TraitTyParamBound(ref trait_ref, _) = *bound {
101+
let bounds = trait_ref.trait_ref
102+
.path
103+
.segments
104+
.last()
105+
.expect("a path must have at least one segment")
106+
.parameters
107+
.lifetimes();
108+
for bound in bounds {
109+
if bound.name != "'static" && !bound.is_elided() {
110+
return;
111+
}
112+
bounds_lts.push(bound);
113+
}
114+
}
115+
}
116+
}
115117
if could_use_elision(cx, decl, body, &generics.lifetimes, bounds_lts) {
116118
span_lint(cx,
117119
NEEDLESS_LIFETIMES,
@@ -121,12 +123,12 @@ fn check_fn_inner<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, decl: &'tcx FnDecl, body
121123
report_extra_lifetimes(cx, decl, generics);
122124
}
123125

124-
fn could_use_elision<'a, 'tcx: 'a, T: Iterator<Item = &'tcx Lifetime>>(
126+
fn could_use_elision<'a, 'tcx: 'a>(
125127
cx: &LateContext<'a, 'tcx>,
126128
func: &'tcx FnDecl,
127129
body: Option<BodyId>,
128130
named_lts: &'tcx [LifetimeDef],
129-
bounds_lts: T
131+
bounds_lts: Vec<&'tcx Lifetime>,
130132
) -> bool {
131133
// There are two scenarios where elision works:
132134
// * no output references, all input references have different LT
@@ -151,7 +153,7 @@ fn could_use_elision<'a, 'tcx: 'a, T: Iterator<Item = &'tcx Lifetime>>(
151153
}
152154

153155
let input_lts = match input_visitor.into_vec() {
154-
Some(lts) => lts_from_bounds(lts, bounds_lts),
156+
Some(lts) => lts_from_bounds(lts, bounds_lts.into_iter()),
155157
None => return false,
156158
};
157159
let output_lts = match output_visitor.into_vec() {

tests/ui/lifetimes.stderr

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,5 @@ error: explicit lifetimes given in parameter types where they could be elided
9191
128 | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) { unimplemented!() }
9292
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
9393

94-
error: explicit lifetimes given in parameter types where they could be elided
95-
--> $DIR/lifetimes.rs:132:1
96-
|
97-
132 | fn trait_bound_bug<'a, T: WithLifetime<'a>>() { unimplemented!() }
98-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
99-
100-
error: aborting due to 15 previous errors
94+
error: aborting due to 14 previous errors
10195

0 commit comments

Comments
 (0)