Problem with std::convert::From

Hi,
I don't understand why this

use std::fmt;

enum MyErrors {
    MyError,
    WriteError(fmt::Error)
}

impl From<fmt::Error> for MyErrors {
    fn from(e: fmt::Error) -> Self {
        MyErrors::WriteError(e)
    }
}

fn test(s: &mut dyn fmt::Write) -> Result<(), MyErrors> {
    write!(s, "test")
}

gives me the error

error[E0308]: mismatched types
  --> src/main.rs:15:5
   |
14 | fn test(s: &mut dyn fmt::Write) -> Result<(), MyErrors> {
   |                                    -------------------- expected `std::result::Result<(), MyErrors>` because of return type
15 |     write!(s, "test")
   |     ^^^^^^^^^^^^^^^^^ expected enum `MyErrors`, found struct `std::fmt::Error`
   |
   = note: expected type `std::result::Result<_, MyErrors>`
              found type `std::result::Result<_, std::fmt::Error>`

The example from the documentation for std::convert::From seems to do the exactly same thing and it compiles. Can anybody explain this, please.

Your test fn does nothing to actually trigger the From conversion. Meanwhile the example in the From documentation uses the ? operator which does invoke the conversion. So if you change your own code to Ok(write!(s, "test")?) then it compiles, though the syntax is slightly awkward. You could also do write!(s, "test").map_err(|e| e.into()) for a more explicit conversion.

Thank you so much. My mental model was that the conversion is always tried automatically.
Actually, in my original code there are some statements using the '?' operator. I completely overlooked them because they didn't give any compiler error.
Would it be idiomatic to use statements with '?' everywhere and just one final 'Ok(())' expression?

Yes.

You can also try adding .into() or .map_err(From::from) to the single expression.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.