You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
proposal: spec: language: make slices of constant strings constant if the indexes are constant #28591
This will probably be assigned a Go2 label, although I think that it could be done during Go 1.
Consider multiline string constants:
constmultiline=`This is a long textthat spans multiple linesand then ends.`
If you feed this text to a parser and it finds a problem on the first line ("This is a long text"), it will actually report that the error is on the second line because of the leading newline. One might think that this is easily solved by slicing the string:
constmultiline=`This is a long textthat spans multiple linesand then ends.`[1:]
(…) For untyped string operands the result is a non-constant value of type string. (…)
Why not make it constant? After all, len(multiline) is constant.
There are other solutions to this. One could just use multiline[1:] everywhere where one doesn't want the leading newline. Or start "This is a long text" on the first line, but that hurts readability and "editability". Another solution is to make multiline a variable. The use case is pretty obscure and there isn't an immediate need for this, so this proposal is more about a question, why are slices (and indexing!) of constant strings not constant in the first place?
changed the title [-]proposal: make slices of constant strings constant if the indexes are constant[/-][+]proposal: spec: make slices of constant strings constant if the indexes are constant[/+]on Nov 5, 2018
changed the title [-]proposal: spec: make slices of constant strings constant if the indexes are constant[/-][+]proposal: Go 2: language: make slices of constant strings constant if the indexes are constant[/+]on Nov 5, 2018
It turns out that this proposed change is not backward-compatible after all ...
Consider "A"[0] : With the proposed change, this expression evaluates to the untyped byte constant 65. But if we try to negate this value, as in:
var_=-"A"[0]
we will get an error: -"A"[0] (constant -65 of type byte) overflows byte . This is currently (without the change) valid code. Oops!
For similar reasons, constant index expressions are not backwards-compatible either. The length of a constant slice expression len("abc"[0:2]) is an untyped integer constant (3), but if we negate it and try to assign it to a variable of uint type, we will get an error.
var_uint=-uint(len("abc"[0:2]))
(Without the change, these values are not constant, and the compiler won't complain.)
Fun times!
Reacted by Dmitri Shuralyov, Marcelo Pires, Bryan C. Mills, Saeed Rasooli, QuantumGhost, Frédéric G. MARAND, Neil, Daniel Martí, cherrymui, Finn Bear and 4 more
Reacted by Gert Cuykens, Oleku Konko, Oleh, caelifer, Saeed Rasooli, QuantumGhost, Thalia Archibald, Andrey Tsvetkov, Frédéric G. MARAND, Daniel Martí and 7 more
The degree to which a strict reading of backward compatibility leaves little room to maneuver is constantly surprising.
Reacted by Josh Bleecher Snyder, jimmyfrasche, Liam Breck, Tej Chajed, Viswajith Venugopal, Aurélien Rainone, Frédéric G. MARAND, Vladimir Skipor, Akhil Indurti, Ahmed W. and 3 more
Reacted by Joop Kiefte, Thalia Archibald and Eric Lagergren
This was proposed for Go 1.15 (https://blog.golang.org/go1.15-proposals) but declined because it is not backwards compatible. Leaving open for some future breaking change (maybe).
Spoiler: the difference arises from the top-down effect of the enclosing type (byte) on the shift operator when its right operand is non-constant. Thus 1 << len(s[:]) is truncated to byte. The type rules for shifts are the most complex of all...
Reacted by Ainar Garipov, zigo101, Tom Thorogood, Eliaz Bobadilla and kiga
Given the new extended forward compatibility mechanism, this breaking change could be implemented in files that set a sufficiently high minimum Go version.
changed the title [-]proposal: Go 2: language: make slices of constant strings constant if the indexes are constant[/-][+]proposal: spec: language: make slices of constant strings constant if the indexes are constant[/+]on Aug 6, 2024
Activity
[-]proposal: make slices of constant strings constant if the indexes are constant[/-][+]proposal: spec: make slices of constant strings constant if the indexes are constant[/+][-]proposal: spec: make slices of constant strings constant if the indexes are constant[/-][+]proposal: Go 2: language: make slices of constant strings constant if the indexes are constant[/+]ianlancetaylor commentedon Nov 5, 2018
Marking as Go 2 because we've decided that all language changes are Go 2.
I know that this has been discussed in the past but I don't remember why it wasn't changed. Maybe simply because it rarely comes up in practice.
ianlancetaylor commentedon Dec 11, 2018
We should also consider accepting
griesemer commentedon Jan 29, 2020
It turns out that this proposed change is not backward-compatible after all ...
Consider
"A"[0]: With the proposed change, this expression evaluates to the untyped byte constant 65. But if we try to negate this value, as in:we will get an error: -"A"[0] (constant -65 of type byte) overflows byte . This is currently (without the change) valid code. Oops!
For similar reasons, constant index expressions are not backwards-compatible either. The length of a constant slice expression
len("abc"[0:2])is an untyped integer constant (3), but if we negate it and try to assign it to a variable of uint type, we will get an error.(Without the change, these values are not constant, and the compiler won't complain.)
Fun times!
griesemer commentedon Jan 29, 2020
Related: #11370, #11368.
jimmyfrasche commentedon Jan 29, 2020
Would
be legal?
griesemer commentedon Jan 29, 2020
@jimmyfrasche Very nice! Indeed it would.
6 remaining items
alandonovan commentedon Feb 6, 2020
The degree to which a strict reading of backward compatibility leaves little room to maneuver is constantly surprising.
TapirLiu commentedon Mar 22, 2020
One more case:
Currently it compiles, but if
len(""[:])returns constant 0, it will not.rsc commentedon May 6, 2020
This was proposed for Go 1.15 (https://blog.golang.org/go1.15-proposals) but declined because it is not backwards compatible. Leaving open for some future breaking change (maybe).
zigo101 commentedon Sep 23, 2020
Another incompatible case:
It will print
4 4if this proposal is adpoted.alandonovan commentedon Sep 23, 2020
@go101 That's diabolical.
Spoiler: the difference arises from the top-down effect of the enclosing type (byte) on the shift operator when its right operand is non-constant. Thus
1 << len(s[:])is truncated to byte. The type rules for shifts are the most complex of all...adonovan commentedon Jan 25, 2024
Given the new extended forward compatibility mechanism, this breaking change could be implemented in files that set a sufficiently high minimum Go version.
[-]proposal: Go 2: language: make slices of constant strings constant if the indexes are constant[/-][+]proposal: spec: language: make slices of constant strings constant if the indexes are constant[/+]