Skip to content
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

spec: result of slice expression of slice is ambiguous #64354

Closed
flimzy opened this issue Nov 23, 2023 · 2 comments
Closed

spec: result of slice expression of slice is ambiguous #64354

flimzy opened this issue Nov 23, 2023 · 2 comments

Comments

@flimzy
Copy link
Contributor

flimzy commented Nov 23, 2023

Quoting from the Go spec of of Aug 2, 2023 (emphasis added):

Slice expressions

For arrays or strings, the indices are in range if 0 <= low <= high <= len(a), otherwise they are out of range. For slices, the upper index bound is the slice capacity cap(a) rather than the length.

This means the following code is valid:

a := [5]int{1, 2, 3, 4, 5}
s := a[:1]
s2 := s[2:4]

Notably, the slice expression s[2:4] contains both a low and high indices that are > len(s).

So while this is explicitly permitted by the spec, the contents of s2 is not defined in the spec. We can infer from the definition of a Slice type that it contains the values of a at the requested indices, but this isn't actually specified. As such, given the following code:

	a := [5]int{1, 2, 3, 4, 5}
	s := a[:1]
	s2 := s[0:5]
	fmt.Println(s2)

My reading of the spec suggests that the output could be any of the following (non-exhaustive list):

[1 2 3 4 5]
[1 0 0 0 0]
[1 9999 9999 9999 9999]

IOW, strictly speaking, the contents of the slice elements which result from a slice expression whose indices exceed len(s) seems to be undefined.

Therefore I propose adding a small clarification to the spec, along the lines of:

For slices, it is the backing array which is consulted for the result elements, and upper index bound is the slice capacity cap(a) rather than the length.

@seankhliao
Copy link
Member

From slice types:

A slice, once initialized, is always associated with an underlying array that holds its elements. A slice therefore shares storage with its array and with other slices of the same array; by contrast, distinct arrays always represent distinct storage.

The array underlying a slice may extend past the end of the slice. The capacity is a measure of that extent: it is the sum of the length of the slice and the length of the array beyond the slice; a slice of length up to that capacity can be created by slicing a new one from the original slice. The capacity of a slice a can be discovered using the built-in function cap(a).

The contents are always known and defined (since array contents cannot arbitrarily change).

@seankhliao seankhliao closed this as not planned Won't fix, can't repro, duplicate, stale Nov 23, 2023
@flimzy
Copy link
Contributor Author

flimzy commented Nov 23, 2023

The contents are always known and defined

Agreed. But that's not the concern, either. The concern is that the spec doesn't make it clear that the underlying array is used when slicing a slice beyond the slice's length.

@golang golang locked and limited conversation to collaborators Nov 22, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants