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: unnecessary error reports #22619

Closed
dotaheor opened this issue Nov 7, 2017 · 16 comments
Closed

cmd/compile: unnecessary error reports #22619

dotaheor opened this issue Nov 7, 2017 · 16 comments
Labels
FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done.
Milestone

Comments

@dotaheor
Copy link

dotaheor commented Nov 7, 2017

Please answer these questions before submitting your issue. Thanks!

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

go version go1.9.2 linux/amd64

Does this issue reproduce with the latest release?

yes

What did you do?

package main

func main() {
	var c chan bool
	
	select {
	default:
		goto A // label A not defined
		A:     // syntax error: missing statement after label
	case <-c:
		goto B // ok
		B:     // ok
	}
	
	select {
	default:
	{
		goto C // ok
		C:     // ok
	}
	case <-c:
		goto D // ok
		D:     // ok
	}
	
	select {
	case <-c:
		goto X // label X not defined
		X:     // syntax error: missing statement after label
	default:
		goto Y // ok
		Y:     // ok
	}
	
	select {
	case <-c:
	{
		goto W // ok
		W:     // ok
	}
	default:
		goto Z // ok
		Z:     // ok
	}
}

same for cases in switch.

What did you expect to see?

No errors are reported.

What did you see instead?

vet: main.go: main.go:10:2: expected statement, found 'case' (and 1 more errors)
vet: no files checked
exit status 1
@ianlancetaylor ianlancetaylor added this to the Unplanned milestone Nov 7, 2017
@ianlancetaylor ianlancetaylor added the NeedsFix The path to resolution is known, but the work has not been done. label Nov 7, 2017
@ianlancetaylor
Copy link
Contributor

CC @griesemer @mdempsky

@griesemer
Copy link
Contributor

Is this a compiler or vet issue? It's not clear from your description. Please describe exactly what you did. (Your "What did you do"? report just shows some code).

FWIW, I get

./x.go:9:4: syntax error: missing statement after label
./x.go:29:4: syntax error: missing statement after label

as the only errors with cmd/compile or go vet.

Please clarify.

@ianlancetaylor
Copy link
Contributor

I can recreate the problem with the Go 1.9 cmd/vet. But it's fixed on tip.

Thanks for the report, but since it's been fixed I'm going to close this. I don't think this is important enough to backport to 1.9.

@dotaheor
Copy link
Author

dotaheor commented Nov 7, 2017

@griesemer
yes, I forgot to attach the compiler errors too. It is both a bug of the compiler and vet.

@ianlancetaylor
glad to know it is fixed.

@dotaheor
Copy link
Author

dotaheor commented Nov 7, 2017

@ianlancetaylor
I just updated the tip and rebuilt it.
But I found the errors are still reported.

The go version shows

go version devel +79f6c280b8 Tue Nov 7 22:06:35 2017 +0000 linux/amd64

@griesemer
Copy link
Contributor

@dotaheor Please describe your exact steps (compiler, go vet invocation) and errors you see.

@dotaheor
Copy link
Author

dotaheor commented Nov 7, 2017

main.go:

package main

func main() {
	var c chan bool
	
	select {
	case <-c:
	{
		goto A
		A: // ok
	}
	case <-c:
		goto B
		B: // syntax error: missing statement after label
	case <-c:
		goto C
		C: // ok
	}
}

'~/go/src/github.com/golang/go/bin/go build main.go`:

./main.go:14:4: syntax error: missing statement after label

@dotaheor
Copy link
Author

dotaheor commented Nov 7, 2017

However, vet is fixed on tip.
~/go/src/github.com/golang/go/bin/go build vet main.go is ok.

@ianlancetaylor
Copy link
Contributor

The error is correct according to the language spec, though the reason is a little complicated. A label must always appear before a statement. However, a statement may be a single semicolon, representing the empty statement. And that semicolon may be omitted before a } character. So that is what is happening for your labels A and C: a semicolon is omitted before the '}', and that omitted semicolon is the empty labeled statement. For B no semicolon is omitted, there is no statement, and so you get a compiler error.

@dotaheor
Copy link
Author

dotaheor commented Nov 7, 2017

But why must there be at least one statement following a label?
I think there are really some reasonable uses like the second case.
Surely the second goto can be replaced with a break.
But in doing programming, for debug purpose, we may temperately
comment off and on the statements following the the label B for multiple times.
Forcing programmers to change the goto into a break, and back and forth, is inconvenient.

On the other hand, from the implementation view,
inserting a ; after the declaration of label B is quite easy.

@ianlancetaylor
Copy link
Contributor

ianlancetaylor commented Nov 7, 2017

@dotaheor Well, now you are talking about a language change. Perhaps it would be a straightforward change, I don't know. Someone would have to work through all the possible issues and make a language change proposal.

For your purposes, you could simply write B:;.

@dotaheor
Copy link
Author

dotaheor commented Nov 7, 2017

OK, a quite good workaround.

@dotaheor
Copy link
Author

dotaheor commented Nov 7, 2017

@ianlancetaylor
but I can't find the rule in spec.

@griesemer
Copy link
Contributor

@dotaheor A labeled statement is simply a statement. A labeled statement may have an empty statement following the ":", and an empty statement is literally nothing.

But, all statements must be followed by a semicolon (*) because statements appear in statement lists.

It would be extremely irregular in the grammar to have some statements be followed by semicolons and not others. (*) Finally, independently, semicolons may be elided before a closing "}".

Altogether, this is what leads to the current behavior. You can be assured that this is not coincidental and has been carefully thought through. The rules are like they are to make a) the syntax regular (all statements must be followed by semicolons), and b) the case where a statement is immediately followed by a closing "}" of a block not overly onerous .

These rules are in the syntax of the spec, and in the prose.

@griesemer
Copy link
Contributor

PS: Most of the time a semicolon does not need to be written because of the semicolon insertion rule ( https://tip.golang.org/ref/spec#Semicolons ). This works out for pretty much all statements, but because empty statements have no tokens (they are empty), the token immediately before determines if a semicolon is inserted or not at the end of a line. In a labelled empty statement, that last token is ":", and ":" does not automatically cause a semicolon to be inserted at the end of a line.

If there was any change to be made, one could perhaps propose that a semicolon can be omitted before a "case" or "default" keyword as well, and then this would work out without error. But I am not recommending such a change; it doesn't seem worthwhile the additional complexity for a corner case that is rare.

@dotaheor
Copy link
Author

dotaheor commented Nov 8, 2017

Ah, it is quite complicated and subtle.

I may make a proposal that inserting a semicolon right after each label declaration.,
but I think this is really not very worthwhile.

Thanks for the detailed explanations.

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

4 participants