Thanks Gavin for proposing this change. I'm also in agreement we should make this change now - especially given JEP 433 is still a preview feature. If we don't standardize the missing enum exception to MatchException now, then as Brian points out, we'll have a hard time making switches over enums consistent with other pattern switches.
--Dan On Mon, Nov 14, 2022 at 7:39 AM Gavin Bierman <[email protected]> wrote: > Dear Experts, > > As we put the final polish on features for JDK20, we noticed that we have > an opportunity to make a very small breaking change (as part of the preview > feature) to simplify our lives. I’m writing to see what you think. > > tldr: A switch expression over an enum class should throw MatchException > rather than IncompatibleClassChangeError if no switch label applies at > runtime. > > Details: > > When we introduced switch expressions, we opted for a design where the > switch body had to be exhaustive. When switching over an enum type, a > switch body with case labels supporting all the enum constants for the enum > type is considered exhaustive, meaning a default clause is not needed. > > However, there is a possibility that the enum class is changed after > compilation of the switch expression, and a new enum constant added. Then > when executing the switchexpression, no label would apply. > > The question we faced in JDK14 was what to do at this point. We decided on > IncompatibleClassChangeError as that was a pre-existing exception that was > generally understood by developers as a signal that things have got out of > sync and re-compilation is needed. > > Back to the present day, with the support of pattern switches, we can now > write switches over a sealed type. When switching over a sealed type, a > switch body with case labels with type patterns matching all the permitted > subclasses is considered exhaustive, meaning a default clause is not needed. > > If the sealed hierarchy has been changed after compilation of the switch, > it is possible that when executing the switch that no label would apply. In > this case we have settled on throwing a MatchException. > > Throughout our design process, we have noticed the connection between enum > classes/enum constants and sealed class/permitted subclasses – they are > essentially the same thing up the term/type hierarchy. Moreover, in a > future release, we plan to support case labels with a mix of sealed class > type patterns and enum constants. > > But we now have an inconsistency - one throws > IncompatibleClassChangeException in a bad situation and the other > MatchException which will make this future development almost impossible. > We need these cases to throw the same exception: MatchException. So we > propose to make the small breaking case to the language that switch > expressions over enum classes throw MatchException should no switch label > apply in the switch body. > > People who deliberately change their enum classes by adding new constants, > and do not recompile their switches over this enum class, and rely on this > throwing ICCE will notice this breaking change. We think this is a > vanishingly small set of developers. The vast majority of developers, on > the other hand, will thank us for this unification, especially if it > enables other new features down the road. > > What do you think? > > Thanks, > Gavin
