Why is "case foo(_ bar: Int)" allowed in enums?

Someone pointed out that the TextMate language grammar (used by GitHub for Swift syntax highlighting) rejects enum Foo { case foo(_ bar: Int) }:

But as far as I can tell, the language grammar/"spec" doesn't allow this:

...
union-style-enum-case → enum-case-name tuple-type opt

tuple-type → ( ) | ( tuple-type-element , tuple-type-element-list )
tuple-type-element-list → tuple-type-element | tuple-type-element , tuple-type-element-list
tuple-type-element → element-name type-annotation | type
element-name → identifier

Is it intentional that the compiler does allow it?

Also, what's going on here — is this just a problem that will be fixed by SE-0155?

let x: Foo = .foo(bar: 4)  // valid
let y: Foo = .foo(4)  // invalid

let z = Foo.foo
z(bar: 4)  // invalid
z(4)  // valid

I think this is an artifact of the parser using common logic to parse enum cases and function parameter lists. At this point I don't think we can ban it without breaking source compatibility.

There is also at least one other place where you can do this -- function types:

func f(_: (_ x: Int, _ y: Int) -> ()) {}

Seems like it would be quite rare, because only _ is allowed in that position (if you use any other label, you get an error). Anyway, if it's not going to be removed, at least the grammar should probably be updated to include it :slight_smile:

Couldn't we start deprecating it as a long-term plan?

Certainly worth considering! Usually we try not to document unintended implementation quirks in the grammar, but if we're going to keep it forever…

Terms of Service

Privacy Policy

Cookie Policy