-
Notifications
You must be signed in to change notification settings - Fork 1.6k
RFC: Split Show into String and Show #504
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Conversation
Today's `Show` trait will be tasked with the purpose of providing the ability to inspect the representation of implementors of the trait. A new trait, `String`, will be introduced to the `std::fmt` module to in order to represent data that can essentially be serialized to a string, typically representing the precise internal state of the implementor. The `String` trait will take over the `{}` format specifier and the `Show` trait will move to the now-open `{:?}` specifier.
cc @nick29581, @wycats, @seanmonstar, @aturon, I believe this is what we discussed during the work week. |
Looks reasonable to me. I think we should also add that if a type implements both String and parse-from-string APIs, parsing an emitted string should likely produce a semantically equivalent value. |
This seems pretty reasonable in general. I think there may be a bit of a distinction that should be made in the intended behavior of For example, rust-postgres's Thoughts? It seems like the intent for |
That is a good point @sfackler! I added a drawback at the last second about how the guarantees provided by
|
I didn't mean to suggest that round-tripping would be mandated; just that if a from-string implementation existed, and String was implemented, it should roundtrip. |
I vaguely recall a suggestion that we would implement (Just something to consider.) |
I specifically would never mention round-tripping, because it causes confusion. If you want round-tripping, use the @huonw yes, fwiw, the RFC I wrote about this on Friday: https://gist.github.com/seanmonstar/94208ff568d1b9f71914 |
@huonw yes as @seanmonstar mentioned the @seanmonstar I do think it's useful to have a distinction where if |
The name I wonder if it would be useful to enforce an invariant that anything implementing |
@alexcrichton I use FromStr for basic parsing in hyper. For example, |
@P1start it's easier to see if you view it as |
I agree with @seanmonstar that we should not use either of these traits for round-trip parsing (or at least we shouldn't grow to expect that behavior) - you should use a more principled system like encodable/decodable. |
@P1start RFC 356 has outlined that module prefixes should not be included in type names while also emphasizing that the name of a type or trait should be scoped to the module that it is defined in. For example the I also have added some specific text that the @seanmonstar I'm not sure I understand your example, that sounds like it fits into the design outlined in this RFC? @reem note that these traits are not necessarily connected to round-trip parsing at all. The |
@alexcrichton Quite often I do something like this in a struct Foo {
x: Vec<int>,
y: Vec<f64>,
}
impl fmt::Show for Foo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.x.fmt(f);
self.y.fmt(f);
}
} With the name Regarding |
…
You can’t have both. If I was confused when first reading the RFC: I expected the round-trippable trait to be the debugging one, both separate from the "default" one. |
I find this very unfortunate, since that static guarantee can likely not be added backward-compatibly. Can you expand on why you’re not willing to stabilize |
@P1start that should compile today and use the @SimonSapin that is correct about string slices, but I also still believe that we cannot stabilize |
Ah, I was confused just as Simon was: I misread and thought Still, I think the round-trip promises should be left to the |
As for @P1start concerns, if you imported both into the same module, you would need to use UFCS to disambiguate. See http://is.gd/gjCmby Instead, I'd need to write |
I'm also just slightly against the
|
Did that decision about
All interesting questions, that I think can be resolved backward-compatibly after 1.0. By the way, from the RFC:
It’s not clear to me at all what the |
No, it prints numbers in binary, just like |
I actually got my traits mixed up ;) For what it's worth, what I was trying to get across actually wasn't "round tripping", but rather the idea that unlike An example of a possible problem for Essentially, what I'm trying to say is that |
That makes sense. |
Yes. When @aturon and I were discussing the traits the questions we raised (some I pasted above) were why we avoided attempting to add a
Maybe, but I'm not personally convinced that they will have answers in a reasonable time frame (e.g. taking into account possible language features coming down the pike). @seanmonstar, @wycats I intend for the following impl to exist: impl fmt::String for String {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.as_slice().fmt(f) }
}
impl fmt::String for str {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write(self.as_bytes()) }
}
impl fmt::Show for String {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.as_slice().fmt(f) }
}
impl fmt::Show for str {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, "\""));
for c in self.chars().flat_map(|c| c.escape_default()) {
try!(write!(f, "{}", c));
}
write!(f, "\"")
}
} Does that help clear up what |
Personally I think So, in a Ruby sense, this proposal suggests |
Note: this may be a good time to reconsider rust-lang/rust#16544 |
@SimonSapin Wow, indeed! Looks like you posted that just before I started on Rust :-) |
Demonstrating my Python background (where these things are the magic methods I also feel that the semantics of these traits needs to be tightened. |
@aturon That's a good point, I had forgotten about that issue! I think we may want to focus this RFC on the semantic meanings of @chris-morgan could you elaborate on how you think the semantics need to be tightened? Do you feel that the |
+1, I like |
I also wonder if the deriving should be opt-out, or even mandatory. My So, String couldn't be mandatory, because not all types have semantic |
Ah, I meant |
@alexcrichton what do you think of including a lint that checks all things implement Show (or allow the lint), similar to Copy? It'd greatly help deriving Show on new structs. |
A lint seems like a good idea to me. |
I'd be ok with adding a lint so long as it was allow-by-default. I personally also believe that the Copy lint should be allow-by-default as it's too noisy as warn-by-default. |
allow-by-default lints are much less useful for discoverability: by definition you have to already know about them to see them. Would it make sense to have another level between allow and warn, where a given lint will print at most one message per crate? Something like "Some types don’t implement |
I'm more okay with a |
I've pushed a commit which tones down the wording about "round tripping" through |
This RFC has been accepted. Thank @alexcrichton for writing this RFC (and @seanmonstar for helping kick it off). It's great to finally resolve this thorny question! There's broad support for the proposed design here, especially now with the toned-down guideline about roundtripping. We'll leave open the question of size hints for formatters (which we intend to address). |
Per this RFC: rust-lang/rfcs#504
Today's
Show
trait will be tasked with the purpose of providing the ability toinspect the representation of implementors of the trait. A new trait,
String
,will be introduced to the
std::fmt
module to in order to represent data thatcan essentially be serialized to a string, typically representing the precise
internal state of the implementor.
The
String
trait will take over the{}
format specifier and theShow
traitwill move to the now-open
{:?}
specifier.Rendered