On Mon, 8 Jan 2024 22:29:47 GMT, Joe Darcy <da...@openjdk.org> wrote:
>>> Since it doesn't seem possible to do so, I did not attempt to relay >>> "non-sealed" information in this PR :-) >> >> Naively, I thought that something like this is possible _in principle_; I >> might be mistaken though: >> >> diff --git a/src/java.base/share/classes/java/lang/Class.java >> b/src/java.base/share/classes/java/lang/Class.java >> index 851d65d06ad..014845860d0 100644 >> --- a/src/java.base/share/classes/java/lang/Class.java >> +++ b/src/java.base/share/classes/java/lang/Class.java >> @@ -4771,6 +4771,30 @@ public boolean isSealed() { >> return getPermittedSubclasses() != null; >> } >> >> + private boolean isNonSealed() { >> + if (isSealed()) >> + return false; >> + if (!isInterface() && Modifier.isFinal(getModifiers())) { >> + // unlike interface, class can be final >> + return false; >> + } >> + // if an ancestor is sealed, this class can either be non-sealed or >> final >> + return hasSealedAncestor(this); >> + } >> + >> + private boolean hasSealedAncestor(Class<?> clazz) { >> + var superclass = clazz.getSuperclass(); >> + if (superclass != null) { >> + if (superclass.isSealed() || hasSealedAncestor(superclass)) >> + return true; >> + } >> + for (var superinterface : clazz.getInterfaces()) { >> + if (superinterface.isSealed() || >> hasSealedAncestor(superinterface)) >> + return true; >> + } >> + return false; >> + } >> + >> private native Class<?>[] getPermittedSubclasses0(); >> >> /* > >> Thanks @pavelrappo; I'll explore incorporating functionality like this into >> the PR, probably next week. > > Pushed an initial cut of non-sealing support; will add more test cases later. Thanks for including `non-sealed`, Joe. Regarding your implementation: you are right that only the direct superclass and direct superinterfaces need to be explored for being `sealed`. No need to explore the full ancestry. So, recursion in my [initial proposal] was superfluous. That said, I have a question on [JLS 8.1.1.2], which you copied as inline commentary: > It is a compile-time error if a class is declared non-sealed but has neither > a sealed direct superclass nor a sealed direct superinterface. > > Thus, a subclass of a non-sealed class cannot itself be declared non-sealed. I wonder if it can be clarified to account for hierarchies where a `non-sealed` class or `non-sealed` interface has a `non-sealed` direct superinterface, or a `non-sealed` class has a `non-sealed` direct superclass. For example: sealed interface A permits B { } sealed interface I permits X { } non-sealed interface B extends A { } non-sealed interface X extends B, I { } and sealed class A permits B { } sealed interface I permits C { } non-sealed class B extends A { } non-sealed class C extends B implements I { } (CC'ing @GavinBierman) [initial proposal]: https://github.com/openjdk/jdk/pull/17239#discussion_r1440867004 [JLS 8.1.1.2]: https://docs.oracle.com/javase/specs/jls/se21/html/jls-8.html#jls-8.1.1.2 ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/17239#discussion_r1446243516