-
Notifications
You must be signed in to change notification settings - Fork 18k
proposal: spec: local func declarations #73502
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
Comments
Would this have the same scoping and shadowing rules as the other three declaration keywords (const, var, type)?
|
Would this allow methods for local types?
|
Can a declaration have no body, and be implemented in assembly? If so, what is its name? Also #71562, methods on function-local types? |
Re. my previous question: This probably prevents methods for local types. |
This would capture outer variables like a closure, right?
|
Are these function definitions fixed like package-level functions and cannot be re-assigned in the same scope?
|
In answer to all the questions:
|
Background: In Go, named functions must be declared at package level. The scope of a
func
declaration includes the function body, so named functions may be directly or mutually recursive.Local functions, which may have free variables, must be anonymous. Therefore they cannot call themselves recursively. Instead, we must resort to the var trick, in which a local variable is first declared, then assigned the value of an anonymous function whose body refers to the variable:
This limitation has three consequences:
(1) The source code for local functions is unnecessarily verbose.
(2) The generated code for local functions is unnecessarily inefficient. Because all calls to g are superficially dynamic, the compiler generates dynamic CALL instructions and inlining is defeated. (To be clear, this is problem is entirely fixable in the compiler.)
(3) Local functions cannot be generic, because there is no way to declare type parameters. In some cases this forces a number of declarations that could otherwise all be local to have to be spilled to the top level, polluting the package namespace.
Proposal: We propose to permit
func
declarations as statements, so the above code could be written:This would allow local functions to be generic:
This does create a minor parsing ambiguity between a DeclStmt of a FuncDecl, and an ExprStmt whose leftmost subtree is a FuncLit, for example:
This ambiguity is easily resolved with an extra token of lookahead: when parsing a statement, if
func
is followed by an identifier, it's a DeclStmt, otherwise, it's an ExprStmt.Initially at least, we should require that references to local generic functions need explicit instantiation, to avoid the issue that appears in ML where type inference is exponential in the depth of nested lets. Perhaps that can be relaxed.
I expect the most difficult part of the implementation to be the elimination of assumptions that FuncDecls are not syntactically nested, throughout the compiler and x/tools. It is of course a breaking change to clients of go/ast.
The text was updated successfully, but these errors were encountered: