Expressions as literals

I just ran into the limitation “Raw value for enum case must be a literal” when my expression was made up of literals. I'm wondering why Swift can't support simple expression evaluation at compile time. I was trying to write this:

	IOC : UInt32
		case void			=	0x20000000
		case out			=	0x40000000
		case `in`			=	0x80000000
		case `inout`		=	0x40000000 | 0x80000000
		case dirMask		=	0xe0000000

or even have inout be like this:

	case `inout`		=	IOC.out.rawValue |

To my untrained eye, there’s no reason the compiler shouldn’t support this, is there? Ideally, any expression it can evaluate at compile time to a suitable value should be allowed.


The or operator is implemented as a normal function, and as there isn't a Swift equivalent of constexpr it can't call that function at compile time.


Shouldn't that be represented as an option set?

struct IOC: OptionSet {
    let rawValue: UInt32
    static let void = Self(rawValue: 1 << 29)
    static let output = Self(rawValue: 1 << 30)
    static let input = Self(rawValue: 1 << 31)
    static let inout1 = Self(rawValue: (1 << 30) | (1 << 31))
    static let inout2 = Self(rawValue: input.rawValue | output.rawValue)

You won't have enum behaviour (like switching exhaustively, etc) but it doesn't look you are going to have it anyway using IOC in the enum form in your particular example.


Sure, it could be I suppose. But it feels like quite the limitation that this stuff can't be figure out at compile time.

I guess it boils down to << being in standard library and Swift, oblivious to what << is doing` must assume "the worst" and doesn't want to open itself for any of the following at the compile time:

public func << (lhs: Self, rhs: Self) -> Self {
    // do whatever here including but not limited to:
    // - crash or trap
    // - infinite loop
    // - do unbound time or space operation
    // - use disk or network
    // - and so on and so forth
1 Like