diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index ca174ed5e8497..f0cc9d774645b 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -1175,11 +1175,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn suggest_derive( &self, err: &mut DiagnosticBuilder<'_>, - unsatisfied_predicates: &Vec<( + unsatisfied_predicates: &[( ty::Predicate<'tcx>, Option>, Option>, - )>, + )], ) { let mut derives = Vec::<(String, Span, String)>::new(); let mut traits = Vec::::new(); @@ -1216,23 +1216,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 0000000000000..df792f118ab76 --- /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, 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, 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); +impl Object { + fn use_clone(&self) {} +} +fn fun3(foo: Object) { + 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 0000000000000..73c91154a7bda --- /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`, 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, 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`, 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, 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`, 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); + | -------------------------- method `use_clone` not found for this +... +LL | foo.use_clone(); + | ^^^^^^^^^ method cannot be called on `Object` 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`.