golang / go

The Go programming language

Home Page:https://go.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

go/types: incorrect error about missing return

dvyukov opened this issue · 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:

  1. The function must end in a terminating statement since it declares a result; and
  2. 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).

With the spec change, this became a duplicate of #14537 which has been fixed. Not-reproducible anymore. Closing.