[0] as [AnyHashable] as? [Bool]

I’m noticing some strange behavior with the following code:

[0] as [AnyHashable] as? [Bool]

swift repl prints nil whereas Xcode prints [false]!

Two questions:

  1. How is swift repl (5.8.1) producing a different result from Xcode (14.3.1)?
  2. Where is this implemented? I see _IntegerAnyHashableBox does implicit type conversions across integer types but I don’t see anything about converting to Bool.

I think you are importing Foundation (perhaps indirectly) in your Xcode testing. You can make the REPL behave like Xcode:

; xcrun swift repl
Welcome to Apple Swift version 5.9 (swiftlang- clang-1500.0.40.1).
Type :help for assistance.
  1> import Foundation
  2> [0] as [AnyHashable] as? [Bool]
$R0: [Bool]? = 1 value {
  [0] = false
1 Like

Int and Bool both bridge to NSNumber, so AnyHashable erases the distinction between them when bridging is involved.


Ah, I did try import Foundation but only later in the session. It seems to only use the Foundation-related stuff if I import it early.

Here’s what happens if I import it later:

  1> [0] as [AnyHashable] as? [Bool]
$R0: [Bool]? = nil
  2> import Foundation
  3> [0] as [AnyHashable] as? [Bool]
$R1: [Bool]? = nil

Ahhh I see, the bridging is implemented here:

#if _runtime(_ObjC)
// Bridge to Objective-C and then attempt the cast from there.
// FIXME: This should also work without the Objective-C runtime.
if let value = _bridgeAnythingToObjectiveC(_box._base) as? T {
  result.initialize(to: value)
  return true

So during the as? [Bool] cast, the Swift runtime bridges the Int elements to NSNumber instances via _bridgeAnythingToObjectiveC and then converts them to Bool via as? T.