[prev in list] [next in list] [prev in thread] [next in thread]
List: openjdk-compiler-dev
Subject: RFR: 8332297: annotation processor that generates records sometimes fails due to NPE in javac
From: Vicente Romero <vromero () openjdk ! org>
Date: 2024-05-17 18:58:27
Message-ID: nBlNqvEvLw0ueaKwIQLFoeFI9s18_z_Zmfg7DEacnfA=.57a00073-65e0-41cc-98bc-2bef032442ca () github ! com
[Download RAW message or body]
This bug is a bit particular regarding how to reproduce it. Having:
import java.lang.annotation.*;
public @interface RecordBuilder {}
interface Conf {
int maxConcurrency( );
}
and:
import java.lang.annotation.*;
public @interface RecordBuilder {
}
and:
import java.util.*;
import java.io.*;
import javax.annotation.processing.*;
import javax.lang.model.element.TypeElement;
import javax.tools.StandardLocation;
@SupportedAnnotationTypes("*")
public class SimplestAP extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment \
roundEnv) { if (roundEnv.processingOver()) {
try (Writer w = \
processingEnv.getFiler().createSourceFile("ConfRecord").openWriter()) \
{
w.append("@RecordBuilder public record ConfRecord(int maxConcurrency) \
implements Conf {}"); } catch (IOException ex) {
throw new IllegalStateException(ex);
}
}
return true;
}
}
do:
javac SimplestAP.java
javac -processor SimplestAP Conf.java //compiles fine
javac -processor SimplestAP Conf.java // fails with:
warning: No SupportedSourceVersion annotation found on SimplestAP, returning \
RELEASE_6.
warning: Supported source version 'RELEASE_6' from annotation processor 'SimplestAP' \
less than -source '23'
warning: File for type 'ConfRecord' created in the last round will not be subject to \
annotation processing. 3 warnings
An exception has occurred in the compiler (23-internal). Please file a bug against \
the Java compiler via the Java bug reporting page (https://bugreport.java.com/) after \
checking the Bug Database (https://bugs.java.com/) for duplicates. Include your \
program, the following diagnostic, and the parameters passed to the Java compiler in \
your report. Thank you.
java.lang.NullPointerException: Cannot invoke \
"com.sun.tools.javac.code.Symbol$MethodSymbol.flags()" because "rc.accessor" is null \
at jdk.compiler/com.sun.tools.javac.comp.Lower.lambda$generateMandatedAccessors$6(Lower.java:2403)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:196)
at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1939)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:570)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:560)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:265)
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:727)
at jdk.compiler/com.sun.tools.javac.comp.Lower.generateMandatedAccessors(Lower.java:2410)
at jdk.compiler/com.sun.tools.javac.comp.Lower.visitRecordDef(Lower.java:2607)
at jdk.compiler/com.sun.tools.javac.comp.Lower.visitClassDef(Lower.java:2300)
at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCClassDecl.accept(JCTree.java:855)
at jdk.compiler/com.sun.tools.javac.tree.TreeTranslator.translate(TreeTranslator.java:58)
at jdk.compiler/com.sun.tools.javac.comp.Lower.translate(Lower.java:2192)
at jdk.compiler/com.sun.tools.javac.comp.Lower.translate(Lower.java:2211)
at jdk.compiler/com.sun.tools.javac.comp.Lower.translateTopLevelClass(Lower.java:4475)
at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.desugar(JavaCompiler.java:1647)
at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.desugar(JavaCompiler.java:1467)
at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:977)
at jdk.compiler/com.sun.tools.javac.main.Main.compile(Main.java:319)
at jdk.compiler/com.sun.tools.javac.main.Main.compile(Main.java:178)
at jdk.compiler/com.sun.tools.javac.Main.compile(Main.java:66)
at jdk.compiler/com.sun.tools.javac.Main.main(Main.java:52)
so the first time file ConfRecord.java is produced by the annotation processor, and \
later compiled by javac so all the information is gathered from a source file. The \
second time, ConfRecord.class is found, loaded and symbol for ConfRecord is completed \
from there. As the class file doesn't store the position of the record components in \
the original source file, method `ClassSymbol::findRecordComponentToRemove` won't \
find a match when trying to remove a record component and then two record components \
with the same name gets added to the record, currently we try to match on name and \
position. But for one of them there won't be an accessor assigned. We remove record \
components when dealing with annotation processors to make sure that later on we are \
propagating the correct annotations to other record elements the annotations could be \
applicable to.
The proposal here is to match only on name if the position is `-1` which is the \
default for all record components when the record class has been loaded from a class \
file.
TIA
-------------
Commit messages:
- 8332297: annotation processor that generates records sometimes fails due to NPE in \
javac
Changes: https://git.openjdk.org/jdk/pull/19288/files
Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=19288&range=00
Issue: https://bugs.openjdk.org/browse/JDK-8332297
Stats: 152 lines in 2 files changed: 150 ins; 0 del; 2 mod
Patch: https://git.openjdk.org/jdk/pull/19288.diff
Fetch: git fetch https://git.openjdk.org/jdk.git pull/19288/head:pull/19288
PR: https://git.openjdk.org/jdk/pull/19288
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic