Error: raw value for enum case must be a literal

For the following code, which includes an expression involving only literals, I get the error "raw value for enum case must be a literal."

enum Flags : UInt16
{
	case zero			=	0b1 <<  9
}

This seems like something that should be acceptable to the compiler. It should just evaluate the expression and use the resulting value, shouldn't it?

2 Likes

Compiler doesn't know what << means, that's defined in standard library.

3 Likes

Even if it did, the result of that expression still wouldn't be a literal. Would it?

this would require some kind of constexpr in the language, similar to @_semantics("constant_evaluable"). it has been proposed multiple times over the past several years but to my knowledge it has never gone anywhere. so the answer is no, just right-pad with the 9 zeros.

1 Like

SE-0382: Expression Macros can make this possible?

#IntLiteral(0b1 << 9)
1 Like

Why should I have to do any of that? I donโ€™t have to in C, the compiler is smart enough to evaluate the expression and generate a constant load wherever the value is used.

4 Likes

this is a valid feature request and something i thinks motivates prioritizing @const in swift language evolution.

9 Likes

OTOH you can't write 0b1000000000 in C hence you have to use "1 << 9" as a workaround.

C compiler knowns what "1 << 9" means which makes it very easy treating it as 0x200. This is much harder task in swift with has a "minimal language + standard library" split. Hopefully still doable.

I'd rather not have to go to any special lengths to write an expression like that. It just seems so plainly obvious to me. The compiler should have all the information it needs to evaluate the expression and turn it into a single value. I would hope it does the same thing for an expression full of literals in a function body somewhere.

What would be the "plainly obvious" value in this code?

func <<(_: UInt16, _: UInt16) -> UInt16 {
    UInt16(readLine()!)!
}

enum Flags : UInt16
{
	case zero			=	0b1 <<  9
}

Any reason you canโ€™t use an OptionSet? That is the ideal representation for bit-field flags. It will let you use the << operator. Otherwise the proposed expression macros feature should solve this problem in the future.

Ideal world scenario should be this (IMHO):

case zero			=	1 << 9 // ๐Ÿ›‘ not a constant expression.

func <<(_: Int, _: Int) -> Int {
    Int(readLine()!)!
}

changing:

case zero			=	1 <<  9 // โœ…

pure func <<(_: Int, _: Int) -> Int { // adding "pure"
    Int(readLine()!)! // ๐Ÿ›‘ not pure
}

further changing:

case zero			=	1 <<  9 // โœ…

pure func <<(_: Int, _: Int) -> Int {
    Int(readLine()!)! // โœ…
}

pure func readLine() -> String? { // adding "pure"
    // commenting out whatever impure it was doing before
    "42" // โœ…
}

Where "pure" function always give the same output for the same input (in other words doesn't depend on global state). Calling a pure function with constant expression argument(s) results into a constant expression in turn.

I'd say even this should work eventually:

enum Flags: Int {
    case x = Int(cos(log(1234.0))*5678) // โœ… - constant expression
}

That's the @const @taylorswift mentioned and @JetForMe rejected :(

3 Likes