go/types: incorrect error about missing return
dvyukov opened this issue · 7 comments
gc successfully compiles the following program:
package a
func f() int {
for {};
;
}
while gotype says:
go.go:5: missing return at end of function
go version devel +9b04852 Sat Jul 11 00:08:50 2015 +0000 linux/amd64
I think the Go spec unambiguously supports the gotype error. Functions with result parameters need to end in a terminating statement, and empty statements are not terminating statements.
Interestingly if we change the body of that function from for {}
to add in conditions ie for true {}
or for i := 0; i < 10; i++ {}
the compiler catches the missing return https://play.golang.org/p/tMrrNlXJI6 or inlined here
package main
import "fmt"
func f() int {
for {
}
}
func f1() int {
for true {
}
}
func main() {
fmt.Printf("hello world")
}
$ tmp/sandbox109964380/main.go:13: missing return at end of function
Per https://golang.org/ref/spec#Terminating_statements these programs contain a for loop without a loop condition or break statement, therefore the for loop is a terminating statement. These programs are thus valid and gotype is failing to detect the terminating statement?
Isn't that this is working as intended for cmd/gc, and a bug
for gotype?
The for loop doesn't terminate, so the function won't ever
return, thus there is no need for a return.
This is now a go/types error. The relevant lines from the spec are:
"If the function's signature declares result parameters, the function body's statement list must end in a terminating statement." (https://tip.golang.org/ref/spec#Function_declarations)
"A statement list ends in a terminating statement if the list is not empty and its final non-empty statement is terminating." (https://golang.org/ref/spec#Terminating_statements, end of paragraph).
Thus:
- The function must end in a terminating statement since it declares a result; and
- The final non-empty statement is the for loop which neither has a loop condition nor a break statement and thus is terminating.
@mdempsky was correct, too, because in 2015 this was still a gc bug :-) The relevant sentence in the spec changed in 2016 (b5ddbb9).