Search code examples
swiftbinarytype-conversionunsigned-integer

Binary operator '|' cannot be applied to operands of type 'Int' and 'UInt8'


I wish to perform simple or logic on 2 bit maps, yet Swift thinks this is wrong:

let u: UInt8 = 0b1
let i: Int = 0b10
i | u // Binary operator '|' cannot be applied to operands of type 'Int' and 'UInit8'

Any way to conform to type inference and still have this working?

I could always do i | Int(u) // 3 but this, I think, is not optimal.


Solution

  • One of the fundamental principles of Swift is that is does not implicitly convert between types.

    let u: UInt8 = 0b1
    let i: Int = 0b10
    i | Int(u)
    

    forces you to think about the necessary conversions and what type the result should have, so that is the correct solution (in my opinion).

    Let's consider another example:

    let u: UInt8 = 128
    let i: Int8 = -128
    

    What should u|i be? Both

    u | UInt8(i)
    Int8(u) | i
    

    crash at runtime because u is not in the range of an Int8, and i is not in the range of an UInt8. Both

    u | UInt8(bitPattern: i)   // result is `UInt8`
    Int8(bitPattern: u) | i    // result is `Int8`
    

    would work, but how should the compiler choose between both? One could convert both to some larger type, for example

    Int(u) | Int(i)
    

    but that type is somewhat arbitrary, how could it automatically be inferred from the compiler? And what is the "larger type" for Int64 + UInt64 arguments?

    That's why I think that an explicit conversion is the right solution.