How can I condition on the size of Int?

Int can be either Int32 or Int64. What if you need to act differently on the size? Is there some flag that can be used in a POUND-if directive, or similar?

1 Like

You can do so by interrogating Int.bitWidth. Because that's a static member the compiler should be able to specialize so that there's no runtime cost.

1 Like

@xwu How do you avoid the following compiler warning?

if Int.bitWidth == 64 { // condition always evaluates to true
    print("64-bit")
} else {
    print("32-bit") // warning: will never be executed
}

That's interesting. If possible, we'd ideally suppress the warning since the intention here is pretty clear.

That said, there is an alternative spelling which doesn't generate the warning:

if MemoryLayout<Int>.size == 8 {
    print("64-bit")
} else {
    print("32-bit")
}

This yields the same optimized binary.

3 Likes

There was a proposal to add #if bitwidth(64) for conditional compilation.

If the Int.bitWidth value is known at compile time, would it be feasible to allow #if Int.bitWidth == 64 instead?

That proposal predated Int.bitWidth (and, I believe, MemoryLayout). I liked it at the time, but since it's now possible to achieve the same thing without #if, why add yet another feature?

I was thinking about scenarios like:

// Define the Golden Ratio in fixed-point
If 64-bit
    X = 2**33  // Not the actual value 
Else
    X = 2**17  // Nor this 

(This is for implementing a hash-combining function, mentioned in another thread I just started.)

Processing the “if” branch should choke on 32-bit systems.

The solution should be in the conditional compilation system, but we need to implement “constexpr” first and change the conditional compilation part of the language to use that.

(In case you’re wondering: it looks like the conditional compilation part of the language has already brought in something like “constexpr,” but no. Its use of Boolean literals, operators, and functions is a hard-coded custom syntax!)

Just write:

let x = MemoryLayout<Int>.size == 8 ? 2 ** 33 : 2 ** 17

This is compiled to a constant.

2 Likes

#if Int.bitWidth == 64 would be allowed at the top-level, etc.

The static if conditional is apparently very useful.

This compiles without warnings in Xcode 10 beta 3, but there is still a problem: Both blocks are compiled on either platform. As an example, the following code fails to compile on a 32-bit platform:

let x: Int
if MemoryLayout<Int>.size == 8 {
    x = 0x123456789ABC // Integer literal '20015998343868' overflows when stored into 'Int'
} else {
    x = 0x1234
}
print(x)

Same problem with

let x  = MemoryLayout<Int>.size == 8 ? 0x123456789ABC : 0x1234
// Integer literal '20015998343868' overflows when stored into 'Int'

A #if Int.bitWidth == 64 directive (presumably) would not have that problem.

1 Like

True! A compilation conditional does have use cases not served with that expression. It’s not hard to add to the language; someone needs to drive the Evolution process:

1 Like