When it fires. A struct or sealed type has a field whose type contains the
type itself by value: an Option, Either, Try, tuple or List of it,
another struct that holds it, or the type itself in a struct. A Go value cannot
contain itself, so the type would have infinite size.
Minimal repro.
package main
struct Node(value int, next Option[Node])
func main() {
val n = Node(1, None[Node]())
Println(n.value)
}
Error output.
error[GALA-E0077]: struct Node holds itself by value: field next has type Option[Node], which contains Node itself
--> main.gala:3:24
|
3 | struct Node(value int, next Option[Node])
| ^^^^ a value cannot contain itself
|
= hint: a value cannot contain itself; declare recursive data as a sealed type whose case field has the type itself (`case Cons(head int, tail Node)`), or hold it through a pointer (`next *Node`)
Fix. Declare recursive data as a sealed type. A case field whose type is the sealed type itself is held by reference, so the type can refer to itself:
package main
sealed type Node {
case Last(value int)
case Link(value int, next Node)
}
func sum(n Node) int = n match {
case Last(v) => v
case Link(v, next) => v + sum(next)
}
func main() {
Println(sum(Link(1, Link(2, Last(3))))) // 6
}
A pointer field (next *Node), an Array, a HashMap, a Go slice or map and
a function also hold the type by reference and are accepted.
Rationale. Without the check the type reached go build, which rejected it
as an invalid recursive type and named the generated std.Immutable and
std.Option wrappers instead of the field.