Skip to content

Commit

Permalink
extract finding implied bound to separate function
Browse files Browse the repository at this point in the history
  • Loading branch information
y21 committed Feb 10, 2024
1 parent d1acbf5 commit a38f44c
Showing 1 changed file with 35 additions and 23 deletions.
58 changes: 35 additions & 23 deletions clippy_lints/src/implied_bounds_in_impls.rs
Expand Up @@ -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,
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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);
}
Expand Down

0 comments on commit a38f44c

Please sign in to comment.