Skip to content

fix(compiler): accept arrays nested in generic type arguments - #24

Merged
Mister-Meeseeks merged 1 commit into
CrocSwap:mainfrom
paulbalaji:fix-generic-array-type-args
Oct 19, 2026
Merged

Mister-Meeseeks merged 1 commit into
CrocSwap:mainfrom
paulbalaji:fix-generic-array-type-args

Conversation

@paulbalaji

Copy link
Copy Markdown
Contributor

Problem

Pair[uint32, [][32]byte] fails Check with array type was not declared before use. Two causes:

  • type arguments are validated while instantiations are discovered, before any array is declared. typeArgRule bounded a top-level array without a lookup but sent everything else to one, so [32]byte passed while [][32]byte, []*[4]byte, []Key, map[K][][4]byte and func([]*[4]byte) failed
  • arrays are declared where source writes them. A generic field V [][3]T on Box[uint16] holds [3]uint16, which source may never write, so it failed even with the first cause fixed

Solution

  • typeArgRule descends through pointers and slices and bounds the arrays it reaches, keeping the pointer and slice rejections.
  • Check and the emitter declare the arrays a struct field holds through pointer, slice, map and array types before using the field. Programs whose arrays are all written in source already have them declared, so their C doesn't change.

An oversized or zero-length array inside a type argument now reports that rule's message instead of the declaration error. ERROR_CONTRACT changelog entry included.

Tests

  • TestGenericArrayTypeArgs*: two programs, 256 inputs each, native Go vs host C: the issue's Pair, a sorted []Pair lookup, pointers, maps, named arrays, nested slices and generics, inferred and function-typed arguments, generic fields with arrays written nowhere else, bounds and nil traps.
  • Real SBF on fogo-v0 and solana-v3: 64 inputs per program, all match, traps roll back.
  • 15 forms rejected at 79cf25c now compile and their C builds; storage rules still apply inside type arguments.
  • Frozen corpus C unchanged. The five examples/* gosvm projects, a fresh starter and the 4 reference ELFs build byte-identical to 79cf25c. make test passes apart from the known TestStdlib* and TestFullSwapFacts host failures.

Linked work

Closes #8. hyperlane-xyz/hyperlane-monorepo#9852 worked around it by wrapping the slice in a struct. Evidence: results/compiler/2026-10-19-generic-array-type-args. Conflicts with the #7 fix on ERROR_CONTRACT and HANDOFF are mechanical.

Pair[uint32, [][32]byte] failed Check with "array type was not declared
before use" (CrocSwap#8). Type arguments are validated while instantiations are
discovered, before any array type is declared, and typeArgRule only
bounded a top-level array (or a pointer to one) without looking it up;
arrays inside slices and pointers went to the lookup. Separately, arrays
reached only through a field of an instantiated generic struct
(V [][3]T, P *[4]T, Rows []Row[T]) were never declared.

typeArgRule now descends through pointers and slices, keeping their
rejections, and Check and the emitter declare the arrays a struct field
holds through pointer, slice, map and array types before using it.
Programs whose arrays are all written in source emit the same C: the
frozen corpus, every example ELF and the reference ELFs are unchanged.
Host differentials against native Go and SBF runs on fogo-v0 and
solana-v3.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

A slice of arrays as a generic type argument is rejected

2 participants