Throwing an opaque Error causes SIL build error in release build

Hello, I wanted to share an error I'm observing that I've been able to distill to a minimal reproducible snippet (built within an otherwise empty SPM project). When an error is returned as an opaque value (some Error), throwing that value causes SIL build errors when building for release (no compilation errors occur when building for debug).

FYI, I've submitted this issue as feedback to Apple already, but wanted to make a post here for the community.

Here's the key snippet of code that causes the build error:

@available(iOS 13, macOS 10.15.0, *)
public func global() {
    var error: some Error {
        MyError.e1
    }

    do {
        throw error
    } catch {

    }
}

public enum MyError: Error {
    case e1
}

This is the output I'm seeing when building for release using swift build.

$ swift build -c release
Building for production...
remark: Incremental compilation has been disabled: it is not compatible with whole module optimization
error: compile command failed due to signal 11 (use -v to see invocation)
Please submit a bug report (https://swift.org/contributing/#reporting-bugs) and include the crash backtrace.
Stack dump:
0.	Program arguments: /Applications/Xcode-15.2.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift-frontend -frontend -c /Users/annalisem/zillow/SomeErrorSILError/Sources/SomeErrorSILError/SomeErrorSILError.swift -emit-module-path /Users/annalisem/zillow/SomeErrorSILError/.build/arm64-apple-macosx/release/SomeErrorSILError.swiftmodule -emit-module-doc-path /Users/annalisem/zillow/SomeErrorSILError/.build/arm64-apple-macosx/release/SomeErrorSILError.swiftdoc -emit-module-source-info-path /Users/annalisem/zillow/SomeErrorSILError/.build/arm64-apple-macosx/release/SomeErrorSILError.swiftsourceinfo -emit-dependencies-path /Users/annalisem/zillow/SomeErrorSILError/.build/arm64-apple-macosx/release/SomeErrorSILError.build/SomeErrorSILError.d -emit-objc-header-path /Users/annalisem/zillow/SomeErrorSILError/.build/arm64-apple-macosx/release/SomeErrorSILError.build/SomeErrorSILError-Swift.h -emit-abi-descriptor-path /Users/annalisem/zillow/SomeErrorSILError/.build/arm64-apple-macosx/release/SomeErrorSILError.abi.json -target arm64-apple-macosx10.13 -Xllvm -aarch64-use-tbi -enable-objc-interop -sdk /Applications/Xcode-15.2.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.2.sdk -I /Users/annalisem/zillow/SomeErrorSILError/.build/arm64-apple-macosx/release -I /Applications/Xcode-15.2.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/lib -F /Applications/Xcode-15.2.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks -color-diagnostics -g -module-cache-path /Users/annalisem/zillow/SomeErrorSILError/.build/arm64-apple-macosx/release/ModuleCache -swift-version 5 -O -D SWIFT_PACKAGE -new-driver-path /Applications/Xcode-15.2.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift-driver -empty-abi-descriptor -resource-dir /Applications/Xcode-15.2.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift -Xcc -isysroot -Xcc /Applications/Xcode-15.2.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.2.sdk -Xcc -F -Xcc /Applications/Xcode-15.2.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks -Xcc -fPIC -module-name SomeErrorSILError -package-name someerrorsilerror -disable-clang-spi -target-sdk-version 14.2 -target-sdk-name macosx14.2 -external-plugin-path /Applications/Xcode-15.2.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.2.sdk/usr/lib/swift/host/plugins#/Applications/Xcode-15.2.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.2.sdk/usr/bin/swift-plugin-server -external-plugin-path /Applications/Xcode-15.2.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.2.sdk/usr/local/lib/swift/host/plugins#/Applications/Xcode-15.2.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.2.sdk/usr/bin/swift-plugin-server -external-plugin-path /Applications/Xcode-15.2.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/lib/swift/host/plugins#/Applications/Xcode-15.2.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/bin/swift-plugin-server -external-plugin-path /Applications/Xcode-15.2.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/local/lib/swift/host/plugins#/Applications/Xcode-15.2.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/bin/swift-plugin-server -plugin-path /Applications/Xcode-15.2.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/host/plugins -plugin-path /Applications/Xcode-15.2.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/local/lib/swift/host/plugins -enable-default-cmo -parse-as-library -num-threads 10 -o /Users/annalisem/zillow/SomeErrorSILError/.build/arm64-apple-macosx/release/SomeErrorSILError.build/SomeErrorSILError.swift.o
1.	Apple Swift version 5.9.2 (swiftlang-5.9.2.2.56 clang-1500.1.0.2.5)
2.	Compiling with the current language version
3.	While emitting IR SIL function "@$s17SomeErrorSILError6globalyyF".
 for 'global()' (at /Users/annalisem/zillow/SomeErrorSILError/Sources/SomeErrorSILError/SomeErrorSILError.swift:7:8)
Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it):
0  swift-frontend           0x0000000105545abc llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 56
1  swift-frontend           0x00000001081abcb0 llvm::sys::RunSignalHandlers() + 112
2  swift-frontend           0x0000000107f15054 SignalHandler(int) + 352
3  libsystem_platform.dylib 0x00000001a98d2a24 _sigtramp + 56
4  swift-frontend           0x0000000103d9c424 emitApplyArgument((anonymous namespace)::IRGenSILFunction&, swift::SILValue, swift::SILType, swift::irgen::Explosion&) + 572
5  swift-frontend           0x00000001051e6600 (anonymous namespace)::IRGenSILFunction::visitFullApplySite(swift::FullApplySite) + 3628
6  swift-frontend           0x0000000105136310 (anonymous namespace)::IRGenSILFunction::visitSILBasicBlock(swift::SILBasicBlock*) + 2788
7  swift-frontend           0x00000001078c9fdc swift::irgen::IRGenModule::emitSILFunction(swift::SILFunction*) + 11680
8  swift-frontend           0x00000001054c89c8 swift::irgen::IRGenerator::emitGlobalTopLevel(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>> const&) + 2516
9  swift-frontend           0x0000000104cf15f0 swift::performIRGeneration(swift::ModuleDecl*, swift::IRGenOptions const&, swift::TBDGenOptions const&, std::__1::unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule>>, llvm::StringRef, swift::PrimarySpecificPaths const&, llvm::ArrayRef<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>, llvm::GlobalVariable**) + 2240
10 swift-frontend           0x0000000107a85a04 generateIR(swift::IRGenOptions const&, swift::TBDGenOptions const&, std::__1::unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule>>, swift::PrimarySpecificPaths const&, llvm::StringRef, llvm::PointerUnion<swift::ModuleDecl*, swift::SourceFile*>, llvm::GlobalVariable*&, llvm::ArrayRef<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>) + 260
11 swift-frontend           0x0000000107a8d6d4 performCompileStepsPostSILGen(swift::CompilerInstance&, std::__1::unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule>>, llvm::PointerUnion<swift::ModuleDecl*, swift::SourceFile*>, swift::PrimarySpecificPaths const&, int&, swift::FrontendObserver*) + 1596
12 swift-frontend           0x0000000107a88f00 performCompile(swift::CompilerInstance&, int&, swift::FrontendObserver*) + 3020
13 swift-frontend           0x0000000107a8c854 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 4568
14 swift-frontend           0x0000000107af3d44 swift::mainEntry(int, char const**) + 4408
15 dyld                     0x00000001a954bf28 start + 2236

