When it fires. The default value of a shorthand struct’s field or a
sealed case’s field reads a field of the same struct or case: another field,
or the field itself, directly or anywhere in the expression. A field default
is evaluated with no field of its type in scope. A name spelled like a field
that resolves to nothing else is this error, and so is one that resolves to a
package-level val or var: the default would read the val where the field was
almost certainly meant. A type, a function or an import spelled like a field
keeps its meaning: Retry Retry = Retry(3) calls the type’s constructor. A function’s default, by contrast, may read the parameters
before it (see GALA-E0094).
Minimal repro.
package main
struct Rect(W int, H int = W)
func main() {
Println(Rect(2).H)
}
Error output.
error[GALA-E0098]: the default value of field H reads field W of Rect
--> main.gala:3:28
|
3 | struct Rect(W int, H int = W)
| ^ a field default may not read a field of its type
|
= hint: a field default may not read a field of its type; give H a default that reads no field, or compute it in a constructor function instead
Fix. Compute the field in a constructor function:
package main
struct Rect(W int, H int)
func square(side int) Rect = Rect(side, side)
func main() {
Println(square(2).H)
}
A package-level val spelled like a field. No field is in scope in a field
default, so a name spelled like a field that resolves to a package-level val
or var reads that val. The field was almost certainly meant, so this is the
same error:
package main
val W = 7
struct Rect(W int, H int = W)
func main() {
Println(Rect(2).H)
}
error[GALA-E0098]: the default value of field H of Rect reads package-level val W, which has the same name as field W
--> main.gala:5:28
|
5 | struct Rect(W int, H int = W)
| ^ rename the val or the field
|
= hint: rename the val or the field; a field default cannot read a field, so W here is the val
Rename the val (or the field), so the default says what it reads:
package main
val defaultHeight = 7
struct Rect(W int, H int = defaultHeight)
func main() {
Println(Rect(2).H)
}
A type, a function or an import spelled like a field is no val: it keeps its
meaning, and Retry Retry = Retry(3) calls the type’s constructor.
Rationale. Go code builds the struct through its generated New<T>
constructor, which sets each field to its default before it applies the
caller’s options, so a default that read another field could not see the value
an option gives that field. Scala rejects the same declaration: case class Rect(w: Int, h: Int = w) does not compile.