Expand what permit can specify in Sealed Classes
Remi Forax
forax at univ-mlv.fr
Wed Nov 11 22:22:28 UTC 2020
----- Mail original -----
> De: "Tagir Valeev" <amaembo at gmail.com>
> À: "Brian Goetz" <brian.goetz at oracle.com>
> Cc: "Suminda Sirinath Salpitikorala Dharmasena" <sirinath1978m at gmail.com>, "amber-dev" <amber-dev at openjdk.java.net>
> Envoyé: Mercredi 11 Novembre 2020 17:17:15
> Objet: Re: Expand what permit can specify in Sealed Classes
> Hello!
Hi
>
> Of all hierarchy-based permits I see that only one of them is useful:
> interface X permits extends A (where A is a non-final, possibly
> abstract class).
It's something the VM has to be aware of, it can not be only enforced by the compiler analysis otherwise it will not play well with separate compilation,
so it's quite far away from the current solution we have.
I'm not saying it's not possible, but that the cost is similar to redoing the work we have done.
> In our codebase we have a number of interfaces that
> are used to extend the functionality of the classes that have common
> ancestor. This usually happens when you already have a complex class
> hierarchy (with a single base superclass A) and want to specialize
> some of the subclasses providing additional functionality. So you end
> up with a new interface X, but the interface is meaningful only for
> inheritors of A. You cannot refactor A to an interface, as it holds
> the state and you will break the compatibility for clients. But
> current Java cannot help you to enforce that X inheritors must be A
> inheritors as well, so you can only hope that clients read the
> documentation and program carefully. If we could enforce that all X
> inheritors must extend A this would 1) make programs more robust 2)
> help people understanding your API (a compilation error like XImpl
> must extend A would be a great pointer on how to use the API) and 3)
> may improve the performance (if VM disables loading classes that
> implement X but don't extend A then checkcast from X to A could be
> completely eliminated without any uncommon trap) 4) allow using
> exhaustive cast operator (was discussed before) from X to A.
For me, you are hunting around the fact that refactoring a class to an interface is not a backward compatible change,
We have discussed several times to change the JVM spec to allow to heal the rift between invokevirtual and invokeinterface (and their corresponding constant pool constants),
by example, by allowing invokevirtual to call interface method too.
>
> Examples from IDEA Community sources:
> TypedLookupItem interface is applicable for LookupElement inheritors only
> https://github.com/JetBrains/intellij-community/blob/master/java/java-impl/src/com/intellij/codeInsight/lookup/TypedLookupItem.java
> TypedLookupItem was introduced many years after LookupElement which is
> very old and heavily used in third-party plugins. It provides some
> additional functionality for completion and when it was introduced,
> some existing leafs in LookupElement hierarchy (including third-party
> plugins) were changed to implement this interface. Probably it would
> be cleaner were LookupElement an interface but what's done is done.
yes,
>
> ControlFlowException interface: a marker for exceptions that should
> not be logged
> https://github.com/JetBrains/intellij-community/blob/master/platform/util/src/com/intellij/openapi/diagnostic/ControlFlowException.java
> If somebody tries to log it, 'Report to JetBrains' feature is
> activated, so we get an alarm and will fix it. Naturally, this
> interface is only applicable for Throwable descendants. Of course, we
> cannot make Throwable an interface. Also, it would be very
> inconvenient to declare ControlFlowException as a subclass somewhere
> in Throwable hierarchy, as some implementors extend RuntimeException
> while others extend Exception directly.
For this one, it's a marker interface, and since Java 5 we have annotations that can be used to check a property of a class at runtime.
Conceptually, an annotation is like an empty interface that is not part of the type lattice.
>
> With best regards,
> Tagir Valeev.
regards,
Rémi
>
> On Wed, Nov 11, 2020 at 8:42 PM Brian Goetz <brian.goetz at oracle.com> wrote:
>>
>> We explored this option (e.g., "permits package") very early on in the
>> feature design, and backed away from it.
>>
>> Essentially, sealed types has a bimodal design center: extension
>> control, and exhaustiveness. The latter is about "I know that A=B+C, so
>> a switch on A that covers B and C is exhaustive." The compiler can use
>> this information to provide better type checking. While the first is
>> more immediately obvious to Java developers (because we already have a
>> system of access control), the second is actually more important in
>> terms of building reliable code. (If we had to pick only one of these,
>> we'd pick the second.)
>>
>> The extensions you are suggesting are all about extension control and
>> not at all about exhaustiveness. While that's not a fatal
>> characteristic for these ideas, it is a red flag, because it's speaking
>> exclusively to the minority motivation.
>>
>> Basically, "permits module" or "permits package" is a purely syntactic
>> convenience; you can express what you mean without it, and I don't think
>> that the few cases where this list is long justifies the feature. For
>> the more complex examples ("permits supertypes of subtypes of classes
>> with a Q in their name"), I think you'd be hard-pressed to come up with
>> more than a handful of examples where it would be sensible.
>>
>>
>>
>> On 11/11/2020 2:17 AM, Suminda Sirinath Salpitikorala Dharmasena wrote:
>> > Hello,
>> >
>> > Can the scope of the permit be expanded so following use cases are
>> > supported:
>> >
>> > - package - permits package x.y.x, package a.b.c, S, T (S, T are classes
>> > or interfaces)
>> > - modules - permits module x.y.x, module a.b.c, S, T
>> > - subtypes - permits extend A, extend B, S, T
>> > - supertypes - permits super A, super B, S, T
>> > - subtypes of supertype - permits extend super A, extend super B
>> > (effectively not a subtype of A or B. Combining with extends can limit the
>> > type hierarchy - e.g.: permits extends A, extends super B)
>> > - class or interface - permits S, T (current implementation and
>> > functionality)
>> >
>> > Suminda
More information about the amber-dev
mailing list