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

cmd/compile: iota can be shaddowed in functions, but can't in top level. #20219

Closed
go101 opened this issue May 3, 2017 · 14 comments
Closed

cmd/compile: iota can be shaddowed in functions, but can't in top level. #20219

go101 opened this issue May 3, 2017 · 14 comments
Labels
FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done.
Milestone

Comments

@go101
Copy link

go101 commented May 3, 2017

Please answer these questions before submitting your issue. Thanks!

What version of Go are you using (go version)?

go version go1.8.1 linux/amd64

What did you do?

package main

const iota = iota // constant definition loop

func g() {
	const iota = iota // ok
}

func main(){}
@go101 go101 changed the title cmd/compile: iota can be shaddowed in functions, but can can't in top level. cmd/compile: iota can be shaddowed in functions, but can't in top level. May 3, 2017
@bradfitz
Copy link
Contributor

bradfitz commented May 3, 2017

/cc @griesemer @mdempsky @josharian

@bradfitz bradfitz added this to the Go1.9Maybe milestone May 3, 2017
@bradfitz bradfitz added the NeedsFix The path to resolution is known, but the work has not been done. label May 3, 2017
@mdempsky mdempsky closed this as completed May 3, 2017
@mdempsky
Copy link
Member

mdempsky commented May 3, 2017

const x = x isn't valid at package scope. What would x's value be?

@go101
Copy link
Author

go101 commented May 3, 2017

iota is predeclared in builtin package.
And if it is invalid in package scope, it should also be invalid in local scopes.

@mdempsky
Copy link
Member

mdempsky commented May 3, 2017

The scope of package level const declarations is the entire package. The scope of function-level const declarations begins after the declaration.

After explicit renaming, your code is:

package main

const iota.0 = iota.0 // constant definition loop

func g() {
	const iota.1 = iota.0 // ok
}

@go101
Copy link
Author

go101 commented May 3, 2017

The program in my first comment is two programs in fact

1:

package main

func g() {
	const iota = iota // ok
}

func main(){}

2:

package main

const iota = iota // constant definition loop

func main(){}

they should be consistent.

@mdempsky
Copy link
Member

mdempsky commented May 3, 2017

That's correct. gccgo and go/types emit the same errors.

This is working according to spec.

@go101
Copy link
Author

go101 commented May 3, 2017

Which paragraph in spec?

@mdempsky
Copy link
Member

mdempsky commented May 3, 2017

Declarations and scope

  1. The scope of an identifier denoting a constant, type, variable, or function (but not method) declared at top level (outside any function) is the package block.
  1. The scope of a constant or variable identifier declared inside a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl for short variable declarations) and ends at the end of the innermost containing block.

@go101
Copy link
Author

go101 commented May 3, 2017

but iota is a predeclared constant.

@mdempsky
Copy link
Member

mdempsky commented May 3, 2017

@go101
Copy link
Author

go101 commented May 3, 2017

I think you misunderstand the spec.

package main


func g() {
	const iota = iota // ok
	
	const a = a // undefined: a

	// they should be consistent if iota is viewed as undeclared.
}

func main(){}

@griesemer
Copy link
Contributor

griesemer commented May 3, 2017

@go101 iota is predeclared, but in your program you're not referring to it:

package p
const iota = iota

The first thing that happens is that you declare a new identifier iota in the package (right after the const keyword) and that identifier is shadowing the predeclared iota. Afterwards you use that same one as initial value (not the predeclared one), hence the cycle.

If you're inside a function, the starting point of the scope of identifier iota is after the complete declaration (i.e., after the initialization expression), thus the iota you're referring to in the initialization expression is the one that's visible from the outer scope (either the package scope or Universe scope), and it this case you get the predeclared iota. Which is why you don't get an error in this case.

The difference between the two is simply the point where visibility of the newly declared identifier starts. At the package level it's right away; inside functions it's always after the declaration (except for types).

@cznic
Copy link
Contributor

cznic commented May 3, 2017

const iota = iota // ok

Because RHS is defined.

const a = a // undefined: a

Because RHS is undefined.

@go101
Copy link
Author

go101 commented May 3, 2017

ok, this is really subtle.

@golang golang locked and limited conversation to collaborators May 3, 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