Skip to content

Commit 94623ee

Browse files
committed
Auto merge of #8737 - smoelius:extra-impl-lifetimes, r=giraffate
Extend `extra_unused_lifetimes` to handle impl lifetimes Fixes #6437 (cc: `@carols10cents)` changelog: fix #6437
2 parents 760f293 + c22bb06 commit 94623ee

File tree

7 files changed

+124
-12
lines changed

7 files changed

+124
-12
lines changed

clippy_lints/src/lifetimes.rs

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
use clippy_utils::diagnostics::span_lint;
22
use clippy_utils::trait_ref_of_method;
33
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
4+
use rustc_hir::intravisit::nested_filter::{self as hir_nested_filter, NestedFilter};
45
use rustc_hir::intravisit::{
5-
walk_fn_decl, walk_generic_param, walk_generics, walk_item, walk_param_bound, walk_poly_trait_ref, walk_ty, Visitor,
6+
walk_fn_decl, walk_generic_param, walk_generics, walk_impl_item_ref, walk_item, walk_param_bound,
7+
walk_poly_trait_ref, walk_trait_ref, walk_ty, Visitor,
68
};
79
use rustc_hir::FnRetTy::Return;
810
use rustc_hir::{
9-
BareFnTy, BodyId, FnDecl, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics, ImplItem,
11+
BareFnTy, BodyId, FnDecl, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics, Impl, ImplItem,
1012
ImplItemKind, Item, ItemKind, LangItem, Lifetime, LifetimeName, ParamName, PolyTraitRef, TraitBoundModifier,
1113
TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WhereClause, WherePredicate,
1214
};
1315
use rustc_lint::{LateContext, LateLintPass};
16+
use rustc_middle::hir::nested_filter as middle_nested_filter;
1417
use rustc_session::{declare_lint_pass, declare_tool_lint};
1518
use rustc_span::source_map::Span;
1619
use rustc_span::symbol::{kw, Ident, Symbol};
@@ -84,6 +87,8 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes {
8487
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
8588
if let ItemKind::Fn(ref sig, ref generics, id) = item.kind {
8689
check_fn_inner(cx, sig.decl, Some(id), None, generics, item.span, true);
90+
} else if let ItemKind::Impl(ref impl_) = item.kind {
91+
report_extra_impl_lifetimes(cx, impl_);
8792
}
8893
}
8994

@@ -194,8 +199,7 @@ fn explicit_self_type<'tcx>(cx: &LateContext<'tcx>, func: &FnDecl<'tcx>, ident:
194199
visitor.visit_ty(self_ty);
195200

196201
!visitor.all_lts().is_empty()
197-
}
198-
else {
202+
} else {
199203
false
200204
}
201205
}
@@ -481,11 +485,29 @@ fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, where_clause: &'tcx WhereCl
481485
false
482486
}
483487

484-
struct LifetimeChecker {
488+
struct LifetimeChecker<'cx, 'tcx, F> {
489+
cx: &'cx LateContext<'tcx>,
485490
map: FxHashMap<Symbol, Span>,
491+
phantom: std::marker::PhantomData<F>,
486492
}
487493

488-
impl<'tcx> Visitor<'tcx> for LifetimeChecker {
494+
impl<'cx, 'tcx, F> LifetimeChecker<'cx, 'tcx, F> {
495+
fn new(cx: &'cx LateContext<'tcx>, map: FxHashMap<Symbol, Span>) -> LifetimeChecker<'cx, 'tcx, F> {
496+
Self {
497+
cx,
498+
map,
499+
phantom: std::marker::PhantomData,
500+
}
501+
}
502+
}
503+
504+
impl<'cx, 'tcx, F> Visitor<'tcx> for LifetimeChecker<'cx, 'tcx, F>
505+
where
506+
F: NestedFilter<'tcx>,
507+
{
508+
type Map = rustc_middle::hir::map::Map<'tcx>;
509+
type NestedFilter = F;
510+
489511
// for lifetimes as parameters of generics
490512
fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) {
491513
self.map.remove(&lifetime.name.ident().name);
@@ -501,6 +523,10 @@ impl<'tcx> Visitor<'tcx> for LifetimeChecker {
501523
walk_generic_param(self, param);
502524
}
503525
}
526+
527+
fn nested_visit_map(&mut self) -> Self::Map {
528+
self.cx.tcx.hir()
529+
}
504530
}
505531

506532
fn report_extra_lifetimes<'tcx>(cx: &LateContext<'tcx>, func: &'tcx FnDecl<'_>, generics: &'tcx Generics<'_>) {
@@ -512,7 +538,7 @@ fn report_extra_lifetimes<'tcx>(cx: &LateContext<'tcx>, func: &'tcx FnDecl<'_>,
512538
_ => None,
513539
})
514540
.collect();
515-
let mut checker = LifetimeChecker { map: hs };
541+
let mut checker = LifetimeChecker::<hir_nested_filter::None>::new(cx, hs);
516542

