Skip to content

Compiler crashes for mutating subscript when targeting Embedded language mode  #77682

Closed
@colemancda

Description

@colemancda

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

ASSERT(hasValidSignatureForEmbedded(f));
and
bool swift::irgen::hasValidSignatureForEmbedded(SILFunction *f) {

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.

Metadata

Metadata

Assignees

Labels

bugA deviation from expected or documented behavior. Also: expected but undesirable behavior.crashBug: A crash, i.e., an abnormal termination of softwaretriage neededThis issue needs more specific labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions