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: definition for iota doesn't make sense for nested ConstDecls #15550

Closed
mdempsky opened this issue May 5, 2016 · 10 comments
Closed

spec: definition for iota doesn't make sense for nested ConstDecls #15550

mdempsky opened this issue May 5, 2016 · 10 comments
Labels
FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done.
Milestone

Comments

@mdempsky
Copy link
Contributor

mdempsky commented May 5, 2016

This program should print 1, but cmd/compile rejects it with an "undefined: iota" error.

package main

import (
        "fmt"
        "unsafe"
)

const (
        _ = unsafe.Sizeof(func() int {
                const (
                        _ = 1
                        _
                        _
                )
                return 0
        }())

        y = iota
)

func main() {
        fmt.Println(y)
}
@mdempsky mdempsky added this to the Go1.8 milestone May 5, 2016
@mdempsky mdempsky self-assigned this May 5, 2016
@mdempsky
Copy link
Contributor Author

mdempsky commented May 5, 2016

Two side thoughts:

  1. Arguably the Go spec says it should print 3 (not 1, like I say above), because the value of iota is said to reset whenever the const keyword appears in the source, not in the block. I suspect that's just because the Go spec's wording wasn't written with nested const declarations in mind.

  2. Should

    const _ = unsafe.Sizeof(func() int {
        var _ int
        return iota
    })
    

    be valid? Arguably iota here is appearing inside a ConstSpec so it should be allowed by the spec, yet cmd/compile, gotype, and gccgo all reject it. (cmd/compile accepts it if you remove the var declaration.)

/cc @griesemer @ianlancetaylor

@griesemer
Copy link
Contributor

Yes, I would agree that there's (among other things) a spec issue here - each scope should have its own iota. I think we can safely make that adjustment in the spec w/o affecting real-life code.

Regarding the comments:

  1. Per the strict spec interpretation, it should print 4 rather than 3, no?
  2. I think if we fix the spec, the example in 2) should not be permitted.

@mdempsky
Copy link
Contributor Author

mdempsky commented May 5, 2016

@griesemer Ah, agreed that strict interpretation supports printing 4, not 3. (And so gccgo is actually technically conforming.)

@mdempsky mdempsky changed the title cmd/compile: mishandling of contrived iota use case spec: definition for iota doesn't make sense for nested ConstDecls Jul 14, 2016
@mdempsky
Copy link
Contributor Author

Per discussion on #15551, I'm reclassifying this as an issue against the spec. Based on how we resolve this issue, we can then (re)open issues against the compilers / typecheckers to fix their behavior as appropriate.

@quentinmit quentinmit added the NeedsFix The path to resolution is known, but the work has not been done. label Oct 10, 2016
@rsc rsc modified the milestones: Go1.9, Go1.8, Go1.9Early Oct 18, 2016
@gopherbot
Copy link
Contributor

CL https://golang.org/cl/36122 mentions this issue.

gopherbot pushed a commit that referenced this issue Feb 2, 2017
When switching to the new parser, I changed cmd/compile to handle iota
per an intuitive interpretation of how nested constant declarations
should work (which also matches go/types).

Note: if we end up deciding that the current spec wording is
intentional (i.e., confirming gccgo's current behavior), the test will
need to be updated to expect 4 instead of 1.

Updates #15550.

Change-Id: I441f5f13209f172b73ef75031f2a9daa5e985277
Reviewed-on: https://go-review.googlesource.com/36122
Reviewed-by: David Crawshaw <[email protected]>
Reviewed-by: Robert Griesemer <[email protected]>
Reviewed-by: Josh Bleecher Snyder <[email protected]>
Run-TryBot: Josh Bleecher Snyder <[email protected]>
TryBot-Result: Gobot Gobot <[email protected]>
@bradfitz bradfitz modified the milestones: Go1.9Maybe, Go1.9Early May 3, 2017
@bradfitz bradfitz modified the milestones: Go1.9Maybe, Go1.10 Jul 20, 2017
@gopherbot
Copy link
Contributor

Change https://golang.org/cl/71750 mentions this issue: spec: clarify that each block has its own version of iota

@mdempsky
Copy link
Contributor Author

mdempsky commented Oct 19, 2017

Oops, I just noticed there are still two mentions of iota being "incremented":

(iota is not used but still incremented)

Within an ExpressionList, the value of each iota is the same because it is only incremented after each ConstSpec:

Since we got rid of the definition that iota "increments" after each ConstSpec, should these be reworded too?

I think there's also still the question of whether this is valid:

const _ = unsafe.Sizeof(func() int { return iota })

Currently, I think the spec's wording permits it, but none of the compilers do. I'm leaning towards the compilers are wrong here. Partly because I think disallowing this in the spec is too clumsy, and partly because it seems natural that function literals should be allowed to still access any declared objects in scope just as if they weren't in a function literal.

@griesemer
Copy link
Contributor

@mdempsky All good points. I'm fixing the "increments" parts ( I think we just don't need those comments anymore, including the references to "reset" ). Still thinking about the use of iota inside a function with const decl.

@griesemer
Copy link
Contributor

@mdempsky We should probably allow iotas anywhere in an expression. There's no real harm here, and as you say, it would be pretty awkward to exclude selected special cases. For instance, this actually works:

const n = len([iota]int{})

( https://play.golang.org/p/iEFCsj_L_0 )

@gopherbot
Copy link
Contributor

Change https://golang.org/cl/71912 mentions this issue: spec: remove vestiges referring to iotas being incremented

gopherbot pushed a commit that referenced this issue Oct 19, 2017
https://golang.org/cl/71750 specifies iota values as indices,
thus making them independent from nested constant declarations.
This CL removes some of the comments in the examples that were
still referring to the old notion of iotas being incremented
and reset.

As an aside, please note that the spec still permits the use
of iota in a nested function (like before). Specifically, the
following cases are permitted by the spec (as before):

1) const _ = len([iota]int{})
2) const _ = unsafe.Sizeof(func(){ _ = iota })

For #15550.

Change-Id: I9e5fec75daf7b628b1e08d970512397e9c348923
Reviewed-on: https://go-review.googlesource.com/71912
Reviewed-by: Ian Lance Taylor <[email protected]>
Reviewed-by: Rob Pike <[email protected]>
Reviewed-by: Matthew Dempsky <[email protected]>
@golang golang locked and limited conversation to collaborators Oct 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done.
Projects
None yet
Development

No branches or pull requests

6 participants