-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC: Split Show into String and Show #504
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