From 478555d468d54105a0202220b7632b08a992b9be Mon Sep 17 00:00:00 2001 From: John Kelly Date: Sun, 30 Apr 2023 13:16:04 +0100 Subject: [PATCH] wip --- clippy_lints/src/trait_bounds.rs | 45 +++++++++++++++++++++++-- tests/ui/trait_duplication_in_bounds.rs | 8 +++++ 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index b5f11b4ac..13651c978 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -9,7 +9,7 @@ use rustc_data_structures::unhash::UnhashMap; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::{ - GenericArg, GenericBound, Generics, Item, ItemKind, Node, Path, PathSegment, PredicateOrigin, QPath, + GenericArg, GenericBound, Generics, Item, ItemKind, MutTy, Node, Path, PathSegment, PredicateOrigin, QPath, TraitBoundModifier, TraitItem, TraitRef, Ty, TyKind, WherePredicate, }; use rustc_lint::{LateContext, LateLintPass}; @@ -37,12 +37,12 @@ declare_clippy_lint! { #[clippy::version = "1.38.0"] pub TYPE_REPETITION_IN_BOUNDS, nursery, - "types are repeated unnecessary in trait bounds use `+` instead of using `T: _, T: _`" + "types are repeated unnecessarily in trait bounds, use `+` instead of using `T: _, T: _`" } declare_clippy_lint! { /// ### What it does - /// Checks for cases where generics are being used and multiple + /// Checks for cases where generics or trait objects are being used and multiple /// syntax specifications for trait bounds are used simultaneously. /// /// ### Why is this bad? @@ -167,6 +167,45 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds { } } } + + fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>) { + let TyKind::Ref( + .., + MutTy { + ty: Ty { + kind: TyKind::TraitObject( + bounds, + .. + ), + .. + }, + .. + } + ) = ty.kind else { return; }; + + if bounds.len() < 2 { + return; + } + + let mut seen_def_ids = FxHashSet::default(); + + for bound in bounds.iter() { + let Some(def_id) = bound.trait_ref.trait_def_id() else { continue; }; + + let already_seen = !seen_def_ids.insert(def_id); + + if already_seen { + span_lint_and_help( + cx, + TRAIT_DUPLICATION_IN_BOUNDS, + bound.span, + "this trait bound is already specified in trait declaration", + None, + "consider removing this trait bound", + ); + } + } + } } impl TraitBounds { diff --git a/tests/ui/trait_duplication_in_bounds.rs b/tests/ui/trait_duplication_in_bounds.rs index a7a1caf28..f4f4a9fcb 100644 --- a/tests/ui/trait_duplication_in_bounds.rs +++ b/tests/ui/trait_duplication_in_bounds.rs @@ -109,4 +109,12 @@ fn qualified_path(arg0: T) { unimplemented!(); } +fn good_trait_object(arg0: &(dyn Any + Send)) { + unimplemented!(); +} + +fn bad_trait_object(arg0: &(dyn Any + Send + Send)) { + unimplemented!(); +} + fn main() {}