A Release build made with Xcode 27 beta and Swift 6.4 can abort with Global is external, but doesn't have external or weak linkage! followed by Broken module found, compilation aborted!. The regression requires an interaction between explicit Cross-Module Optimization, a public generic function, and a dynamic cast to a non-public protocol.
Representative log
Global is external, but doesn't have external or weak linkage!
ptr @"$s...Updatable...WP"
<unknown>:0: error: fatal error encountered during compilation
<unknown>:0: note: Broken module found, compilation aborted!
Stack dump:
0. Running pass "verify" on module ".../Client.o"
If the protocol is changed from private to internal, the frontend crash may become a linker failure instead:
Undefined symbols for architecture arm64:
"protocol conformance descriptor for Types.Incident.Update : Core.Updatable in Core"
Cause
Swift issue #91771 describes a public generic function in a module built with -cross-module-optimization. Its body dynamically casts a value to a non-public protocol, while the conforming type comes from another module. Client-side specialization folds the cast into direct references to a conformance descriptor and witness table that cannot be resolved outside the defining module.
This is not the usual missing-library linker error. A Debug build that succeeds while the optimized Release build fails is an important diagnostic clue.
Affected versions and conditions
- Xcode 27.0 beta; the public reproducer used build
27A5252f - Apple Swift 6.4, including
swiftlang-6.4.0.33.1 - A Release module built with explicit
-cross-module-optimization - A public generic function that performs
as?against a non-public protocol - The conforming type is imported from another module
The reproducer succeeds with Xcode 26.6 and Swift 6.3.3, in Debug, and in Release after removing explicit CMO. The issue also notes that SwiftPM’s conservative -enable-default-cmo does not trigger the reduced case by itself.
Reduced structure
// Core module, built with -cross-module-optimization
import Types
private protocol Updatable {
func write()
}
extension Incident.Update: Updatable {
func write() {}
}
public func process<T>(_ value: T) {
guard let value = value as? any Updatable else { return }
value.write()
}
Recommended fix
- Confirm the toolchain and failing configuration.
xcodebuild -version xcrun swiftc --version swift build -c release -v - Remove explicit
-cross-module-optimizationfrom the affected module and rebuild Release. Check Other Swift Flags in Xcode andswiftSettingsin SwiftPM. - Separate the non-public protocol cast from the public generic body. Prefer keeping the implementation inside its defining module so it is not serialized and specialized by a client.
- Only when it is appropriate API design, reconsider whether the protocol and conformance must be externally visible. Merely changing
privatetointernalcan turn the crash into the undefined-symbol failure shown above. - When a Swift or Xcode build containing the fix is verified, update, clear generated artifacts, and retest.
rm -rf ~/Library/Developer/Xcode/DerivedData/* swift package clean swift build -c release
Alternative workarounds
- Temporarily build with Xcode 26.6 and Swift 6.3.3 if project requirements allow it
- Disable explicit CMO only for the affected module after measuring the performance impact
- Move the cast from the public generic function into a non-public, non-generic helper
The issue reports a workaround using @_semantics("optimize.no.crossmodule"), but underscored attributes are unsupported implementation details. Do not treat that attribute as a stable permanent fix.
How to verify
- Build Debug and Release separately
- Use verbose output to confirm explicit
-cross-module-optimizationis absent from the affected Release compilation - Confirm that both the LLVM verifier message and the protocol-conformance undefined symbol are gone
- Measure performance and binary size after changing optimization settings
Important notes
Undefined symbols for architecture arm64 has many unrelated causes, including missing libraries and target configuration mistakes. Attribute this failure to issue #91771 only when Swift 6.4, Release, explicit CMO, and non-public protocol conformance are all present. The issue is closed, but the public record does not identify the first shipping Xcode release containing the fix.
Summary
This Swift 6.4 regression lets CMO emit a reference to a non-public protocol conformance that a client module cannot resolve. Disable explicit CMO for the affected module first, then redesign the boundary between the public generic function and the non-public protocol where practical.
