I am getting Fatal Error: Negative value is not representable in the last do block.
Can anyone help me understand why?
do {
let u: Int = -1
let v = unsafeBitCast(u, to: UInt.self) // Suggestion: 'unsafeBitCast' from 'Int' to 'UInt' can be replaced with 'bitPattern:' initializer on 'UInt'
print ("u:", u, "v:", v)
assert (v == UInt.max)
}
do {
let u: Int = -1
let v = UInt (bitPattern: u)
print ("u:", u, "v:", v)
assert (v == UInt.max)
}
do {
let u: Int = -1
let v: UInt = numericCast (u) // Fatal Error: Negative value is not representable
print ("u:", u, "v:", v)
assert (v == UInt.max)
}
numericCast is not a bit-pattern cast; it's a value-preserving cast (like the normal init(_:) on the built-in numeric types). It's there mostly as a convenience for connecting two APIs that chose different integer types, like Int and Int32, or Int and UInt, where in practice your values are going to match up. If you want a bit-pattern cast, use init(bitPattern:); if you want a bit-pattern cast from an integer with a different size, spell out the steps you want the code to take (e.g. UInt(bitPattern: Int(someInt32)) vs. UInt(UInt32(bitPattern: someInt32)), which behave differently for negative numbers and 64-bit UInt).
(I'm not a numericCast fan. I think code is usually clearer if you just write the destination type, and in cases when it's not .init(u) does the same thing in practice. But numericCast is also usable in generic contexts, and maybe that's important to someone.numericCast should be exactly equivalent to BinaryInteger.init(_:).)
EDIT: init(truncatingIfNeeded:) does multiple steps of the bit-pattern cast. I find that a little magical when extending because of the case I mentioned above, which is probably why I forgot to mention it, but it's there if you want it.