Result::expect except stringify err?


#1

Greetings,

It seems strange to me that (especially in a testing context) there isn’t a form of Result::expect or the like that simply stringifies the error and uses that as the panic message.

Have I somehow missed this?

For testing purposes, I may call a function with a set of parameters or input that I know should not fail, and if it does, I want the error printed in the panic message.

While I know I can write a macro to do this, it seems like something fairly reasonable to have as part of Result.

Any thoughts or ideas?

Result::unwrap() doesn’t seem to stringify the Err; instead it “{:?}” prints the value.


#2

I’m not sure what you mean, both unwrap and expect print a message and the value in Err.


#3

Yes, the value in Err – which if it is an Error object instead of a string, causes the “{:?}” representation of the object to be printed instead of the string representation:

---- parser stdout ----
	thread 'parser' panicked at 'called `Result::unwrap()` on an `Err` value: Malformed { astr: "file", apos: 4, aerr: "no attributes", afmri: None }', ../src/libcore/result.rs:837
note: Run with `RUST_BACKTRACE=1` for a backtrace.

While I can see why some might prefer the “{:?}” representation of the Err, I’d prefer the fmt::Display representation instead.

Note that I said in the context of testing – I’m not sure if this oddity is particular to “cargo test”.


#4

Result sadly doesn’t constrain the error variant to be std::error::Error which means that it’s not easily possible to stringify all errors :).


#5

This particular Error type (ActionError::Malformed) is one I created, and that fmt::Display is implemented for:

impl<'a> fmt::Display for ActionError {...}

impl<'a> error::Error for ActionError {...}

…so I don’t understand what you mean by that?

This particular error can be stringified, so why is it not stringified in Display form?


#6

The signature is:

impl<T, E> Result<T, E> where E: Debug {
    fn unwrap(self) -> T {...}
    fn expect(self, msg: &str) -> T {...}
}

So these can only use traits within the constraints. It doesn’t know that your E actually does implement Display and Error, only Debug. However, this might be something specialization could handle.


#7

Ah, I don’t know why I didn’t think to check the signature. Thanks.

Do you think that if I suggested a specialization that it would be accepted or would the change in behaviour be sufficiently different that it would be considered too surprising?

I had assume it might and so had thought perhaps another form would be acceptable, such as Result::panic or the like.


#8

IMO it seems reasonable to specialize this for Error in particular, but less so for all Display.


#9

So then, if I understand correctly:

impl<T, E> Result<T, E> where E: Error + Display {
    fn unwrap(self) -> T {...}
    fn expect(self, msg: &str) -> T {...}
}

#10

Error already implies Display, so you don’t need to mention that.

I think you need an additional trait behind the scenes to make specialization work. See how SpecExtend works for extending vectors, for instance. So the signature of the impl Result wouldn’t change, but it would use a specialized trait to do different things depending on whether Error is implemented.


#11

Doh! I don’t know how I overlooked that, of course, thanks.

Thanks for the pointer, I’ll take a look when I get a moment.


#12

Can’t you just implement Debug for your Err ?


#13

I did implement Debug for my err. I would prefer not to get the debug representation on failure.