Skip to content

build: adopt the zero-cost Swift 7 upcoming features on VRMMetalKit - #392

Merged
arkavo-com merged 3 commits into
mainfrom
feat/swift7-upcoming-features
Aug 21, 2026
Merged

build: adopt the zero-cost Swift 7 upcoming features on VRMMetalKit#392
arkavo-com merged 3 commits into
mainfrom
feat/swift7-upcoming-features

Conversation

@arkavo-com

@arkavo-com arkavo-com commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Adopts the Swift 7 upcoming features that cost nothing, and documents — with measurements — what adopting each of the rest would buy and cost. The intent is that this PR answers "why not the others?" without anyone having to re-run the experiment.

Draft: the scope question at the end is worth a decision before this lands.

Measured

Each feature enabled one at a time on the VRMMetalKit target, Swift 6.3.3, from a clean 0-diagnostic baseline. Mirrors the MuseCore methodology, so the numbers are comparable.

setting diagnostics unique sites adopted MuseCore
InferIsolatedConformances 0 0 0
ImmutableWeakCaptures 0 0 0
MemberImportVisibility 3 errors 3 0
ExistentialAny 1,255 warnings 210 0
NonisolatedNonsendingByDefault 0 0 15
InternalImportsByDefault 2,619 errors 85 files 8,926

Count sites, not diagnostics. ExistentialAny's 1,255 warnings are 210 real sites — a raw diagnostic count overstates the work ~6×. Same distinction behind MuseCore's "was 83 sites, not 1,169" note.

Adopted — what each buys

  • InferIsolatedConformances — conformances on actor-isolated types infer that isolation instead of requiring explicit annotation. Removes a class of spurious isolation errors before they appear.
  • ImmutableWeakCapturesweak captures in closures become immutable. Catches the reassign-a-weak-capture bug, where the write silently doesn't do what the author intended.
  • MemberImportVisibility — members require an explicit import of their defining module. This one earned its keep immediately: it found three places relying on transitive imports, which would break silently if a dependency ever changed what it re-exports.

Cost of adoption was exactly three imports:

  • CoreGraphics in SpriteCacheSystemCGSize.init(width:height:)
  • Metal in VRMMaterialReportMTLTexture.width / .height
  • Metal in SpringBoneBreastColliderMTLBuffer.contents()

Not adopted

ExistentialAny — 210 sites, buys forward-compat only

Warnings-only in Swift 6 language mode, so it never blocks a build today. It becomes a hard error in Swift 7, so these sites must be fixed eventually regardless.

What adopting buys: exactly one thing — Swift 7 readiness. It converts a forced future migration, arriving on the toolchain's schedule, into a chosen one.

What it does not buy, which matters before spending review budget on a 210-site sweep:

sites
Metal Obj-C protocols (MTLBuffer 60, MTLDevice 37, MTLRenderPipelineState 23, MTLTexture 17, MTLCommandBuffer 14, …) 194 (92%)
Error 6
AnimationLayer 4
Decoder / Encoder 6
  • No performance gain. Metal's protocols are class-bound, so the existential is already a single pointer — there is no witness-table boxing to eliminate. any MTLBuffer is identical codegen to MTLBuffer.
  • No refactoring signal. You cannot swap MTLBuffer for some/generics; Metal hands you existentials by construction. The annotation surfaces nothing a reader didn't know.
  • No consumer impact either way. any P and P denote the same type and the spelling requirement is per-module, so downstream consumers are unaffected whether we adopt or not. This is not a source break being got ahead of.

The one interesting slice is AnimationLayer (4 sites) — a project protocol, where any vs some is a genuine design question and might reveal an existential that needn't be one. The other ~206 are find-and-replace.

If adopted, sequence it after #380. Of the six heaviest files, only SpringBoneComputeSystem.swift (23 sites) is also touched by that 68-commit branch — one conflict, but a tedious one to resolve by hand across a mechanical sweep.

NonisolatedNonsendingByDefault — 0 diagnostics, but not free

SE-0461. Measures 0 here where MuseCore measured 15, so it looks like the obvious next adoption. It isn't.

What it would buy: nonisolated async functions begin executing on the caller's executor instead of hopping to the generic executor — fewer actor hops and less Sendable friction at call boundaries.

Why not yet: that is a runtime semantic change, not a compile-time one. A 0 means the compiler found nothing to complain about, not that behavior is unchanged. #384/#387 deliberately established a nonisolated drawOffscreen driven from a non-main render thread with a documented single-producer contract; this feature changes where such work starts running. The test suite drives rendering synchronously, so neither a clean build nor a green suite is evidence that contract survives. This wants a concurrency review, not a diagnostic count.

InternalImportsByDefault — 2,619 diagnostics across 85 files

SE-0409. Imports become internal by default; anything appearing in the public API needs public import.

