-
Notifications
You must be signed in to change notification settings - Fork 18k
proposal: spec: allow slice-to-array conversion expressions to present as L-values. #47987
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
Converting a slice to an array results in a new, distinct array value (https://play.golang.org/p/9gaPIPkAe1I). So in [3]T(s[500:]) = [3]T{500, 501, 502} the store would be to a newly-allocated |
In contrast, the equivalent non-dead store (converting to a pointer-to-array rather than an array) works today (https://play.golang.org/p/jSgzz1SspWM): *(*[3]T)(s[500:]) = [3]T{500, 501, 502} |
@bcmills I reposted your code on play site here: package main
import "fmt"
type T int
func main() {
var s = make([]T, 10000)
var a [3]T = *(*[3]T)(s[500:])
fmt.Println(&a[0], &s[500])
}
It is depended on how the semantics is defined. In the above code, after the array |
I think my interpretation of the semantics is more consistent with the current pointer dereference: package main
import "fmt"
func main() {
var a = [3]int{1, 2, 3}
var p = &a
(*p)[2] = 9
fmt.Println(a) // 1 2 9
} |
Your interpretation is only more consistent with an incorrect understanding of Go's value semantics and conversion operations. Your proposal makes as much sense as this:
|
@dominikh they are two different conversions. The comparison is not fair. |
Again, this depends on how the slice-2-array conversion semantics is defined. Currently the following code is valid: package main
func main() {
var s = []int{1, 2, 3}
(*(*[1]int)(s))[0] = 9
println(s[0]) // 9
} If the conversion semantics is simply defined as a shortened form of package main
func main() {
var s = []int{1, 2, 3}
([1]int(s))[0] = 9
println(s[0]) // 9
} |
To me, the matter is rather simple: arrays are value-typed, conversions to arrays copy, and conversions to types with value semantics shouldn't be valid on the lhs. Whether conversions should ever be valid lhs is a different matter; currently they are not, which is another way in which your proposal is not consistent with the current language. Your "shortened form" interpretation is not just a "shortened form", it is akin to a macro, requiring the user (and the compiler, as far as semantics are concerned) to do string substitution in their mind to make sense of that assignment. Your proposal seems only consistent given the macro interpretation. Under any other interpretation, it is inconsistent with the existing language, the way conversions work, and the way value types work. You are proposing the addition of new behavior to the language; your proposal does not improve consistency with the existing semantics. |
As I have mentioned above. The new conversion might be different to the old ones. So the old rules might not work here. Off-topic, there are already some semantics inconsistencies in Go:
|
I think that is a red flag in and of itself. The new conversion should not be different from the old ones, because that would be an inconsistency in the language — and thus a source of complexity when reasoning about Go programs, for both end users and tool authors. |
Will the new conversion in the following code duplicate? package main
func main() {
var a [3]int
var s = make([]int, 9)
if a == [3]int(s[2:]) {
println("equal")
}
} |
Semantically, yes. But, as an optimization, the compiler may elide the copy, since that program can't actually detect whether a copy was made in memory. (This is analogous to the optimization that the compiler already does for many conversions from |
I agree with @bcmills and @dominikh. I don't think this proposal is consistent with Go semantics. Only variables are assignable, whereas conversions yield merely a value. The case can be made that this is a particular special case of conversions where an assignment can be reasonably defined. But that would make the language more irregular, not more regular. In my opinion, this is comparable to suggesting that we allow the assignment |
This proposal is more a suggestion to a new possibility. However, the comparison (and the above @dominikh's one) is not very appropriate. In fact, the conversion is more like the following one (though this one is not legal now): var x = new(int)
int(x) = 2 |
This proposal has been added to the active column of the proposals project |
Based on the discussion above, this proposal seems like a likely decline. |
No change in consensus, so declined. |
This proposal allow conversion from slice to array has already been accepted. But whether or not such conversion could be used as L-values is not decided along together. @ianlancetaylor suggested this undecided problem should be discussed in a new issue thread, so I created this one.
After the "allow conversion from slice to array" proposal is accepted, the following code will become valid in Go 1.18:
By my understanding, the semantics of the conversion
[N]T(s)
means viewing the firstN
elements (of typeT
) ins
as an array (of type[N]T
).The elements of a slice are always addressable and could be modified, even if the slice itself is not addressable. For example:
So the conversion results of
[N]T(s)
should be also always an addressable array, which means it could be used as L-values, a.k.a. it could be used as the destination values in value assignments. An example:The above is the rationale of this proposal.
The text was updated successfully, but these errors were encountered: