For when the static world and the dynamic world disagree, i think your analysis has miss an important question, switching on an enum throw an ICCE very late when we discover an unknown value, but in the case of a sealed type,
Actually, I thought about that quite a bit before proposing this. And my conclusion is: using ICCE was mostly a (well intentioned) mistake here, and "doubling down" on that path is more trouble than it is worth. So we are minimally consistent with the ICCE choice in the cases that were compilable in 12, but for anything else, we follow the general rule.
The thought experiment that I did was: what if we had not done switch expressions in 12. Then the only precedent we have to deal with is the null case, which has a pretty obvious answer. So what would we do? Would we introduce 10s of catch-all cases solely for the purpose of diagnosing the source of remainder, or would we introduce a throwing default that throws MatchException on everything but null? I concluded we would do the latter, so what is proposed here is basically that, but carving out the 12-compatibility case.
Remainders are dangling else in a cascade of if ... else, so yes, we have to care of them.
Yes, but we can care for all of them in one swoop with a synthetic default.
So yes, it may a lot of bytecodes if we choose to add all branches but the benefit is not questionable, it's far better than the alternative which is GoodLuckFigureByYourselfException.
Yes, when you get a dynamic error here in a complex switch, the range of what could have gone wrong is large. (The same will be true outside of switches when we have more kinds of patterns (list patterns, map patterns, etc) and more ways to compose patterns into bigger patterns; if we have a big complex pattern that matches the JSON document with the keys we want, if it doesn't match because (say) some integer nested nine levels deep overflowed 32 bits, this is also going to be hard to diagnose.) But you are proposing a new and significant language requirement -- that the language should mandate an arbitrarily complex explanation of why something didn't match. I won't dispute that this has benefit -- but I am not convinced this is necessarily the place for this, or whether the cost is justified by the benefit.
Also, note that the two are not inconsistent. If the switch is required to throw MatchException on remainder, the compiler is *allowed* to try and diagnose the root cause (the ME can wrap something more specific), but not required to. Pattern failure diagnosis then becomes a quality of implementation choice, rather than having complex, brittle rules mandated by the spec. There's nothing to stop us from doing the equivalent of the "helpful NPE" JEP in the future.