this is possibly because you are using the downloadable toolchains from swift.org, which are far less reliable than the same version that ships with Xcode. do you get the same build failure when you compile with the default system toolchain?

Assertions enabled ≠ less reliable. If you’re hitting assertions using the swift.org toolchains, you are hitting untested and possibly undefined codepaths in the Xcode toolchains.

2 Likes

you have to wonder then why the decision was made to ship assertionless toolchains with Xcode. i wasn’t in the room for that, but i imagine one possibility is that if the Xcode toolchains shipped with assertions enabled, then sourcekit-lsp would crash more frequently, and many users would suddenly find themselves unable to build their projects because the compiler keeps crashing.

if you were in that position, the nuances of compiler reliability might not be so important to you. your only actionable solution would be to obtain a toolchain that has the assertions disabled, so that you can start developing your project again. oftentimes this involves spending a lot of time trying to compile the toolchain from source with the correct settings, and then figuring out the logistics of distributing those custom toolchains within your organization.

is this ideal? of course not! stack corruption is scary as hell. i reckon there are quite a few folks out there who remember when Swift has stack corruption bugs. and even if you weren’t worried about things like that, no one wants to take a monthlong detour just to enter the business of distributing assertionless Swift compilers. but if you are responsible for a company that is burning through capital in real time, you don’t have a lot of better alternatives. you can’t just stop working because there might be a bug in the compiler.

It was years ago when that decision was made, but I believe download size and performance factored into it—running the assertions does take time, though I don’t remember the percentages then and they probably aren’t accurate anymore. I honestly don’t remember how correctness and crashes factored into the decision—they both must have been brought up, but I wouldn’t have been involved in those discussions even when I worked there, and I suspect the decision hasn’t been revisited since, say, Swift 2.

The build failure that OP posted is from the Xcode toolchain and the crash is a segmentation fault not an assertion.

i guess if OP has a new enough Mac, the next thing to try then is to update Xcode to 15.3 and start using the 5.10 compiler instead. i did not see the crash when i tried compiling her snippet with the 5.10 toolchain that comes with Xcode.

Yeah, this is just the associated Swift 5.9 that came with Xcode 15.2.

I'm sticking to 15.2 locally mostly because of CI issues with 15.3, but when I have some time I'll download 15.3 and see if that fixes things.