What it would buy: an explicit, checked statement of which dependencies are part of the API versus implementation detail — and, in principle, less transitive module loading for consumers. (Build-time impact not measured here; treat it as a claim, not a finding.)

Why not: same story as MuseCore's 8,926, and arguably worse in kind. A library's broad public surface is the module's purpose, so most of the 85 files would need public import rather than benefiting from the tightening. High churn, low return.

Verification

  • swift package clean + full swift build: the only remaining diagnostics are two pre-existing warnings (GLTFCore/Loader/BufferLoader.swift:209 and :293, withUnsafeMutableBytes result unused), unrelated to this change and already visible on the Xcode Cloud visionOS build.
  • Full test suite: zero failures.

Scope

Only the VRMMetalKit target is covered — that is what was measured. GLTFCore, GLTFMetalKit, the CLI executables, and the test targets remain unadopted. Extending the three settings package-wide is a reasonable follow-up, but needs the same per-target measurement first; I would rather not assume GLTFCore is clean because VRMMetalKit is.

arkavo-com and others added 3 commits August 6, 2026 22:33
Measured one at a time against the VRMMetalKit target on Swift 6.3.3
from a clean 0-diagnostic baseline, counting `swift build --target
VRMMetalKit` output:

| setting                          | diagnostics | sites | adopted |
|----------------------------------|-------------|-------|---------|
| InferIsolatedConformances        |           0 |     0 | yes     |
| ImmutableWeakCaptures            |           0 |     0 | yes     |
| MemberImportVisibility           |    3 errors |     3 | yes     |
| ExistentialAny                   | 1255 warn   |   210 | no      |
| NonisolatedNonsendingByDefault   |           0 |     0 | no      |
| InternalImportsByDefault         | 2619 errors |    85 | no      |

MemberImportVisibility needed three explicit imports for members that
were previously reaching this module transitively: CoreGraphics in
SpriteCacheSystem (CGSize.init(width:height:)), and Metal in
VRMMaterialReport (MTLTexture.width/height) and SpringBoneBreastCollider
(MTLBuffer.contents()). That is the whole cost.

Not adopted, with reasons:

- ExistentialAny is warnings-only in Swift 6 language mode, so it does
  not block, but it is 210 unique sites across 30+ files (44 in
  VRMRenderer alone) — mostly `MTLBuffer`/`MTLTexture` existentials.
  Mechanical but large enough to swamp review; belongs in its own PR.
- NonisolatedNonsendingByDefault compiles clean, but SE-0461 changes
  runtime semantics (nonisolated async functions start on the caller's
  actor). #384/#387 deliberately established a nonisolated `drawOffscreen`
  driven from a non-main render thread; a 0 here is not evidence that
  contract is unaffected, and the suite drives rendering synchronously so
  it would not catch a regression.
- InternalImportsByDefault needs `public import` across the API surface,
  which for a library is the whole point of the module.

Full suite passes; the only remaining build diagnostics are two
pre-existing `withUnsafeMutableBytes` warnings in GLTFCore/BufferLoader.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The two packed-accessor fast paths reached for the C `memcpy` symbol, which
BufferLoader only sees through Foundation's implicit re-export of Darwin.
UnsafeMutableRawPointer.copyMemory is the stdlib equivalent for the same
non-overlapping copy, so the call no longer depends on a transitively
imported module. These were the only memcpy uses in GLTFCore.

GLTFCore does not enable MemberImportVisibility, so this is preparatory
rather than required by the target's current settings.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FHQ86b5tGQUF2kJKgCZ8mc
@arkavo-com
arkavo-com marked this pull request as ready for review August 21, 2026 22:19
@github-actions

Copy link
Copy Markdown

Claude Code Review ran on 104cf15 — result: success.

Findings (if any) are posted as inline comments; none means the review found nothing to flag. Run log.

@arkavo-com

Copy link
Copy Markdown
Contributor Author

Gitar review

@gitar-bot

gitar-bot Bot commented Aug 21, 2026

Copy link
Copy Markdown

Note

Automatic reviews are paused because your team has used its included automatic processing for this billing period (headroom scales with your seat count). You can still comment "Gitar review" to run one anytime, and automatic reviews resume on their own by September 1. Add seats for more headroom.
Learn more

Code Review ✅ Approved

Adopts zero-cost Swift 7 upcoming features (InferIsolatedConformances, ImmutableWeakCaptures, and MemberImportVisibility) on VRMMetalKit. No issues found.

Was this helpful? React with 👍 / 👎 | Gitar

@gitar-bot

gitar-bot Bot commented Aug 21, 2026

Copy link
Copy Markdown

Gitar review

Running the review now — results will be posted to the dashboard shortly.

@arkavo-com
arkavo-com merged commit bdc100d into main Aug 21, 2026
13 checks passed
@arkavo-com
arkavo-com deleted the feat/swift7-upcoming-features branch August 21, 2026 22:30
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.

1 participant