Skip to content

Commit 0198ea4

Browse files
committed
Fix duplicate derive clone suggestion
1 parent 14c1e71 commit 0198ea4

File tree

3 files changed

+96
-16
lines changed

3 files changed

+96
-16
lines changed

compiler/rustc_typeck/src/check/method/suggest.rs

+17-16
Original file line numberDiff line numberDiff line change
@@ -1175,11 +1175,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11751175
fn suggest_derive(
11761176
&self,
11771177
err: &mut DiagnosticBuilder<'_>,
1178-
unsatisfied_predicates: &Vec<(
1178+
unsatisfied_predicates: &[(
11791179
ty::Predicate<'tcx>,
11801180
Option<ty::Predicate<'tcx>>,
11811181
Option<ObligationCause<'tcx>>,
1182-
)>,
1182+
)],
11831183
) {
11841184
let mut derives = Vec::<(String, Span, String)>::new();
11851185
let mut traits = Vec::<Span>::new();
@@ -1216,23 +1216,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12161216
traits.push(self.tcx.def_span(trait_pred.def_id()));
12171217
}
12181218
}
1219-
derives.sort();
1220-
let derives_grouped = derives.into_iter().fold(
1221-
Vec::<(String, Span, String)>::new(),
1222-
|mut acc, (self_name, self_span, trait_name)| {
1223-
if let Some((acc_self_name, _, ref mut traits)) = acc.last_mut() {
1224-
if acc_self_name == &self_name {
1225-
traits.push_str(format!(", {}", trait_name).as_str());
1226-
return acc;
1227-
}
1228-
}
1229-
acc.push((self_name, self_span, trait_name));
1230-
acc
1231-
},
1232-
);
12331219
traits.sort();
12341220
traits.dedup();
12351221

1222+
derives.sort();
1223+
derives.dedup();
1224+
1225+
let mut derives_grouped = Vec::<(String, Span, String)>::new();
1226+
for (self_name, self_span, trait_name) in derives.into_iter() {
1227+
if let Some((last_self_name, _, ref mut last_trait_names)) = derives_grouped.last_mut()
1228+
{
1229+
if last_self_name == &self_name {
1230+
last_trait_names.push_str(format!(", {}", trait_name).as_str());
1231+
continue;
1232+
}
1233+
}
1234+
derives_grouped.push((self_name, self_span, trait_name));
1235+
}
1236+
12361237
let len = traits.len();
12371238
if len > 0 {
12381239
let span: MultiSpan = traits.into();

src/test/ui/derives/issue-91492.rs

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Reproduce the issue with vec
2+
pub struct NoDerives;
3+
fn fun1(foo: &mut Vec<NoDerives>, bar: &[NoDerives]) {
4+
foo.extend_from_slice(bar); //~ ERROR
5+
}
6+
7+
// Reproduce the issue with vec
8+
// and demonstrate that other derives are ignored in the suggested output
9+
#[derive(Default, PartialEq)]
10+
pub struct SomeDerives;
11+
fn fun2(foo: &mut Vec<SomeDerives>, bar: &[SomeDerives]) {
12+
foo.extend_from_slice(bar); //~ ERROR
13+
}
14+
15+
// Try and fail to reproduce the issue without vec.
16+
// No idea why it doesnt reproduce the issue but its still a useful test case.
17+
struct Object<T, A>(T, A);
18+
impl<T: Clone, A: Default> Object<T, A> {
19+
fn use_clone(&self) {}
20+
}
21+
fn fun3(foo: Object<NoDerives, SomeDerives>) {
22+
foo.use_clone(); //~ ERROR
23+
}
24+
25+
fn main() {}
+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
error[E0599]: the method `extend_from_slice` exists for mutable reference `&mut Vec<NoDerives>`, but its trait bounds were not satisfied
2+
--> $DIR/issue-91492.rs:4:9
3+
|
4+
LL | pub struct NoDerives;
5+
| --------------------- doesn't satisfy `NoDerives: Clone`
6+
LL | fn fun1(foo: &mut Vec<NoDerives>, bar: &[NoDerives]) {
7+
LL | foo.extend_from_slice(bar);
8+
| ^^^^^^^^^^^^^^^^^
9+
|
10+
= note: the following trait bounds were not satisfied:
11+
`NoDerives: Clone`
12+
help: consider annotating `NoDerives` with `#[derive(Clone)]`
13+
|
14+
LL | #[derive(Clone)]
15+
|
16+
17+
error[E0599]: the method `extend_from_slice` exists for mutable reference `&mut Vec<SomeDerives>`, but its trait bounds were not satisfied
18+
--> $DIR/issue-91492.rs:12:9
19+
|
20+
LL | pub struct SomeDerives;
21+
| ----------------------- doesn't satisfy `SomeDerives: Clone`
22+
LL | fn fun2(foo: &mut Vec<SomeDerives>, bar: &[SomeDerives]) {
23+
LL | foo.extend_from_slice(bar);
24+
| ^^^^^^^^^^^^^^^^^
25+
|
26+
= note: the following trait bounds were not satisfied:
27+
`SomeDerives: Clone`
28+
help: consider annotating `SomeDerives` with `#[derive(Clone)]`
29+
|
30+
LL | #[derive(Clone)]
31+
|
32+
33+
error[E0599]: the method `use_clone` exists for struct `Object<NoDerives, SomeDerives>`, but its trait bounds were not satisfied
34+
--> $DIR/issue-91492.rs:22:9
35+
|
36+
LL | pub struct NoDerives;
37+
| --------------------- doesn't satisfy `NoDerives: Clone`
38+
...
39+
LL | struct Object<T, A>(T, A);
40+
| -------------------------- method `use_clone` not found for this
41+
...
42+
LL | foo.use_clone();
43+
| ^^^^^^^^^ method cannot be called on `Object<NoDerives, SomeDerives>` due to unsatisfied trait bounds
44+
|
45+
= note: the following trait bounds were not satisfied:
46+
`NoDerives: Clone`
47+
help: consider annotating `NoDerives` with `#[derive(Clone)]`
48+
|
49+
LL | #[derive(Clone)]
50+
|
51+
52+
error: aborting due to 3 previous errors
53+
54+
For more information about this error, try `rustc --explain E0599`.

0 commit comments

Comments
 (0)