I just experimented with using the
? operator with
Option<T> and was surprised to find that the resulting error wouldn’t convert into
Box<Error>. It’s not that I have a real use case for this – instead of propagating a rather meaningless
NoneError, it would certainly be better to implement a conversion into a custom error type. I was surprised anyway, since currently
NoneError is the only error type in the standard that does not implement the
Error trait. Is this difference intentional?
I just experimented with using the
I don’t recall it being discussed in the RFC or the PR.
Personally, it not existing so people use
.ok_or(something)? in a
Result method feels reasonable.
I certainly agree with @smarnach on this. It is a bit unclear to me as to why it does not implement
Error. It is at least a bit deceiving that it is called
NoneError but does not implement
Either way it’s not great:
Lack of the
Errorimplementation looks like an inconsistency, and when used with
Box<Error>gives an IMHO unfriendly error message:
error[E0277]: the trait bound
std::option::NoneError: std::error::Erroris not satisfied
(the message is technically entirely accurate, but the PLT jargon and number of
::s in there is off-putting for me)
NoneErrordoes not contain file/line number that caused it, so when wrapped in
Box<Error>it may become coompletely detached from the place that generated the error, and may be super hard to figure out what caused it in a large application.
So pushing users towards adding
.ok_or("msg")might actually save them some headache later.
So I’d suggest:
NoneErrorcompiled in debug mode display (via
fmt::Debug?) the file/line it came from.
If it’s not supposed to implement
Error, customize E0277 to suggest using
I have seen a lot of activity around this question, but have not been able to find a clear, succinct explanation as to why
NoneError should not implement the
A few examples:
- “I’m not sure myself”: https://github.com/rust-lang/rust/pull/42526#issuecomment-311065346
- “I rather got the impression that the omission is deliberate”: Should NoneError implement the Error trait?
- Q asked but not answered: https://github.com/rust-lang/rust/pull/42526#pullrequestreview-57652383
- conversations with multiple people on #rust-beginners IRC came to the same conclusions (no clear understanding of the rationale)
The actual reasoning is very unclear (at least to me). Could some kind soul please summarize (or point to a succinct summary of) the reasoning?
- “something I really want”: https://github.com/rust-lang-nursery/failure/issues/59#issuecomment-347512030
- “I scoured the docs and had a bit of a hard time”: https://github.com/rust-lang-nursery/failure/issues/61
Personally, I must use
.ok_or(MyError::MyVariant)? instead of just
? when I need to convert a
None into an
Result::Err, and it chafes every single time. Either implementing the
Error trait for
NoneError or having a better understanding of why the extra boilerplate should be necessary would be very much appreciated.
Personally, I still feel unclear on whether
NoneError should exist at all. I’ve not been especially happy with the setup where the
Try trait makes all
? types be isomorphic with result, as I wrote about here – it seems to diminish the applicability of
Try significantly to me. The need to define an artificial
NoneError to make
Option fit (or else use
(), which also feels somewhat artificial to me, but would be more “common”) is sort of a case in point.