Help with trait method magic in generic bounds

I am not sure whether it is even possible, but I currently have this helper function on a type:

    fn format<T, U>(&self, f: &mut Formatter<'_>, node_id_f: T, ieee_address_f: U) -> fmt::Result
    where
        T: FnOnce(&u16, &mut Formatter<'_>) -> fmt::Result,
        U: FnOnce(&IeeeAddress, &mut Formatter<'_>) -> fmt::Result,
    {
        node_id_f(&self.node_id, f)?;
        write!(f, " (")?;

        if let Some(ieee_address) = self.ieee_address {
            ieee_address_f(&ieee_address, f)?;
        } else {
            write!(f, "N/A")?;
        }

        f.write_str(")")
    }

So that I can do this:

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

impl LowerHex for Source {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        self.format(f, LowerHex::fmt, Display::fmt)
    }
}

impl UpperHex for Source {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        self.format(f, UpperHex::fmt, UpperHex::fmt)
    }
}

Can I specify in the helper function a trait bound for the function, so that I can simplify the trait impls to:

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

impl LowerHex for Source {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        self.format(f, LowerHex::fmt)
    }
}

impl UpperHex for Source {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        self.format(f, UpperHex::fmt)
    }
}

(I guess not, since the trait method probably resolves to a concrete implementation for a type).

EDIT: Fun fact: The bug in the LowerHex impl, which I just noticed, is the exact reason for why I want that. :smiley:

I think this would require some sort of higher-kinded polymorphism the type system currently doesn't support. Instead, to avoid typos like in the snippet, you could use a macro instead of implementing format traits by hand:

macro_rules! impl_fmt_for_source {
    ($($tr:path),+ $(,)?) => {
        $(
            impl $tr for Source {
                fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
                    self.format(f, <u16 as $tr>::fmt, <IeeeAddress as $tr>::fmt)
                }
            } 
        )+
    }
}

impl_fmt_for_source! { Display, UpperHex, LowerHex }

Playground.