Skip to main content

MEP-49 research note 12, Risks and alternatives for MEP-49

Author: research pass for MEP-49 (Mochi to Swift transpiler). Date: 2026-05-23 (GMT+7).

This note catalogues the load-bearing risks of MEP-49 and the alternatives that were considered and rejected. Each entry links back to the load-bearing decision in 02-design-philosophy and the affected implementation note.

1. Risk register

R1: Swift Concurrency runtime evolution

Risk. Swift Concurrency landed in Swift 5.5 (Sept 2021) and has seen breaking-ish changes through 5.7 (existential any), 5.9 (macros and ownership), 6.0 (strict concurrency, region isolation, typed throws), 6.2 (approachable concurrency, closures default non-isolated). A Mochi codebase compiled against Swift 6.0 may emit warnings or even fail to compile under Swift 6.5 if Apple adjusts the language mode default again.

Mitigation. MEP-49 floors at Swift 6.0 language mode and pins to it. The codegen pass emits explicit isolation annotations on every closure, function, and actor method so the meaning is unambiguous regardless of future default changes. CI runs the ceiling (Swift 6.1, 6.2) advisory matrix to catch regressions early.

Residual risk. Medium. Swift's evolution velocity is higher than JVM's; the analogous .NET risk (R3 in mep-0048) is lower because .NET LTS cadence is more conservative.

See 02-design-philosophy §3, 09-agent-streams §15.

R2: App Store / Apple Developer Program gatekeeping

Risk. Apple controls the iOS distribution chain. App Review can reject apps for arbitrary reasons: novelty, "spam," competition with first-party apps. Mochi-generated apps may face higher scrutiny if Apple flags them as transpiled or AI-generated.

Mitigation. MEP-49 emits idiomatic Swift indistinguishable from hand-written Swift after swift-format. The generated code does not embed Mochi compiler watermarks, does not call private SPI, does not bundle a runtime evaluator (no JIT). App Review heuristics target webviews and HyperCard-style content engines; Mochi output is plain native Swift.

Residual risk. Low-medium. We cannot influence Apple's discretion; we can only minimise the attack surface.

See 07-swift-target-portability §10-11, 11-testing-gates §8.

R3: Sendable enforcement false positives

