Could core::fmt::Formatter be an alias to a trait object?

As far as I know there is currently no way to use a Debug implementation with anything but core::fmt::Formatter.

Since core::fmt::Formatter is only ever accessible by reference and is neither Clone nor Copy, would it be possible to change the definition of core::fmt::Formatter to pub type Formatter = dyn FormatterTrait where FormatterTrait implements all methods that core::fmt::Formatter currently does?

The standard library could then make the current core::fmt::Formatter private and implement FormatterTrait for it.

As far as I can see, this would allow custom formatters and wouldn't break any existing code.

Unfortunately not; it's rather trivial to observe Formatter: Sized.

Ah, I forgot the docs don't tell you if a type is Sized. That's unfortunate. Especially since observing if Formatter is Sized is such a useless thing to do... I'm still not quite sure what an edition can actually change but would this be something Rust 2024 could change?

It's more properly a Formatter<'a>. Conceivably it could hold a &'a dyn FormatterTrait. Or become generic with a default underlying type. I think it would take a lot of motivation though.

1 Like

It's worth noting that Formatter already effectively does do dynamic dispatch - to some fmt::Write or io::Write. So if you want to use the Debug representation of some type, you implement fmt::Write and write! to it.

It won't give you structured data (it's not supposed to! the Formatter helpers are just helpers over write!ing simple data) but it will give you access to the debug formatted stream without requiring a temp string buffer.

2 Likes

Hmm, yeah I guess under the lense of the data being completely unstructured it doesn't make sense.

I was thinking about ways to have colored debug output à la nodejs and this seemed to solve the problem of having to derive a trait for unrelated crates to be able to print them. I guess this is not really sufficient motivation for this change if it isn't trivial.