feat: Allow null at comptime - #2877
Conversation
|
@pullfrog review |
|
pkg.pr.new packages benchmark commit |
Bundle size comparison (
|
| 🟢 Decreased | ➖ Unchanged | 🔴 Increased (max 0.08%) | ❔ Unknown |
|---|---|---|---|
| 0 | 304 | 21 | 0 |
import { ... } in PR vs import * as ... in PR (is the library tree-Shakeable?):
| Test | tsdown |
|---|---|
| tgpu_init.ts | 263.31 kB ( |
| tgpu_initFromDevice.ts | 262.77 kB ( |
| tgpu_resolve.ts | 161.96 kB ( |
| tgpu_resolveWithContext.ts | 161.90 kB ( |
| tgpu_bindGroupLayout.ts | 62.32 kB ( |
| tgpu_mutableAccessor.ts | 57.04 kB ( |
| tgpu_accessor.ts | 57.04 kB ( |
| tgpu_privateVar.ts | 55.73 kB ( |
| tgpu_workgroupVar.ts | 55.73 kB ( |
| tgpu_const.ts | 55.15 kB ( |
| tgpu_lazy.ts | 54.95 kB ( |
| tgpu_fragmentFn.ts | 39.68 kB ( |
| tgpu_fn.ts | 39.62 kB ( |
| tgpu_vertexFn.ts | 39.50 kB ( |
| tgpu_computeFn.ts | 39.20 kB ( |
| tgpu_vertexLayout.ts | 28.33 kB ( |
| tgpu_comptime.ts | 15.93 kB ( |
| tgpu_unroll.ts | 1.75 kB ( |
| tgpu_slot.ts | 1.70 kB ( |
If you wish to run a comparison for other, slower bundlers, run the 'Tree-shake test' from the GitHub Actions menu.
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.67, 1.35, 2.96, 4.10, 5.14, 6.80, 15.37, 17.08]
line [0.56, 1.16, 2.46, 4.13, 4.79, 8.23, 15.54, 16.83]
line [0.70, 1.35, 2.81, 4.36, 5.16, 7.87, 16.25, 17.41]
---
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.19, 0.35, 0.47, 0.56, 0.95, 0.81, 0.98, 1.10]
line [0.19, 0.35, 0.50, 0.60, 0.80, 0.83, 0.99, 1.00]
line [0.19, 0.32, 0.51, 0.60, 0.80, 0.83, 0.98, 1.04]
---
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.60, 1.62, 2.44, 4.83, 7.83, 17.11, 37.43, 74.80]
line [0.64, 1.66, 2.26, 4.31, 7.76, 16.63, 36.38, 74.14]
line [0.62, 1.63, 2.58, 4.51, 8.12, 16.80, 38.57, 76.02]
|
4715dd2 to
44abdfa
Compare
44abdfa to
60810de
Compare
60810de to
5eb127c
Compare
There was a problem hiding this comment.
ℹ️ Minor suggestions — the null-at-comptime feature is sound, well-scoped, and verified green on the rebased head; one still-open docs nitpick below.
Reviewed changes — this re-review covers the branch after a rebase onto main. The vectorOps portmanteau and the chore/drop-acorn base are gone, so the diff is now feature-only (12 files): a clean null-at-comptime change.
nullLiteraltinyest node — node code106inNodeTypeCatalog, aNulltuple type, and inclusion in theLiteralunion (nodes.ts).- Parsing both backends — the babel
NullLiteral()transpiler and theLiteral.raw === 'null'path both emit[nullLiteral]; thedualTestinparsers.test.tsexercises acorn and babel. - WGSL emission —
WgslGenerator._expressionrendersnullLiteralassnip(null, UnknownData, 'constant', false); since the value is not a string,isKnownAtComptimeis true, so===/!==fold and prune branches/ternaries. - Runtime guard —
resolutionCtx.resolve(null)throws a comptime-specific'null' is only allowed in comptime checkserror instead of silently lowering to0(the priorNumber(null)behavior). - Consumers in lockstep —
tseynitstringifiesnull,isExpressionaccepts the node, and the obfuscator passes it through untouched. - Tests — parser,
tseynit, slot,comptime,tgslFn(incl. runtime negatives), and obfuscation cases. All affected suites pass on the rebased head (parsers 18,typegpu113, unplugin 25).
The design holds together: a null literal becomes a comptime-known snippet that folds away during branch/ternary pruning, while any path that would emit null into runtime WGSL throws. The previously-raised runtime-path concern (x !== null with a non-foldable operand surfacing a generic "right-hand side of unknown type") was discussed and resolved by the author and reviewer as acceptable. A maintainer has approved.
ℹ️ Docs: branch-pruning list still omits null
packages/typegpu docs apps/typegpu-docs/src/content/docs/apis/utils.mdx (§ conds comptime-known at resolution) enumerates which values enable branch pruning: referenced JS values/operations, slot values, and comptime-returned values. Now that x === null / x !== null folds during pruning (this PR's core capability), a one-line mention of null-safety comparisons would make the feature discoverable to users hitting number | null slots or externals. Worth adding since the whole point of this PR is that null is legal only at comptime.
DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

No description provided.