Skip to content

Program crash when trying to print property of optional #90031

@nickasd

Description

@nickasd

Description

The program below crashes at line 76, which tries to print a property of an optional:

print(data?.a)

This crash is not easy to reproduce: renaming certain symbols, reordering them, removing apparently unused protocols or reducing the cases of either enum may fix it.

In my original code, the crash is preceded by several logged warnings like

warning: the Swift runtime was unable to demangle the type of field '(null)'. the mangled type name is 'ed': unknown error. this field will show up as an empty tuple in Mirrors

In my original code, printing the nil object actually prints an object with nonsensical properties (interleaved with the above warning), like

ID(name: (), instance: 16)

I'm grateful for any insight into what the cause of the crash is, if there is a workaround, and if it will work for current as well as past operating systems.

Reproduction

enum B: Hashable, Codable {
    case c(C)
    case d(D)
}

enum C: String, Codable {
    case _1
    case _2
    case _3
    case _4
    case _5
    case _6
    case _7
    case _8
    case _9
    case _10
    case _11
    case _12
    case _13
    case _14
    case _15
    case _16
    case _17
    case _18
    case _19
    case _20
    case _21
    case _22
    case _23
    case _24
    case _25
    case _26
    case _27
    case _28
    case _29
    case _30
    case _31
    case _32
    case _33
}

enum D: String, CaseIterable, Codable {
    case _1
    case _2
    case _3
    case _4
    case _5
    case _6
    case _7
    case _8
    case _9
    case _10
    case _11
    case _12
}

struct ID: Hashable, Codable {
    let name: B
    let instance: Int
}

class A1 {
    
    init() {
        let actionHandler = ActionHandler()
        actionHandler.register(b)
        try! actionHandler.handle(context: 0)
    }
    
    struct A2: Codable {
        let a: ID?
    }
    
    func b(data: inout A2?, context: Int) {
        print(data) // nil
        print(data?.a) // crash: Thread 1: EXC_BAD_ACCESS (code=1, address=0x16341e660)
    }
    
}

let a = A1()

class ActionHandler {
    
    private var handle: ((Int) -> Void)!

    init() {
    }
    
    func register<T: Codable>(_ handle: @escaping (_ data: inout T?, _ context: Int) -> Void) {
        self.handle = { context in
            var data: T?
            handle(&data, context)
        }
    }
    
    func handle(context: Int) throws {
        handle(context)
    }
    
}

Stack dump

* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0x16e701cb0)
    frame #0: 0x0000000187ae0ac4 libsystem_platform.dylib`_platform_strlen + 4
    frame #1: 0x000000019b1bb70c libswiftCore.dylib`(anonymous namespace)::getFieldAt(swift::TargetMetadata<swift::InProcess> const*, unsigned int) + 284
    frame #2: 0x000000019b1b7b5c libswiftCore.dylib`swift_reflectionMirror_count + 864
    frame #3: 0x000000019b479754 libswiftCore.dylib`Mirror.init(internalReflecting:subjectType:customAncestor:) + 132
    frame #4: 0x000000019b1b6cb4 libswiftCore.dylib`Mirror.init(reflecting:) + 248
    frame #5: 0x000000019b1b8dd8 libswiftCore.dylib`_adHocPrint_unlocked(_:_:_:isDebugPrint:) + 3568
    frame #6: 0x000000019b1c1114 libswiftCore.dylib`_debugPrint_unlocked(_:_:) + 932
    frame #7: 0x000000019b1b855c libswiftCore.dylib`_adHocPrint_unlocked(_:_:_:isDebugPrint:) + 1396
    frame #8: 0x000000019b1c1114 libswiftCore.dylib`_debugPrint_unlocked(_:_:) + 932
    frame #9: 0x000000019b4601e8 libswiftCore.dylib`specialized _debugPrint(_:separator:terminator:to:) + 1668
    frame #10: 0x000000019b4566fc libswiftCore.dylib`Swift.Optional.debugDescription.getter : Swift.String + 392
    frame #11: 0x000000019b1bc46c libswiftCore.dylib`_print_unlocked(_:_:) + 492
    frame #12: 0x000000019b4605a4 libswiftCore.dylib`specialized _print(_:separator:terminator:to:) + 140
    frame #13: 0x000000019b45fa0c libswiftCore.dylib`print(_:separator:terminator:) + 620
  * frame #14: 0x0000000100006560 problem`A.b(data=nil, context=0) at main.swift:303:9
    frame #15: 0x0000000100005c78 problem`implicit closure #2 in implicit closure #1 in A.init() at main.swift:0
    frame #16: 0x0000000100006b84 problem`closure #1 in ActionHandler.register<problem.A.C>(context=0, handle=0x0000000100009b34 problem`partial apply forwarder for implicit closure #2 (inout Swift.Optional<problem.A.C>, Swift.Int) -> () in implicit closure #1 @Sendable (problem.A) -> (inout Swift.Optional<problem.A.C>, Swift.Int) -> () in problem.A.init() -> problem.A at <compiler-generated>) at main.swift:320:13
    frame #17: 0x0000000100006d20 problem`ActionHandler.handle(context=0) at main.swift:325:9
    frame #18: 0x0000000100005074 problem`A.init() at main.swift:294:28
    frame #19: 0x0000000100000d2c problem`A.__allocating_init() at main.swift:0
    frame #20: 0x0000000100000cc4 problem`main at main.swift:308:9
    frame #21: 0x000000018771be00 dyld`start + 6992

Expected behavior

No crash.

Environment

swift-driver version: 1.148.6 Apple Swift version 6.3.2 (swiftlang-6.3.2.1.108 clang-2100.1.1.101)
Target: arm64-apple-macosx26.0

Additional information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    crashBug: A crash, i.e., an abnormal termination of softwaretriage neededThis issue needs more specific labels

    Type

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions