From 3c6ae00204456dd08dc09e707f8e8e070e5b5694 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Thu, 2 Oct 2025 22:14:11 +0000 Subject: [PATCH] Make diagnostics clearer for binop-related errors in foreign crates Fixes redundant language and bad grammar. --- .../rustc_hir_typeck/src/method/suggest.rs | 52 +++++-------------- tests/ui/array-slice-vec/vec-res-add.stderr | 4 +- .../autoderef-box-no-add.stderr | 8 +-- .../binary-op-not-allowed-issue-125631.stderr | 26 +++++----- tests/ui/binop/binop-bitxor-str.stderr | 4 +- tests/ui/error-codes/E0067.stderr | 4 +- .../box-arithmetic-14915.stderr | 4 +- tests/ui/pattern/pattern-tyvar-2.stderr | 4 +- .../ui/typeck/assign-non-lval-derefmut.stderr | 8 +-- tests/ui/typeck/minus-string.stderr | 4 +- 10 files changed, 47 insertions(+), 71 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 44602e6289940..0954a768c11fa 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -2985,46 +2985,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } foreign_preds.sort_by_key(|pred: &&ty::TraitPredicate<'_>| pred.trait_ref.to_string()); - let foreign_def_ids = foreign_preds - .iter() - .filter_map(|pred| match pred.self_ty().kind() { - ty::Adt(def, _) => Some(def.did()), - _ => None, - }) - .collect::>(); - let mut foreign_spans: MultiSpan = foreign_def_ids - .iter() - .filter_map(|def_id| { - let span = self.tcx.def_span(*def_id); - if span.is_dummy() { None } else { Some(span) } - }) - .collect::>() - .into(); - for pred in &foreign_preds { - if let ty::Adt(def, _) = pred.self_ty().kind() { - foreign_spans.push_span_label( - self.tcx.def_span(def.did()), - format!("not implement `{}`", pred.trait_ref.print_trait_sugared()), - ); + + for pred in foreign_preds { + let ty = pred.self_ty(); + let ty::Adt(def, _) = ty.kind() else { continue }; + let span = self.tcx.def_span(def.did()); + if span.is_dummy() { + continue; } - } - if foreign_spans.primary_span().is_some() { - let msg = if let [foreign_pred] = foreign_preds.as_slice() { - format!( - "the foreign item type `{}` doesn't implement `{}`", - foreign_pred.self_ty(), - foreign_pred.trait_ref.print_trait_sugared() - ) - } else { - format!( - "the foreign item type{} {} implement required trait{} for this \ - operation to be valid", - pluralize!(foreign_def_ids.len()), - if foreign_def_ids.len() > 1 { "don't" } else { "doesn't" }, - pluralize!(foreign_preds.len()), - ) - }; - err.span_note(foreign_spans, msg); + let mut mspan: MultiSpan = span.into(); + mspan.push_span_label(span, format!("`{ty}` is defined in another crate")); + err.span_note( + mspan, + format!("`{ty}` does not implement `{}`", pred.trait_ref.print_trait_sugared()), + ); } let preds: Vec<_> = errors diff --git a/tests/ui/array-slice-vec/vec-res-add.stderr b/tests/ui/array-slice-vec/vec-res-add.stderr index 34fd69426a8bb..4e13dbd0366d0 100644 --- a/tests/ui/array-slice-vec/vec-res-add.stderr +++ b/tests/ui/array-slice-vec/vec-res-add.stderr @@ -6,10 +6,10 @@ LL | let k = i + j; | | | Vec | -note: the foreign item type `Vec` doesn't implement `Add` +note: `Vec` does not implement `Add` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL | - = note: not implement `Add` + = note: `Vec` is defined in another crate error: aborting due to 1 previous error diff --git a/tests/ui/autoref-autoderef/autoderef-box-no-add.stderr b/tests/ui/autoref-autoderef/autoderef-box-no-add.stderr index 20ef3352831a4..d861d103bde4f 100644 --- a/tests/ui/autoref-autoderef/autoderef-box-no-add.stderr +++ b/tests/ui/autoref-autoderef/autoderef-box-no-add.stderr @@ -6,11 +6,11 @@ LL | let z: isize = a.x + b.y; | | | Box | -note: the foreign item type `Box` doesn't implement `Add` +note: `Box` does not implement `Add` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL ::: $SRC_DIR/alloc/src/boxed.rs:LL:COL | - = note: not implement `Add` + = note: `Box` is defined in another crate error[E0369]: cannot add `Box` to `Box` --> $DIR/autoderef-box-no-add.rs:31:33 @@ -20,11 +20,11 @@ LL | let answer: isize = forty.a + two.a; | | | Box | -note: the foreign item type `Box` doesn't implement `Add` +note: `Box` does not implement `Add` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL ::: $SRC_DIR/alloc/src/boxed.rs:LL:COL | - = note: not implement `Add` + = note: `Box` is defined in another crate error: aborting due to 2 previous errors diff --git a/tests/ui/binop/binary-op-not-allowed-issue-125631.stderr b/tests/ui/binop/binary-op-not-allowed-issue-125631.stderr index 1cf75bbc1a570..d95876659c7ac 100644 --- a/tests/ui/binop/binary-op-not-allowed-issue-125631.stderr +++ b/tests/ui/binop/binary-op-not-allowed-issue-125631.stderr @@ -11,10 +11,10 @@ note: an implementation of `PartialEq` might be missing for `T1` | LL | struct T1; | ^^^^^^^^^ must implement `PartialEq` -note: the foreign item type `std::io::Error` doesn't implement `PartialEq` +note: `std::io::Error` does not implement `PartialEq` --> $SRC_DIR/std/src/io/error.rs:LL:COL | - = note: not implement `PartialEq` + = note: `std::io::Error` is defined in another crate help: consider annotating `T1` with `#[derive(PartialEq)]` | LL + #[derive(PartialEq)] @@ -29,13 +29,14 @@ LL | (Error::new(ErrorKind::Other, "2"), thread::current()) LL | == (Error::new(ErrorKind::Other, "2"), thread::current()); | ^^ ------------------------------------------------------ (std::io::Error, Thread) | -note: the foreign item types don't implement required traits for this operation to be valid - --> $SRC_DIR/std/src/io/error.rs:LL:COL - | - = note: not implement `PartialEq` +note: `Thread` does not implement `PartialEq` --> $SRC_DIR/std/src/thread/mod.rs:LL:COL | - = note: not implement `PartialEq` + = note: `Thread` is defined in another crate +note: `std::io::Error` does not implement `PartialEq` + --> $SRC_DIR/std/src/io/error.rs:LL:COL + | + = note: `std::io::Error` is defined in another crate error[E0369]: binary operation `==` cannot be applied to type `(std::io::Error, Thread, T1, T2)` --> $DIR/binary-op-not-allowed-issue-125631.rs:14:9 @@ -52,13 +53,14 @@ LL | struct T1; | ^^^^^^^^^ must implement `PartialEq` LL | struct T2; | ^^^^^^^^^ must implement `PartialEq` -note: the foreign item types don't implement required traits for this operation to be valid - --> $SRC_DIR/std/src/io/error.rs:LL:COL - | - = note: not implement `PartialEq` +note: `Thread` does not implement `PartialEq` --> $SRC_DIR/std/src/thread/mod.rs:LL:COL | - = note: not implement `PartialEq` + = note: `Thread` is defined in another crate +note: `std::io::Error` does not implement `PartialEq` + --> $SRC_DIR/std/src/io/error.rs:LL:COL + | + = note: `std::io::Error` is defined in another crate help: consider annotating `T1` with `#[derive(PartialEq)]` | LL + #[derive(PartialEq)] diff --git a/tests/ui/binop/binop-bitxor-str.stderr b/tests/ui/binop/binop-bitxor-str.stderr index d4bb0c17bfa78..014a41f9e3ac7 100644 --- a/tests/ui/binop/binop-bitxor-str.stderr +++ b/tests/ui/binop/binop-bitxor-str.stderr @@ -6,10 +6,10 @@ LL | fn main() { let x = "a".to_string() ^ "b".to_string(); } | | | String | -note: the foreign item type `String` doesn't implement `BitXor` +note: `String` does not implement `BitXor` --> $SRC_DIR/alloc/src/string.rs:LL:COL | - = note: not implement `BitXor` + = note: `String` is defined in another crate error: aborting due to 1 previous error diff --git a/tests/ui/error-codes/E0067.stderr b/tests/ui/error-codes/E0067.stderr index 71b7208054423..d350805da8340 100644 --- a/tests/ui/error-codes/E0067.stderr +++ b/tests/ui/error-codes/E0067.stderr @@ -6,11 +6,11 @@ LL | LinkedList::new() += 1; | | | cannot use `+=` on type `LinkedList<_>` | -note: the foreign item type `LinkedList<_>` doesn't implement `AddAssign<{integer}>` +note: `LinkedList<_>` does not implement `AddAssign<{integer}>` --> $SRC_DIR/alloc/src/collections/linked_list.rs:LL:COL ::: $SRC_DIR/alloc/src/collections/linked_list.rs:LL:COL | - = note: not implement `AddAssign<{integer}>` + = note: `LinkedList<_>` is defined in another crate error[E0067]: invalid left-hand side of assignment --> $DIR/E0067.rs:4:23 diff --git a/tests/ui/operator-recovery/box-arithmetic-14915.stderr b/tests/ui/operator-recovery/box-arithmetic-14915.stderr index 1dd80472bb875..5ff73fce2ff81 100644 --- a/tests/ui/operator-recovery/box-arithmetic-14915.stderr +++ b/tests/ui/operator-recovery/box-arithmetic-14915.stderr @@ -6,11 +6,11 @@ LL | println!("{}", x + 1); | | | Box | -note: the foreign item type `Box` doesn't implement `Add<{integer}>` +note: `Box` does not implement `Add<{integer}>` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL ::: $SRC_DIR/alloc/src/boxed.rs:LL:COL | - = note: not implement `Add<{integer}>` + = note: `Box` is defined in another crate error: aborting due to 1 previous error diff --git a/tests/ui/pattern/pattern-tyvar-2.stderr b/tests/ui/pattern/pattern-tyvar-2.stderr index be52fa8b23943..6676d5129872b 100644 --- a/tests/ui/pattern/pattern-tyvar-2.stderr +++ b/tests/ui/pattern/pattern-tyvar-2.stderr @@ -6,10 +6,10 @@ LL | fn foo(t: Bar) -> isize { match t { Bar::T1(_, Some(x)) => { return x * 3; | | | Vec | -note: the foreign item type `Vec` doesn't implement `Mul<{integer}>` +note: `Vec` does not implement `Mul<{integer}>` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL | - = note: not implement `Mul<{integer}>` + = note: `Vec` is defined in another crate error: aborting due to 1 previous error diff --git a/tests/ui/typeck/assign-non-lval-derefmut.stderr b/tests/ui/typeck/assign-non-lval-derefmut.stderr index f57b5abe2eedc..a0ba0eae1e443 100644 --- a/tests/ui/typeck/assign-non-lval-derefmut.stderr +++ b/tests/ui/typeck/assign-non-lval-derefmut.stderr @@ -19,10 +19,10 @@ LL | x.lock().unwrap() += 1; | | | cannot use `+=` on type `std::sync::MutexGuard<'_, usize>` | -note: the foreign item type `std::sync::MutexGuard<'_, usize>` doesn't implement `AddAssign<{integer}>` +note: `std::sync::MutexGuard<'_, usize>` does not implement `AddAssign<{integer}>` --> $SRC_DIR/std/src/sync/poison/mutex.rs:LL:COL | - = note: not implement `AddAssign<{integer}>` + = note: `std::sync::MutexGuard<'_, usize>` is defined in another crate help: `+=` can be used on `usize` if you dereference the left-hand side | LL | *x.lock().unwrap() += 1; @@ -51,10 +51,10 @@ LL | y += 1; | | | cannot use `+=` on type `std::sync::MutexGuard<'_, usize>` | -note: the foreign item type `std::sync::MutexGuard<'_, usize>` doesn't implement `AddAssign<{integer}>` +note: `std::sync::MutexGuard<'_, usize>` does not implement `AddAssign<{integer}>` --> $SRC_DIR/std/src/sync/poison/mutex.rs:LL:COL | - = note: not implement `AddAssign<{integer}>` + = note: `std::sync::MutexGuard<'_, usize>` is defined in another crate help: `+=` can be used on `usize` if you dereference the left-hand side | LL | *y += 1; diff --git a/tests/ui/typeck/minus-string.stderr b/tests/ui/typeck/minus-string.stderr index d2ebcd01ff9c1..fee723baff196 100644 --- a/tests/ui/typeck/minus-string.stderr +++ b/tests/ui/typeck/minus-string.stderr @@ -4,10 +4,10 @@ error[E0600]: cannot apply unary operator `-` to type `String` LL | -"foo".to_string(); | ^^^^^^^^^^^^^^^^^^ cannot apply unary operator `-` | -note: the foreign item type `String` doesn't implement `Neg` +note: `String` does not implement `Neg` --> $SRC_DIR/alloc/src/string.rs:LL:COL | - = note: not implement `Neg` + = note: `String` is defined in another crate error: aborting due to 1 previous error