Repository navigation
fix: convert array elements when casting between array types - #3302
DevShoaib78 wants to merge 1 commit into
Conversation
Any two array schemas counted as the same type, so a cast between different element types or lengths silently generated invalid WGSL. Convert element by element, keep array literals as array expressions, and throw when the lengths differ.
There was a problem hiding this comment.
Caution
This PR introduces a circular dependency. dpdm reports one cycle on this branch and none on main, so the required test:circular-deps job (.github/workflows/test-misc.yml) will fail.
Reviewed changes
- Array element-wise casting —
needsArrayCastnow flags twoWgslArrayschemas as needing a cast when their element counts differ or their element types need conversion, so mismatched arrays are no longer silently treated as the same type. - Cast codegen — the
case 'cast'branch inapplyActionToSnippetresolves an array→array cast toarray<T,N>(elem0, elem1, …), converting each element; array literals stayArrayExpressions to preserve comptime values. - Tests — five cases added to
array.test.ts(variable→array element conversion, struct-element conversion, same-type no-cast, length mismatch throws, side-effecting source throws). I confirmed four of them fail on the pre-fixconversion.tsand that the rest ofpackages/typegpu/tests(3085 tests) and the docs example snapshots still pass;tsc,oxlint, andoxfmtare clean on the two files.
deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏
| import { logger } from '../tgpuLogger.ts'; | ||
| import type { ResolutionCtx } from '../types.ts'; | ||
| import { accessStructProp } from './accessStructProp.ts'; | ||
| import { ArrayExpression } from './generationHelpers.ts'; |
There was a problem hiding this comment.
This new import edge closes a dependency cycle and fails the repo's test:circular-deps gate. dpdm exits 0 on main but exits 1 on this branch, reporting:
core/function/createCallableSchema.ts
-> tgsl/conversion.ts
-> tgsl/generationHelpers.ts
-> data/numeric.ts
-> core/function/createCallableSchema.ts
Technical details
# Move `ArrayExpression` out of `generationHelpers.ts` to break the cycle
## Affected sites
- `packages/typegpu/src/tgsl/conversion.ts:30` — new `import { ArrayExpression } from './generationHelpers.ts'`.
- `packages/typegpu/src/tgsl/generationHelpers.ts:2` — imports `../data/numeric.ts`, which imports `../core/function/createCallableSchema.ts`, which imports `./conversion.ts` (closing the loop).
## Required outcome
- The import graph reachable from `packages/**/src/index.ts` must be acyclic (the repo enforces this with `pnpm test:circular-deps` in `.github/workflows/test-misc.yml` and in the `prepack` script).
## Suggested approach
- Move the `ArrayExpression` class (or just an `isArrayExpression` guard) into a leaf module that does not transitively reach `data/numeric.ts` / `createCallableSchema.ts` (its dependencies would be `data/snippet.ts`, `data/wgslTypes.ts`, `shared/symbols.ts`, `errors.ts`, `types.ts`), and import it from both `generationHelpers.ts` and `conversion.ts`.
- `conversion.ts`'s existing imports do not reach `createCallableSchema` (base `12f5cba` is cycle-free), so a genuinely leaf module breaks the loop.
- Verify with `pnpm test:circular-deps`.There was a problem hiding this comment.
🟡 Changes recommended
Array conversion has critical gaps: nested-array inference depends on row order and can truncate fractional values, while aliases bypass required element casts and length checks.
2 open issues
What changed in this PR
This PR updates TypeGPU’s array conversions to address invalid WGSL reported in #3251 and #2521.
Changes:
- Adds element-by-element casts between array schemas, including arrays of different structs.
- Rejects mismatched lengths and conversions that would repeat possible side effects, while preserving compile-time array literals.
- Adds five regression tests covering conversions, errors, and equivalent schemas.
| File | Description |
|---|---|
packages/typegpu/tests/array.test.ts |
Adds array-conversion regression tests. |
packages/typegpu/src/tgsl/conversion.ts |
Adds array-cast detection, element conversion, and validation. |
Review effort: Balanced
| if (isWgslArray(trueSrc) && isWgslArray(trueDst) && needsArrayCast(trueSrc, trueDst)) { | ||
| return { rank: 1, action: 'cast', targetType: dest }; |
| if (isWgslArray(trueSrc) && isWgslArray(trueDst) && needsArrayCast(trueSrc, trueDst)) { | ||
| return { rank: 1, action: 'cast', targetType: dest }; |


Fixes #3251. Also covers the case in #2521.
Any two array schemas counted as the same type in
getAutoConversionRank, so both snippets in the issue silently generated invalid WGSL. Arrays now get a cast when the lengths differ or the elements need one, the same way structs do.What it generates now
Arrays of different structs convert element by element too, as in #2521.
Decisions to check
Cannot auto-convert array ... because their element counts differ.ArrayExpressions, so their elements can still be known at comptime. The nested array test incomptime.test.tsneeds this.implicit-conversionwarning, even for an explicitd.arrayOf(...)(arr). Struct casts do the same.Testing
Added 5 tests to
array.test.ts. 4 of them fail without the fix; the fifth pins that identical schemas don't cast.tsc,oxlintandoxfmtare clean on the changed files.On Windows,
vitest run --project=!browserhas the same 20 failures with and without this change, intgpu-gen,unplugin-typegpuand the docsprobabilityexample, and nothing new. I did not run the built-package tests or the circular dependency check (dpdmfound no entry files on Windows), and I only checked the generated WGSL text, not on a real GPU.