Skip to content

Commit d60f29e

Browse files
committed
Fix 13578
1 parent 5873cb9 commit d60f29e

File tree

2 files changed

+55
-8
lines changed

2 files changed

+55
-8
lines changed

clippy_lints/src/lifetimes.rs

Lines changed: 48 additions & 8 deletions
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;
@@ -492,18 +493,23 @@ fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, generics: &'tcx Generics<'_
492493
struct Usage {
493494
lifetime: Lifetime,
494495
in_where_predicate: bool,
496+
in_bounded_ty: bool,
495497
in_generics_arg: bool,
496498
}
497499

498500
struct LifetimeChecker<'cx, 'tcx, F> {
499501
cx: &'cx LateContext<'tcx>,
500502
map: FxIndexMap<LocalDefId, Vec<Usage>>,
501503
where_predicate_depth: usize,
504+
bounded_ty_depth: usize,
502505
generic_args_depth: usize,
503506
phantom: std::marker::PhantomData<F>,
504507
}
505508

506-
impl<'cx, 'tcx, F> LifetimeChecker<'cx, 'tcx, F> {
509+
impl<'cx, 'tcx, F> LifetimeChecker<'cx, 'tcx, F>
510+
where
511+
F: NestedFilter<'tcx>,
512+
{
507513
fn new(cx: &'cx LateContext<'tcx>, generics: &'tcx Generics<'_>) -> LifetimeChecker<'cx, 'tcx, F> {
508514
let map = generics
509515
.params
@@ -519,10 +525,30 @@ impl<'cx, 'tcx, F> LifetimeChecker<'cx, 'tcx, F> {
519525
cx,
520526
map,
521527
where_predicate_depth: 0,
528+
bounded_ty_depth: 0,
522529
generic_args_depth: 0,
523530
phantom: std::marker::PhantomData,
524531
}
525532
}
533+
534+
// `visit_where_bound_predicate` is based on:
535+
// https://github.com/rust-lang/rust/blob/864cee3ea383cc8254ba394ba355e648faa9cfa5/compiler/rustc_hir/src/intravisit.rs#L936-L939
536+
fn visit_where_bound_predicate(
537+
&mut self,
538+
hir_id: HirId,
539+
bounded_ty: &'tcx Ty<'tcx>,
540+
bounds: &'tcx [GenericBound<'tcx>],
541+
bound_generic_params: &'tcx [GenericParam<'tcx>],
542+
) {
543+
try_visit!(self.visit_id(hir_id));
544+
545+
self.bounded_ty_depth += 1;
546+
try_visit!(self.visit_ty(bounded_ty));
547+
self.bounded_ty_depth -= 1;
548+
549+
walk_list!(self, visit_param_bound, bounds);
550+
walk_list!(self, visit_generic_param, bound_generic_params);
551+
}
526552
}
527553

528554
impl<'tcx, F> Visitor<'tcx> for LifetimeChecker<'_, 'tcx, F>
@@ -540,14 +566,27 @@ where
540566
usages.push(Usage {
541567
lifetime: *lifetime,
542568
in_where_predicate: self.where_predicate_depth != 0,
569+
in_bounded_ty: self.bounded_ty_depth != 0,
543570
in_generics_arg: self.generic_args_depth != 0,
544571
});
545572
}
546573
}
547574

548575
fn visit_where_predicate(&mut self, predicate: &'tcx WherePredicate<'tcx>) {
549576
self.where_predicate_depth += 1;
550-
walk_where_predicate(self, predicate);
577+
if let &WherePredicate::BoundPredicate(WhereBoundPredicate {
578+
hir_id,
579+
bounded_ty,
580+
bounds,
581+
bound_generic_params,
582+
origin: _,
583+
span: _,
584+
}) = predicate
585+
{
586+
self.visit_where_bound_predicate(hir_id, bounded_ty, bounds, bound_generic_params);
587+
} else {
588+
walk_where_predicate(self, predicate);
589+
}
551590
self.where_predicate_depth -= 1;
552591
}
553592

@@ -571,7 +610,7 @@ fn report_extra_lifetimes<'tcx>(cx: &LateContext<'tcx>, func: &'tcx FnDecl<'_>,
571610
for (def_id, usages) in checker.map {
572611
if usages
573612
.iter()
574-
.all(|usage| usage.in_where_predicate && !usage.in_generics_arg)
613+
.all(|usage| usage.in_where_predicate && !usage.in_bounded_ty && !usage.in_generics_arg)
575614
{
576615
span_lint(
577616
cx,
@@ -598,7 +637,7 @@ fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<'
598637
for (&def_id, usages) in &checker.map {
599638
if usages
600639
.iter()
601-
.all(|usage| usage.in_where_predicate && !usage.in_generics_arg)
640+
.all(|usage| usage.in_where_predicate && !usage.in_bounded_ty && !usage.in_generics_arg)
602641
{
603642
span_lint(
604643
cx,
@@ -614,8 +653,8 @@ fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<'
614653

615654
// An `impl` lifetime is elidable if it satisfies the following conditions:
616655
// - It is used exactly once.
617-
// - That single use is not in `GenericArgs` in a `WherePredicate`. (Note that `GenericArgs` are
618-
// different from `GenericParam`s.)
656+
// - That single use is not in a bounded type or `GenericArgs` in a `WherePredicate`. (Note that
657+
// `GenericArgs` are different from `GenericParam`s.)
619658
fn report_elidable_impl_lifetimes<'tcx>(
620659
cx: &LateContext<'tcx>,
621660
impl_: &'tcx Impl<'_>,
@@ -632,6 +671,7 @@ fn report_elidable_impl_lifetimes<'tcx>(
632671
}
633672
| Usage {
634673
lifetime,
674+
in_bounded_ty: false,
635675
in_generics_arg: false,
636676
..
637677
},

tests/ui/extra_unused_lifetimes.rs

Lines changed: 7 additions & 0 deletions
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)