RFR: 8332230: jshell throws AssertionError when processing annotations
Jan Lahoda
jlahoda at openjdk.org
Thu May 23 15:59:15 UTC 2024
Passing snippet `k=aa:a. at a` to JShell crashes it:
jshell> k=aa:a. at a
...
Caused by: java.lang.AssertionError
at jdk.compiler/com.sun.tools.javac.util.Assert.error(Assert.java:155)
at jdk.compiler/com.sun.tools.javac.util.Assert.checkNonNull(Assert.java:62)
at jdk.compiler/com.sun.tools.javac.comp.Annotate.fromAnnotations(Annotate.java:167)
at jdk.compiler/com.sun.tools.javac.comp.Annotate.lambda$annotateTypeSecondStage$5(Annotate.java:1059)
at jdk.compiler/com.sun.tools.javac.comp.Annotate.flush(Annotate.java:194)
at jdk.compiler/com.sun.tools.javac.comp.Annotate.unblockAnnotations(Annotate.java:144)
There are two places where relevant work for type annotations is scheduled:
- Attr.visitMethodDef will schedule and perform first stage of type annotation processing before processing the method's body: https://github.com/openjdk/jdk/blob/90758f6735620776fcb60da9e0e2c91a4f53aaf1/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java#L1215
- Attr.visitAnnotatedType will schedule the second phase of type annotation processing: https://github.com/openjdk/jdk/blob/90758f6735620776fcb60da9e0e2c91a4f53aaf1/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java#L5224
There are two problems here:
a) it may happen that `visitAnnotatedType` schedules the second phase for the given type, but noone calls `Annotate.flush()` anymore before javac finishes. `flush` is in `Attr` called at the beginning of processing of classes, methods, many, but not all variables, etc., but if there's none of them in the source after the task has been scheduled, the task will remain in the queue. This has twofold effect: 1) the model for the type is slightly broken (if we ask of the type annotations on the type, we won't get the annotation); 2) since JShell is using `JavacTaskPool`, and reuses javac tasks, the pending type annotation task may remain in the queue, and be invoked when doing reusing the `JavacTask` for unrelated processing. My proposal here is to call `Annotate.flush()` after "top-level" declarations, to make sure all annotation tasks are always finished.
b) `Attr` visits even erroneous subtrees, so annotated types inside erroneous subtrees will have the second stage scheduled; but the first stage of type annotation processing is not looking inside erroneous subtrees, so the first stage is not done for annotated types inside these subtrees. And the second stage then crashes. My proposal is to let the first stage look into erroneous subtrees.
-------------
Commit messages:
- 8332230: jshell throws AssertionError when processing annotations
Changes: https://git.openjdk.org/jdk/pull/19371/files
Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=19371&range=00
Issue: https://bugs.openjdk.org/browse/JDK-8332230
Stats: 197 lines in 5 files changed: 193 ins; 0 del; 4 mod
Patch: https://git.openjdk.org/jdk/pull/19371.diff
Fetch: git fetch https://git.openjdk.org/jdk.git pull/19371/head:pull/19371
PR: https://git.openjdk.org/jdk/pull/19371
More information about the compiler-dev
mailing list