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
proposal: Go 2: spec: remove special cases for strings in conversions, append, and copy #24529
Comments
In making this argument, it would help to see counts of how often the feature is used in the standard library and in some collection of popular Go packages. If a feature is used frequently, then it is likely worth keeping even if removing it would simplify the language. Perhaps the feature should never have been added in the first place, but now that it is there removing it will have a cost. Go 2 is not starting from a blank slate; we can't ignore the cost of changing the existing language. |
@ianlancetaylor Agreed, but there's been talk of removing features from Go 2 to keep the language simple on balance. I've had more than my share to say about what should be added so I thought it only fair to look for something that could be removed. Replacing all of the conversions with library functions is easily go fixable. For copy and append, removing these special cases could allow them to be defined as standard generic functions and is as go fixable. I wrote a program to count uses of these special cases (as best as I was able, I'm not sure if I got all the cases correct, review/PRs welcome) https://github.com/jimmyfrasche/string-special-case-counter Running
(has to type check so this is just for GOARCH=amd64 GOOS=linux and it skips all vendor directories to avoid double counting) reports:
(lloc are counted as distinct lines reported by the FileSet per File). |
Thanks. I'm curious now: can you tell us what the 10 instances of |
Interestingly that particular one seems to almost entirely exist in xtest packages: import/path:file:line
|
|
A potential upgrade path, should this (or a subset, like #3939) be accepted:
That
The majority of the work can be done under Go 1. |
To me, the conversion operations and the special-cases in The conversion operations, as you note, hide expensive operations in seemingly-simple conversions and add a bunch of complexity when reasoning about defined types. On the other hand, the special-cases in |
@bcmills that's very true but it would still be more consistent and simpler if they were all gone. I'd rather something cheap looked expensive (and explicit) but was optimized out, personally. Also, if Go2 gets generics, the existing generic built ins are going to have to work with whatever that entails and having a simpler type parameterization may make that simpler. My main goal with this issue was to consider this class of cases as a whole: all, some, or none can be removed, of course. |
I wonder how many times I should update my program to count those separately. I wouldn't expect to find many, if any at all, in the stdlib or x/ packages. @ianlancetaylor do you have any suggestions for a collection of popular Go packages to analyze? I guess I can just go with what gddo lists as popular (not otherwise counted so far). |
If you find many |
In cmd std golang.org/x/{crypto,image,net,sys,text,tools}/... there are
and
(for go 1.10.1 and I updated golang.org/x/ less than a week ago) |
Here are the results for a handful of random packages. I looked at some others but only included results from trees that my program could fully analyze due to test deps I didn't want to track down: gopkg.in/yaml.v2/... string(rune): 1 append([]byte, string...): 0 append([]byte, []byte(string)...): 0 packages examined: 2 github.com/gorilla/websocket/... string(rune): 0 append([]byte, string...): 28 append([]byte, []byte(string)...): 0 packages examined: 6 github.com/gorilla/mux/... string(rune): 0 append([]byte, string...): 0 append([]byte, []byte(string)...): 0 packages examined: 2 github.com/dgrijalva/jwt-go/... string(rune): 0 append([]byte, string...): 0 append([]byte, []byte(string)...): 0 packages examined: 5 github.com/aws/aws-sdk-go/... string(rune): 0 append([]byte, string...): 0 append([]byte, []byte(string)...): 0 packages examined: 386 github.com/pkg/errors/... string(rune): 0 append([]byte, string...): 0 append([]byte, []byte(string)...): 0 packages examined: 2 |
How is that substantially different than other compiler intrinsics? |
It's my understanding that methods, intrinsic or not, are not allowed in constant expressions (feel free to provide a counter-example if I've forgotten something.) |
@jvusich that's a good point. Without additional loosening of what's considered a constant expression (unlikely), those are lost. But they're not exactly widely used now and can be rewritten using escapes in string literals A const block using that and It would work if the functions were built ins ( |
Conversions between |
Strings have a number of special cases in the spec.
Some or all of these special cases should be considered for removal in Go 2 in order to to buy complexity for more general features.
Conversions from
string
to[]byte
or[]rune
These can be replaced by conversion functions in the
strings
package.strings.Bytes(s)
is not as concise as[]byte(s)
but it clearer that work (allocation) is being done.Conversion from
[]byte
tostring
This can be a function in the
bytes
package.Conversion from
byte
orrune
tostring
This could be a function in
unicode/utf8
(takingrune
since you can convert abyte
torune
easily)Append and copy
There is a special case in
append
allowingand a special case in
copy
allowingThe equivalent code with an explicit conversion is clearer.
The text was updated successfully, but these errors were encountered: