diff options
| -rw-r--r-- | clippy_lints/src/implied_bounds_in_impls.rs | 58 |
1 files changed, 35 insertions, 23 deletions
diff --git a/clippy_lints/src/implied_bounds_in_impls.rs b/clippy_lints/src/implied_bounds_in_impls.rs index 3527a39e2da..cc6ece45fcd 100644 --- a/clippy_lints/src/implied_bounds_in_impls.rs +++ b/clippy_lints/src/implied_bounds_in_impls.rs @@ -61,7 +61,7 @@ fn emit_lint( implied_bindings: &[rustc_hir::TypeBinding<'_>], bound: &ImplTraitBound<'_>, ) { - let implied_by = snippet(cx, bound.impl_trait_bound_span, ".."); + let implied_by = snippet(cx, bound.span, ".."); span_lint_and_then( cx, @@ -101,7 +101,7 @@ fn emit_lint( ([.., arg], [.., binding]) => arg.span().max(binding.span).shrink_to_hi(), ([.., arg], []) => arg.span().shrink_to_hi(), ([], [.., binding]) => binding.span.shrink_to_hi(), - ([], []) => bound.impl_trait_bound_span.shrink_to_hi(), + ([], []) => bound.span.shrink_to_hi(), }; let mut associated_tys_sugg = if needs_angle_brackets { @@ -223,8 +223,9 @@ fn is_same_generics<'tcx>( struct ImplTraitBound<'tcx> { /// The span of the bound in the `impl Trait` type - impl_trait_bound_span: Span, - /// The predicates defined in the trait referenced by this bound + span: Span, + /// The predicates defined in the trait referenced by this bound. This also contains the actual + /// supertrait bounds predicates: &'tcx [(ty::Clause<'tcx>, Span)], /// The `DefId` of the trait being referenced by this bound trait_def_id: DefId, @@ -257,7 +258,7 @@ fn collect_supertrait_bounds<'tcx>(cx: &LateContext<'tcx>, opaque_ty: &OpaqueTy< args: path.args.map_or([].as_slice(), |p| p.args), bindings: path.args.map_or([].as_slice(), |p| p.bindings), trait_def_id, - impl_trait_bound_span: bound.span(), + span: bound.span(), }) } else { None @@ -266,6 +267,34 @@ fn collect_supertrait_bounds<'tcx>(cx: &LateContext<'tcx>, opaque_ty: &OpaqueTy< .collect() } +/// Given a bound in an `impl Trait` type, looks for a trait in the set of supertraits (previously +/// collected in [`collect_supertrait_bounds`]) that matches (same trait and generic arguments). +fn find_bound_in_supertraits<'a, 'tcx>( + cx: &LateContext<'tcx>, + trait_def_id: DefId, + args: &'tcx [GenericArg<'tcx>], + bounds: &'a [ImplTraitBound<'tcx>], +) -> Option<&'a ImplTraitBound<'tcx>> { + bounds.iter().find(|bound| { + bound.predicates.iter().any(|(clause, _)| { + if let ClauseKind::Trait(tr) = clause.kind().skip_binder() + && tr.def_id() == trait_def_id + { + is_same_generics( + cx.tcx, + tr.trait_ref.args, + bound.args, + args, + bound.trait_def_id, + trait_def_id, + ) + } else { + false + } + }) + }) +} + fn check(cx: &LateContext<'_>, decl: &FnDecl<'_>) { if let FnRetTy::Return(ty) = decl.output && let TyKind::OpaqueDef(item_id, ..) = ty.kind @@ -287,24 +316,7 @@ fn check(cx: &LateContext<'_>, decl: &FnDecl<'_>) { && let implied_args = path.args.map_or([].as_slice(), |a| a.args) && let implied_bindings = path.args.map_or([].as_slice(), |a| a.bindings) && let Some(def_id) = poly_trait.trait_ref.path.res.opt_def_id() - && let Some(bound) = supertraits.iter().find(|bound| { - bound.predicates.iter().any(|(clause, _)| { - if let ClauseKind::Trait(tr) = clause.kind().skip_binder() - && tr.def_id() == def_id - { - is_same_generics( - cx.tcx, - tr.trait_ref.args, - bound.args, - implied_args, - bound.trait_def_id, - def_id, - ) - } else { - false - } - }) - }) + && let Some(bound) = find_bound_in_supertraits(cx, def_id, implied_args, &supertraits) { emit_lint(cx, poly_trait, opaque_ty, index, implied_bindings, bound); } |
