Skip to content

fix: Reject decorated element types in arrayOf - #2781

Open
vende11s wants to merge 2 commits into
mainfrom
fix/arrayof-decorated
Open

fix: Reject decorated element types in arrayOf#2781
vende11s wants to merge 2 commits into
mainfrom
fix/arrayof-decorated

Conversation

@vende11s

@vende11s vende11s commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

Fixes #2754

Throws when a non-@location decorated element type is passed to arrayOf.

@location on array elements remains allowed, since it's used effectively with vertexLayout.

Copilot AI review requested due to automatic review settings August 3, 2026 11:19
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

pkg.pr.new

packages
Ready to be installed by your favorite package manager ⬇️

https://pkg.pr.new/software-mansion/TypeGPU/eslint-plugin-typegpu@d11f0723047b188be41135f53f180e2ed2066529
https://pkg.pr.new/software-mansion/TypeGPU/tgpu-gen@d11f0723047b188be41135f53f180e2ed2066529
https://pkg.pr.new/software-mansion/TypeGPU/tinyest-for-wgsl@d11f0723047b188be41135f53f180e2ed2066529
https://pkg.pr.new/software-mansion/TypeGPU/typegpu@d11f0723047b188be41135f53f180e2ed2066529
https://pkg.pr.new/software-mansion/TypeGPU/@typegpu/cli@d11f0723047b188be41135f53f180e2ed2066529
https://pkg.pr.new/software-mansion/TypeGPU/@typegpu/color@d11f0723047b188be41135f53f180e2ed2066529
https://pkg.pr.new/software-mansion/TypeGPU/@typegpu/gl@d11f0723047b188be41135f53f180e2ed2066529
https://pkg.pr.new/software-mansion/TypeGPU/@typegpu/noise@d11f0723047b188be41135f53f180e2ed2066529
https://pkg.pr.new/software-mansion/TypeGPU/@typegpu/radiance-cascades@d11f0723047b188be41135f53f180e2ed2066529
https://pkg.pr.new/software-mansion/TypeGPU/@typegpu/react@d11f0723047b188be41135f53f180e2ed2066529
https://pkg.pr.new/software-mansion/TypeGPU/@typegpu/sdf@d11f0723047b188be41135f53f180e2ed2066529
https://pkg.pr.new/software-mansion/TypeGPU/@typegpu/three@d11f0723047b188be41135f53f180e2ed2066529
https://pkg.pr.new/software-mansion/TypeGPU/unplugin-typegpu@d11f0723047b188be41135f53f180e2ed2066529

benchmark
view benchmark

commit
view commit

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

Resolution Time Benchmark

---
config:
  themeVariables:
    xyChart:
      plotColorPalette: "#E63946, #3B82F6, #059669"
---
xychart
  title "Random Branching (🔴 PR | 🔵 main | 🟢 release)"
  x-axis "max depth" [1, 2, 3, 4, 5, 6, 7, 8]
  y-axis "time (ms)"
  line [0.46, 1.01, 2.23, 3.35, 4.04, 6.73, 12.52, 12.43]
  line [0.51, 1.04, 2.37, 3.82, 4.54, 6.51, 12.02, 13.19]
  line [0.55, 1.05, 2.36, 3.50, 3.98, 5.56, 11.65, 13.04]
Loading
---
config:
  themeVariables:
    xyChart:
      plotColorPalette: "#E63946, #3B82F6, #059669"
---
xychart
  title "Linear Recursion (🔴 PR | 🔵 main | 🟢 release)"
  x-axis "max depth" [1, 2, 3, 4, 5, 6, 7, 8]
  y-axis "time (ms)"
  line [0.16, 0.34, 0.41, 0.46, 0.67, 0.66, 0.78, 0.86]
  line [0.20, 0.33, 0.38, 0.44, 0.62, 0.68, 0.80, 0.84]
  line [0.18, 0.28, 0.40, 0.49, 0.67, 0.68, 0.79, 0.85]
Loading
---
config:
  themeVariables:
    xyChart:
      plotColorPalette: "#E63946, #3B82F6, #059669"
---
xychart
  title "Full Tree (🔴 PR | 🔵 main | 🟢 release)"
  x-axis "max depth" [1, 2, 3, 4, 5, 6, 7, 8]
  y-axis "time (ms)"
  line [0.71, 1.48, 2.59, 4.19, 6.36, 13.63, 29.77, 60.81]
  line [0.54, 1.33, 2.15, 3.59, 6.39, 13.53, 29.18, 59.57]
  line [0.56, 1.34, 2.59, 3.72, 6.42, 13.69, 29.66, 60.54]
Loading

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

Bundle size comparison (import * as ... in PR vs import * as ... in target):

🟢 Decreased ➖ Unchanged 🔴 Increased (max 0.92%) ❔ Unknown
0 296 26 0

import * as ... in PR vs import * as ... in target (did bundle size increase?):

Test tsdown
d_arrayOf.ts 26.84 kB ($${\color{red}+0.9\%}$$)
d_builtin.ts 29.30 kB ($${\color{red}+0.8\%}$$)

import { ... } in PR vs import * as ... in PR (is the library tree-Shakeable?):

