RFR: JEP 360: Sealed Types (Preview)

Brian Goetz brian.goetz at oracle.com
Wed Apr 15 12:58:01 UTC 2020


This is a good observation, but I think you've overstated somewhat (and, 
to some degree, this incompatibility may actually be doing your clients 
a favor.)

Here's the case I think you're concerned about:

// Maintenance domain A
sealed interface X permits X.A, X.B {
     public class A implements X {}
     public class B implements X {}
}

// Maintenance domain B
int z = switch (x) {
     case A a: ...
     case B b: ...
     // no default
}

Your concern is that the compiler will accept this switch as exhaustive 
(so far, that's good), and later, if we refactor the X subtypes, this 
might be a source-incompatible change.  (It always has been an 
incompatible change to remove a class, or to remove a supertype from a 
class, so that's not what we're talking about here -- we're talking 
about removing it from the permits clause.)

Indeed, using the sealing information to switch exhaustively over a 
sealed type is a form of *tight coupling*; client code that wants to 
take advantage of this information should either be part of the same 
maintenance domain as the hierarchy, or be confident that the API is set 
in stone, or be ready to change when the hierarchy changes.  These are 
all reasonable choices to make with one's eyes open, but I think your 
concern is that this sort of tight coupling could arise _accidentally_ 
from ordinary use.

And, that's true.  However, I think it's not as bad as you think (and 
this has already been discussed a fair bit on the EG list.)  First, 
merely dropping A from the permits clause is a binary-compatible change, 
so existing binaries will continue to run just fine.  It is 
source-incompatible, but I would argue that this is, in many cases, 
better than the alternative. Getting a compilation error here is type 
checking at work; the compiler has identified an assumption baked into 
your program that is no longer valid.  If it's a matter of having 
dropped a permitted subtype, the change to your code is easy -- just 
drop the case, and you are correct again.  If its a matter of having 
added a permitted subtype, the change is also easy; if you don't want to 
handle the new case, add a default clause that throws (which is what you 
would have done in the first place if you didn't have the option to lean 
on exhaustiveness checking in the compiler.)


It is certainly good to write down some promoted practices for using 
sealed types, and this is something to consider pointing out, but the 
JEP is not the place for that; if it were, JEPs would be 100 pages (and 
then people would complain they were too big, as in fact some people 
already do.)  For other features (e.g., var, text blocks) there have 
been separate "style guide" documents that have the luxury describe the 
nuances in more detail.



On 4/15/2020 8:32 AM, Kłeczek, Michał wrote:
> Hi Vicente,
>
> IMHO there is one thing I think is worth pointing out in the 
> documentation (as it is going to be cited on thousands of web sites):
>
> One has to be very careful when exposing sealed types with only public 
> permitted subtypes in public APIs.
> Doing that makes it impossible to change the list of subtypes - both 
> removal and adding of a subtype is an incompatible change.
>
> I think it might be surprising for many library developers and I've 
> raised the concerns about this before - maybe it is a good idea to 
> make it more apparent.
>
> Thanks,
> Michal
>
> On 13/04/2020 18:03:18, "Vicente Romero" <vicente.romero at oracle.com> 
> wrote:
>
>> Hi all,
>>
>> The sealed types JEP was already reviewed a while back when we were 
>> planning to include it in JDK14. It finally fell off that boat but it 
>> is being considered now for JDK15. There have been some changes since 
>> then mostly related to subtypes of a sealed type. Before we were 
>> planning to infer finality, sealness or non-sealness in the subtypes. 
>> We steered away from that direction in favor of explicit declaration 
>> at the subtype. I would like to ask for another review of the current 
>> version of the JEP that reflects these changes. The JEP is at [1] and 
>> the last version of the spec is at [2],
>>
>> Thanks,
>> Vicente
>>
>> [1] https://bugs.openjdk.java.net/browse/JDK-8227043
>> [2] 
>> http://cr.openjdk.java.net/~gbierman/jep360/jep360-20200228/specs/sealed-types-jls.html
>>
>



More information about the amber-dev mailing list