[expo-modules-jsi] SDK 57 local iOS build fails on Swift 6.2+: SWIFT_RETURNS_RETAINED on RuntimeScheduler constructors
Minimal reproducible example
https://github.com/thiago-slb/expo-modules-jsi-swift62-repro
Summary
A blank SDK 57 app (create-expo-app --template blank, no app code changed) fails to build for iOS. Two constructors in expo-modules-jsi's RuntimeScheduler.h are annotated SWIFT_RETURNS_RETAINED, which Swift 6.2+ rejects:
node_modules/expo-modules-jsi/apple/Sources/ExpoModulesJSI-Cxx/include/RuntimeScheduler.h:53:26:
error: 'RuntimeScheduler' cannot be annotated with either SWIFT_RETURNS_RETAINED or
SWIFT_RETURNS_UNRETAINED because it is not returning a SWIFT_SHARED_REFERENCE type
SWIFT_RETURNS_RETAINED RuntimeScheduler(void *scheduler, ScheduleFn fn) noexcept
node_modules/expo-modules-jsi/apple/Sources/ExpoModulesJSI-Cxx/include/RuntimeScheduler.h:61:26:
error: (same)
SWIFT_RETURNS_RETAINED RuntimeScheduler() {}
** BUILD FAILED **
Failing phase: [CP-User] Build ExpoModulesJSI xcframework.
The class does carry SWIFT_SHARED_REFERENCE, but only on the closing brace (line 90), while the annotated constructors are on lines 53 and 61. Swift 6.2+ rejects returns_retained on a constructor of an import_reference type.
expo-modules-jsi is not a direct dependency — it arrives via expo → expo-modules-core → expo-modules-jsi, so this affects every SDK 57 project doing local iOS builds on a machine with Swift 6.2+ (i.e. current Xcode).
Steps to reproduce
Platform: iOS, standalone/local build, package manager npm.
git clone https://github.com/thiago-slb/expo-modules-jsi-swift62-repro
cd expo-modules-jsi-swift62-repro
npm install
npx expo prebuild -p ios --no-install
cd ios && pod install
xcodebuild -workspace reprojsi.xcworkspace -scheme reprojsi \
-configuration Release -sdk iphoneos -destination 'generic/platform=iOS' \
CODE_SIGNING_ALLOWED=NO build
Expected: build succeeds.
Actual: ** BUILD FAILED ** with the two errors above.
Already ruled out
- Not a stale artifact.
node_modules/expo-modules-jsi/apple/Productsdid not exist; the xcframework was built from scratch. Also reproduced afterrm -rf iosand clearing~/Library/Developer/Xcode/DerivedData. - Not fixed in the next major.
npm pack [email protected], diffed against 57.1.0: the header is byte-for-byte identical, both annotations and the trailingSWIFT_SHARED_REFERENCEincluded. - Not declaration order. Moving
SWIFT_SHARED_REFERENCEonto the class declaration (with forward declarations for the retain/release functions) makes the header compile standalone underclang++ -fsyntax-only, but the xcframework build fails identically. - Not fixed by a newer Xcode. Also reproduced on Xcode 26.6 / Apple Swift 6.3.3 (
swiftlang-6.3.3.1.3 clang-2100.1.1.101). Newer Swift is stricter, not looser.
The macros come from <swift/bridging> in the active toolchain, with _CXX_INTEROP_HAS_ATTRIBUTE(swift_attr) true — these are the real attribute definitions, not the empty fallbacks.
Workaround
EAS cloud builds succeed, so the build image ships a Swift older than 6.2. Only local builds are blocked.
Environment
expo-env-info 2.1.0 environment info:
System:
OS: macOS 15.7.5
Shell: 5.9 - /bin/zsh
Binaries:
Node: 22.22.3
Yarn: 1.22.22
npm: 10.9.8
Watchman: 2026.06.01.00
Managers:
CocoaPods: 1.16.2
SDKs:
iOS SDK:
Platforms: DriverKit 25.2, iOS 26.2, macOS 26.2, tvOS 26.2, visionOS 26.2, watchOS 26.2
IDEs:
Android Studio: 2025.3 AI-253.32098.37.2534.15232325
Xcode: 26.3/17C529 - /usr/bin/xcodebuild
Expo Workflow: managed
expo 57.0.22 · expo-modules-jsi 57.1.0 · react-native 0.86.3 · Apple Swift 6.2.4 (swiftlang-6.2.4.1.4 clang-1700.6.4.2)
(Previously filed as #50061 and #50062, both auto-closed for lack of a linked repro — this one has the repository.)
Source: expo/expo