Test tsdown
tgpu_init.ts 260.24 kB ($${\color{green}-3.2\%}$$)
tgpu_initFromDevice.ts 259.71 kB ($${\color{green}-3.4\%}$$)
tgpu_resolve.ts 165.61 kB ($${\color{green}-38.4\%}$$)
tgpu_resolveWithContext.ts 165.55 kB ($${\color{green}-38.4\%}$$)
tgpu_bindGroupLayout.ts 69.27 kB ($${\color{green}-74.2\%}$$)
tgpu_mutableAccessor.ts 66.27 kB ($${\color{green}-75.3\%}$$)
tgpu_accessor.ts 66.26 kB ($${\color{green}-75.3\%}$$)
tgpu_privateVar.ts 65.61 kB ($${\color{green}-75.6\%}$$)
tgpu_workgroupVar.ts 65.60 kB ($${\color{green}-75.6\%}$$)
tgpu_const.ts 64.85 kB ($${\color{green}-75.9\%}$$)
tgpu_fn.ts 38.45 kB ($${\color{green}-85.7\%}$$)
tgpu_fragmentFn.ts 38.45 kB ($${\color{green}-85.7\%}$$)
tgpu_vertexFn.ts 38.27 kB ($${\color{green}-85.8\%}$$)
tgpu_computeFn.ts 37.97 kB ($${\color{green}-85.9\%}$$)
tgpu_vertexLayout.ts 27.08 kB ($${\color{green}-89.9\%}$$)
tgpu_comptime.ts 14.77 kB ($${\color{green}-94.5\%}$$)
tgpu_unroll.ts 1.66 kB ($${\color{green}-99.4\%}$$)
tgpu_slot.ts 1.54 kB ($${\color{green}-99.4\%}$$)
tgpu_lazy.ts 1.19 kB ($${\color{green}-99.6\%}$$)

If you wish to run a comparison for other, slower bundlers, run the 'Tree-shake test' from the GitHub Actions menu.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a schema correctness gap in d.arrayOf by rejecting array element types that carry non-@location decorations (e.g. @align, @size), since those decorations have no effect on WGSL array element layout. @location remains allowed to support patterns used with vertexLayout.

Changes:

  • Add a runtime guard and type-level error overload to arrayOf to reject decorated element types except @location.
  • Extend array-related tests to validate the allowed (@location) and rejected (non-@location) cases.
  • Update documentation to warn that d.align/d.size must be wrapped in a struct when used with arrays, and adjust an affected buffer test schema.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
packages/typegpu/src/data/array.ts Enforces the “only @location allowed” rule for array element types (runtime + type-level) and documents the constraint.
packages/typegpu/tests/array.test.ts Adds assertions for allowed @location decorated elements and for throwing on forbidden decorations.
packages/typegpu/tests/buffer.test.ts Updates a schema in a usage-validity test to avoid now-forbidden element decorations.
apps/typegpu-docs/src/content/docs/apis/data-schemas.mdx Documents the new restriction and the recommended struct-wrapping workaround.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 60 to +65
) => {
if (isDecorated(elementType) && !elementType.attribs.every(isLocationAttrib)) {
throw new Error(
'Arrays cannot hold decorated types other than @location. Wrap it in a struct instead, e.g. d.arrayOf(d.struct({ value: d.align(16, d.u32) }), n).',
);
}
Comment on lines +569 to +574
it('throws when a non-location decorated element type is passed', () => {
expect(() => d.arrayOf(d.align(16, d.u32), 4)).toThrowErrorMatchingInlineSnapshot(
`[Error: Arrays cannot hold decorated types other than @location. Wrap it in a struct instead, e.g. d.arrayOf(d.struct({ value: d.align(16, d.u32) }), n).]`,
);
expect(() => d.arrayOf(d.size(16, d.u32), 3)).toThrow();
expect(() => d.arrayOf(d.location(0, d.align(16, d.u32)), 3)).toThrow();

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ No critical issues — one minor inconsistency inline.

Reviewed changes

  • ForbiddenDecoratedArrayElement type + overload — adds a type-level guard to WgslArrayConstructor that resolves to a descriptive error string when arrayOf receives a decorated element type with anything other than @location.
  • Runtime throw in arrayOf implementation — throws if the element type is isDecorated with any non-@location attribute, matching the type-level guard.
  • Tests — verifies @location is allowed, generic helper passthrough still works, runtime throw for d.align/d.size/mixed attributes, and type-level error return type.
  • Buffer test fix — replaces d.arrayOf(d.align(16, d.u32), 32) with d.arrayOf(d.u32, 32) in the "ignore decorated types" test, since decorated element types are now rejected.
  • Docs caution — adds a :::caution callout on the data-schemas page noting the restriction and showing the struct workaround.

Pullfrog  | Fix all ➔Fix 👍s ➔View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) (Kimi K2 not used — the program covers this model; add its provider key to run your pick) | 𝕏

*/
<TElement extends AnyWgslData>(
elementType: ForbiddenDecoratedArrayElement<TElement>,
count?: number,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter name count in this error overload differs from elementCount used in the two productive overloads below and in the JSDoc @param. Consider renaming to elementCount for consistency.

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.

bug: d.align and d.size can be passed to d.arrayOf but do not have any effect

2 participants