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:

	enum
	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 | IOC.in.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.

2 Likes

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.

7 Likes

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.

4 Likes

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