Call trait method on wrapped value of enum

i have code like this, with the idea of adding a lot more code in the future:

use std::fmt;

enum Value {
    Int(u32),
    Str(String),
}

impl fmt::Display for Value {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        use Value::*;
        match &self {
            Int(x) => {
                write!(f, "{}", x)
            }
            Str(x) => {
                write!(f, "{}", x)
            }
        }
    }
}

i want to get rid of the repeated write! calls, preferably without using a complex macro.

my first idea was something like this:

use std::fmt;

enum Value {
    Int(u32),
    Str(String),
}

impl fmt::Display for Value {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        use Value::*;
        match &self {
            Int(x) | Str(x) => {
                write!(f, "{}", x)
            }
        }
    }
}

where x is coerced into &dyn Display within the match arm. this might be possible with type ascription, but that has been gone for some time.

macros don't even help that much, as they can't expand to match arms.

also, i want to be add some cases that are more complex.

Macros can't expand to just a match arm, but they can expand to the whole match expression.

macro_rules! impl_display_for_value {
    ($($variant:ident),* $(,)?) => {
        impl fmt::Display for Value {
            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                match self {
                    $(
                        Self::$variant(x) => write!(f, "{x}"),
                    )*
                }
            }
        }
    };
}

impl_display_for_value! { Int, Str }

yeah, i was thinking that might be the best solution, but i was really hoping there was a better way..

Sometimes crates like ambassador or enum_dispatch can help.

If you're using the same trait many places, you can write a method to get from &Value to &dyn Trait.[1]

(AFAIK dyn Trait coercion via pattern has never been possible. Slice patterns are a type of coercion I suppose, but also pretty special.)


  1. ala AsRef, but actually using that may be confusing in some cases since you would not be converting &self ↩ī¸Ž

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.