0

I'm struggling to understand the nuances of the ? operator. Take the following code:

link to playground

use std::{error::Error as StdError, fmt};

#[derive(Debug)]
struct MyError(Box<dyn StdError>);

impl fmt::Display for MyError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Debug::fmt(self, f)
    }
}

impl StdError for MyError{}

impl From<Box<dyn StdError>> for MyError {
    fn from(err: Box<dyn StdError>) -> Self {
        MyError(err)
    }
}

#[derive(Debug)]
struct RandomErr(String);

impl fmt::Display for RandomErr {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Debug::fmt(self, f)
    }
}

impl StdError for RandomErr{}

fn no_custom() -> Result<(), Box<dyn StdError>> {
    Err(RandomErr("hello there".to_owned()))?
}

// This fails to compile
fn custom() -> Result<(), MyError> {
    Err(RandomErr("hello there".to_owned()))?
}

I would think that custom() should compile. RandomError is a StdError, so RandomErr should be convertable to MyError since there's an impl for converting from StdError, no?

1 Answer 1

3

I would think that custom() should compile. RandomError is a StdError, so RandomErr should be convertable to MyError since there's an impl for converting from StdError, no?

Nope. There is no transitivity in From (or any trait, as far as I know). Rustc generally does what you tell it and no more to avoid problems like combinatory explosions in trait resolution.

So that C: From<B> and B: From<A> does not imply / translate to C: From<A>, you can write that reduced case and will hit E0277 (trait not satisfied):

struct A;
struct B;
struct C;

impl From<A> for B {
    fn from(a: A) -> Self { B }
}
impl From<B> for C {
    fn from(b: B) -> Self { C }
}

fn main() {
    let _: C = From::from(A);
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.