Why Scala can do exhaustiveness checking for ADT/Enums but not Union types

5 views
Skip to first unread message

Ben Hutchison

unread,
Jul 17, 2026, 6:43:26 AM (4 days ago) Jul 17
to Melbourne Compose Group
When a type can consist of multiple alternatives, "exhaustiveness checking" refers to the compiler verifying that all the possible alternatives have been considered, in say a pattern-match expression.

One common place where exhaustiveness checking is used is when you have an enum (aka "ADT") defining a closed set of several possible cases.

enum TrafficLight:
  case Green, Yellow, Red

def action(light: TrafficLight): String = light match
  case TrafficLight.Red    => "Stop"
  case TrafficLight.Yellow => "Caution"
  case TrafficLight.Green  => "Go"

Scala also permits "Union Types", which allow you to combine unrelated types with an Or relation 

//nrelated types
object Red
object Yellow
object Green
object Blue

type TrafficLight = Green.type | Yellow
.type | Red.type

Union types can be useful when you need to compose multiple different subsets drawn from the same vocabulary of elements, which a single enum/ADT cannot do:

type AmbulanceLight = Red.type | Blue.type


It's a subtle distinction, but today an LLM explained to me why union types don't allow exhaustiveness checking, but an enums/ADT do:

In Scala 3's design, union types (A | B | C) are structural, not nominal — the compiler doesn't know the union is "closed." So pattern matching on a union type won't warn on non-exhaustive matches the way sealed traits/enums do. 

Ah, of course! The old structural vs nominal distinction! The compiler couldn't know the union is "closed" could it?


The problem is, the LLM is bullshitting. Bamboozling me with a meaningless sentence composed of plausible jargon.

In truth, exhaustiveness checking works equally well for union types as for enums.

-Ben

John Walker

unread,
Jul 20, 2026, 5:14:43 PM (11 hours ago) Jul 20
to Melbourne Compose Group
I wonder how many users would see through the BS vs internalising it. 
Reply all
Reply to author
Forward
0 new messages