517543
walk_generics(&mut checker, generics);
518544
walk_fn_decl(&mut checker, func);
@@ -527,6 +553,32 @@ fn report_extra_lifetimes<'tcx>(cx: &LateContext<'tcx>, func: &'tcx FnDecl<'_>,
527553
}
528554
}
529555

556+
fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<'_>) {
557+
let hs = impl_
558+
.generics
559+
.params
560+
.iter()
561+
.filter_map(|par| match par.kind {
562+
GenericParamKind::Lifetime { .. } => Some((par.name.ident().name, par.span)),
563+
_ => None,
564+
})
565+
.collect();
566+
let mut checker = LifetimeChecker::<middle_nested_filter::All>::new(cx, hs);
567+
568+
walk_generics(&mut checker, &impl_.generics);
569+
if let Some(ref trait_ref) = impl_.of_trait {
570+
walk_trait_ref(&mut checker, trait_ref);
571+
}
572+
walk_ty(&mut checker, impl_.self_ty);
573+
for item in impl_.items {
574+
walk_impl_item_ref(&mut checker, item);
575+
}
576+
577+
for &v in checker.map.values() {
578+
span_lint(cx, EXTRA_UNUSED_LIFETIMES, v, "this lifetime isn't used in the impl");
579+
}
580+
}
581+
530582
struct BodyLifetimeChecker {
531583
lifetimes_used_in_body: bool,
532584
}

tests/ui/crashes/ice-2865.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#[allow(dead_code)]
1+
#![allow(dead_code, clippy::extra_unused_lifetimes)]
22

33
/// Test for https://github.com/rust-lang/rust-clippy/issues/2865
44

tests/ui/crashes/ice-3151.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/// Test for https://github.com/rust-lang/rust-clippy/issues/2865
1+
/// Test for https://github.com/rust-lang/rust-clippy/issues/3151
22
33
#[derive(Clone)]
44
pub struct HashMap<V, S> {

tests/ui/extra_unused_lifetimes.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,46 @@ mod issue4291 {
7272
}
7373
}
7474

75+
mod issue6437 {
76+
pub struct Scalar;
77+
78+
impl<'a> std::ops::AddAssign<&Scalar> for &mut Scalar {
79+
fn add_assign(&mut self, _rhs: &Scalar) {
80+
unimplemented!();
81+
}
82+
}
83+
84+
impl<'b> Scalar {
85+
pub fn something<'c>() -> Self {
86+
Self
87+
}
88+
}
89+
}
90+
91+
// https://github.com/rust-lang/rust-clippy/pull/8737#pullrequestreview-951268213
92+
mod first_case {
93+
use serde::de::Visitor;
94+
pub trait Expected {
95+
fn fmt(&self, formatter: &mut std::fmt::Formatter);
96+
}
97+
98+
impl<'de, T> Expected for T
99+
where
100+
T: Visitor<'de>,
101+
{
102+
fn fmt(&self, formatter: &mut std::fmt::Formatter) {}
103+
}
104+
}
105+
106+
// https://github.com/rust-lang/rust-clippy/pull/8737#pullrequestreview-951268213
107+
mod second_case {
108+
pub trait Source {
109+
fn hey();
110+
}
111+
112+
impl<'a, T: Source + ?Sized + 'a> Source for Box<T> {
113+
fn hey() {}
114+
}
115+
}
116+
75117
fn main() {}

tests/ui/extra_unused_lifetimes.stderr

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,23 @@ error: this lifetime isn't used in the function definition
2424
LL | fn unused_lt<'a>(x: u8) {}
2525
| ^^
2626

27-
error: aborting due to 4 previous errors
27+
error: this lifetime isn't used in the impl
28+
--> $DIR/extra_unused_lifetimes.rs:78:10
29+
|
30+
LL | impl<'a> std::ops::AddAssign<&Scalar> for &mut Scalar {
31+
| ^^
32+
33+
error: this lifetime isn't used in the impl
34+
--> $DIR/extra_unused_lifetimes.rs:84:10
35+
|
36+
LL | impl<'b> Scalar {
37+
| ^^
38+
39+
error: this lifetime isn't used in the function definition
40+
--> $DIR/extra_unused_lifetimes.rs:85:26
41+
|
42+
LL | pub fn something<'c>() -> Self {
43+
| ^^
44+
45+
error: aborting due to 7 previous errors
2846

tests/ui/impl.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![allow(dead_code)]
1+
#![allow(dead_code, clippy::extra_unused_lifetimes)]
22
#![warn(clippy::multiple_inherent_impl)]
33

44
struct MyStruct;

tests/ui/new_without_default.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![allow(dead_code, clippy::missing_safety_doc)]
1+
#![allow(dead_code, clippy::missing_safety_doc, clippy::extra_unused_lifetimes)]
22
#![warn(clippy::new_without_default)]
33

44
pub struct Foo;

0 commit comments

Comments
 (0)