// this is not even remotely worth it but technically it doesn't use the heap I think xdddddddddd use std::marker::PhantomData; pub trait Labeler = Fn(&mut std::fmt::Formatter<'_>, &S) -> std::fmt::Result; pub trait Labelable { fn labeled>(&self, l: L) -> Labeled where Self: Sized; } pub struct Labeled<'a, T, L: Labeler, S> { data: &'a T, labeler: L, pd: PhantomData, } pub trait LabeledFmt { fn fmt_label( &self, f: &mut std::fmt::Formatter<'_>, label: &dyn Labeler, ) -> std::fmt::Result; } impl, S> Labelable for T { fn labeled>(&self, l: L) -> Labeled { Labeled { data: self, labeler: l, pd: PhantomData, } } } impl, L: Labeler, S> std::fmt::Debug for Labeled<'_, T, L, S> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.data.fmt_label(f, &self.labeler) } }