golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
123.06k stars 17.55k forks source link

spec: use (*[4]int)(x) to convert slice x into array pointer #395

Closed rogpeppe closed 3 years ago

rogpeppe commented 14 years ago
Currently, it's possible to convert from an array or array pointer to a slice, but
there's no way of reversing 
this.

A possible syntax could be similar to the current notation for type assertions:

ArrayAssertion  = "." "[" Expression ":" Expression
"]" .

where the operands either side of the ":" are constant expressions.

One motivation for doing this is that using an array pointer allows the compiler to
range check constant 
indices at compile time.

a function like this:

func foo(a []int) int
{
    return a[0] + a[1] + a[2] + a[3];
}

could be turned into:

func foo(a []int) int
{
    b := a.[0:4];
    return b[0] + b[1] + b[2] + b[3];
}

allowing the compiler to check all the bounds once only and give compile-time errors
about out of range 
indices.
bcmills commented 3 years ago

Personally I'd prefer that we use the length of the slice. If a[i] would panic for the original slice, then I think (*A)(a)[i] should either panic or be statically disallowed.

josharian commented 3 years ago

the length of the slice must equal the length of the pointed-to array

Why == instead of >=? The conversation above has pretty consistently discussed >=.

mdempsky commented 3 years ago

To simplify measuring opinions here, I recommend:

josharian commented 3 years ago

Seems like there are some clear trends. :) I'll update the CLs.

nightlyone commented 3 years ago

@josharian I didn't see any release notes related to this. Could you make sure any of the changes get a RELNOTES=yes Tag so it won't be forgotten?

josharian commented 3 years ago

@nightlyone done. (None of them have been submitted yet, waiting on reviews.)

betawaffle commented 3 years ago

What about allowing conversion from *T to *[1]T as well? I would find that quite useful when trying to call a function that accepts a slice, but I have a single item already allocated from elsewhere.

bcmills commented 3 years ago

@betawaffle, that's an interesting idea, but this proposal was already approved as-is — want to file a separate proposal for converting between *T and *[1]T?

betawaffle commented 3 years ago

@bcmills: Thanks for the suggestion. Opened #45545.

gopherbot commented 3 years ago

Change https://golang.org/cl/312070 mentions this issue: cmd/compile: allow export/import OSLICE2ARRPTR

gopherbot commented 3 years ago

Change https://golang.org/cl/315169 mentions this issue: cmd/compile/internal/types2: slice-to-array-pointer conversion requires go1.17

gopherbot commented 3 years ago

Change https://golang.org/cl/325549 mentions this issue: doc/go1.17: document slice to array pointer conversion

gopherbot commented 3 years ago

Change https://golang.org/cl/327649 mentions this issue: cmd/compile: allow ir.OSLICE2ARRPTR in mayCall

gopherbot commented 3 years ago

Change https://golang.org/cl/334669 mentions this issue: reflect: add Value.CanConvert

gopherbot commented 3 years ago

Change https://golang.org/cl/336890 mentions this issue: doc: clarify non-nil zero length slice to array pointer conversion

gopherbot commented 3 years ago

Change https://golang.org/cl/338630 mentions this issue: compiler, runtime: allow slice to array pointer conversion

gopherbot commented 3 years ago

Change https://golang.org/cl/339329 mentions this issue: compiler: check slice to pointer-to-array conversion element type

danieljl commented 3 years ago

the length of the slice must equal the length of the pointed-to array

Why == instead of >=? The conversation above has pretty consistently discussed >=.

Maybe it's a bit too late to comment since the feature is already landed on Go 1.17, but I just want to point out that the >= behavior might lead to a hidden bug due to a different behavior expected by many programmers, i.e. they expect the conversion will success only if the lengths are equal. It violates the principle of least surprise.

The == behavior is also more explicit, which is usually preferred by the Go community, than the >= behavior: If the original slice's length is larger than the destination array's length, the slice needs to be first resized to the array's size.