Skip to content

Modern Swift concurrency (breaking)#3

Merged
RISCfuture merged 2 commits into
masterfrom
modern-concurrency
Jun 27, 2026
Merged

Modern Swift concurrency (breaking)#3
RISCfuture merged 2 commits into
masterfrom
modern-concurrency

Conversation

@RISCfuture

@RISCfuture RISCfuture commented Jun 27, 2026

Copy link
Copy Markdown
Owner

Summary

Adopts the Approachable Concurrency upcoming-feature flags
(NonisolatedNonsendingByDefault, InferIsolatedConformances) across the
library, test, and E2E targets, and migrates the codebase off legacy
concurrency constructs onto plain structured concurrency.

  • Removed the downloader's GCD DispatchQueue.main.async hop and the per-chunk
    Task { @MainActor in … } hops in the archive and directory distributions,
    replacing them with direct, thread-safe Progress mutation. This also removes
    a hazard where progress could be reported out of order or after a stream had
    finished.
  • Replaced the two nonisolated(unsafe) statics in the test URL-protocol mock
    with an OSAllocatedUnfairLock (chosen over Synchronization.Mutex, which
    requires macOS 15 vs the package's macOS 13 floor).
  • Modernized the manual smoke-test harness from RunLoop.main.run() to
    top-level await.

Kept intentionally: UnitSlope's @unchecked Sendable (Foundation
Dimension), the @preconcurrency import ZIPFoundation lines (load-bearing for
the non-Sendable Archive), and the @preconcurrency import RegexBuilder
lines (Reference<…> is still non-Sendable; the build proved them
load-bearing).

Breaking changes

JSONZipEncoder and JSONZipDecoder changed from open
JSONEncoder/JSONDecoder subclasses marked @unchecked Sendable into
Sendable structs, eliminating an unsound @unchecked conformance on mutable
classes. The encoder gains init(outputFormatting: JSONEncoder.OutputFormatting = [])
and a public var outputFormatting; encode(_:) and decode(_:from:) are now
value-type methods.

This is source-breaking for anyone who:

  • subclassed JSONZipEncoder/JSONZipDecoder,
  • used them polymorphically as JSONEncoder/JSONDecoder, or
  • set JSONEncoder/JSONDecoder properties other than outputFormatting.

The no-argument JSONZipEncoder() / JSONZipDecoder() initializers still
compile.

Verification

  • swift build --build-tests succeeds with zero new warnings.
  • Full unit-test suite passes (110/110).
  • The SwiftNASR_E2E executable target was run end-to-end against live FAA
    data and passed.

Version

This change set includes a source-breaking change — JSONZipEncoder and
JSONZipDecoder are now Sendable value types (struct) instead of
JSONEncoder/JSONDecoder subclasses. The previously-unreleased [3.1.0]
CHANGELOG section (which had only additive changes) has therefore been promoted
to [4.0.0], folding in those pending additions plus this migration. The
GitHub release will be cut after merge.

@RISCfuture RISCfuture force-pushed the modern-concurrency branch from 068374d to b95f5a3 Compare June 27, 2026 06:55
RISCfuture and others added 2 commits June 27, 2026 01:09
…rrency

Enable the Approachable Concurrency upcoming-feature flags
(NonisolatedNonsendingByDefault, InferIsolatedConformances) across the
library, test, and E2E targets, and migrate the codebase off legacy
concurrency constructs to plain structured concurrency.

Concretely:

- Remove the downloader's GCD DispatchQueue.main.async hop and the
  per-chunk Task { @mainactor in … } hops in the archive and directory
  distributions, replacing them with direct, thread-safe Progress
  mutation. This also removes a hazard where progress could be reported
  out of order or after a stream had finished.
- Replace the two nonisolated(unsafe) statics in the test URL-protocol
  mock with an OSAllocatedUnfairLock (chosen over Synchronization.Mutex,
  which requires macOS 15 vs the package's macOS 13 floor).
- Modernize the manual smoke-test harness from RunLoop.main.run() to
  top-level await.

Kept intentionally: UnitSlope's @unchecked Sendable (Foundation
Dimension), the @preconcurrency import ZIPFoundation lines (load-bearing
for the non-Sendable Archive), and the @preconcurrency import
RegexBuilder lines (Reference<…> is still non-Sendable; the build proved
them load-bearing).

BREAKING: JSONZipEncoder and JSONZipDecoder are now Sendable value types
(struct) instead of JSONEncoder/JSONDecoder subclasses, eliminating
their unsound @unchecked Sendable conformances. The encoder gains
init(outputFormatting: JSONEncoder.OutputFormatting = []) and a public
var outputFormatting; encode(_:) and decode(_:from:) are now value-type
methods. The no-argument JSONZipEncoder()/JSONZipDecoder() initializers
still compile, but code that subclassed these types, used them
polymorphically as JSONEncoder/JSONDecoder, or set JSONEncoder/
JSONDecoder properties other than outputFormatting must be updated.

Verified with swift build --build-tests (zero new warnings) and the full
unit-test suite (110/110 passing).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Dropping the unsound `@unchecked Sendable` on `JSONZipEncoder`/`JSONZipDecoder`
(now `Sendable` value types) is source-breaking, so the previously-unreleased
3.1.0 section is promoted to 4.0.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@RISCfuture RISCfuture force-pushed the modern-concurrency branch from b95f5a3 to 47cf455 Compare June 27, 2026 08:09
@RISCfuture RISCfuture merged commit 47cf455 into master Jun 27, 2026
6 checks passed
@RISCfuture RISCfuture deleted the modern-concurrency branch June 27, 2026 18: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