Here is just some code to get the compiler error I'm talking about:
struct S; // not serde::Serialize
fn main() {
// will fail with E0277:
// the trait bound `S: serde::ser::Serialize` is not satisfied
let s = serde_json::to_string(&S).unwrap();
}
Here is the portion of the compiler’s error message that I think could be improved:
= note: for local types consider adding `#[derive(serde::Serialize)]` to your `S` type
= note: for types from other crates check whether the crate offers a `serde` feature flag
= help: the following other types implement trait `serde::ser::Serialize`:
&'a T
&'a mut T
()
(T,) // somewhat redundant
(T0, T1) // and this one too
(T0, T1, T2)
(T0, T1, T2, T3)
(T0, T1, T2, T3, T4) // all the way up to here
and 131 others
The last six types shown can be succinctly described as “tuples of serializable types”. But the compiler does not know this; all it can see is the expanded macro that serde uses to implement Serialize
for tuples up to length 16. Serde does some trickery I don't understand to get this to look ok in the docs.rs docs, where it simply reads:
impl<T> Serialize for (T₁, T₂, …, Tₙ) where T: Serialize,
This trait is implemented for tuples up to 16 items long.
Nice and succinct! It would be great if the compiler could use similar logic to understand (or be told by the crate author) which trait implementations were redundant in this error message and/or how best to display them. The result would be something like this:
= help: the following other types implement trait `serde::ser::Serialize`:
&'a T
&'a mut T
tuples of serializable types up to length 16
// more important implementations shown here
and 126 others