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

Comments

Projects
None yet
6 participants
@go101
Copy link

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

This comment has been minimized.

Copy link
Member

commented May 3, 2017

@bradfitz bradfitz added this to the Go1.9Maybe milestone May 3, 2017

@bradfitz bradfitz added the NeedsFix label May 3, 2017

@mdempsky mdempsky closed this May 3, 2017

@mdempsky

This comment has been minimized.

Copy link
Member

commented May 3, 2017

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

@go101

This comment has been minimized.

Copy link
Author

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

This comment has been minimized.

Copy link
Member

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

This comment has been minimized.

Copy link
Author

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

This comment has been minimized.

Copy link
Member

commented May 3, 2017

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

This is working according to spec.

@go101

This comment has been minimized.

Copy link
Author

commented May 3, 2017

Which paragraph in spec?

@mdempsky

This comment has been minimized.

Copy link
Member

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

This comment has been minimized.

Copy link
Author

commented May 3, 2017

but iota is a predeclared constant.

@mdempsky

This comment has been minimized.

Copy link
Member

commented May 3, 2017

@go101

This comment has been minimized.

Copy link
Author

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

This comment has been minimized.

Copy link
Contributor

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

This comment has been minimized.

Copy link
Contributor

commented May 3, 2017

const iota = iota // ok

Because RHS is defined.

const a = a // undefined: a

Because RHS is undefined.

@go101

This comment has been minimized.

Copy link
Author

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.
You can’t perform that action at this time.