Is it possible to implement Debug for Fn type

I'll sketch something out if you need me to

even if you don't need it, I did this anyways :stuck_out_tongue:

/// Extends a (possibly unsized) value with a Debug string.
// (This type is unsized when T is unsized)
pub struct Debuggable<T: ?Sized> {
    text: &'static str,
    value: T,
}

/// Produce a Debuggable<T> from an expression for T
macro_rules! dbg {
    ($($body:tt)+) => {
        Debuggable {
            text: stringify!($($body)+),
            value: $($body)+,
        }
    };
}

// Note: this type is unsized
pub type PolFn = Debuggable<Fn(Rc<Pol>) -> Rc<Pol>>;

impl<T: ?Sized> fmt::Debug for Debuggable<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
    { write!(f, "{}", self.text) }
}

// This makes Debuggable have most methods of the thing it wraps.
// It also lets you call it when T is a function.
impl<T: ?Sized> ::std::ops::Deref for Debuggable<T>
{
    type Target = T;
    fn deref(&self) -> &T { &self.value }
}

fn main() {
    let d: &PolFn = &dbg!(|x| {
        let _ = "random code so you can see how it's formatted";
        assert_eq!(3 * (1 + 2), 9);
        x
    });
    println!("{:?}", d);
}

Updated 1/09: @juggle-tux has pointed out these objects can actually be called using standard function-call syntax (I didn't realize Deref could do that!), so I removed the call method.

In Pol you would store Rc<PolFn>. In your code you will need to wrap dbg!() around a lot of your closures.

In the playground this prints:

| x | {
let _ = "random code so you can see how it's formatted" ; assert_eq ! (
3 * ( 1 + 2 ) , 9 ) ; x }

as you can see, the formatting is not spectacular, but that's because all the whitespace gets normalized away during tokenization. I don't think you can get much better without resorting to crazy hacks like preprocessing your code in a build script.

9 Likes