Sealed class type inference with non-exhaustive `when`

I have a class defined like this:

sealed class Animal {
  class Cat(val isFluffy: Boolean): Animal()
  class Dog: Animal()
}

And a test function like this, which doesn’t currently compile:

fun isFluffyCat(someAnimal: Animal): Boolean {
  when (someAnimal) {
    is Animal.Dog -> return false
  }
 return someAnimal.isFluffy
}

However, if I change it to this, it compiles:

fun isFluffyCat(someAnimal: Animal): Boolean {
  when (someAnimal) {
    is Animal.Dog -> return false
    is Animal.Cat -> {} // no-op, just here to satisfy the compiler
  }
  return someAnimal.isFluffy
}

It seems like it should be possible for the compiler to infer type on a nearly-exhaustive when clause if all other types trigger a return or throw an exception. Is this a change planned for a future release?

Yeah. I was under the impression (thought I can’t say for certain that I’ve read it before) that when when is used as a statement instead of an expression, it shouldn’t be required to be exhaustive.

I must say, though, that I’d redo your function like this:

fun isFluffyCat(someAnimal: Animal): Boolean =
  when(someAnimal) {
    is Animal.Cat -> someAnimal.isFluffy
    else -> false
  }

That last one allows you to add other animals without needing to update it. Plus, it uses the function expression format, which uses when as an expression also.

1 Like