What it means. A zero-argument constructor of a generic sealed type is used somewhere the parent type’s parameter cannot be pinned. The transpiler takes it from the slot the constructor fills before giving up:
Box[int]) and the constructor is the result value — not one bound to an unannotated val in the body.val / var type annotation supplying an expected type.The type of an enclosing match subject is not one: None() in an arm of a match over an Option[int] takes no type from it.
If none of those resolve the parameter, generated Go would contain a bare Variant{} literal whose type argument Go cannot deduce — producing an obscure cannot infer T far from the GALA source.
A constructor called with arguments fires it too when the arguments do not carry the parameter and nothing else names it: val x = Failure(err) (nothing says what Try it is) or Left("x") (nothing says the right side). The message then names the parameter and the constructor as "Failure(...)". A sibling branch whose type is known supplies it: val x = if (ok) Success(1) else Failure(err) is a Try[int].
package main
sealed type Box[T any] {
case Empty()
}
func main() {
val x = Empty() // no annotation, no enclosing type — T is unbound
Println(x)
}
error[GALA-E0018]: cannot infer type parameter for sealed variant constructor "Empty()"
--> e0018.gala:8:18
|
8 | val x = Empty()
| ^ annotate the binding
|
= hint: annotate the binding (e.g. `val x Box[int] = Empty()`) or pass type args explicitly (`Empty[int]()`)
The hint is built from the variant’s own parent type, so it names the exact annotation to paste in.
Give the parameter a home. Annotate the binding:
sealed type Box[T any] {
case Empty()
case Filled(value T)
}
val x Box[int] = Empty()
…or instantiate the constructor explicitly:
sealed type Box[T any] {
case Empty()
case Filled(value T)
}
val x = Empty[int]()
When the constructor is an arm of a match against a value of the parent type, or the body of a function whose declared return type is concrete, the signal is already present and no annotation is needed:
sealed type Box[T any] {
case Empty()
case Filled(value T)
}
func emptyInts() Box[int] = Empty() // the concrete return type pins T
A generic return type does not count as a signal. func empty[T any]() Box[T] = Empty() still reports GALA-E0018, because T is itself unbound at the constructor — there is nothing to pin. Pass the argument explicitly (Empty[T]()) in that case.
GALA’s downward inference relies on a single expected-type signal flowing from the enclosing context. When that signal is absent, the transpiler would otherwise fall through to an untyped composite literal and let Go deduce — which fails confusingly and far from the source. Failing fast, with a hint naming the three resolving signals, points at the cheapest fix.
Scope. Only zero-argument constructors of generic sealed types. Variants of non-generic sealed types, and constructors whose arguments contribute to inference, are unaffected.