apple / apple/swift-openapi-urlsession
Library-evolution build fails on Xcode 26.5 / Swift 6.3: `@inlinable` deinit/inits in Lock.swift require `@_fixed_layout`/`@frozen`
- Dominant language
- Swift
- Stars
- 216
- Forks
- 44
- PR merge metrics
- No merged PRs in 30d
Description
### Summary
We ship a binary **XCFramework** that bundles `OpenAPIURLSession` (used internally for REST API calls), and that XCFramework is distributed to **React Native developers** who integrate it into their apps.
Because those developers build against our prebuilt binary with their *own* (often older) Xcode/Swift toolchains, we need module stability — i.e. `BUILD_LIBRARY_FOR_DISTRIBUTION=YES` — so the framework keeps working across compiler versions. That's exactly the configuration that propagates library evolution to `OpenAPIURLSession` and trips the errors above.
Building `OpenAPIURLSession` with library evolution enabled (`-enable-library-evolution` / `BUILD_LIBRARY_FOR_DISTRIBUTION=YES`) fails to compile on **Xcode 26.5 / Swift 6.3**. This happens when the package is a (transitive) dependency of a framework that is archived for binary distribution as an XCFramework. The same configuration compiled on earlier toolchains, so this is a regression triggered by the newer compiler's stricter enforcement.
### Environment
- Xcode 26.5 (build 17F42)
- Apple Swift 6.3.2 (swiftlang-6.3.2.1.108, clang-2100.1.1.101)
- `swift-openapi-urlsession` `main` (the constructs below are present in all 1.0.0–1.3.0 releases)
### Errors
```
Sources/OpenAPIURLSession/BufferedStream/Lock.swift:190:5: error: deinitializer can only be '@inlinable' if the class is '@_fixed_layout'
Sources/OpenAPIURLSession/BufferedStream/Lock.swift:244:14: error: 'let' property '_storage' may not be initialized directly; use "self.init(...)" or "self = ..." instead
Sources/OpenAPIURLSession/BufferedStream/Lock.swift:322:14: error: 'let' property '_storage' may not be initialized directly; use "self.init(...)" or "self = ..." instead
```
### Reproduction
```bash
swift build -Xswiftc -enable-library-evolution
```
### Cause
In `Sources/OpenAPIURLSession/BufferedStream/Lock.swift`:
- `LockStorage` (a `final class`) declares an `@inlinable deinit`.
- `Lock` and `LockedValueBox` (structs) declare `@inlinable` initializers that directly initialize their stored `let _storage` property.
Under library evolution, types have resilient (non-fixed) layout, so the compiler requires `@_fixed_layout` (class) / `@frozen` (struct) before allowing an `@inlinable` deinit or an `@inlinable` initializer that directly assigns a stored property.
### Possible fixes
1. Mark `LockStorage` `@_fixed_layout` and `Lock` / `LockedValueBox` `@frozen` — keeps the `@inlinable` optimizations and requires no opt-in from consumers.
2. Drop `@inlinable` from those three members (negligible perf impact — a lock's deinit/init are not hot paths).
A PR follows with option (2) gated behind a compilation condition so the default build is byte-for-byte unchanged, but maintainers may prefer option (1).
Contributor guide
Research direction
Start with Sources/OpenAPIURLSession/BufferedStream/Lock.swift and reproduce the failure using swift build -Xswiftc -enable-library-evolution. Inspect the @inlinable deinitializer and initializers for LockStorage, Lock, and LockedValueBox, then apply the maintainer-approved approach. Done means the library-evolution build succeeds on the reported Swift toolchain without changing the default build behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- swift
- Domain
- build-system
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100