Risk. Swift 6.0's complete sendable checking is conservative. Mochi codegen may emit a value that Mochi's static check knows is sendable (because Mochi's type system already proves it) but Swift's checker rejects (because it requires explicit : Sendable).

Mitigation. Mochi codegen emits explicit : Sendable conformances on every type. Where Mochi knows a closure is sendable (no captures or only sendable captures), the codegen emits @Sendable. Where Swift's check fails, the codegen falls back to boxing the value in a wrapper class that uses a lock (the "we know this is fine, but Swift doesn't" escape hatch).

Residual risk. Low. The fallback is correct but slower; Mochi emits a warning when the fallback fires, prompting the user to adjust Mochi-side type annotations.

See 06-type-lowering §17, 11-testing-gates §4.

R4: swift-corelibs-foundation parity gaps

Risk. swift-corelibs-foundation (Linux, Windows) is not a 1:1 reimplementation of Apple Foundation. As of Swift 6.0: NSCalendar is partial, NSTimeZone needs tzdata, Process semantics differ, NSXMLParser is missing.

Mitigation. Mochi runtime polyfills the gaps via swift-system (FilePath, FileDescriptor), swift-foundation-icu (Foundation substitute being built), and pure-Swift implementations of missing features. The polyfill is tested against both Apple and corelibs Foundation in CI.

Residual risk. Medium. Apple is rewriting Foundation in Swift (swift-foundation, github.com/swiftlang/swift-foundation, Sept 2023 announcement) targeting full parity by Swift 6.x. By 2026-2027 the gap should close.

See 04-runtime §3, 07-swift-target-portability §5.

R5: swift-syntax dependency size

Risk. apple/swift-syntax is ~10MB compiled. If Mochi codegen uses it directly, every Mochi build pulls a large dependency.

Mitigation. MEP-49 does NOT take a direct dependency on swift-syntax. The codegen pass implements a Go-side syntax model that emits canonical Swift text. swift-format is invoked optionally post-emit if the user has a Swift toolchain installed.

Residual risk. Low. The trade-off is hand-rolling Swift formatting logic; we lean on swift-format for canonicalisation.

See 05-codegen-design §1, §7, §8.

R6: SwiftPM build performance

Risk. SwiftPM is slower than go build or cargo build for medium-sized projects. Cold build of a 50K-LOC Swift project on M1 macOS arm64 takes 2-5 minutes. Mochi adds 4000 LOC of generated Swift per Mochi module on top.

Mitigation. Mochi codegen emits multiple .swift files per module to enable parallel compilation. SwiftPM build cache (~/.swiftpm/build) reuses incremental compilation results. CI uses actions/cache to persist .swiftpm-cache across runs.

Residual risk. Medium. Slow builds hurt iteration loop; mitigated by mochi run keeping vm3 path fast.

See 10-build-system §22.

R7: iOS app bundle reproducibility

Risk. Apple's codesign tool embeds the codesign timestamp into the binary. Notarization adds a unique ticket. .ipa archives are zips that may have non-deterministic file ordering. Two runs of mochi build --target=swift-ios may produce different bytes even on the same machine.

Mitigation. MEP-49 reproducibility gate (Phase 16) excludes codesign and notarization from the byte-equality check. The unsigned, unstapled binary is bit-identical. Signing is a final distribution step.

Residual risk. Low (with the scope carve-out).

See 11-testing-gates §10.

R8: Static Linux SDK breakage

Risk. swift-static-linux-sdk is a young addition (Swift 5.9, Sept 2023). Toolchain bugs may surface when statically linking complex Mochi programs that pull C dependencies. Specifically: ICU must be statically embedded; Foundation networking via libcurl is statically linked; TLS via mbedTLS (swift-static-linux-sdk's choice).

Mitigation. MEP-49 v1 ships static Linux as Phase 17 (not v1 landing), letting the SDK stabilise. We test against Static Linux SDK 6.0 + 6.1 and pin to the working versions.

Residual risk. Medium. Apple ships the SDK; quality is high but young.

See 07-swift-target-portability §4, 11-testing-gates §9.

R9: Foundation-models opacity

Risk. Apple's FoundationModels framework (iOS 18+, macOS 15+ Apple Silicon only) is the on-device LLM. API stability is not guaranteed; the framework is marked Beta in some headers.

Mitigation. Mochi generate lowers to FoundationModels on eligible Apple platforms with a swift-openai-async fallback for ineligible platforms (Linux, Windows, old Apple). The fallback path is the default for CI.

Residual risk. Medium-high. FoundationModels may break between iOS minor versions.

See 04-runtime §4, 01-language-surface §9.

R10: Cross-target divergence on streams

Risk. Streams have observable nondeterminism: ordering of interleaved AsyncSequence elements depends on Task scheduler. Five backends scheduling Tasks differently produce different stdouts.

Mitigation. Stream fixtures are explicitly marked as non-deterministic and excluded from differential testing (11-testing-gates §3). Mochi assertions on stream output use set-equality or sort-then-compare.

Residual risk. Low (with scope carve-out).

See 09-agent-streams §20, 11-testing-gates §12.

R11: Windows toolchain stability

Risk. Swift on Windows reached 1.0 quality in Swift 5.9 (Sept 2023) but the ecosystem is thin. Some packages (apple/swift-nio) have spotty Windows CI. Mochi runtime depends on swift-collections, swift-algorithms, swift-async-algorithms; verify Windows builds.

Mitigation. CI runs windows-2025 matrix on every PR. Verified all swift-* runtime deps build clean on Windows as of Swift 6.0.

Residual risk. Low-medium.

See 07-swift-target-portability §6-7, 10-build-system §18.

R12: ARC reference cycles in agents

Risk. Mochi agents lower to Swift actor. If two agents reference each other strongly through stored closures, ARC leaks. Erlang-style supervised actor topologies are common; the leak risk is real.

Mitigation. MochiRuntime.Supervisor holds children as weak references. Cross-agent references emitted by the codegen pass use unowned for parent links and weak for sibling caches. Mochi's type system distinguishes "owning" from "referencing" links.

Residual risk. Medium. Cycle detection in ARC requires manual care; a future MEP could ship an ARC cycle detector.

See 09-agent-streams §10-12, 02-design-philosophy §9.

R13: ABI churn in Swift 6.x

Risk. Apple promised ABI stability in Swift 5.0 (Mar 2019) and has held it through 6.x. But ABI applies only to the standard library; third-party packages (swift-collections etc.) have no ABI guarantee. A swift-collections 2.0 could break Mochi.Runtime binary compatibility.

Mitigation. Mochi.Runtime pins exact versions of swift-* dependencies in Package.resolved and ships a major-version pin in Package.swift (e.g., from: "1.1.0"). Major-version bumps require a Mochi.Runtime major bump.

Residual risk. Low. swift-collections has not had a major version bump and is unlikely to in the MEP-49 v1 timeframe.

See 04-runtime, 10-build-system §3.

R14: Mochi codegen complexity drift

Risk. Five target codegens (C, BEAM, JVM, .NET, Swift) sharing an aotir IR but each with target-specific lowering is operationally complex. A Mochi language change that lands easily for vm3 may require five separate target updates.

Mitigation. All five targets share monomorphisation and closure-conversion passes (05-codegen-design §5). Target-specific codegen passes are small (~4000 LOC each). The fixture corpus is shared, so a Mochi feature must produce identical output across targets, catching divergence early.

Residual risk. Medium. As Mochi grows, target maintenance burden grows. Mitigated by automated cross-target gates.

See 11-testing-gates §12.

2. Alternatives considered

A1: Objective-C as the target language

Rejected. See 02-design-philosophy §2. Objective-C is on a long decommissioning path; no Swift 6 features map cleanly; new Apple frameworks are Swift-only.

A2: Swift as the target language, but Swift 5.10 as floor

Rejected. See 02-design-philosophy §3. Swift 5.10 lacks typed throws (SE-0413), strict concurrency by default, region-based isolation (SE-0414). Floor-ing at 5.10 forces dual codepaths (5.10 language mode vs. 6.0 mode) for marginal benefit (Xcode 15.x support, which will be EOL by App Store cadence by 2026 H2).

A3: Apple-only platform scope

Rejected. See 02-design-philosophy §4. Locks Mochi out of server-side Swift, which is the fastest-growing Swift segment. Forces users to choose a different Mochi target for backend code.

A4: GCD DispatchQueue for agent mailboxes

Rejected. See 02-design-philosophy §5. Bypasses Swift Concurrency's sendable checking. Combine, the natural reactive companion, is Apple-only.

A5: Custom Mochi-runtime actor scheduler

Rejected. See 02-design-philosophy §5. Duplicates work Swift Concurrency does well. Decouples Mochi from Swift's evolution at the cost of reinventing the scheduler.

A6: Swift Macros for code generation

Rejected. See 02-design-philosophy §15. Macros expand per- call-site, not per-module. Whole-program Mochi codegen needs module-level analysis. Macros also require a Swift toolchain at Mochi's compile time, complicating self-bootstrap.

A7: LLVM IR direct emission

Rejected. Bypasses the Swift type system, loses ARC and sendable checks, makes the output non-debuggable, prevents Library Evolution. Closest analogue is .NET IL emission, where MEP-48 chose Roslyn source over IL for the same reasons.

A8: SwiftSyntax as a hard dependency

Rejected. See 05-codegen-design §7. swift-syntax is ~10MB compiled and requires a Swift host toolchain at build time. Mochi self-bootstraps from Go; pulling Swift into Mochi's build chain adds friction.

A9: Combine for streams

Rejected. See 02-design-philosophy §12. Apple-only. Backpressure correctness issues. Superseded by AsyncSequence in Apple's own framework direction.

A10: Foundation-only, no Apple Frameworks

Rejected. Loses access to SwiftData, Observation, FoundationModels. These provide value on Apple platforms; making them opt-in via @available plus runtime detection is better.

A11: Kotlin Multiplatform / Skip.tools as the Swift target

Rejected. Kotlin Multiplatform compiles Kotlin to Swift via the Skip.tools transpiler. Using KMP as Mochi's Swift target would add a Kotlin compilation layer (Mochi → Kotlin → Swift) for no benefit. Mochi's type system is already at the Swift level of expressiveness; KMP adds latency.

A12: Direct .ipa packaging without Xcode

Rejected. iOS .ipa requires codesigning against a Provisioning Profile that only Apple's Developer Portal issues. xcodebuild is the canonical packaging tool; replacing it requires reverse- engineering the Mach-O format, embedded provisioning profile, and asset catalog format. Out of scope for v1.

3. Open questions

Q1: Should Mochi-on-Swift expose SwiftUI?

A future MEP-N could add a view keyword that lowers to SwiftUI View types. Not in MEP-49 scope; tracked as candidate v2.

Q2: Should Mochi-on-Swift expose SwiftData?

A persisted record keyword that lowers to @Model. Tracked as candidate v2.

Q3: Should Mochi target Embedded Swift?

Microcontroller deployment via the Embedded Swift subset. Tracked as v2 (deferred to MEP-49 Phase 19, not in v1 scope per 11-testing-gates §16).

Q4: Should Mochi target SwiftWasm?

WebAssembly via swift-wasm. Tracked as v2 (deferred to MEP-49 Phase 20, 11-testing-gates §17). Likely a separate MEP given the differing constraints (no Foundation, no URLSession).

Q5: Should Mochi target Windows ARM64?

Swift on Windows ARM64 is in early development (Swift 6.0 ships x86_64 only). Tracked as candidate v2 when toolchain matures.

Q6: Should Mochi support distributed actors?

distributed actor (SE-0336) for cross-process actor systems. A natural fit for Mochi remote agents but requires a separate MEP to design the ActorSystem (decouple from Swift Distributed Tracing, swift-cluster, etc.).

Q7: Should Mochi ship App Store submission automation?

mochi build --target=swift-ios --publish-testflight could shell out to xcrun notarytool and App Store Connect API. Tracked as candidate v2 (out of Phase 18 scope, which only validates).

4. Comparison with sibling MEPs

DimensionMEP-45 (C)MEP-46 (BEAM)MEP-47 (JVM)MEP-48 (.NET)MEP-49 (Swift)
Target langC11Erlang (Core Erlang)Java 21C# 12Swift 6.0
Codegen IRC sourceCore Erlang via cerlJava source via JavaPoetC# via RoslynSwift source
Toolchain versionclang/gccOTP 27/28JDK 21/25 LTS.NET 8/10 LTSSwift 6.0/6.1
Concurrency primitivepthreadsOTP processLoom virtual threadChannel + asyncactor + AsyncStream
Streams primitivecallbackgen_eventFlow.PublisherIAsyncEnumerableAsyncSequence
Memorymanual + arenaper-process GCTracing GCTracing GCARC
Build drivermake/cmakerebar3Gradle/Mavendotnet CLISwiftPM
Package registry(none / system)hex.pmMaven CentralNuGetswift-package-index
AOT/JITAOTBEAM bytecode + JITHotSpot JIT + GraalVMJIT + ReadyToRun + AOTAOT only
Distribution shapessingle binaryescript / OTP releaseuberjar / jlink / nativedll / self-contained / AOT.ipa / .app / static
Hot reloadnoyes (BEAM purge)yes (HotSwap, limited)nono
Mobile target(via Embed manual)noAndroid via D8/R8MAUI via .NET MAUIiOS/iPad/visionOS native
App-store-friendlynonopartial (Android)partial (.NET MAUI)yes (iOS/Mac App Store)

The Swift target uniquely covers Apple platforms App-Store-friendly deployment, complementing the other four backends.

5. Out of scope for v1

Documented elsewhere but listed for closure:

  • SwiftUI lowering (Q1).
  • SwiftData persistence (Q2).
  • Embedded Swift (Q3).
  • SwiftWasm (Q4).
  • Windows ARM64 (Q5).
  • Distributed actors (Q6).
  • App Store automation (Q7).
  • Property-based testing.
  • Fuzzing harness.
  • ARC cycle detector.

Each of these is a candidate v2 follow-up; none block v1 landing.

6. Failure modes if MEP-49 is not done

The "do nothing" alternative: skip MEP-49 entirely, keep Mochi on vm3 plus C/BEAM/JVM/.NET. The cost:

  • No first-class iOS app development from Mochi.
  • No first-class macOS app development from Mochi.
  • No visionOS reach (the only AR/VR platform Apple ships).
  • Server-side Swift users (Vapor/Hummingbird shops) must use a different Mochi backend or switch languages.
  • Mochi positioning is "general-purpose" but missing the Apple ecosystem dents that claim.

The risk-adjusted value of doing MEP-49 is high: the user-facing goal (Mochi on Apple platforms) is gated entirely on this MEP.

Cross-references: 02-design-philosophy for the decision rationale, 01-language-surface for the surface contract, 11-testing-gates for the gate matrix that validates each decision.