Skip to content

Bump Slang to 2026.19 and release 0.0.10 - #18

Merged
RefuX merged 6 commits into
mainfrom
bump/slang-2026.19
Oct 2, 2026
Merged

RefuX merged 6 commits into
mainfrom
bump/slang-2026.19

Conversation

@RefuX

@RefuX RefuX commented Oct 2, 2026

Copy link
Copy Markdown
Owner

Bumps Slang 2026.16 → 2026.19 and releases 0.0.10.

Slang 2026.17 broke its append-only ABI: IGlobalSession vtable slot 32 changed from getDownstreamCompilerVersion to getDownstreamCompilerPath, and CompilerOptionName::CompilerVersion was removed. That is why the ABI canary has failed since 2026-09-07, and why slang-bump.yml refuses this bump. It was done by hand instead, rebuilding the lock with --reset-lock; the regen commit lists every lock line dropped.

Commits

  • extract: fold global constants with clang's evaluator. kUnboundedSyntheticResourceArraySize = ~uint32_t(0) was being extracted as 0; a regression test now runs in the abi-lock CI job.
  • slang: regenerate against 2026.19: natives, manifests (each zip checked against GitHub's SHA-256 digest), model, lock, generated Java.
  • session: modules written before Slang 2026.18.3 (a retired serialization format) now fail with an actionable SlangCompileException.
  • session: loadModuleFromIr lets Slang's own module-version range decide on 2026.18.3+; older libraries keep the exact-version guard.
  • docs: README note on serialized modules.
  • release: 0.0.10.

Breaking (generated ffi.gen layer only)

  • IGlobalSession.getDownstreamCompilerVersion / VT_getDownstreamCompilerVersion → getDownstreamCompilerPath
  • CompilerOptionName.CompilerVersion removed

Verification

  • :slang:test 43/43 against 2026.19 on macos-aarch64; javadoc clean; both extractor test suites pass.
  • The crash guard for older libraries was checked against the real 2026.16 binaries.
  • The other platforms are left to this PR's CI.

Closes #13, closes #14, closes #15, closes #16, closes #17.

🤖 Generated with Claude Code

RefuX and others added 6 commits October 2, 2026 13:25
…literal

const_var_value() returned the first integer literal in an initializer's AST, so
Slang 2026.16.1's `kUnboundedSyntheticResourceArraySize = ~uint32_t(0)` came out
as 0 instead of 0xffffffff. Regenerating against any release since would have
shipped that wrong constant in SlangMiscConstants and frozen it into the lock,
where correcting it later would itself read as an ABI break.

It now asks libclang's own constant evaluator (clang_Cursor_Evaluate), which
clang.cindex does not wrap, so the five calls are bound via ctypes on first use;
importing the module still never touches libclang, which test_abi_lock.py's stub
relies on. Behaviour-preserving for everything already extracted: re-running
against the 2026.16 headers reproduces the committed api/slang-api.json byte for
byte.

test_const_eval.py pins it down from an in-memory snippet (bitwise not, shifts,
ORed enum references, negative signed values); five of its eight cases fail on
the old code. It needs a real libclang, so the abi-lock CI job installs the
wheel's bindings for it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…m's break

Slang 2026.17 broke its own append-only ABI, and every release since carries
the break: IGlobalSession vtable slot 32 went from
getDownstreamCompilerVersion(SlangPassThrough, int*, int*) to
getDownstreamCompilerPath(SlangPassThrough, ISlangBlob**) -- same slot, new
signature -- and CompilerOptionName::CompilerVersion (153) was dropped for
GetCompilerPath (159). The weekly canary has failed on it since 2026-09-07,
and slang-bump.yml refuses it by design, so this bump was done by hand.

The lock was rebuilt with --reset-lock, with James's go-ahead, after a
--verify run against v2026.19 (all six triples) flagged exactly those two
facts. Every lock line it drops:

  enum CompilerOptionName CompilerVersion 153           removed upstream
  iface IGlobalSession 32 getDownstreamCompilerVersion  slot repurposed upstream
  enum CompilerOptionName CountOf 158                   now 161, as appends move it
  struct SyntheticResourceInfo size 56                  now 64, a tail extension

Everything else is an append: the BitfieldPackingRules enum and option (160),
TraceCoverageBindlessIndex (158), GetCompilerPath (159),
spReflectionTypeLayout_GetContentVarLayout, SyntheticResourceInfo.bindlessIndex
at offset 56, and kUnboundedSyntheticResourceArraySize = 0xffffffff, which is
right only because of the previous commit (the old extractor read it as 0).
Re-running the extractor in enforcing mode against the rebuilt lock passes and
rewrites nothing. CLAUDE.md now says when a reset like this one is allowed.

Neither removed symbol was used by the idiomatic API; only the generated
ffi.gen layer exposed them. Of the 118 generated files, 108 change only in
their "Slang <version>" header line; the substance is in the 9 others plus the
new BitfieldPackingRules.java.

The six release zips were fetched with curl (Java cannot reach one of GitHub's
CDN addresses from this network) and each matched GitHub's published SHA-256
digest before downloadNatives recorded its manifest. Each platform gains five
standard-module files (functional, numerics/*); nothing else in the payloads
moved.

Tested locally against the macos-aarch64 payload: 37 of 39 pass. The two
ModuleIrCompatibilityTest failures come from upstream retiring the IR
serialization format the test fixture uses; the next commit handles that.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Slang 2026.18.3 (upstream #12905) bumped the IR serialization format to 2 and
stopped reading format 1, which is everything written before it -- including
the 2026.8 test fixture. It no longer even reads such a module's metadata:
slang_loadModuleInfoFromIRBlob returns SLANG_E_NOT_AVAILABLE (garbage bytes
still get SLANG_FAIL, so the two are distinguishable).

loadModuleFromIr runs that metadata read as its pre-check, so against 2026.19
a stale module surfaced as a bare "ISession::loadModuleInfoFromIRBlob failed"
-- worse than Slang's own E00132 ("cannot load serialized module format
version 1; regenerate the serialized module with this compiler"), which the
pre-check now pre-empts. It now throws SlangCompileException naming the module,
the running Slang build and the remedy, like the version-mismatch branch does.

Upstream also stopped aborting: 2026.18.3+ report an unloadable module with
E00130/E00132 rather than killing the process (checked by handing the raw
loader the fixture in a throwaway JVM). The pre-check stays -- it still
protects older libraries, and gives every kind of stale IR the same exception
-- and the javadoc now dates the abort.

ModuleIrCompatibilityTest follows upstream: the fixture is now the
retired-format case, so moduleInfo on it must fail with SLANG_E_NOT_AVAILABLE
and loadModuleFromIr must throw the actionable message (the writer version is
no longer readable, so that assertion goes). Reading name and writer from
readable IR moves to self-serialized IR, since no released Slang writes
format 2 at a module version other than 2026.19's 32 to make a new fixture
from. nonModuleBytesThrow now also pins that garbage never passes for a
retired format. 40 of 40 pass against the macos-aarch64 payload.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
loadModuleFromIr let through only the exact module version the running build
writes, because Slang used to abort the process on IR it could not read and
the version it writes is the one it certainly reads. That made it stricter
than Slang: a build reads a range (2026.19 reads 31 through 32, writes 32),
so IR Slang would have loaded was refused.

Since 2026.18.3 (upstream #12905) Slang checks a module's format and version
before deserializing and reports what it cannot read (E00130/E00132), so the
abort that justified the strictness is gone there. Against those releases
loadModuleFromIr now hands the IR to Slang and lets it decide; a cross-version
refusal is rethrown with the module, both versions and the remedy ahead of
Slang's own diagnostics. Against older releases nothing changes: the exact
check still stands between them and native code. Which side a library is on
comes from its build tag; a tag that is no release number (a local build
without git tags) counts as older, the safe direction.

No released Slang writes a module 2026.19 reads at any version but 32, so the
new tests forge versions: they relabel self-serialized IR by patching its
64-bit module version field, found by asking moduleInfo which patch it reports
back. Against 2026.19, version 31 now loads (refused before), and versions 33
and 1 throw SlangCompileException naming the module, its version and the
remedy. The release-tag parsing is pinned down separately. 43 of 43 pass
against the macos-aarch64 payload.

The guard on older libraries was checked against a real one: with these
classes on the official 2026.16 binaries (zip matched the SHA-256 in main's
manifest), a forged in-range version 27 and the 2026.8 fixture were both
refused before reaching native code, and the JVM survived.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Slang-Version floor covers the ABI, not serialized modules, which each
release reads only within a narrow range of module versions. README now says
to treat them as a cache, and points at loadModuleFromIr's exception and
moduleInfo's up-front check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ships the Slang 2026.19 regeneration: the bundled binaries go 2026.16 ->
2026.19 and PINNED_SLANG_VERSION with them.

Not purely additive, because upstream was not. Slang 2026.17 repurposed
IGlobalSession vtable slot 32 and dropped CompilerOptionName::CompilerVersion,
so the generated ffi.gen layer loses IGlobalSession.getDownstreamCompilerVersion
(and its VT_ constant) and CompilerOptionName.CompilerVersion, and gains
getDownstreamCompilerPath. The idiomatic API used neither. Worth a line in the
release notes: 0.0.9 pointed at a 2026.17+ library through libraryPath, calling
the raw getDownstreamCompilerVersion, passes int* where Slang now writes an
ISlangBlob*.

Serialized modules, user-visible:
- loadModuleFromIr now lets Slang 2026.18.3+ decide which module versions load,
  so older versions still in its range load instead of being refused; older
  libraries keep the exact-version guard that stops them aborting.
- Modules written before Slang 2026.18.3 no longer load at all (upstream
  retired serialization format 1); that now fails with an actionable
  SlangCompileException rather than a bare loadModuleInfoFromIRBlob failure.

gradle.properties is the single version source for the library and both
natives artifacts; README's coordinates, manifest example and both dependency
snippets move to 0.0.10 with it.

Verified locally: :slang:test 43/43 against the 2026.19 macos-aarch64 payload,
javadoc warning-free, both extractor test suites. The other platforms are for
the PR's CI, and release.yml re-runs the suite against the pinned binaries
before it publishes anything.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

Qodana for JVM

It seems all right 👌

No new problems were found according to the checks applied

💡 Qodana analysis was run in the pull request mode: only the changed files were checked

View the detailed Qodana report

To be able to view the detailed Qodana report, you can either:

To get *.log files or any other Qodana artifacts, run the action with upload-result option set to true,
so that the action will upload the files as the job artifacts:

      - name: 'Qodana Scan'
        uses: JetBrains/qodana-action@v2026.1.3
        with:
          upload-result: true
Contact Qodana team

Contact us at qodana-support@jetbrains.com

@RefuX
RefuX merged commit 17b2361 into main Oct 2, 2026
7 checks passed
@RefuX
RefuX deleted the bump/slang-2026.19 branch October 2, 2026 08:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant