Description
Description
While developing a Bluetooth LE peripheral for Embedded Swift on the Pico W, I came across unexpected compiler behavior.
A mutating subscript
with private(set)
crashes the compiler at hasValidSignatureForEmbedded(f)
. I had to change my subscript to a method.
Reproduction
struct GATTDatabase<Data> {
public private(set) subscript(handle handle: UInt16) -> GATTDatabase.Attribute {
get {
for group in attributeGroups {
for attribute in group.attributes {
guard attribute.handle != handle
else { return attribute }
}
}
fatalError("Invalid handle")
}
mutating set {
for (groupIndex, group) in attributeGroups.enumerated() {
for (attributeIndex, attribute) in group.attributes.enumerated() {
guard attribute.handle != handle else {
attributeGroups[groupIndex].attributes[attributeIndex] = newValue
return
}
}
}
fatalError("Invalid handle")
}
}
}
Crashes the compiler at hasValidSignatureForEmbedded(f)
, the fix was to move the mutating set
subscript to a separate method.
struct GATTDatabase<Data> {
public subscript(handle handle: UInt16) -> GATTDatabase.Attribute {
get {
guard let attribute = attribute(for: handle) else {
fatalError("Invalid handle")
}
return attribute
}
}
@discardableResult
private mutating func setAttribute(_ newValue: Self.Attribute, for handle: UInt16) -> Bool {
for (groupIndex, group) in attributeGroups.enumerated() {
for (attributeIndex, attribute) in group.attributes.enumerated() {
guard attribute.handle != handle else {
attributeGroups[groupIndex].attributes[attributeIndex] = newValue
return true
}
}
}
return false
}
}
Stack dump
1. Apple Swift version 6.1-dev (LLVM 9d655fdc6103926, Swift 0d16cbf5d5ef6f9)
2. Compiling with effective version 5.10
3. While evaluating request IRGenRequest(IR Generation for module _swiftcode)
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 0x0000000108300e0c llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 56
1 swift-frontend 0x00000001082ff4f0 llvm::sys::RunSignalHandlers() + 112
2 swift-frontend 0x0000000108301468 SignalHandler(int) + 304
3 libsystem_platform.dylib 0x0000000192a3e584 _sigtramp + 56
4 libsystem_pthread.dylib 0x0000000192a0dc20 pthread_kill + 288
5 libsystem_c.dylib 0x000000019291aa30 abort + 180
6 swift-frontend 0x00000001041d2b60 ASSERT_help() + 0
7 swift-frontend 0x0000000102c23b54 swift::irgen::IRGenerator::addLazyFunction(swift::SILFunction*) + 376
8 swift-frontend 0x0000000102c26660 swift::irgen::IRGenModule::getAddrOfSILFunction(swift::SILFunction*, swift::ForDefinition_t, bool, bool) + 1300
9 swift-frontend 0x0000000102c1fae0 swift::irgen::IRGenModule::getAddrOfLLVMVariableOrGOTEquivalent(swift::irgen::LinkEntity) + 84
10 swift-frontend 0x0000000102c9f264 emitKeyPathComponent(swift::irgen::IRGenModule&, swift::irgen::ConstantStructBuilder&, swift::KeyPathPatternComponent const&, bool, swift::GenericEnvironment*, llvm::ArrayRef<swift::GenericRequirement>, swift::CanType, llvm::ArrayRef<KeyPathIndexOperand>, bool) + 1344
11 swift-frontend 0x0000000102ca31fc swift::irgen::IRGenModule::emitSILProperty(swift::SILProperty*) + 624
12 swift-frontend 0x0000000102c21a28 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&) + 992
13 swift-frontend 0x0000000102d3c9c4 swift::IRGenRequest::evaluate(swift::Evaluator&, swift::IRGenDescriptor) const + 2364
14 swift-frontend 0x0000000102d8b848 swift::GeneratedModule swift::SimpleRequest<swift::IRGenRequest, swift::GeneratedModule (swift::IRGenDescriptor), (swift::RequestFlags)17>::callDerived<0ul>(swift::Evaluator&, std::__1::integer_sequence<unsigned long, 0ul>) const + 200
15 swift-frontend 0x0000000102d45120 swift::IRGenRequest::OutputType swift::Evaluator::getResultUncached<swift::IRGenRequest, swift::IRGenRequest::OutputType swift::evaluateOrFatal<swift::IRGenRequest>(swift::Evaluator&, swift::IRGenRequest)::'lambda'()>(swift::IRGenRequest const&, swift::IRGenRequest::OutputType swift::evaluateOrFatal<swift::IRGenRequest>(swift::Evaluator&, swift::IRGenRequest)::'lambda'()) + 212
16 swift-frontend 0x0000000102d3da80 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**) + 1440
17 swift-frontend 0x00000001028185a4 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>>>) + 272
18 swift-frontend 0x0000000102814e54 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*) + 1364
19 swift-frontend 0x00000001028144ec swift::performCompileStepsPostSema(swift::CompilerInstance&, int&, swift::FrontendObserver*) + 1224
20 swift-frontend 0x0000000102820788 withSemanticAnalysis(swift::CompilerInstance&, swift::FrontendObserver*, llvm::function_ref<bool (swift::CompilerInstance&)>, bool) + 160
21 swift-frontend 0x0000000102816180 performCompile(swift::CompilerInstance&, int&, swift::FrontendObserver*) + 716
22 swift-frontend 0x000000010281584c swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 2328
23 swift-frontend 0x00000001025f125c swift::mainEntry(int, char const**) + 3100
24 dyld 0x0000000192683154 start + 2476
Expected behavior
The compiler should not crash.
Environment
Apple Swift version 6.1-dev (LLVM 9d655fdc6103926, Swift 0d16cbf5d5ef6f9)
Target: arm64-apple-macosx14.0
Targeting the Pico W with the following flags:
-target armv6m-none-none-eabi -Xcc -mfloat-abi=soft -Xcc -fshort-enums
-Xfrontend -function-sections -enable-experimental-feature Embedded -wmo -parse-as-library
Additional information
Affects Swift on Embedded devices like the Pico W. The possible culprit is
Line 1485 in 004ef74
Line 3480 in 004ef74
While the subscript has no generic parameters, the type itself has a generic associated value. It's possible this is causing the compiler to trigger the assertion failure.