Occasionally I get into a situation where a trait is implemented for a lot of types and the compiler won't show them all to me. Example is below. Instead, it just tells me how many it has refused to print.
Is there a way to get the full list? Ideally, using a flag on "cargo check", but I'll settle for any option (LSP based, hacking the code using some trick, etc.).
error[E0277]: the trait bound `MaybeMissing<std::string::String>: Reconcile` is not satisfied
--> src/main.rs:3:19
|
3 | #[derive(Hydrate, Reconcile)]
| ^^^^^^^^^ the trait `Reconcile` is not implemented for `MaybeMissing<std::string::String>`, which is required by `&MaybeMissing<std::string::String>: Reconcile`
4 | struct S {
5 | s: MaybeMissing<String>,
| - required by a bound introduced by this call
|
= help: the following other types implement trait `Reconcile`:
bool
i8
i16
i32
i64
u8
u16
u32
and 17 others
= note: required for `&MaybeMissing<std::string::String>` to implement `Reconcile`
note: required by a bound in `autosurgeon::reconcile::MapReconciler::put`
--> /home/matt/.cargo/registry/src/index.crates.io-6f17d22bba15001f/autosurgeon-0.8.3/src/reconcile.rs:114:15
|
114 | fn put<R: Reconcile, P: AsRef<str>>(&mut self, prop: P, value: R) -> Result<(), Self::Error>;
| ^^^^^^^^^ required by this bound in `MapReconciler::put`
This does not cover implementations in other crates unless you build the docs yourself. But building yourself is not possible if your code fails to compile.
Sorry but I needed a code example, so here: (playground)
trait Reconcile {
fn reconcile(&self);
}
// Implementing the trait for some types
impl Reconcile for bool {
fn reconcile(&self) {
println!("Reconciling bool");
}
}
impl Reconcile for i8 {
fn reconcile(&self) {
println!("Reconciling i8");
}
}
impl Reconcile for i16 {
fn reconcile(&self) {
println!("Reconciling i16");
}
}
impl Reconcile for i32 {
fn reconcile(&self) {
println!("Reconciling i32");
}
}
impl Reconcile for i64 {
fn reconcile(&self) {
println!("Reconciling i64");
}
}
impl Reconcile for u8 {
fn reconcile(&self) {
println!("Reconciling u8");
}
}
impl Reconcile for u16 {
fn reconcile(&self) {
println!("Reconciling u16");
}
}
impl Reconcile for u32 {
fn reconcile(&self) {
println!("Reconciling u32");
}
}
impl Reconcile for i128 {
fn reconcile(&self) {
println!("Reconciling u32");
}
}
impl Reconcile for u128 {
fn reconcile(&self) {
println!("Reconciling u32");
}
}
fn process<T: Reconcile>(item: T) {
item.reconcile();
}
fn main() {
let value = String::from("This will cause an error");
process(value); // This line will cause a compilation error
}
output:
⣿
Errors
Exited with status 101
Standard Error
Compiling playground v0.0.1 (/playground)
error[E0277]: the trait bound `String: Reconcile` is not satisfied
--> src/main.rs:72:13
|
72 | process(value); // This line will cause a compilation error
| ------- ^^^^^ the trait `Reconcile` is not implemented for `String`
| |
| required by a bound introduced by this call
|
= help: the following other types implement trait `Reconcile`:
bool
i128
i16
i32
i64
i8
u128
u16
and 2 others
note: required by a bound in `process`
--> src/main.rs:66:15
|
66 | fn process<T: Reconcile>(item: T) {
| ^^^^^^^^^ required by this bound in `process`
For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` (bin "playground") due to 1 previous error
local rustc patch, because of course:
Index: /var/tmp/portage/dev-lang/rust-1.76.0-r1/work/rustc-1.76.0-src/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
===================================================================
--- .orig/var/tmp/portage/dev-lang/rust-1.76.0-r1/work/rustc-1.76.0-src/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
+++ rustc-1.76.0-src/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
@@ -2096,16 +2096,10 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for Ty
})
.collect();
- let end = if candidates.len() <= 9 { candidates.len() } else { 8 };
err.help(format!(
- "the following {other}types implement trait `{}`:{}{}",
+ "the following {other}types implement trait `{}`:{}",
trait_ref.print_trait_sugared(),
- candidates[..end].join(""),
- if candidates.len() > 9 {
- format!("\nand {} others", candidates.len() - 8)
- } else {
- String::new()
- }
+ candidates.join(""),
));
true
};
output:
Compiling and_17_others v0.1.0 (/home/user/sandbox/rust/05_sandbox/error/and_17_others)
error[E0277]: the trait bound `String: Reconcile` is not satisfied
--> /home/user/sandbox/rust/05_sandbox/error/and_17_others/src/main.rs:72:13
|
72 | process(value); // This line will cause a compilation error
| ------- ^^^^^ the trait `Reconcile` is not implemented for `String`
| |
| required by a bound introduced by this call
|
= help: the following other types implement trait `Reconcile`:
bool
i8
i16
i32
i64
i128
u8
u16
u32
u128
note: required by a bound in `process`
--> /home/user/sandbox/rust/05_sandbox/error/and_17_others/src/main.rs:66:15
|
66 | fn process<T: Reconcile>(item: T) {
| ^^^^^^^^^ required by this bound in `process`
For more information about this error, try `rustc --explain E0277`.
error: could not compile `and_17_others` (bin "and_17_others") due to 1 previous error
ah, much better, thanks Bruecki for pointing to the implementation!
The most pragmatic option to finding which types implement which traits is often to go check the docs.
To get better output from the compiler, hack it yourself. This is a half joke. I know in clang there are a few cases where it refuses to spam long lists of details in its errors, but you can opt in to more with a command line flag. Rust lacks a flag for this case, but it could probably be added.
In my experience I've never needed the full list of implementers when encountering an E0277 and there were more than a handful, but not providing a way to show the full list is an oversight.