mirror of
https://github.com/rust-lang/rust-clippy
synced 2025-02-16 14:08:37 +00:00
Fix 13578 (#13583)
changelog: don't consider lifetimes in bounded types unused (fix `extra_unused_lifetimes` FP #13578)
This commit is contained in:
parent
53994bda92
commit
eaec0cab7e
2 changed files with 55 additions and 8 deletions
|
@ -1,6 +1,7 @@
|
|||
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
|
||||
use clippy_utils::trait_ref_of_method;
|
||||
use itertools::Itertools;
|
||||
use rustc_ast::visit::{try_visit, walk_list};
|
||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::FnRetTy::Return;
|
||||
|
@ -11,8 +12,8 @@ use rustc_hir::intravisit::{
|
|||
};
|
||||
use rustc_hir::{
|
||||
BareFnTy, BodyId, FnDecl, FnSig, GenericArg, GenericArgs, GenericBound, GenericParam, GenericParamKind, Generics,
|
||||
Impl, ImplItem, ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, Node, PolyTraitRef,
|
||||
PredicateOrigin, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WherePredicate, lang_items,
|
||||
HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, Node, PolyTraitRef,
|
||||
PredicateOrigin, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WhereBoundPredicate, WherePredicate, lang_items,
|
||||
};
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_middle::hir::map::Map;
|
||||
|
@ -483,6 +484,7 @@ fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, generics: &'tcx Generics<'_
|
|||
struct Usage {
|
||||
lifetime: Lifetime,
|
||||
in_where_predicate: bool,
|
||||
in_bounded_ty: bool,
|
||||
in_generics_arg: bool,
|
||||
}
|
||||
|
||||
|
@ -490,11 +492,15 @@ struct LifetimeChecker<'cx, 'tcx, F> {
|
|||
cx: &'cx LateContext<'tcx>,
|
||||
map: FxIndexMap<LocalDefId, Vec<Usage>>,
|
||||
where_predicate_depth: usize,
|
||||
bounded_ty_depth: usize,
|
||||
generic_args_depth: usize,
|
||||
phantom: std::marker::PhantomData<F>,
|
||||
}
|
||||
|
||||
impl<'cx, 'tcx, F> LifetimeChecker<'cx, 'tcx, F> {
|
||||
impl<'cx, 'tcx, F> LifetimeChecker<'cx, 'tcx, F>
|
||||
where
|
||||
F: NestedFilter<'tcx>,
|
||||
{
|
||||
fn new(cx: &'cx LateContext<'tcx>, generics: &'tcx Generics<'_>) -> LifetimeChecker<'cx, 'tcx, F> {
|
||||
let map = generics
|
||||
.params
|
||||
|
@ -510,10 +516,30 @@ impl<'cx, 'tcx, F> LifetimeChecker<'cx, 'tcx, F> {
|
|||
cx,
|
||||
map,
|
||||
where_predicate_depth: 0,
|
||||
bounded_ty_depth: 0,
|
||||
generic_args_depth: 0,
|
||||
phantom: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
// `visit_where_bound_predicate` is based on:
|
||||
// https://github.com/rust-lang/rust/blob/864cee3ea383cc8254ba394ba355e648faa9cfa5/compiler/rustc_hir/src/intravisit.rs#L936-L939
|
||||
fn visit_where_bound_predicate(
|
||||
&mut self,
|
||||
hir_id: HirId,
|
||||
bounded_ty: &'tcx Ty<'tcx>,
|
||||
bounds: &'tcx [GenericBound<'tcx>],
|
||||
bound_generic_params: &'tcx [GenericParam<'tcx>],
|
||||
) {
|
||||
try_visit!(self.visit_id(hir_id));
|
||||
|
||||
self.bounded_ty_depth += 1;
|
||||
try_visit!(self.visit_ty(bounded_ty));
|
||||
self.bounded_ty_depth -= 1;
|
||||
|
||||
walk_list!(self, visit_param_bound, bounds);
|
||||
walk_list!(self, visit_generic_param, bound_generic_params);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, F> Visitor<'tcx> for LifetimeChecker<'_, 'tcx, F>
|
||||
|
@ -531,6 +557,7 @@ where
|
|||
usages.push(Usage {
|
||||
lifetime: *lifetime,
|
||||
in_where_predicate: self.where_predicate_depth != 0,
|
||||
in_bounded_ty: self.bounded_ty_depth != 0,
|
||||
in_generics_arg: self.generic_args_depth != 0,
|
||||
});
|
||||
}
|
||||
|
@ -538,7 +565,19 @@ where
|
|||
|
||||
fn visit_where_predicate(&mut self, predicate: &'tcx WherePredicate<'tcx>) {
|
||||
self.where_predicate_depth += 1;
|
||||
walk_where_predicate(self, predicate);
|
||||
if let &WherePredicate::BoundPredicate(WhereBoundPredicate {
|
||||
hir_id,
|
||||
bounded_ty,
|
||||
bounds,
|
||||
bound_generic_params,
|
||||
origin: _,
|
||||
span: _,
|
||||
}) = predicate
|
||||
{
|
||||
self.visit_where_bound_predicate(hir_id, bounded_ty, bounds, bound_generic_params);
|
||||
} else {
|
||||
walk_where_predicate(self, predicate);
|
||||
}
|
||||
self.where_predicate_depth -= 1;
|
||||
}
|
||||
|
||||
|
@ -562,7 +601,7 @@ fn report_extra_lifetimes<'tcx>(cx: &LateContext<'tcx>, func: &'tcx FnDecl<'_>,
|
|||
for (def_id, usages) in checker.map {
|
||||
if usages
|
||||
.iter()
|
||||
.all(|usage| usage.in_where_predicate && !usage.in_generics_arg)
|
||||
.all(|usage| usage.in_where_predicate && !usage.in_bounded_ty && !usage.in_generics_arg)
|
||||
{
|
||||
span_lint(
|
||||
cx,
|
||||
|
@ -589,7 +628,7 @@ fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<'
|
|||
for (&def_id, usages) in &checker.map {
|
||||
if usages
|
||||
.iter()
|
||||
.all(|usage| usage.in_where_predicate && !usage.in_generics_arg)
|
||||
.all(|usage| usage.in_where_predicate && !usage.in_bounded_ty && !usage.in_generics_arg)
|
||||
{
|
||||
span_lint(
|
||||
cx,
|
||||
|
@ -605,8 +644,8 @@ fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<'
|
|||
|
||||
// An `impl` lifetime is elidable if it satisfies the following conditions:
|
||||
// - It is used exactly once.
|
||||
// - That single use is not in `GenericArgs` in a `WherePredicate`. (Note that `GenericArgs` are
|
||||
// different from `GenericParam`s.)
|
||||
// - That single use is not in a bounded type or `GenericArgs` in a `WherePredicate`. (Note that
|
||||
// `GenericArgs` are different from `GenericParam`s.)
|
||||
fn report_elidable_impl_lifetimes<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
impl_: &'tcx Impl<'_>,
|
||||
|
@ -623,6 +662,7 @@ fn report_elidable_impl_lifetimes<'tcx>(
|
|||
}
|
||||
| Usage {
|
||||
lifetime,
|
||||
in_bounded_ty: false,
|
||||
in_generics_arg: false,
|
||||
..
|
||||
},
|
||||
|
|
|
@ -134,4 +134,11 @@ struct Human<'a> {
|
|||
pub name: &'a str,
|
||||
}
|
||||
|
||||
// https://github.com/rust-lang/rust-clippy/issues/13578
|
||||
mod issue_13578 {
|
||||
pub trait Foo {}
|
||||
|
||||
impl<'a, T: 'a> Foo for Option<T> where &'a T: Foo {}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
Loading…
Add table
Reference in a new issue