GALA-E0055 — Go keyword used as a name

When it fires. A name is spelled like one of Go’s keywords that GALA does not reserve itself: break, chan, const, continue, default, defer, fallthrough, go, goto, select or switch.

GALA compiles to Go, and every name a GALA program declares becomes a name in the generated Go. Go’s other keywords (func, type, map, if, for, …) are GALA keywords too, so the parser already rejects them as names. These eleven are not, so they parse as ordinary identifiers — and the Go they produced did not.

The check covers every place a name is introduced: a val, var or := binding, a tuple destructuring, a parameter or lambda parameter, a pattern binding (case go =>, Some(go)), a struct or sealed-case field, a function or method, an interface method, a type, type alias, sealed type or sealed case, a type parameter, the package name, and an import alias. It points at the declaration, even when a use of the name comes first in the file. A use with no declaration — Println(default), go(work()), a bare switch statement — is reported where it stands, as "go" is a Go keyword and is not part of GALA; for defer, go, goto, fallthrough, select and chan the hint is the replacement GALA-E0036 gives.

Minimal repro.

package main

func main() {
    val default = 8080
    Println(s"listening on ${default}")
}

Error output.

error[GALA-E0055]: "default" is a Go keyword and cannot be used as a name
  --> main.gala:4:9
  |
4 |     val default = 8080
  |         ^^^^^^^ rename it
  |
  = hint: rename it; GALA compiles to Go, where "default" is reserved, so nothing a GALA program declares can have that name

A function called above its declaration is reported at the declaration, where the rename starts:

package main

func main() {
    go("build")
}

func go(task string) {
    Println(s"running ${task}")
}
error[GALA-E0055]: "go" is a Go keyword and cannot be used as a name
  --> main.gala:7:6
  |
7 | func go(task string) {
  |      ^^ rename it
  |
  = hint: rename it; GALA compiles to Go, where "go" is reserved, so nothing a GALA program declares can have that name

Fix. Pick another name and use it everywhere:

package main

func run(task string) {
    Println(s"running ${task}")
}

func main() {
    val defaultPort = 8080
    Println(s"listening on ${defaultPort}")
    run("build")
}

What still works.

Rationale. These names used to be emitted into the generated Go unchanged. Go rejected the file before it could report anything about the source, so the author got the internal GALA-E0017 — “the generated Go is not parseable” — instead of a diagnostic about their own code.

GALA rejects the name rather than renaming it behind the author’s back. A renamed local (go to go_) would be harmless, but a renamed struct field, exported function or package-level val is visible to Go code, to JSON field names and to reflection under a name the author never wrote. And break and continue already mean loop control as statements, so a binding with either name could not be referred to unambiguously. A rule with no exceptions is the one that is easy to predict.

Scope. Names in the file being compiled. Go keywords that are also GALA keywords never reach this check: the parser rejects them first, with a syntax error.