var foo: String? = nil
let bar = foo as Any
print(bar) // -> nil
print(bar == nil) // -> false
This feels like it doesn't make much sense. bar is not optional in this case, and thus should never be nil, but it can be nil. Because bar is not optional, you cannot utilize any of the unwrapping methods Swift provides (guard, if let, ??, !)
I understand the reasoning behind this, but it doesn't feel like it fits with the rest of Swift's type system and only works this way on a technicality.
In my opinion, either variables should need to be Any? to be nil, or unwrapping methods should be enabled for variables of type Any.
t2a.swift:1:16: error: nil cannot initialize specified type 'Any'
let any: Any = nil
^
t2a.swift:1:10: note: add '?' to form the optional type 'Any?'
let any: Any = nil
^
( )?
It's turning bar into an Any? and checking whether it's nil. The == being used is defined here. The intent is to allow one to use == nil or != nil to check whether a value of type T? contains a value, when T does not conform to Equatable.
Maybe we should have simply required developers to use a different "test for nil" expression.
This is an interesting one! I suspect this is due to Optional's special subtyping rules, which have T?: U? whenever T: U. So the as! cast is upcasting from the runtime type String? to Any?, rather than from Any to Any?. If we use an as cast instead we get false: