What it means. A generic struct declares a field whose name matches another generic type (struct or sealed type) in the same package. Both sides must be generic for the rule to fire — non-generic shapes like struct Route(Handler Handler) remain accepted.
package main
sealed type Mode[T any] {
case A(Fn func(int) T)
case B(Fn func(string) T)
}
// Field `Mode` collides with the sealed type `Mode`.
struct Box[T any](Mode Mode[T])
func main() {
Println("hi")
}
error[GALA-E0016]: field "Mode" in generic "Box" shares its name with generic type "Mode" in package "main"
--> e0016.gala:8:19
|
8 | struct Box[T any](Mode Mode[T])
| ^^^^ rename the field
|
= hint: rename the field (e.g. "Mode" → "M") so it does not shadow the type name
Rename the field (or the type) so the two identifiers are distinct:
struct Box[T any](M Mode[T])
Idiomatic GALA picks field names that hint at the role rather than restating the type — mode HarnessMode[T], or a short M when the type already says everything.
When a match scrutinee is a field access whose field shares a name with a type in scope, the generated wrapper’s parameter type can come out with duplicated type arguments (func(obj Mode[T][T]) T {…}), which is not valid Go. The collision is also a readability smell on its own: b.Mode on a Box[T any] where Mode is also a type forces every reader to disambiguate field from type.
Scope. Limited to struct and shorthand-struct fields whose name matches another type in the same package. Field-vs-function, field-vs-variable, and field-name-equals-own-struct-name are not flagged.