RFR: 8343306: javac is failing to determine disjoint-ness between a class and a sealed interface [v3]

Jan Lahoda jlahoda at openjdk.org
Thu Oct 31 18:06:34 UTC 2024


On Thu, 31 Oct 2024 17:57:45 GMT, Vicente Romero <vromero at openjdk.org> wrote:

>> For code like:
>> 
>> 
>> class Test {
>>     sealed interface I permits C1 {}
>>     non-sealed class C1 implements I {}
>>     class C2 extends C1 {}
>>     class C3 {}
>>     I m(int s, C3 c3) {
>>         I i = (I)c3;
>>     }
>> }
>> 
>> javac is failing to issue an error and accepts this code. The spec is clear stating that code like this should be rejected. See:
>> 
>> 5.1.6.1 Allowed Narrowing Reference Conversion:
>> 
>> • A class named C is disjoint from an interface named I if (i) it is not the case that
>>   C <: I , and (ii) one of the following cases applies:
>>   – C is freely extensible (§8.1.1.2), and I is sealed , and C is disjoint from all of
>>   the permitted direct subclasses and subinterfaces of I .
>> 
>> and just below it continues:
>> • A class named C is disjoint from another class named D if (i) it is not the case
>> that C <: D , and (ii) it is not the case that D <: C .
>> 
>> so here we have the `C3` is a freely extensible class and interface `I` is sealed and `C3` is disjoint from `C1` which is is the permitted subclass of interface `I`
>> 
>> This PR should sync javac with the spec
>> 
>> TIA
>
> Vicente Romero has updated the pull request incrementally with one additional commit since the last revision:
> 
>   implementation closer to the spec

src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java line 1719:

> 1717: 
> 1718:             private boolean isClassFreelyExtensible(ClassSymbol csym) {
> 1719:                 boolean anySuperIsSealed = (csym.getSuperclass().tsym != null && csym.getSuperclass().tsym.isSealed()) || csym.getInterfaces().stream().anyMatch(i -> i.tsym.isSealed());

I am not sure about these checks. Should it be simply `isClassFreelyExtensible == !csym.isSealed() && !csym.isFinal()`? Or is the a particular case this is solving.

(Besides this code being more complex, I suspect "non-sealed" is not restored when reading from classfiles - is that correct? Will this code do something sensible when `csym` is read from a classfile, and has a sealed supertype?)

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/21794#discussion_r1824942423


More information about the compiler-dev mailing list