More Useful Debug Formatting


#1

Currently we have two kinds of formatting traits: std::fmt::Show and its friends, and debug::fmt::Poly. The former traits intend to be used for generic stringification, and the latter trait intends to be used for debugging.

Unfortunately, debug::fmt::Poly is currently not very usable as many have pointed out. For example, println!("{:?}", vec![3u, 4, 5]) gives collections::vec::Vec<uint>{len: 3u, cap: 4u, ptr: (0x7ff94bc0f040 as *mut ())}, which is clearly not what one wants. It follows that the debugging information is best left to the type itself; the current Poly exposes the implementation details, which the end user should not concern about.

As the first attempt (pre-pre-RFC), I’d like to propose two suggestions connected to each other:

  1. Make a separate trait for inspection. I think Ruby-esque Inspect::inspect is fine (Python has repr, but Repr is already used in some (obscure) cases from stdlib). It can be either in std or debug (TBD). There would be #[deriving(Inspect)] which does the same as #[deriving(Show)]. (I think there was a concern about having #[deriving(Show)] itself, so it might be simply renamed in that case.) Otherwise it should be same to Show::fmt; one can also think about the pretty-formatting, but that would be another story (we don’t have a stdlib-agreed way to do the pretty printing after all).

  2. Make TyDesc contain a glue to either Show::fmt or Inspect::inspect. This way {:?} can continue to be used for structural inspection (henceforth relieving the burden of implementing Show or Inspect for every type) but can switch to Inspect whenever appropriate. This affects the binary size, so it should be made optional or dependent to the use of debug crate (by defining a relevant lang item in debug, for example) or so.


#2

Assuming Vec implements Inspect, how would I inspect a Vec instance? With println!("{:?}", vec)?

Do I understand it right that the implementation of Inspect for Vec<T> could be written so that T doesn’t have to implement Inspect? If so, #[deriving(Inspect)] seems not needed because for types with data behind pointers we need to manually implement Inspect, and for all other cases {:?} should work.


#3

Under the second suggestion, yes, println!("{:?}", vec) will use Inspect if possible. Otherwise Poly and Inspect have to be separated. Likewise, #[deriving(Inspect)] is only needed when the second suggestion is not in place.