-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[SR-11001] Collections description ends up invoking debugDescription of elements #53391
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
Comments
Comment by Jens Jakob Jensen (JIRA) I vote for this being a bug and not a new feature. |
Collections deliberately call |
Comment by Jens Jakob Jensen (JIRA) Would it be possible to fix that in another way? I.e. what if a custom I really think |
Why does it matter, though? A collection's (cc @airspeedswift and @jckarter) |
I can see the intent behind trying to make
For reference the outputs are in CLI/Playgrounds: 16> thing
$R0: Thing = {
name = "Bob"
_hidden = "hello long text"
_dontTellAnyone = "so many words!!!"
}
17> "\(thing)"
$R1: String = "DESC"
18> String(describing: thing)
$R2: String = "DESC"
19> String(reflecting: thing)
$R3: String = "DEBUG"
20> String(describing: [thing])
$R4: String = "[DEBUG]"
21> String(reflecting: [thing])
$R5: String = "[DEBUG]" thing // DEBUG // ok, makes sense; we are interactive and inspecting after all
"\(thing)" // "DESC" // ok, the string repr is the .description after all
String(describing: thing) // "DESC" // ok
String(reflecting: thing) // "DEBUG" // ok
String(describing: [thing]) // "[DEBUG]" // weird (!)
String(reflecting: [thing]) // "[DEBUG]" // ok, I requested "debug info" > Why does it matter, though? A collection's description already isn't suitable for anything in particular. From my perspective there's two or three use cases when people might see such printouts:
If we are mostly worried about string outputs in collections, perhaps as Hugin777 (JIRA User) suggests, it should be the collection's `.description` implementations task to do something about it? (escape) — What it comes down to for libraries I think is this: If we can't reasonably expect that Since it may print out all the internal complex details that my types abstract away for not-expecting users which just wanted to log "what are my things?", and the things happened to be in a collection, while printing them one by one is totally fine... It would feel wrong to have to tell users "you can include this value in your logs, but whoa, better don't log a collection of them!", so we'd have to make sure the "not scary" output happens in those cases as well by not using On the other hand, since playgrounds always invoke |
This part of Swift was very intentionally designed as it is, modeled on Python. In [22]: class X(object):
...: def __repr__(self): return 'repr' # analogous to debugDescription
...: def __str__(self): return 'str' # analogous to description
...:
In [23]: str([X(), X()])
Out[23]: '[repr, repr]' The reason for this design is that preserves a number of properties that I consider to be essential to an understandable experience for users:
where
If there's another design that preserves these output properties and achieves the requested consistency, I'd have no objection, but I cannot imagine most users being willing to sacrifice these properties in order to get more consistent dispatching of functionality to |
Thanks for more background here Dave. I can definitely see that as being desirable when explained like that. Could we somehow improve documentation, be it here https://developer.apple.com/documentation/swift/customdebugstringconvertible or elsewhere to give these examples (explaining that this is one purpose, and for those reasons)? It would have helped a lot when deciding if and how to conform to this protocol. In my case, it is datastructures which will definitely be printed and logged by users a lot, yet they really never should care about many fields those structures have (and thus I should not show them in neither More in general my takeaway from this discussion is that "description"/"debugDescription" should not be used to hide/show fields which you'd not want users to see in "normal day to day programming" (which is how we understood those protocols when we started out adopting them). And rather, as the docs do suggest – but I didn't quite get the message when first reading it, without the context from this ticket – one would want also not show that "not important for normal users" field in Would that be a fair characterization of how to best to view the print capabilities? |
Perhaps the issue lies in the fact that we're using two customization points to describe three or four different concepts:
We don't seem to have consensus that #3 is usable for #2, despite that being what Swift does today. |
Hey Nate, yeah I think that's the root problem... I could always work around all this by doing It feels a bit off that for actual interactive println debugging |
I don't think it would be entirely unreasonable to handle aggregate elements via a special case for things conforming to Strings are just different from other things in that their printed representations are too irregular to be presented among other data without qualification by quotes and escapes. |
I'm with @ktoso here and really like @dabrahams suggestion. I feel it's pretty strange to call @natecook1000's 3/4 concepts in 2 customisation points seems to indeed be the core issue. The current solution however means that |
@swift-ci create |
Additional Detail from JIRA
md5: 1d0d6cf976a9b368d4533a89dca6f9ab
Issue Description:
Swift version Apple Swift version 5.0-dev (LLVM f961e3dd74, Swift ff641d3)
Let's say I have a carefully designed type with information which is definitely enough for users to identify and observe a value, as well as some "very internal, noone should care, unless debugging" state:
Printing the type works as expected:
Yet printing it as part of a collection now, which users of my library may happen to do:
Now all that carefully hidden state is being printed while invoking the collection's `.description`⚠️
This seems like an omission / confusion;
Current behavior
Expected behavior
The reason this happens seems to be that all collections share an implementation here, which ends up calling
debugPrint(item
, regardless if debug printing or not: https://github.com/apple/swift/blob/e9d827ca3c809f511ebb53d169d6ce11d396eec3/stdlib/public/core/ArrayShared.swift#L83Happy to work on a fix if this indeed was an oversight and not intended behavior (albeit quite weird one then).
The text was updated successfully, but these errors were encountered: