Skip to content

Clear every compiler warning in our own sources (Swift 6 groundwork), and fix the blur relay's fake weak capture - #305

Merged
straff2002 merged 1 commit into
mainfrom
claude/epic-mayer-dbd622
Aug 9, 2026
Merged

Clear every compiler warning in our own sources (Swift 6 groundwork), and fix the blur relay's fake weak capture#305
straff2002 merged 1 commit into
mainfrom
claude/epic-mayer-dbd622

Conversation

@straff2002

Copy link
Copy Markdown
Owner

Clears every compiler warning in our own sources (app + test targets). Several were "this is an error in the Swift 6 language mode", so this is also Swift 6 migration groundwork. Vendored/SPM warnings are out of scope.

One real bug

OutboundFrameRelay.blur — the inner queue.async sat inside a closure that had already bound self strongly via guard let self, so its [weak self] Task was decorative. A relay released mid-pipeline was held alive to finish the composite and publish one more frame. The outer capture is weak now, which is what the surrounding code always intended.

Main-actor isolation

Immutable configuration made genuinely nonisolated rather than hopping — these are read from CoreBluetooth and capture callbacks where an actor hop would change timing.

  • EvenBLETransport's characteristic UUIDs and advertised-name prefix. CBUUID isn't annotated Sendable, so the three UUIDs are nonisolated(unsafe) — immutable value objects created once, stated rather than worked around.
  • LocalLLMService.visionModelIds, LLMService.localSafeTools, VideoRecordingService.frameStallSeconds.
  • FingerspellingModelDownloader.liveInstaller moves onto the nonisolated FingerspellingModelBundle, mirroring the existing ASRModelBundle precedent. That also resolves the redundant await progress(...): the closure is no longer main-actor-inferred, so the hop is real — and the download's file I/O leaves the main thread.

Sendable

  • The vision turn's UserInput (and the CIImage in it) is built inside the @Sendable closure from Sendable ingredients only, instead of crossing the boundary.
  • MediaTriggerService's notification handler is typed @Sendable.
  • BroadcastAudioProviding is @MainActor — the adopter and both call sites already were; only the handlers it registers are @Sendable.

iOS 26 deprecations

Deployment target is 26.0, so no availability gates were needed.

  • The OAuth presentation anchor walks connected scenes: foreground-active key window → any key window → any window → a new window on a scene. init(windowScene:) is the only surviving UIWindow initialiser, so the scene-less tail traps rather than returning an unpresentable empty window. Worth a reviewer's eye — it's a new trap where there wasn't one, though signIn() is only reachable from a Settings button tap, which requires a live scene, and the empty window it replaced could never have presented anything.
  • Walking routes use MKMapItem(location:address:) instead of the deprecated MKPlacemark.

Also

Two discarded capturePhoto() results made explicit (it files every capture to the "Glasses" album itself), a discarded seekToEnd(), two redundant trys on non-throwing closures passed to a rethrows function, and three redundant awaits in the download tests.

Verification

  • Debug simulator build: clean, 2852 tests, 0 failures, 3 skipped
  • Release build (device arm64, real SDK): succeeded, zero warnings in our sources
  • Debug device build: clean, installed and running on hardware

Every edited file was confirmed present in the build's SwiftCompile lines — an incremental build can silently skip a file, making a fixed warning and an unrecompiled file look identical. Three fixes initially looked verified and weren't; they were forced to rebuild and re-checked.

Build bumped to 351 per the per-merge convention; marketing version unchanged (no new feature).

Not addressed

Two xcodebuild notices remain, both pre-existing and neither a compiler warning: OpenGlasses/Sources/Models and .../Shared are members of multiple groups in the generated project. That's a project.base.yml group-layout artifact from the widget target referencing individual files inside a directory the app target includes wholesale — changing shared-file group placement risks the widget's target membership, so it's left alone.

Separately, a Release build does not launch on device — see #304. That's a vendored-dependency static-init deadlock, unrelated to this PR (the Release compile here is clean; the hang is pre-main).

🤖 Generated with Claude Code

…y's fake weak capture

A Debug simulator build was emitting 22 warnings across the app and test targets.
Several were "this is an error in the Swift 6 language mode", so clearing them is
also Swift 6 migration groundwork.

One was a real defect. In OutboundFrameRelay.blur, the inner `queue.async` sat
inside a closure that had already bound `self` strongly via `guard let self`, so
its `[weak self]` Task was decorative: a relay released mid-pipeline was held
alive to finish the composite and publish one more frame. The outer capture is
weak now, which is what the surrounding code always intended.

Main-actor isolation — immutable configuration made genuinely `nonisolated`
rather than hopping, since these are read from CoreBluetooth and capture
callbacks where a hop would change timing:
  - EvenBLETransport's characteristic UUIDs and advertised-name prefix. CBUUID
    isn't annotated Sendable, so the three UUIDs are `nonisolated(unsafe)` —
    immutable value objects created once, stated rather than worked around.
  - LocalLLMService.visionModelIds, LLMService.localSafeTools,
    VideoRecordingService.frameStallSeconds.
  - FingerspellingModelDownloader.liveInstaller moves onto the (nonisolated)
    FingerspellingModelBundle, mirroring ASRModelBundle. That also resolves the
    redundant `await progress(...)`: the closure is no longer main-actor-inferred,
    so the hop is real, and the download's file I/O leaves the main thread.

Sendable:
  - The vision turn's UserInput (and the CIImage in it) is built inside the
    @sendable closure from Sendable ingredients only, instead of crossing the
    boundary.
  - MediaTriggerService's notification handler is typed @sendable.
  - BroadcastAudioProviding is @mainactor — the adopter and both call sites
    already were; only the handlers it registers are @sendable.

iOS 26 deprecations (deployment target is 26.0, so no availability gates):
  - The OAuth presentation anchor walks connected scenes — foreground-active key
    window, any key window, any window, then a new window on a scene.
    init(windowScene:) is the only surviving UIWindow initialiser, so the
    scene-less tail traps instead of returning an unpresentable empty window;
    signIn() is only reachable from a Settings button tap, which requires a live
    scene.
  - Walking routes use MKMapItem(location:address:) instead of MKPlacemark.

Also: two discarded capturePhoto() results made explicit (it files every capture
to the "Glasses" album itself), a discarded seekToEnd(), two redundant `try`s on
non-throwing closures passed to a rethrows function, and three redundant `await`s
in the download tests.

Verified: Debug simulator build and the full suite are clean — 2852 tests, 0
failures, 3 skipped, and zero compiler warnings in our own sources. The only
warnings left are two pre-existing xcodebuild group-membership notices about the
generated project.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@straff2002
straff2002 merged commit 9e66de5 into main Aug 9, 2026
1 check passed
@straff2002
straff2002 deleted the claude/epic-mayer-dbd622 branch August 9, 2026 00:19
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