Debug for Fn, FnOnce, FnMut

A good rule in Rust is that every struct should have std::debug::Debug. But what if that struct contains closures.

I initially had a struct that looked like:

pub struct Move {
    from: CardIndex,
    to: CardIndex,
    on_after: Option<DisplayFn>,
    on_after_reverse: Option<DisplayFn>,
}

pub type DisplayFn = Box<dyn FnOnce(&mut Card)>;

The usecase for this code is a cardgame that has an undo button. When a card moves, its display may change, but when undo happens its display needs to be reversed.

If we try to derive Debug for it, we will get a compiler error because FnOnce does not impl Debug.

The solution is to declare a trait that has FnOnce and impl it for all functions that have FnOnce, and then impl Debug for that trait.

pub trait DisplayFnT: FnOnce(&mut Card);

impl<F> DisplayFnT for F where F: FnOnce(&mut Card) { }

impl std::fmt::Debug for DisplayFnT {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "DisplayFunction")
    }
}

pub type DisplayFn = Box<dyn DisplayFnT>;

Then the final struct looks like:

#[derive(Debug)]
pub struct Move {
    from: CardIndex,
    to: CardIndex,
    on_after: Option<DisplayFn>,
    on_after_reverse: Option<DisplayFn>,
}

I got the solution to this problem from this users.rust-lang.org question and answer.