Expression switch exception naming

Kevin Bourrillion kevinb at
Wed Mar 28 19:35:15 UTC 2018

On Wed, Mar 28, 2018 at 11:29 AM, Brian Goetz <brian.goetz at>

ICCE indicates that a _binary incompatible_ change was detected, which by
> definition the client cannot recover from.  Adding an enum constant is not
> a binary incompatibility (though removing one is).  (Interestingly, neither
> is changing an enum to a class, if you have static fields for all the
> constants -- I learned this recently.)
> However, adding an enum constant is a potential _behavioral_
> incompatibility -- specifically, it could cause exceptions like this to be
> thrown under some circumstances.  And it is only potential because in order
> to have a problem, both the enum and the client must each bring a piece of
> the responsibility -- it is something the client could recover from it if
> it wished (by having a default).  This is an incompatibility, but also
> substantially less severe in a few ways than deleting a method.  (Maybe its
> like a method starting to return null where it never had before.)

I have been figuring that if the client *has* a reasonable way to handle
unknown values then it will probably go ahead and do that (with a

Therefore I assumed that what we're talking about in this conversation is
the* other* kind, where there is nothing safe they can do - for example if
I wrote a method that displays a time interval as "10 ns" or "20 s", I may
not find it acceptable for me to start displaying "30 <unknown unit>" once
I get handed TimeUnit.DAYS. My code is broken either way. If a constant is
added, I need to react to that, just like I do with a new interface method.
What does it really mean to say that this client "brings a piece of the
responsibility" if it doesn't really have a choice?

(also, I think we could probably provide evidence from our codebase that
this is the far more common situation than the first (reasonable default)
kind. Note that we have had compile-time enforcement of exhaustiveness for
enum switches turned on for a while now, though we haven't done much to
goad users into removing their defaults in order to activate it. Liam could
say much more about how this is working if desired.)

So, I'm not quite yet following why the binary/source compatibility
distinction, or the opt-in distinction, really makes all the difference

> If a client has a default in their switch, there's no problem.  If a
> client doesn't have a default, but provides all the known items, the
> compiler builds in a default that throws, to prevent it from being silently
> ignored.  That's all good, and things are blowing up in the right place
> with an informative message.  The behavior incompatibility is an
> interaction between the enum and the client's use of that enum.  So I think
> the exception should point as much to the client as the enum.
> A concrete proposal:
>     UnexpectedClassChangeException <: RuntimeException
>     UnexpectedSwitchTarget <: UCCE  // works both for enum and sealed
> classes
> On 3/28/2018 2:06 PM, Kevin Bourrillion wrote:
> On Wed, Mar 28, 2018 at 8:51 AM, Brian Goetz <brian.goetz at>
> wrote:
>> Adding a new enum value is not the same sort of obviously-incompatible
>>> change as changing a static method to instance, or a concrete method to
>>> abstract, which are the sorts of things that trigger ICCError. ... Adding a
>>> new enum constant isn't intrinsically evil.  If anything, the issue is on
>>> the client, who relied on the assumption of of exhaustiveness.
> Okay, this sentiment is what I'm disagreeing with.
> I think that what we are doing here is turning that change (add constant
> to enum) into an incompatible class change, just as much as any of the
> other kinds. It's directly analogous to adding an interface method. Clients
> were required to specify how to handle all the methods of that interface,
> but then one more showed up, and those clients are now broken.
> Users will find this counter-intuitive, but that's only because they won't
> be used to it yet. They'll have to learn.
> More to the point I think: the problem isn't "on" the client code; it's
> having jars in your runtime classpath that are newer than the jars you
> compiled against; that's always a dangerous idea and it continues to be so
> here. Today, an experienced developer knows that there is a category of
> Errors that, when you see them in the absence of reflection, always
> implicate this kind of classpath issue. I can't see why this would not
> belong in that same category.
> --
> Kevin Bourrillion | Java Librarian | Google, Inc. | kevinb at

Kevin Bourrillion | Java Librarian | Google, Inc. | kevinb at
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the amber-spec-experts mailing list