Open yuhr opened 1 year ago
I don't think we should be adding more flags (let alone what is effectively infinite number of flags ^^'). I think wrapper structs are preferrable over more flags. Basically:
println!("{}", IsoDisplay(time)); // This,
println!("{}", time.display_iso()); // or this,
println!("{:#iso}", time); // but not this.
For various reasons:
{:#flags}
, the flags would be silently ignored if the Display implementation doesn't check the flags.{:#flags}
, the Display implementation has to support all the possible flags, making the Display::fmt function very large. At least today, the compiler cannot optimize parts of that function away based on usage, which means pulling in a lot of unnecessary code. (This is already an issue today, where e.g. <&str as Display>::fmt
pulls in fill and alignment related code that is likely unused.){:#flags}
wouldn't be extensible outside of the Display implementation. E.g. a terminal color library couldn't provide {:#red}
, but can provide Red(_)
as a wrapper.{:#flags}
wouldn't be enforced; different libraries can interpret it in very different ways. (E.g. would {:#abc}
be interpreted as three flags, or as one? It'd depend on the library.)
Proposal
(Originally I've posted this to https://github.com/rust-lang/rfcs/issues/3359 but I've noticed this place is more reachable by the libs team)
Problem statement
Currently,
std::fmt::Formatter::alternate
feature is meant to support just a singlebool
value, being written like"{:#}"
in format templates, but what if one wants to support multiple flags?There seemed to be a dedicated API for it:
std::fmt::Formatter::flags
, but this was marked as deprecated and even the return type is a magic numberu32
. A possible workaround is to abusestd::fmt::Formatter::fill
API to indicate a flag by a singlechar
, but this is still magical and there's no natural way to specify multiple flags at a time.Therefore, at this time, the only correct way to solve this is to provide a dedicated method like
MyType::to_string_with_flags
on the formatted type, that may cause unnecessary cognitive loads to their users.Motivation, use-cases
I wonder if the syntax
"{:#}"
was more extensive like"{:#flags}"
. This way, users can fully utilize the well-known macroformat!
instead of calling a dedicated method.I think the format of the flag string should be completely left to users because use cases definitely vary, such as:
#
!)Solution sketches
Ideally, the signature of
std::fmt::Formatter::alternate
should be changed to:But obviously this is a breaking change, so I'd propose a new method to be added:
where the resulting
&str
is the string after the#
. Of course it can be empty, i.e."{:#}"
=>Some("")
, so that thealternate
method can be implemented by justself.alternate_flags().is_some()
.Links and related work
What happens now?
This issue is part of the libs-api team API change proposal process. Once this issue is filed the libs-api team will review open proposals in its weekly meeting. You should receive feedback within a week or two.