Why does casting to Any make my forced downcast not crash?

Here are two implementations that I'd expect to be equivalent, but
something's different because the first example crashes, whereas the second
example does not crash.

What's the difference between these two? Why does casting to Any before the
forced downcast to T have any effect?

Example 1: (`unexpectedly found nil while unwrapping an Optional value`)

func cast<T>(_ name: String?) -> T {
    return name as! T
}

debugPrint((cast(nil) as String?) as Any))

Example 2: (prints `nil`)

func cast<T>(_ name: String?) -> T {
return (name as Any) as! T
}

debugPrint((cast(nil) as String?) as Any)

Here are two implementations that I'd expect to be equivalent, but something's different because the first example crashes, whereas the second example does not crash.

What's the difference between these two? Why does casting to Any before the forced downcast to T have any effect?

It shouldn't. Please file a bug, if you haven't already.

-Joe

···

On Mar 13, 2017, at 5:13 AM, Kim Burgestrand via swift-users <swift-users@swift.org> wrote:

Example 1: (`unexpectedly found nil while unwrapping an Optional value`)

func cast<T>(_ name: String?) -> T {
    return name as! T
}

debugPrint((cast(nil) as String?) as Any))

Example 2: (prints `nil`)

func cast<T>(_ name: String?) -> T {
return (name as Any) as! T
}

debugPrint((cast(nil) as String?) as Any)

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

Will do! I'll file a bug that casting to `Any` first causes different
behavior.

Follow-up question, looking at the expression `name as! T`, is it expected
to cause a nil-unwrapping runtime error when `name == nil` and `T ==
Optional<String>`? Mind you, `(nil as! Optional<String>)` does not cause an
error.

If the nil-unwrapping error is expected, how can I write it so that it
doesn't, and instead returns nil?

···

On Tue, 14 Mar 2017 at 19:50 Joe Groff <jgroff@apple.com> wrote:

It shouldn't. Please file a bug, if you haven't already.

If you're casting to an Optional destination type, then the cast ought to succeed and produce a `nil` result if the input is nil.

-Joe

···

On Mar 15, 2017, at 4:47 AM, Kim Burgestrand <kim@burgestrand.se> wrote:

On Tue, 14 Mar 2017 at 19:50 Joe Groff <jgroff@apple.com <mailto:jgroff@apple.com>> wrote:

It shouldn't. Please file a bug, if you haven't already.

Will do! I'll file a bug that casting to `Any` first causes different behavior.

Follow-up question, looking at the expression `name as! T`, is it expected to cause a nil-unwrapping runtime error when `name == nil` and `T == Optional<String>`? Mind you, `(nil as! Optional<String>)` does not cause an error.

Found the answer to my follow-up question! It's a known and reported bug:

Thanks!

···

On Wed, 15 Mar 2017 at 12:47 Kim Burgestrand <kim@burgestrand.se> wrote:

On Tue, 14 Mar 2017 at 19:50 Joe Groff <jgroff@apple.com> wrote:

It shouldn't. Please file a bug, if you haven't already.

Will do! I'll file a bug that casting to `Any` first causes different
behavior.

Follow-up question, looking at the expression `name as! T`, is it
expected to cause a nil-unwrapping runtime error when `name == nil` and `T
== Optional<String>`? Mind you, `(nil as! Optional<String>)` does not
cause an error.

If the nil-unwrapping error is expected, how can I write it so that it
doesn't, and instead returns nil?

Oh, wow, the reported bug is quite similar but not exactly.

Anyway, I reported the problem here https://bugs.swift.org/browse/SR-4248\.
I guess the discussion will continue in there.

Thanks again!

···

On Wed, 15 Mar 2017 at 12:51 Kim Burgestrand <kim@burgestrand.se> wrote:

Found the answer to my follow-up question! It's a known and reported bug:
[SR-912] Runtime exception casting an Any nil to an Optional. · Issue #43524 · apple/swift · GitHub

Thanks!

On Wed, 15 Mar 2017 at 12:47 Kim Burgestrand <kim@burgestrand.se> wrote:

On Tue, 14 Mar 2017 at 19:50 Joe Groff <jgroff@apple.com> wrote:

It shouldn't. Please file a bug, if you haven't already.

Will do! I'll file a bug that casting to `Any` first causes different
behavior.

Follow-up question, looking at the expression `name as! T`, is it
expected to cause a nil-unwrapping runtime error when `name == nil` and `T
== Optional<String>`? Mind you, `(nil as! Optional<String>)` does not
cause an error.

If the nil-unwrapping error is expected, how can I write it so that it
doesn't, and instead returns nil?