Whenever you have a deconstruction pattern, there's always a remainder null. (Point(var x, var y) NPEs on null.)

Whenever you cover a sealed type with alternatives (but no total pattern), there's always remainder null and "novel".

Whenever you lift over a nestable pattern (like D(T), or String[] { P }), you have to wrap the remainder with the nestable thing.

So yes, Container(Pizza) is also remainder.

Based on historical precedent, its tempting to specify NPE for null remainder and ICCE for novel remainder.  (I can also imagine cases where the logical exception type is CCE.)  But that doesn't scale up very well; what do we throw for DoubleLunchPack(null, pizza)?  It has both null- and novel-derived remainders.  I don't think we want the compiler generating tons of code just so each remainder can get a different exception; more likely, the compiler will want to generate some sort of "default: throwSomethingSimple" clause.


On 4/29/2021 5:43 AM, Maurizio Cimadamore wrote:


If I read the rules correctly, Box(Soup) + Bag(Soup) "cover" Container<Lunch>, with the exception of the { null, Box(null), Bag(null) }. So the above will throw when `lunch` is null, and will also throw with Box(null) or Bag(null). Correct?


Correct (under the "we make switches total" plan.)

I realized there's also another remainder Box/Bag(*) - e.g. Box/Bag(Pizza), where Pizza is a new type that shows up in the sealed hierarchy.

To cover that (not that it's required at compile-time, just to imagine what javac would emit), we need probably one of these:

case Box b:

or

case Container c

Right?

Maurizio



Reply via email to