Skip to content

Commit f51aade

Browse files
committed
Auto merge of rust-lang#9397 - Jarcho:trait_dup_order, r=dswij
Fix the emission order of `trait_duplication_in_bounds` Makes the lint emit in source order rather than whatever order the hash map happens to be in. This is currently blocking the sync into rustc. changelog: None
2 parents 09e4659 + 19ef04f commit f51aade

4 files changed

+33
-17
lines changed

clippy_lints/src/trait_bounds.rs

+25-9
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use rustc_hir::{
1515
use rustc_lint::{LateContext, LateLintPass};
1616
use rustc_session::{declare_tool_lint, impl_lint_pass};
1717
use rustc_span::{BytePos, Span};
18+
use std::collections::hash_map::Entry;
1819

1920
declare_clippy_lint! {
2021
/// ### What it does
@@ -255,7 +256,7 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
255256
then {
256257
return Some(
257258
rollup_traits(cx, bound_predicate.bounds, "these where clauses contain repeated elements")
258-
.into_keys().map(|trait_ref| (path.res, trait_ref)))
259+
.into_iter().map(|(trait_ref, _)| (path.res, trait_ref)))
259260
}
260261
}
261262
None
@@ -295,8 +296,13 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
295296
}
296297
}
297298

298-
#[derive(PartialEq, Eq, Hash, Debug)]
299+
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
299300
struct ComparableTraitRef(Res, Vec<Res>);
301+
impl Default for ComparableTraitRef {
302+
fn default() -> Self {
303+
Self(Res::Err, Vec::new())
304+
}
305+
}
300306

301307
fn get_trait_info_from_bound<'a>(bound: &'a GenericBound<'_>) -> Option<(Res, &'a [PathSegment<'a>], Span)> {
302308
if let GenericBound::Trait(t, tbm) = bound {
@@ -339,7 +345,7 @@ fn into_comparable_trait_ref(trait_ref: &TraitRef<'_>) -> ComparableTraitRef {
339345
)
340346
}
341347

342-
fn rollup_traits(cx: &LateContext<'_>, bounds: &[GenericBound<'_>], msg: &str) -> FxHashMap<ComparableTraitRef, Span> {
348+
fn rollup_traits(cx: &LateContext<'_>, bounds: &[GenericBound<'_>], msg: &str) -> Vec<(ComparableTraitRef, Span)> {
343349
let mut map = FxHashMap::default();
344350
let mut repeated_res = false;
345351

@@ -351,23 +357,33 @@ fn rollup_traits(cx: &LateContext<'_>, bounds: &[GenericBound<'_>], msg: &str) -
351357
}
352358
};
353359

360+
let mut i = 0usize;
354361
for bound in bounds.iter().filter_map(only_comparable_trait_refs) {
355362
let (comparable_bound, span_direct) = bound;
356-
if map.insert(comparable_bound, span_direct).is_some() {
357-
repeated_res = true;
363+
match map.entry(comparable_bound) {
364+
Entry::Occupied(_) => repeated_res = true,
365+
Entry::Vacant(e) => {
366+
e.insert((span_direct, i));
367+
i += 1;
368+
},
358369
}
359370
}
360371

372+
// Put bounds in source order
373+
let mut comparable_bounds = vec![Default::default(); map.len()];
374+
for (k, (v, i)) in map {
375+
comparable_bounds[i] = (k, v);
376+
}
377+
361378
if_chain! {
362379
if repeated_res;
363380
if let [first_trait, .., last_trait] = bounds;
364381
then {
365382
let all_trait_span = first_trait.span().to(last_trait.span());
366383

367-
let mut traits = map.values()
368-
.filter_map(|span| snippet_opt(cx, *span))
384+
let traits = comparable_bounds.iter()
385+
.filter_map(|&(_, span)| snippet_opt(cx, span))
369386
.collect::<Vec<_>>();
370-
traits.sort_unstable();
371387
let traits = traits.join(" + ");
372388

373389
span_lint_and_sugg(
@@ -382,5 +398,5 @@ fn rollup_traits(cx: &LateContext<'_>, bounds: &[GenericBound<'_>], msg: &str) -
382398
}
383399
}
384400

385-
map
401+
comparable_bounds
386402
}

tests/ui/trait_duplication_in_bounds.fixed

+2-2
Original file line numberDiff line numberDiff line change
@@ -97,15 +97,15 @@ fn good_generic<T: GenericTrait<u64> + GenericTrait<u32>>(arg0: T) {
9797
unimplemented!();
9898
}
9999

100-
fn bad_generic<T: GenericTrait<u32> + GenericTrait<u64>>(arg0: T) {
100+
fn bad_generic<T: GenericTrait<u64> + GenericTrait<u32>>(arg0: T) {
101101
unimplemented!();
102102
}
103103

104104
mod foo {
105105
pub trait Clone {}
106106
}
107107

108-
fn qualified_path<T: Clone + foo::Clone>(arg0: T) {
108+
fn qualified_path<T: std::clone::Clone + foo::Clone>(arg0: T) {
109109
unimplemented!();
110110
}
111111

tests/ui/trait_duplication_in_bounds.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,13 @@ error: these bounds contain repeated elements
4444
--> $DIR/trait_duplication_in_bounds.rs:100:19
4545
|
4646
LL | fn bad_generic<T: GenericTrait<u64> + GenericTrait<u32> + GenericTrait<u64>>(arg0: T) {
47-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `GenericTrait<u32> + GenericTrait<u64>`
47+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `GenericTrait<u64> + GenericTrait<u32>`
4848

4949
error: these bounds contain repeated elements
5050
--> $DIR/trait_duplication_in_bounds.rs:108:22
5151
|
5252
LL | fn qualified_path<T: std::clone::Clone + Clone + foo::Clone>(arg0: T) {
53-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + foo::Clone`
53+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::clone::Clone + foo::Clone`
5454

5555
error: aborting due to 8 previous errors
5656

tests/ui/trait_duplication_in_bounds_unfixable.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error: this trait bound is already specified in the where clause
2-
--> $DIR/trait_duplication_in_bounds_unfixable.rs:6:23
2+
--> $DIR/trait_duplication_in_bounds_unfixable.rs:6:15
33
|
44
LL | fn bad_foo<T: Clone + Default, Z: Copy>(arg0: T, arg1: Z)
5-
| ^^^^^^^
5+
| ^^^^^
66
|
77
note: the lint level is defined here
88
--> $DIR/trait_duplication_in_bounds_unfixable.rs:1:9
@@ -12,10 +12,10 @@ LL | #![deny(clippy::trait_duplication_in_bounds)]
1212
= help: consider removing this trait bound
1313

1414
error: this trait bound is already specified in the where clause
15-
--> $DIR/trait_duplication_in_bounds_unfixable.rs:6:15
15+
--> $DIR/trait_duplication_in_bounds_unfixable.rs:6:23
1616
|
1717
LL | fn bad_foo<T: Clone + Default, Z: Copy>(arg0: T, arg1: Z)
18-
| ^^^^^
18+
| ^^^^^^^
1919
|
2020
= help: consider removing this trait bound
2121

0 commit comments

Comments
 (0)