Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 478555d

Browse files
committed
wip
1 parent 7bc3da9 commit 478555d

File tree

2 files changed

+50
-3
lines changed

2 files changed

+50
-3
lines changed

clippy_lints/src/trait_bounds.rs

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_data_structures::unhash::UnhashMap;
99
use rustc_errors::Applicability;
1010
use rustc_hir::def::Res;
1111
use rustc_hir::{
12-
GenericArg, GenericBound, Generics, Item, ItemKind, Node, Path, PathSegment, PredicateOrigin, QPath,
12+
GenericArg, GenericBound, Generics, Item, ItemKind, MutTy, Node, Path, PathSegment, PredicateOrigin, QPath,
1313
TraitBoundModifier, TraitItem, TraitRef, Ty, TyKind, WherePredicate,
1414
};
1515
use rustc_lint::{LateContext, LateLintPass};
@@ -37,12 +37,12 @@ declare_clippy_lint! {
3737
#[clippy::version = "1.38.0"]
3838
pub TYPE_REPETITION_IN_BOUNDS,
3939
nursery,
40-
"types are repeated unnecessary in trait bounds use `+` instead of using `T: _, T: _`"
40+
"types are repeated unnecessarily in trait bounds, use `+` instead of using `T: _, T: _`"
4141
}
4242

4343
declare_clippy_lint! {
4444
/// ### What it does
45-
/// Checks for cases where generics are being used and multiple
45+
/// Checks for cases where generics or trait objects are being used and multiple
4646
/// syntax specifications for trait bounds are used simultaneously.
4747
///
4848
/// ### Why is this bad?
@@ -167,6 +167,45 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds {
167167
}
168168
}
169169
}
170+
171+
fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>) {
172+
let TyKind::Ref(
173+
..,
174+
MutTy {
175+
ty: Ty {
176+
kind: TyKind::TraitObject(
177+
bounds,
178+
..
179+
),
180+
..
181+
},
182+
..
183+
}
184+
) = ty.kind else { return; };
185+
186+
if bounds.len() < 2 {
187+
return;
188+
}
189+
190+
let mut seen_def_ids = FxHashSet::default();
191+
192+
for bound in bounds.iter() {
193+
let Some(def_id) = bound.trait_ref.trait_def_id() else { continue; };
194+
195+
let already_seen = !seen_def_ids.insert(def_id);
196+
197+
if already_seen {
198+
span_lint_and_help(
199+
cx,
200+
TRAIT_DUPLICATION_IN_BOUNDS,
201+
bound.span,
202+
"this trait bound is already specified in trait declaration",
203+
None,
204+
"consider removing this trait bound",
205+
);
206+
}
207+
}
208+
}
170209
}
171210

172211
impl TraitBounds {

tests/ui/trait_duplication_in_bounds.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,4 +109,12 @@ fn qualified_path<T: std::clone::Clone + Clone + foo::Clone>(arg0: T) {
109109
unimplemented!();
110110
}
111111

112+
fn good_trait_object(arg0: &(dyn Any + Send)) {
113+
unimplemented!();
114+
}
115+
116+
fn bad_trait_object(arg0: &(dyn Any + Send + Send)) {
117+
unimplemented!();
118+
}
119+
112120
fn main() {}

0 commit comments

Comments
 (0)