swiftlang / swift

The Swift Programming Language
https://swift.org
Apache License 2.0
67.36k stars 10.34k forks source link

[SR-2282] Accessing Mirror's child.value for property with IUO type and nil value causes runtime crash #44889

Open swift-ci opened 8 years ago

swift-ci commented 8 years ago
Previous ID SR-2282
Radar None
Original Reporter ilyapuchka (JIRA User)
Type Bug
Environment Xcode 8 beta 4, swift 3
Additional Detail from JIRA | | | |------------------|-----------------| |Votes | 0 | |Component/s | Compiler, Standard Library | |Labels | Bug | |Assignee | None | |Priority | Medium | md5: 69cb7c66adbb24f9d508a7d33fd983ea

Issue Description:

Following code example fails when trying to cast child.value:

    class SomeClass {
      var someProperty: AnotherType!
    }
    class AnotherType {}
    protocol SomeProtocol: class {}

    Mirror(reflecting: SomeClass()).children.forEach { child in
      let _ = child.value as? SomeProtocol // fatal error: attempt to bridge an implicitly unwrapped optional containing nil
    }

But following code examples do not fail:

    class SomeClass {
      var someProperty: AnotherType!
    }
    class AnotherType {}
    protocol SomeProtocol {} //not a class protocol

    Mirror(reflecting: SomeClass()).children.forEach { child in
      let _ = child.value as? SomeProtocol // ok!
    }
    class SomeClass {
      var someProperty: SomeProtocol! //the same type as in as? later
    }

    class AnotherType {}

    Mirror(reflecting: SomeClass()).children.forEach { child in
      let _ = child.value as? SomeProtocol //ok!
    }
    class SomeClass {
      var someProperty: AnotherType? //Optional instead of IUO
    }

    class AnotherType {}

    Mirror(reflecting: SomeClass()).children.forEach { child in
      let _ = child.value as? SomeProtocol //ok!
    }
    class SomeClass {
      var someProperty: AnotherType!
    }

    struct AnotherType {} //value type instead of class

    Mirror(reflecting: SomeClass()).children.forEach { child in
      let _ = child.value as? SomeProtocol //ok!
    }

Also is it intentional that Mirror.Child is now (String?, Any) and not (String?, Any?)

belkadan commented 8 years ago

cc granataenrico (JIRA User) to start

swift-ci commented 8 years ago

Comment by Jin Wang (JIRA)

Any updates on this one?

swift-ci commented 7 years ago

Comment by Ilya Puchka (JIRA)

Is there any progress with that? With Xcode 8 it is still crashing but now prints "fatal error: attempt to bridge an implicitly unwrapped optional containing nil"

Can it be that the problem is that Mirror.Child is now defined as (String, Any) instead of (String, Any?). If it is Any with nil value how do I unwrap it to check if there is value or not?

Here is the example of code from my project that causes the crash:

public protocol AutoInjectedPropertyBox: class {...}

private func resolveChild(child: Mirror.Child) throws {
    guard let injectedPropertyBox = child.value as? AutoInjectedPropertyBox else { return } <- crashes here on a property of mirrored instance which is nil and it's type is IUO
    ...
}