On 28/04/2021 15:31, Brian Goetz wrote:
It depends on how much sealing there is.  Suppose we have sealed types Container = Box|Bag and Lunch=Soup|Sandwich.  If we are switching on a Container<Lunch>:

    switch (lunch) {
        case Box(Soup s):
        case Box(Sandwich s):
        case Bag(Soup s):
        case Bag(Sandwich s):
    }

This switch is exhaustive because:
 - { Soup, Sandwich } is total on on Lunch (with remainder null)
 - therefore { Box(Soup), Box(Sandwich) } is total on Box<Lunch> (with remainder null, Box(null) }  - similarly { Bag(Soup), Bag(Sandwich) } is total on Bag<Lunch> (with remainder null, Bag(null) }
 - { Box, Bag } is total on Container (with remainder null)
 - therefore the cases in our switch are exhaustive on Container<Lunch>

I guess the case I'm referring to is:

switch (lunch) {
        case Box(Soup s):
        case Bag(Soup s):
}

Where Soup is the only know subtype of Lunch. This code is exhaustive, but is Sandwich is added, it is no longer so.

That said, if an error is issued whenever a switch statement is not exhaustive, that would alleviate my concerns - I think the error would cover this case also.

The think the I find mildly odd is that when Sandwich is added, it might not be enough to add another `case`. If there was null-related logic inside `case Box(Soup s):` that would have to be moved somewhere else. So while in most cases it will be a straightforward refactoring, I can see some puzzlers emerging here.

Maurizio


Reply via email to