Migrate to the Swift 6 language mode#8
Merged
Merged
Conversation
Move all first-party targets off the Swift 5 language mode (and consumers off `@preconcurrency import`) to full Swift 6 strict concurrency, on both AppKit and UIKit. Approach (swift-tools-version 6.2, per-target): - MarkdownParser: `.v6`, remains nonisolated Sendable data. - Litext + MarkdownView: `.v6` + `.defaultIsolation(MainActor.self)` for the UI layers. - `isolated deinit` for the two deinits that touch main-actor state (LTXLabel, MathPreviewDataSource). The main subtlety: `defaultIsolation(MainActor)` would force MarkdownView's genuine background-processing layer (the `com.markdownview.preprocessing` Combine pipeline) onto the main actor — compiling clean but trapping at runtime in `dispatch_assert_queue`. The processing subsystem is therefore kept explicitly `nonisolated`: CodeHighlighter and ImageLoader (`@unchecked Sendable`), PreprocessedContent (background init nonisolated, math members `@MainActor`), the diff/highlight helpers, and the pipeline's background stage extracted into a `nonisolated static` function. Minor public-API changes: - Removed the unused `theme:` parameter from `CodeHighlighter.highlight`. - `PreprocessedContent.init(...backgroundSafe:)` now always defers math rendering (the `backgroundSafe: false` full-render path is not expressible off the main actor; use `@MainActor init(parserResult:theme:)` instead). Tests that exercise the main-actor UI API are annotated `@MainActor`. Full suite is at parity with the base branch (the two Python-trait failures are pre-existing under `swift test`, which excludes the Python trait). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
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 free
to 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.
What
Migrates all first-party targets off the Swift 5 language mode (and consumers off
@preconcurrency import MarkdownView) to full Swift 6 strict concurrency. Builds green with zero concurrency errors/warnings on both AppKit (macOS) and UIKit (iOS).Why
A consuming app had to mark the library
@preconcurrency import MarkdownViewbecause, in Swift 5 mode, the library's public API carried no isolation/Sendableinformation. This adds proper isolation so downstream Swift 6 consumers can drop@preconcurrency.Approach (per-target,
swift-tools-version: 6.2).v6; unchanged (already cleanSendabledata)..v6+.defaultIsolation(MainActor.self)(Swift 6.2 "single-threaded by default" for the UI layers). This cleared ~80% of diagnostics on its own.isolated deinitfor the two deinits that touch main-actor state (LTXLabel,MathPreviewDataSource).MainActor.assumeIsolatedon a main-runloop timer,nonisolated overrideonNSObjecthash/isEqual,@Sendablecompletion +nonisolatedservice classes.The important subtlety
defaultIsolation(MainActor)compiled clean but crashed at runtime (SIGTRAPindispatch_assert_queue) because it forced MarkdownView's genuine background-processing layer — thecom.markdownview.preprocessingCombine pipeline — onto the main actor. The processing subsystem is therefore kept explicitlynonisolated:CodeHighlighterandImageLoader(@unchecked Sendable),PreprocessedContent(background init nonisolated; math members@MainActor), the diff/highlight helpers, and the pipeline's background stage extracted into anonisolated static func. (Note:nonisolatedon a class does not propagate to itsextensions — those are annotated individually.)Public-API changes (reviewer sign-off appreciated)
theme:parameter fromCodeHighlighter.highlight(...)— it was vestigial (colors come from tree-sitter; no caller passed it).PreprocessedContent.init(...backgroundSafe:)now always defers math rendering; thebackgroundSafe: falsefull-synchronous-render path (no callers) is not expressible off the main actor. Use@MainActor init(parserResult:theme:)when a fully-rendered value is needed up front.If you'd rather preserve exact source compatibility on either, they can become deprecated no-ops instead.
Testing
swift buildandxcodebuild -destination 'generic/platform=iOS Simulator'both succeed with no concurrency diagnostics.main— the only 2 failures (HighlighterTests/testHighlightReturnsMap,DiffViewTests/testSingleTokenFenceAutoDetectsUnifiedDiffAndUsesInnerLanguage) are pre-existing and fail identically on the base branch underswift test(Python isn't a default-enabled trait, so highlighting returns empty). Zero regressions.Out of scope
16 pre-existing
#no-usage(unusedNSMenuItem) lint warnings inLTXLabel+Interaction@AppKit.swiftare unrelated to concurrency and left untouched.🤖 Generated with Claude Code