What all non-enum types have compiler-defined exhaustion?

For example, unlike in the past, this compiles:

switch Bool() {
case true, false: break
}

But that's not based on ExpressibleByBooleanLiteral. You still need a default for other ones.

struct 🧡: Equatable, ExpressibleByBooleanLiteral {
  init(booleanLiteral _: Bool) { }
}

switch true as 🧡 {
case true, false: break
default: break
}

Is it just Bool that gets the special treatment? :princess:t4:


(Thanks to @allevato for noting that ExpressibleByBooleanLiteral doesn't actually denote that a type only has two possible values. I was just trying to express that ExpressibleByBooleanLiteral is the only protocol that Bool adopts which looked at all to me like something that might be a possibility for supporting the behavior. Nope!)

Yeah, it's just Bool that gets special treatment from an exhaustivity checking perspective. The pattern grammar in the compiler has separate BoolPattern/SpaceKind::BooleanConstant to convey this. If we had something like "computed cases" you could potentially have this behavior for user-defined structs too, such as imported discriminated unions from C or C++.

1 Like

Seems like CaseIterable should enable exhaustive switch statements for (at least one class of) arbitrary types.

Never thought about it. Interesting question.

// UPDATE: This doesn't compile either.
On a side note, I noticed that this compiles:

let value = 34 as UInt8

switch value {
case 0...255:
  print("covered")
}

But this doesn't:

switch value {
case 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255:
  print("covered")
}

I wonder if that is a bug?

Your first example doesn't compile for me on recent main or on older compiler versions using Compiler Explorer; what version of the compiler are you using?

My bad. I can't get it to compile now either. I was using an Xcode 12.2 playground and swear I got the "covered" message printed to the console. Maybe I somehow short-circuited the switch? Sorry for the false alarm!