Compiler errors for auto traits can be very unhelpful, especially when combined with min_specialization
.
#90601
Labels
A-diagnostics
Area: Messages for errors, warnings, and lints
F-auto_traits
`#![feature(auto_traits)]`
T-compiler
Relevant to the compiler team, which will review and decide on the PR/issue.
I have here a collection of scenarios where the compiler fails to produce a helpful error message in response to a missing auto trait implementation. All examples are done on
1.58.0-nightly
.Why do I care?
This issue cost me the entirety of an afternoon as I attempted to track down the cause of a very vague error. I've provided a minimal repro of that particular scenario in Example 4. Figuring out that it was due to a missing auto trait implementation was... not fun.
The root of the problem is that a type only a receives an auto trait implementation if the entire recursive closure of types that make it up implements the trait. If there is some unknown (to the user) negative impl somewhere deep inside that recursive closure of types, or (as was the case for me) there is some
Box<T: !Sized>
1 hidden somewhere in there, then the compiler needs to point out the offending type to the user, or otherwise leave them baffled as to what's going on.Example 1: Good
Below is an example where the compiler does give a diagnostic that I find satisfactory:
Code
The compiler correctly identifies the offending type,
dyn ToString
:Compile error
https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=3b256c12fe5979c5372ed94c3b4f939a
Example 2: What if it was a trait?
This example is like Example 1 but I've turned the
destroy
function into a trait,Destroy
:Code
With this little change, suddenly the compiler has lost all context regarding
dyn ToString
:Compile error
https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=72b138ae232c87f5b34e9d96f3aff0bd
Example 3: With specialization
This expands on Example 2 by adding a specialized implementation of
Destroy
usingfeature(min_specialization)
:Code
The error message is even less helpful!
Compile error
https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=bc60361c1dbdcb0a26c128965def0239
Example 4: Specialization and Result
This is a representative example of what I was working on when I encountered these unhelpful errors:
https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=06c83fd106d7b7f9ac3b489a18459099
My project involves modifying
core::result::Result
to have specializedFromResidual
behavior for error types that implement a certain trait. I then have a wrapper type in "user space" that wraps some arbitrary error type and implements the specialization trait.To enable
?
-conversion from one wrapper to another, I provide a blanketFrom
impl. I utilize auto traits and negative impls to ensure that it does not collide with the blanketFrom<T> for T
from the standard library.If the wrapped error type does not receive the
NotSame
auto trait, then the blanketFrom
impl fails to apply to it, which in turn makes theFromResidual
impl fail to apply, and I get the error below:Compile error
This error message is even less helpful than the last, as it doesn't even mention any trait or type that is remotely related to my actual test code!
A few things seem clear here:
I'd be happy to take a stab at improving things here, but I do not know what part of the compiler is responsible for doing this sort of inference (if that's even the correct term to use).
cc #13231 #31844 #68970
maybe also cc #84277
Footnotes
I will say that it's remarkably unintuitive that non-sized types do not receive auto traits by default. I only ended up learning this when I stumbled across this code. There is no mention of this peculiarity in the Unstable Book. ↩
The text was updated successfully, but these errors were encountered: