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: an uninitialized slice (and other types) is nil, yet a slice variable is initialized to its zero (nil) value #20186

Open
alercah opened this issue Apr 30, 2017 · 5 comments

Comments

@alercah
Copy link

commented Apr 30, 2017

I have two small issues with the definition of a slice type:

A slice, once initialized, is always associated with an underlying array that holds its elements.

This is not true of a nil slice. Since this refers to initialization, it is talking about variables and not values. Changing this to "A non-nil slice value..." would probably fix this, since initialization of slices is already well-defined elsewhere.

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; ...

This is not true of a slice whose capacity has been explicitly reduced. This is easily fixed by removing the explicit definition of capacity here and then, in the section on slice expressions, explicitly saying that the capacity of the slice a[low:high] is cap(a) - low. This also solves an ambiguity in that the capacity of a[:] is not actually defined and, based on the quoted statement, could be argued to extend the capacity back of up that of the underlying array if a is a limited-capacity slice.

@bradfitz bradfitz added this to the Unplanned milestone Apr 30, 2017

@Merovius

This comment has been minimized.

Copy link

commented Jul 22, 2019

In a similar vein:

  • The spec doesn't specify length and capacity of []int{}. It says that a slice-literal has length/capacity of "the maximum element index plus one", but there is no element index in this case, so this isn't technically specified
  • The spec says that slices may be compared to the predeclared identifier nil - but it doesn't actually specify the results of that comparison.
  • The spec says that an uninitialized slice has value nil. It doesn't say, that an initialized slice doesn't have the value nil. So, I'd argue, technically comparison to nil could always be true and still be compliant. At the very least, I think it would be compliant to have every zero-length slice be nil.

I think the spec basically treats "uninitialized" and "nil" as equivalent. In particular, it does specify that a slice-literal, make and dereferencing a pointer returned by new all yield an initialized value. I think the simplest fix to the issues I'm bringing up would be to specify that comparison to nil yields true if and only if the slice is an initialized value. A different fix would be to specify "non-nil", whenever we talk about initialized values.

However, especially with the issues originally brought up here, I don't really feel confident to judge whether these actually yield consistent results…

@griesemer griesemer changed the title spec: small issues with slice type definition spec: an uninitialized slice (and other types) is nil, yet a slice variable is initialized to its zero (nil) value Sep 11, 2019

@griesemer

This comment has been minimized.

Copy link
Contributor

commented Sep 11, 2019

@alercah Thanks for this issue, I finally took a look at this. I think you're absolutely right about the initialization problem. In fact, the spec says elsewhere that variables which have no initialization expression are initialized to their zero value, which would be nil for slices, which directly contradicts what we say about the underlying array.

The same is true for pointers (an uninitialized pointer is nil, but then aren't pointer variables initialized to their zero value, which is nil?), function types, maps, channels, interfaces, etc. Seems inconsistent and probably deserves some careful rewording or more selective use of the word "initialize".

Regarding the capacity of an explicitly reduced slice: You're right that in the implementation the length of the array beyond the slice is (may be) longer than what the reduced capacity claims it is, but there's no way to access that part of the array from that slice, so it might as well not exist (and theoretically, one could imagine a system that actually shrinks that underlying array). So I'm not sure there's much to do here.

Retitling this issue to be clearer what it's about.

@griesemer

This comment has been minimized.

Copy link
Contributor

commented Sep 11, 2019

@Merovius Regarding:

  • a slice-literal has length/capacity of "the maximum element index plus one"

Here the maximum element index is considered in the abstract - it's the highest index of any element present. Even if there are literal element indices, not all elements are required to have one, and the element with the largest actual index may not have literally an index in the source. But perhaps this can be formulated a bit clearer.

  • slices may be compared to the predeclared identifier nil

You're correct, in a mathematically exact sense this is underspecified. Maybe this can be written down w/o the spec coming across overly pedantic.

  • It doesn't say, that an initialized slice doesn't have the value nil

Fair enough. I'd say, this is similar to your 2nd point. We've been trying to keep the spec reasonably readable, probably at the cost of some precision.

Will try to address when we try to fix this issue. Not urgent.

@griesemer griesemer modified the milestones: Unplanned, Go1.14 Sep 11, 2019

@alercah

This comment has been minimized.

Copy link
Author

commented Sep 11, 2019

With respect to the second issue, I don't think there's nothing to be done. Perhaps focusing on the language about the underlying array was a mistake there. Regardless, though, slice expressions that don't explicitly specify the capacity of the resulting slice and I believe that they should.

@griesemer

This comment has been minimized.

Copy link
Contributor

commented Sep 11, 2019

@alercah Ah, I see your point. Yes, it's unclear what the size of the underlying array is in these cases and this muddles the notion of capacity. Agree that this should be clearer. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants
You can’t perform that action at this time.