package nullawaytest;
class Outer {
class Inner {}
static Inner f(Outer outer) { return outer.new Inner() {}; }
}
Using JDK 21 and NullAway 0.12.6:
Outer.java:4: error: An unhandled exception was thrown by the Error Prone static analysis plugin.
static Inner f(Outer outer) { return outer.new Inner() {}; }
^
Please report this at https://github.com/google/error-prone/issues/new and include the following:
error-prone version: 2.37.0
BugPattern: NullAway
Stack Trace:
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at jdk.compiler/com.sun.tools.javac.util.List.get(List.java:476)
at com.uber.nullaway.NullAway.handleInvocation(NullAway.java:1986)
at com.uber.nullaway.NullAway.matchNewClass(NullAway.java:453)
at com.google.errorprone.scanner.ErrorProneScanner.processMatchers(ErrorProneScanner.java:509)
...
Analysis
When the outer.new Inner(){} syntax is used, the constructor symbol has an extra formal parameter.
b3646ef added some special-case code to work around this issue, but it does not take effect when in a static method (methodSymbol.enclClass().isInner() returns false - I think the anonymous subclass of Inner` is not itself considered an inner class)
Interestingly, this bug does not occur when Inner's constructor has explicit parameters, because in that case, matchNewClass uses the superclass's constructor instead:
|
if (tree.getClassBody() != null && actualParams.size() > 0) { |
if (tree.getClassBody() != null && actualParams.size() > 0) {
// passing parameters to constructor of anonymous class
// this constructor just invokes the constructor of the superclass, and
// in the AST does not have the parameter nullability annotations from the superclass.
// so, treat as if the superclass constructor is being invoked directly
// see https://github.com/uber/NullAway/issues/102
methodSymbol = getSymbolOfSuperConstructor(methodSymbol, state);
}
So I think you could just remove the actualParams.size() > 0 check, and this would handle all cases, making the special-case in handleInvocation unnecessary.
Vaguely-related minor bug I noticed while looking at this code
matchNewClass also should check that tree.getEnclosingExpression(), if it exists, is non-nullable. outer.new ... will throw NPE if outer is null.
Using JDK 21 and NullAway 0.12.6:
Analysis
When the
outer.new Inner(){}syntax is used, the constructor symbol has an extra formal parameter.b3646ef added some special-case code to work around this issue, but it does not take effect when in a static method (
methodSymbol.enclClass().isInner()returns false - I think the anonymous subclass of Inner` is not itself considered an inner class)Interestingly, this bug does not occur when
Inner's constructor has explicit parameters, because in that case,matchNewClassuses the superclass's constructor instead:NullAway/nullaway/src/main/java/com/uber/nullaway/NullAway.java
Line 445 in 649f25a
So I think you could just remove the
actualParams.size() > 0check, and this would handle all cases, making the special-case inhandleInvocationunnecessary.Vaguely-related minor bug I noticed while looking at this code
matchNewClassalso should check thattree.getEnclosingExpression(), if it exists, is non-nullable.outer.new ...will throw NPE ifouteris null.