Fix build and two runtime crashes on Xcode 16.4 / Swift 6.1 - #66
Open
danilmezor wants to merge 2 commits into
Open
Fix build and two runtime crashes on Xcode 16.4 / Swift 6.1#66danilmezor wants to merge 2 commits into
danilmezor wants to merge 2 commits into
Conversation
ProceduralSplatController's async init is nonisolated, so calling it from a @mainactor context sends the non-Sendable MTLDevice across an isolation boundary: "sending 'self.device' risks causing data races". Swift 6.2 makes nonisolated async functions run on the caller's actor (nonisolated(nonsending)) so this compiles there, but Xcode 16.4 ships Swift 6.1. An explicit `isolated` parameter defaulted to #isolation gets the same behaviour on 6.1, and keeps the non-isolated visionOS call site working too. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Pkf6MUWwCwkz9jDjcQ6f4Q
1. Command buffer completion handler trapped on the first rendered frame. MetalKitSceneRenderer is @mainactor and MTLCommandBufferHandler is not audited for Sendable, so the closure was inferred @MainActor-isolated. Metal invokes it on its own completion queue, so the Swift 6 runtime executor check failed: dispatch_assert_queue_fail swift_task_isCurrentExecutorWithFlagsImpl closure scier#1 in MetalKitSceneRenderer.draw(in:) -[_MTLCommandBuffer didCompleteWithStartTime:endTime:error:] Marking the closure @sendable makes it nonisolated. It only signals a DispatchSemaphore, which is already Sendable. 2. Logger init force-unwrapped Bundle.main.bundleIdentifier, which is nil because the target never set PRODUCT_BUNDLE_IDENTIFIER and Info.plist has no CFBundleIdentifier. Any log call trapped -- including the error path in draw(in:), so a render failure crashed instead of being reported. Set a bundle identifier and stop force-unwrapping. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Pkf6MUWwCwkz9jDjcQ6f4Q
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Building the sample app with Xcode 16.4 (Swift 6.1.2) currently fails, and once it builds it crashes on the first rendered frame. Three related fixes, one per commit.
1. Build failure:
sending 'self.device' risks causing data racesProceduralSplatController'sasync initis nonisolated, so calling it from@MainActorcode sends the non-SendableMTLDeviceacross an isolation boundary.Swift 6.2 makes nonisolated async functions run on the caller's actor (
nonisolated(nonsending)), which is presumably why this builds for you — but Xcode 16.4 ships Swift 6.1. Adding anisolated (any Actor)? = #isolationparameter gets the same behaviour on 6.1, and keeps the non-isolatedVisionSceneRenderercall site working.2. Crash: actor-isolation trap in the command buffer completion handler
MetalKitSceneRendereris@MainActor, andMTLCommandBufferHandleris not audited forSendablein the SDK, so the completion closure is inferred@MainActor-isolated. Metal invokes it oncom.Metal.CompletionQueueDispatch, so the Swift 6 runtime executor check fails:This fires on the first rendered frame of any model, so Sample Box, Procedural Splat and a loaded scene all crash identically. Marking the closure
@Sendablemakes it nonisolated; it only signals aDispatchSemaphore, which is alreadySendable.3. Crash: force-unwrapped
Bundle.main.bundleIdentifierThe
Loggerinitialisers force-unwrapBundle.main.bundleIdentifier, which isnil— the target never setsPRODUCT_BUNDLE_IDENTIFIERandInfo.plisthas noCFBundleIdentifier, so a macOS build has no identifier at all.Any log call therefore traps. That includes the error path in
draw(in:):so a render failure crashed instead of being reported. This sets a bundle identifier and stops force-unwrapping in both renderers.
Testing
Builds clean for macOS and iOS Simulator on Xcode 16.4. Verified against a 9.2M-splat scene on an M1 Pro.