Rollup merge of #126925 - surechen:fix_125631, r=compiler-errors
Change E0369 to give note informations for foreign items. Change E0369 to give note informations for foreign items. Make it easy for developers to understand why the binop cannot be applied. fixes #125631
This commit is contained in:
commit
95332b8918
@ -2831,32 +2831,38 @@ pub(crate) fn note_unmet_impls_on_type(
|
||||
errors: Vec<FulfillmentError<'tcx>>,
|
||||
suggest_derive: bool,
|
||||
) {
|
||||
let all_local_types_needing_impls =
|
||||
errors.iter().all(|e| match e.obligation.predicate.kind().skip_binder() {
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
|
||||
match pred.self_ty().kind() {
|
||||
ty::Adt(def, _) => def.did().is_local(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
_ => false,
|
||||
});
|
||||
let mut preds: Vec<_> = errors
|
||||
let preds: Vec<_> = errors
|
||||
.iter()
|
||||
.filter_map(|e| match e.obligation.predicate.kind().skip_binder() {
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => Some(pred),
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
|
||||
match pred.self_ty().kind() {
|
||||
ty::Adt(_, _) => Some(pred),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
preds.sort_by_key(|pred| pred.trait_ref.to_string());
|
||||
let def_ids = preds
|
||||
|
||||
// Note for local items and foreign items respectively.
|
||||
let (mut local_preds, mut foreign_preds): (Vec<_>, Vec<_>) =
|
||||
preds.iter().partition(|&pred| {
|
||||
if let ty::Adt(def, _) = pred.self_ty().kind() {
|
||||
def.did().is_local()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
});
|
||||
|
||||
local_preds.sort_by_key(|pred: &&ty::TraitPredicate<'_>| pred.trait_ref.to_string());
|
||||
let local_def_ids = local_preds
|
||||
.iter()
|
||||
.filter_map(|pred| match pred.self_ty().kind() {
|
||||
ty::Adt(def, _) => Some(def.did()),
|
||||
_ => None,
|
||||
})
|
||||
.collect::<FxIndexSet<_>>();
|
||||
let mut spans: MultiSpan = def_ids
|
||||
let mut local_spans: MultiSpan = local_def_ids
|
||||
.iter()
|
||||
.filter_map(|def_id| {
|
||||
let span = self.tcx.def_span(*def_id);
|
||||
@ -2864,11 +2870,10 @@ pub(crate) fn note_unmet_impls_on_type(
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.into();
|
||||
|
||||
for pred in &preds {
|
||||
for pred in &local_preds {
|
||||
match pred.self_ty().kind() {
|
||||
ty::Adt(def, _) if def.did().is_local() => {
|
||||
spans.push_span_label(
|
||||
ty::Adt(def, _) => {
|
||||
local_spans.push_span_label(
|
||||
self.tcx.def_span(def.did()),
|
||||
format!("must implement `{}`", pred.trait_ref.print_trait_sugared()),
|
||||
);
|
||||
@ -2876,24 +2881,69 @@ pub(crate) fn note_unmet_impls_on_type(
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
if all_local_types_needing_impls && spans.primary_span().is_some() {
|
||||
let msg = if preds.len() == 1 {
|
||||
if local_spans.primary_span().is_some() {
|
||||
let msg = if local_preds.len() == 1 {
|
||||
format!(
|
||||
"an implementation of `{}` might be missing for `{}`",
|
||||
preds[0].trait_ref.print_trait_sugared(),
|
||||
preds[0].self_ty()
|
||||
local_preds[0].trait_ref.print_trait_sugared(),
|
||||
local_preds[0].self_ty()
|
||||
)
|
||||
} else {
|
||||
format!(
|
||||
"the following type{} would have to `impl` {} required trait{} for this \
|
||||
operation to be valid",
|
||||
pluralize!(def_ids.len()),
|
||||
if def_ids.len() == 1 { "its" } else { "their" },
|
||||
pluralize!(preds.len()),
|
||||
pluralize!(local_def_ids.len()),
|
||||
if local_def_ids.len() == 1 { "its" } else { "their" },
|
||||
pluralize!(local_preds.len()),
|
||||
)
|
||||
};
|
||||
err.span_note(spans, msg);
|
||||
err.span_note(local_spans, msg);
|
||||
}
|
||||
|
||||
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::<FxIndexSet<_>>();
|
||||
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::<Vec<_>>()
|
||||
.into();
|
||||
for pred in &foreign_preds {
|
||||
match pred.self_ty().kind() {
|
||||
ty::Adt(def, _) => {
|
||||
foreign_spans.push_span_label(
|
||||
self.tcx.def_span(def.did()),
|
||||
format!("not implement `{}`", pred.trait_ref.print_trait_sugared()),
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
if foreign_spans.primary_span().is_some() {
|
||||
let msg = if foreign_preds.len() == 1 {
|
||||
format!(
|
||||
"the foreign item type `{}` doesn't implement `{}`",
|
||||
foreign_preds[0].self_ty(),
|
||||
foreign_preds[0].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 preds: Vec<_> = errors
|
||||
|
@ -5,6 +5,11 @@ LL | let k = i + j;
|
||||
| - ^ - Vec<R>
|
||||
| |
|
||||
| Vec<R>
|
||||
|
|
||||
note: the foreign item type `Vec<R>` doesn't implement `Add`
|
||||
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
|
|
||||
= note: not implement `Add`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -5,6 +5,12 @@ LL | let z: isize = a.x + b.y;
|
||||
| --- ^ --- Box<isize>
|
||||
| |
|
||||
| Box<isize>
|
||||
|
|
||||
note: the foreign item type `Box<isize>` doesn't implement `Add`
|
||||
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||
::: $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||
|
|
||||
= note: not implement `Add`
|
||||
|
||||
error[E0369]: cannot add `Box<isize>` to `Box<isize>`
|
||||
--> $DIR/autoderef-full-lval.rs:21:33
|
||||
@ -13,6 +19,12 @@ LL | let answer: isize = forty.a + two.a;
|
||||
| ------- ^ ----- Box<isize>
|
||||
| |
|
||||
| Box<isize>
|
||||
|
|
||||
note: the foreign item type `Box<isize>` doesn't implement `Add`
|
||||
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||
::: $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||
|
|
||||
= note: not implement `Add`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
16
tests/ui/binop/binary-op-not-allowed-issue-125631.rs
Normal file
16
tests/ui/binop/binary-op-not-allowed-issue-125631.rs
Normal file
@ -0,0 +1,16 @@
|
||||
use std::io::{Error, ErrorKind};
|
||||
use std::thread;
|
||||
|
||||
struct T1;
|
||||
struct T2;
|
||||
|
||||
fn main() {
|
||||
(Error::new(ErrorKind::Other, "1"), T1, 1) == (Error::new(ErrorKind::Other, "1"), T1, 2);
|
||||
//~^ERROR binary operation `==` cannot be applied to type
|
||||
(Error::new(ErrorKind::Other, "2"), thread::current())
|
||||
== (Error::new(ErrorKind::Other, "2"), thread::current());
|
||||
//~^ERROR binary operation `==` cannot be applied to type
|
||||
(Error::new(ErrorKind::Other, "4"), thread::current(), T1, T2)
|
||||
== (Error::new(ErrorKind::Other, "4"), thread::current(), T1, T2);
|
||||
//~^ERROR binary operation `==` cannot be applied to type
|
||||
}
|
75
tests/ui/binop/binary-op-not-allowed-issue-125631.stderr
Normal file
75
tests/ui/binop/binary-op-not-allowed-issue-125631.stderr
Normal file
@ -0,0 +1,75 @@
|
||||
error[E0369]: binary operation `==` cannot be applied to type `(std::io::Error, T1, {integer})`
|
||||
--> $DIR/binary-op-not-allowed-issue-125631.rs:8:48
|
||||
|
|
||||
LL | (Error::new(ErrorKind::Other, "1"), T1, 1) == (Error::new(ErrorKind::Other, "1"), T1, 2);
|
||||
| ------------------------------------------ ^^ ------------------------------------------ (std::io::Error, T1, {integer})
|
||||
| |
|
||||
| (std::io::Error, T1, {integer})
|
||||
|
|
||||
note: an implementation of `PartialEq` might be missing for `T1`
|
||||
--> $DIR/binary-op-not-allowed-issue-125631.rs:4:1
|
||||
|
|
||||
LL | struct T1;
|
||||
| ^^^^^^^^^ must implement `PartialEq`
|
||||
note: the foreign item type `std::io::Error` doesn't implement `PartialEq`
|
||||
--> $SRC_DIR/std/src/io/error.rs:LL:COL
|
||||
|
|
||||
= note: not implement `PartialEq`
|
||||
help: consider annotating `T1` with `#[derive(PartialEq)]`
|
||||
|
|
||||
LL + #[derive(PartialEq)]
|
||||
LL | struct T1;
|
||||
|
|
||||
|
||||
error[E0369]: binary operation `==` cannot be applied to type `(std::io::Error, Thread)`
|
||||
--> $DIR/binary-op-not-allowed-issue-125631.rs:11:9
|
||||
|
|
||||
LL | (Error::new(ErrorKind::Other, "2"), thread::current())
|
||||
| ------------------------------------------------------ (std::io::Error, Thread)
|
||||
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`
|
||||
--> $SRC_DIR/std/src/thread/mod.rs:LL:COL
|
||||
|
|
||||
= note: not implement `PartialEq`
|
||||
|
||||
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
|
||||
|
|
||||
LL | (Error::new(ErrorKind::Other, "4"), thread::current(), T1, T2)
|
||||
| -------------------------------------------------------------- (std::io::Error, Thread, T1, T2)
|
||||
LL | == (Error::new(ErrorKind::Other, "4"), thread::current(), T1, T2);
|
||||
| ^^ -------------------------------------------------------------- (std::io::Error, Thread, T1, T2)
|
||||
|
|
||||
note: the following types would have to `impl` their required traits for this operation to be valid
|
||||
--> $DIR/binary-op-not-allowed-issue-125631.rs:4:1
|
||||
|
|
||||
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`
|
||||
--> $SRC_DIR/std/src/thread/mod.rs:LL:COL
|
||||
|
|
||||
= note: not implement `PartialEq`
|
||||
help: consider annotating `T1` with `#[derive(PartialEq)]`
|
||||
|
|
||||
LL + #[derive(PartialEq)]
|
||||
LL | struct T1;
|
||||
|
|
||||
help: consider annotating `T2` with `#[derive(PartialEq)]`
|
||||
|
|
||||
LL + #[derive(PartialEq)]
|
||||
LL | struct T2;
|
||||
|
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0369`.
|
@ -5,6 +5,11 @@ LL | fn main() { let x = "a".to_string() ^ "b".to_string(); }
|
||||
| --------------- ^ --------------- String
|
||||
| |
|
||||
| String
|
||||
|
|
||||
note: the foreign item type `String` doesn't implement `BitXor`
|
||||
--> $SRC_DIR/alloc/src/string.rs:LL:COL
|
||||
|
|
||||
= note: not implement `BitXor`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -5,6 +5,12 @@ LL | LinkedList::new() += 1;
|
||||
| -----------------^^^^^
|
||||
| |
|
||||
| cannot use `+=` on type `LinkedList<_>`
|
||||
|
|
||||
note: the foreign item type `LinkedList<_>` doesn't 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}>`
|
||||
|
||||
error[E0067]: invalid left-hand side of assignment
|
||||
--> $DIR/E0067.rs:4:23
|
||||
|
@ -5,6 +5,12 @@ LL | println!("{}", x + 1);
|
||||
| - ^ - {integer}
|
||||
| |
|
||||
| Box<isize>
|
||||
|
|
||||
note: the foreign item type `Box<isize>` doesn't implement `Add<{integer}>`
|
||||
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||
::: $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||
|
|
||||
= note: not implement `Add<{integer}>`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -3,6 +3,11 @@ error[E0600]: cannot apply unary operator `-` to type `String`
|
||||
|
|
||||
LL | fn main() { -"foo".to_string(); }
|
||||
| ^^^^^^^^^^^^^^^^^^ cannot apply unary operator `-`
|
||||
|
|
||||
note: the foreign item type `String` doesn't implement `Neg`
|
||||
--> $SRC_DIR/alloc/src/string.rs:LL:COL
|
||||
|
|
||||
= note: not implement `Neg`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -5,6 +5,11 @@ LL | fn foo(t: Bar) -> isize { match t { Bar::T1(_, Some(x)) => { return x * 3;
|
||||
| - ^ - {integer}
|
||||
| |
|
||||
| Vec<isize>
|
||||
|
|
||||
note: the foreign item type `Vec<isize>` doesn't implement `Mul<{integer}>`
|
||||
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
|
|
||||
= note: not implement `Mul<{integer}>`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -19,6 +19,10 @@ LL | x.lock().unwrap() += 1;
|
||||
| |
|
||||
| cannot use `+=` on type `MutexGuard<'_, usize>`
|
||||
|
|
||||
note: the foreign item type `MutexGuard<'_, usize>` doesn't implement `AddAssign<{integer}>`
|
||||
--> $SRC_DIR/std/src/sync/mutex.rs:LL:COL
|
||||
|
|
||||
= note: not implement `AddAssign<{integer}>`
|
||||
help: `+=` can be used on `usize` if you dereference the left-hand side
|
||||
|
|
||||
LL | *x.lock().unwrap() += 1;
|
||||
@ -47,6 +51,10 @@ LL | y += 1;
|
||||
| |
|
||||
| cannot use `+=` on type `MutexGuard<'_, usize>`
|
||||
|
|
||||
note: the foreign item type `MutexGuard<'_, usize>` doesn't implement `AddAssign<{integer}>`
|
||||
--> $SRC_DIR/std/src/sync/mutex.rs:LL:COL
|
||||
|
|
||||
= note: not implement `AddAssign<{integer}>`
|
||||
help: `+=` can be used on `usize` if you dereference the left-hand side
|
||||
|
|
||||
LL | *y += 1;
|
||||
|
Loading…
Reference in New Issue
Block a user