diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2021-12-23 00:28:51 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-12-23 00:28:51 +0100 |
| commit | d8bf974df56618f75ecd38d7e61fe0d720a9c8c4 (patch) | |
| tree | 40d4887860b696d494c84ff87e014ba8d6806a36 | |
| parent | 60625a6ef0ef57a2934918430be0121431ba96c9 (diff) | |
| parent | 0198ea47d8f0a9d99820f9a3c168ab3d26fd4f2a (diff) | |
| download | rust-d8bf974df56618f75ecd38d7e61fe0d720a9c8c4.tar.gz rust-d8bf974df56618f75ecd38d7e61fe0d720a9c8c4.zip | |
Rollup merge of #91544 - rukai:91492, r=wesleywiser
Fix duplicate derive clone suggestion closes https://github.com/rust-lang/rust/issues/91492 The addition of: ```rust derives.sort(); derives.dedup(); ``` is what actually solves the problem. The rest is just cleanup. I want to improve the diagnostic message to provide the suggestion as a proper diff but ran into some problems, so I'll attempt that again in a follow up PR.
| -rw-r--r-- | compiler/rustc_typeck/src/check/method/suggest.rs | 33 | ||||
| -rw-r--r-- | src/test/ui/derives/issue-91492.rs | 25 | ||||
| -rw-r--r-- | src/test/ui/derives/issue-91492.stderr | 54 |
3 files changed, 96 insertions, 16 deletions
diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index d5a4de86d4d..f3a5fbbb444 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -1195,11 +1195,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn suggest_derive( &self, err: &mut DiagnosticBuilder<'_>, - unsatisfied_predicates: &Vec<( + unsatisfied_predicates: &[( ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>, Option<ObligationCause<'tcx>>, - )>, + )], ) { let mut derives = Vec::<(String, Span, String)>::new(); let mut traits = Vec::<Span>::new(); @@ -1236,23 +1236,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { traits.push(self.tcx.def_span(trait_pred.def_id())); } } - derives.sort(); - let derives_grouped = derives.into_iter().fold( - Vec::<(String, Span, String)>::new(), - |mut acc, (self_name, self_span, trait_name)| { - if let Some((acc_self_name, _, ref mut traits)) = acc.last_mut() { - if acc_self_name == &self_name { - traits.push_str(format!(", {}", trait_name).as_str()); - return acc; - } - } - acc.push((self_name, self_span, trait_name)); - acc - }, - ); traits.sort(); traits.dedup(); + derives.sort(); + derives.dedup(); + + let mut derives_grouped = Vec::<(String, Span, String)>::new(); + for (self_name, self_span, trait_name) in derives.into_iter() { + if let Some((last_self_name, _, ref mut last_trait_names)) = derives_grouped.last_mut() + { + if last_self_name == &self_name { + last_trait_names.push_str(format!(", {}", trait_name).as_str()); + continue; + } + } + derives_grouped.push((self_name, self_span, trait_name)); + } + let len = traits.len(); if len > 0 { let span: MultiSpan = traits.into(); diff --git a/src/test/ui/derives/issue-91492.rs b/src/test/ui/derives/issue-91492.rs new file mode 100644 index 00000000000..df792f118ab --- /dev/null +++ b/src/test/ui/derives/issue-91492.rs @@ -0,0 +1,25 @@ +// Reproduce the issue with vec +pub struct NoDerives; +fn fun1(foo: &mut Vec<NoDerives>, bar: &[NoDerives]) { + foo.extend_from_slice(bar); //~ ERROR +} + +// Reproduce the issue with vec +// and demonstrate that other derives are ignored in the suggested output +#[derive(Default, PartialEq)] +pub struct SomeDerives; +fn fun2(foo: &mut Vec<SomeDerives>, bar: &[SomeDerives]) { + foo.extend_from_slice(bar); //~ ERROR +} + +// Try and fail to reproduce the issue without vec. +// No idea why it doesnt reproduce the issue but its still a useful test case. +struct Object<T, A>(T, A); +impl<T: Clone, A: Default> Object<T, A> { + fn use_clone(&self) {} +} +fn fun3(foo: Object<NoDerives, SomeDerives>) { + foo.use_clone(); //~ ERROR +} + +fn main() {} diff --git a/src/test/ui/derives/issue-91492.stderr b/src/test/ui/derives/issue-91492.stderr new file mode 100644 index 00000000000..73c91154a7b --- /dev/null +++ b/src/test/ui/derives/issue-91492.stderr @@ -0,0 +1,54 @@ +error[E0599]: the method `extend_from_slice` exists for mutable reference `&mut Vec<NoDerives>`, but its trait bounds were not satisfied + --> $DIR/issue-91492.rs:4:9 + | +LL | pub struct NoDerives; + | --------------------- doesn't satisfy `NoDerives: Clone` +LL | fn fun1(foo: &mut Vec<NoDerives>, bar: &[NoDerives]) { +LL | foo.extend_from_slice(bar); + | ^^^^^^^^^^^^^^^^^ + | + = note: the following trait bounds were not satisfied: + `NoDerives: Clone` +help: consider annotating `NoDerives` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | + +error[E0599]: the method `extend_from_slice` exists for mutable reference `&mut Vec<SomeDerives>`, but its trait bounds were not satisfied + --> $DIR/issue-91492.rs:12:9 + | +LL | pub struct SomeDerives; + | ----------------------- doesn't satisfy `SomeDerives: Clone` +LL | fn fun2(foo: &mut Vec<SomeDerives>, bar: &[SomeDerives]) { +LL | foo.extend_from_slice(bar); + | ^^^^^^^^^^^^^^^^^ + | + = note: the following trait bounds were not satisfied: + `SomeDerives: Clone` +help: consider annotating `SomeDerives` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | + +error[E0599]: the method `use_clone` exists for struct `Object<NoDerives, SomeDerives>`, but its trait bounds were not satisfied + --> $DIR/issue-91492.rs:22:9 + | +LL | pub struct NoDerives; + | --------------------- doesn't satisfy `NoDerives: Clone` +... +LL | struct Object<T, A>(T, A); + | -------------------------- method `use_clone` not found for this +... +LL | foo.use_clone(); + | ^^^^^^^^^ method cannot be called on `Object<NoDerives, SomeDerives>` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `NoDerives: Clone` +help: consider annotating `NoDerives` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0599`. |
