RFR: 8361570: Incorrect 'sealed is not allowed here' compile-time error [v2]

Chen Liang liach at openjdk.org
Tue Jul 8 12:30:40 UTC 2025


On Tue, 8 Jul 2025 09:28:58 GMT, Jan Lahoda <jlahoda at openjdk.org> wrote:

>> Consider code like this:
>> 
>> $ cat /tmp/T.java 
>> import java.lang.ref.*;
>> public class T {
>>     public static void main(String[] args) {
>>         new WeakReference<>(null) {};
>>     }
>> }
>> 
>> 
>> Compiling this with JDK 25/26 leads to:
>> 
>> $ ./jdk-25/bin/javac /tmp/T.java
>> /tmp/T.java:4: error: modifier sealed not allowed here
>>         new WeakReference<>(null) {};
>>                                   ^
>> 1 error
>> 
>> 
>> Which does not make much sense.
>> 
>> The reason for this is as follows:
>> - the type parameter for `WeakReference` is marked with `@jdk.internal.RequiresIdentity`, and the `WeakReference`'s constructor has a parameter whose type is this type parameter.
>> - as a consequence, this parameter has internally in javac flag `REQUIRES_IDENTITY`. Note this flag has currently the same `long` value as `SEALED`, as the value is reused to mean different things for different Symbol kinds.
>> - when creating the anonymous class, javac creates a constructor, copying the `REQUIRES_IDENTITY` together with the constructor's parameter
>> - then javac goes on and checks whether the flags on the parameter are correct. And it sees the value for `SEALED` is set, and reports the error
>> 
>> Ultimately, I don't think we can reuse the value of `SEALED` to mean different things (and the same for all other similar cases). This PR assigns a different value for `SEALED`, and tries to add a test that strives to hopefully prevent similar cases in the future by saying that no `Flags` in `ExtendedStandardFlags` can be reused.
>
> Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision:
> 
>   Fixing tests.

src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java line 559:

> 557:         RECORD(Flags.RECORD),
> 558:         RECOVERABLE(Flags.RECOVERABLE),
> 559:         RESTRICTED(Flags.RESTRICTED),

Why do we need to add RESTRCITED this time?

test/langtools/tools/javac/flags/ExtendedStandardFlagsOverlayFlagsConflict.java line 66:

> 64:             }
> 65:             long flag = ((Number) f.get(null)).longValue();
> 66:             value2FlagFields.computeIfAbsent(flag, _ -> new ArrayList<>())

If we are performing general flag checks, I recommend including checks to ensure there is exactly one bit set (like `Long.lowestOneBit(flag) == flag`)

So we no longer need a map, but can use a Field[64] and use `Long.numberOfTrailingZeros` to map to the array index.

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

PR Review Comment: https://git.openjdk.org/jdk/pull/26181#discussion_r2192368072
PR Review Comment: https://git.openjdk.org/jdk/pull/26181#discussion_r2192378480


More information about the compiler-dev mailing list