Skip to content

Commit 10677c3

Browse files
authored
Don't consider lifetimes in bounded types unused (fix extra_unused_lifetimes FP) (rust-lang#13583)
Fixes rust-lang#13578 r? @Alexendoo changelog: don't consider lifetimes in bounded types unused (fix `extra_unused_lifetimes` FP rust-lang#13578)
2 parents 53994bd + eaec0ca commit 10677c3

File tree

2 files changed

+55
-8
lines changed

2 files changed

+55
-8
lines changed

clippy_lints/src/lifetimes.rs

+48-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
22
use clippy_utils::trait_ref_of_method;
33
use itertools::Itertools;
4+
use rustc_ast::visit::{try_visit, walk_list};
45
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
56
use rustc_errors::Applicability;
67
use rustc_hir::FnRetTy::Return;
@@ -11,8 +12,8 @@ use rustc_hir::intravisit::{
1112
};
1213
use rustc_hir::{
1314
BareFnTy, BodyId, FnDecl, FnSig, GenericArg, GenericArgs, GenericBound, GenericParam, GenericParamKind, Generics,
14-
Impl, ImplItem, ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, Node, PolyTraitRef,
15-
PredicateOrigin, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WherePredicate, lang_items,
15+
HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, Node, PolyTraitRef,
16+
PredicateOrigin, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WhereBoundPredicate, WherePredicate, lang_items,
1617
};
1718
use rustc_lint::{LateContext, LateLintPass, LintContext};
1819
use rustc_middle::hir::map::Map;
@@ -483,18 +484,23 @@ fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, generics: &'tcx Generics<'_
483484
struct Usage {
484485
lifetime: Lifetime,
485486
in_where_predicate: bool,
487+
in_bounded_ty: bool,
486488
in_generics_arg: bool,
487489
}
488490

489491
struct LifetimeChecker<'cx, 'tcx, F> {
490492
cx: &'cx LateContext<'tcx>,
491493
map: FxIndexMap<LocalDefId, Vec<Usage>>,
492494
where_predicate_depth: usize,
495+
bounded_ty_depth: usize,
493496
generic_args_depth: usize,
494497
phantom: std::marker::PhantomData<F>,
495498
}
496499

497-
impl<'cx, 'tcx, F> LifetimeChecker<'cx, 'tcx, F> {
500+
impl<'cx, 'tcx, F> LifetimeChecker<'cx, 'tcx, F>
501+
where
502+
F: NestedFilter<'tcx>,
503+
{
498504
fn new(cx: &'cx LateContext<'tcx>, generics: &'tcx Generics<'_>) -> LifetimeChecker<'cx, 'tcx, F> {
499505
let map = generics
500506
.params
@@ -510,10 +516,30 @@ impl<'cx, 'tcx, F> LifetimeChecker<'cx, 'tcx, F> {
510516
cx,
511517
map,
512518
where_predicate_depth: 0,
519+
bounded_ty_depth: 0,
513520
generic_args_depth: 0,
514521
phantom: std::marker::PhantomData,
515522
}
516523
}
524+
525+
// `visit_where_bound_predicate` is based on:
526+
// https://github.com/rust-lang/rust/blob/864cee3ea383cc8254ba394ba355e648faa9cfa5/compiler/rustc_hir/src/intravisit.rs#L936-L939
527+
fn visit_where_bound_predicate(
528+
&mut self,
529+
hir_id: HirId,
530+
bounded_ty: &'tcx Ty<'tcx>,
531+
bounds: &'tcx [GenericBound<'tcx>],
532+
bound_generic_params: &'tcx [GenericParam<'tcx>],
533+
) {
534+
try_visit!(self.visit_id(hir_id));
535+
536+
self.bounded_ty_depth += 1;
537+
try_visit!(self.visit_ty(bounded_ty));
538+
self.bounded_ty_depth -= 1;
539+
540+
walk_list!(self, visit_param_bound, bounds);
541+
walk_list!(self, visit_generic_param, bound_generic_params);
542+
}
517543
}
518544

519545
impl<'tcx, F> Visitor<'tcx> for LifetimeChecker<'_, 'tcx, F>
@@ -531,14 +557,27 @@ where
531557
usages.push(Usage {
532558
lifetime: *lifetime,
533559
in_where_predicate: self.where_predicate_depth != 0,
560+
in_bounded_ty: self.bounded_ty_depth != 0,
534561
in_generics_arg: self.generic_args_depth != 0,
535562
});
536563
}
537564
}
538565

539566
fn visit_where_predicate(&mut self, predicate: &'tcx WherePredicate<'tcx>) {
540567
self.where_predicate_depth += 1;
541-
walk_where_predicate(self, predicate);
568+
if let &WherePredicate::BoundPredicate(WhereBoundPredicate {
569+
hir_id,
570+
bounded_ty,
571+
bounds,
572+
bound_generic_params,
573+
origin: _,
574+
span: _,
575+
}) = predicate
576+
{
577+
self.visit_where_bound_predicate(hir_id, bounded_ty, bounds, bound_generic_params);
578+
} else {
579+
walk_where_predicate(self, predicate);
580+
}
542581
self.where_predicate_depth -= 1;
543582
}
544583

@@ -562,7 +601,7 @@ fn report_extra_lifetimes<'tcx>(cx: &LateContext<'tcx>, func: &'tcx FnDecl<'_>,
562601
for (def_id, usages) in checker.map {
563602
if usages
564603
.iter()
565-
.all(|usage| usage.in_where_predicate && !usage.in_generics_arg)
604+
.all(|usage| usage.in_where_predicate && !usage.in_bounded_ty && !usage.in_generics_arg)
566605
{
567606
span_lint(
568607
cx,
@@ -589,7 +628,7 @@ fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<'
589628
for (&def_id, usages) in &checker.map {
590629
if usages
591630
.iter()
592-
.all(|usage| usage.in_where_predicate && !usage.in_generics_arg)
631+
.all(|usage| usage.in_where_predicate && !usage.in_bounded_ty && !usage.in_generics_arg)
593632
{
594633
span_lint(
595634
cx,
@@ -605,8 +644,8 @@ fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<'
605644

606645
// An `impl` lifetime is elidable if it satisfies the following conditions:
607646
// - It is used exactly once.
608-
// - That single use is not in `GenericArgs` in a `WherePredicate`. (Note that `GenericArgs` are
609-
// different from `GenericParam`s.)
647+
// - That single use is not in a bounded type or `GenericArgs` in a `WherePredicate`. (Note that
648+
// `GenericArgs` are different from `GenericParam`s.)
610649
fn report_elidable_impl_lifetimes<'tcx>(
611650
cx: &LateContext<'tcx>,
612651
impl_: &'tcx Impl<'_>,
@@ -623,6 +662,7 @@ fn report_elidable_impl_lifetimes<'tcx>(
623662
}
624663
| Usage {
625664
lifetime,
665+
in_bounded_ty: false,
626666
in_generics_arg: false,
627667
..
628668
},

tests/ui/extra_unused_lifetimes.rs

+7
Original file line numberDiff line numberDiff line change
@@ -134,4 +134,11 @@ struct Human<'a> {
134134
pub name: &'a str,
135135
}
136136

137+
// https://github.com/rust-lang/rust-clippy/issues/13578
138+
mod issue_13578 {
139+
pub trait Foo {}
140+
141+
impl<'a, T: 'a> Foo for Option<T> where &'a T: Foo {}
142+
}
143+
137144
fn main() {}

0 commit comments

Comments
 (0)