-
Notifications
You must be signed in to change notification settings - Fork 329
Closed
Labels
crashjspecifyRelated to support for jspecify standard (see jspecify.dev)Related to support for jspecify standard (see jspecify.dev)
Description
Description
When using the latest NullAway (0.12.15) in JSpecify mode, ClassCastException occurs while handling array types with null-marking at generic positions.
Minimal reproducible example
Code:
import java.util.function.Function;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
@NullMarked
class MinExample {
void use(AsyncTask<AsyncTask<@Nullable Void>[]> tasks) {
tasks.flatMap(readyTasks -> consume(readyTasks));
// ^
}
interface AsyncTask<T extends @Nullable Object> {
<U extends @Nullable Object> AsyncTask<U> flatMap(
Function<T, ? extends AsyncTask<U>> mapper
);
}
AsyncTask<@Nullable Void> consume(AsyncTask<@Nullable Void>[] tasks) {
throw new UnsupportedOperationException("TODO");
}
}Expected behaviour: successful compilation.
Actual behaviour: javac crash
Stacktace
MinExample.java:9: error: An unhandled exception was thrown by the Error Prone static analysis plugin.
tasks.flatMap(readyTasks -> consume(readyTasks));
^
Please report this at https://github.com/google/error-prone/issues/new and include the following, as well as a reproducing code sample (if possible):
error-prone version: 2.45.0
BugPattern: NullAway
Stack Trace:
java.lang.ClassCastException: class com.sun.tools.javac.code.Type$TypeVar cannot be cast to class com.sun.tools.javac.code.Type$ArrayType (com.sun.tools.javac.code.Type$TypeVar and com.sun.tools.javac.code.Type$ArrayType are in module jdk.compiler of loader 'app')
at com.uber.nullaway.generics.CheckIdenticalNullabilityVisitor.visitArrayType(CheckIdenticalNullabilityVisitor.java:101)
at com.uber.nullaway.generics.CheckIdenticalNullabilityVisitor.visitArrayType(CheckIdenticalNullabilityVisitor.java:17)
at jdk.compiler/com.sun.tools.javac.code.Type$ArrayType.accept(Type.java:1378)
at com.uber.nullaway.generics.CheckIdenticalNullabilityVisitor.visitClassType(CheckIdenticalNullabilityVisitor.java:77)
at com.uber.nullaway.generics.CheckIdenticalNullabilityVisitor.visitClassType(CheckIdenticalNullabilityVisitor.java:17)
at jdk.compiler/com.sun.tools.javac.code.Type$ClassType.accept(Type.java:1056)
at com.uber.nullaway.generics.GenericsChecks.identicalTypeParameterNullability(GenericsChecks.java:1099)
at com.uber.nullaway.generics.GenericsChecks.subtypeParameterNullability(GenericsChecks.java:1130)
at com.uber.nullaway.generics.GenericsChecks.lambda$compareGenericTypeParameterNullabilityForCall$0(GenericsChecks.java:1264)
at com.uber.nullaway.InvocationArguments.forEach(InvocationArguments.java:86)
at com.uber.nullaway.generics.GenericsChecks.compareGenericTypeParameterNullabilityForCall(GenericsChecks.java:1235)
at com.uber.nullaway.NullAway.handleInvocation(NullAway.java:2003)
at com.uber.nullaway.NullAway.matchMethodInvocation(NullAway.java:444)
at com.google.errorprone.scanner.ErrorProneScanner.processMatchers(ErrorProneScanner.java:539)
at com.google.errorprone.scanner.ErrorProneScanner.visitMethodInvocation(ErrorProneScanner.java:888)
at com.google.errorprone.scanner.ErrorProneScanner.visitMethodInvocation(ErrorProneScanner.java:178)
at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCMethodInvocation.accept(JCTree.java:1876)
at jdk.compiler/com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:92)
at com.google.errorprone.scanner.Scanner.scan(Scanner.java:74)
at com.google.errorprone.scanner.Scanner.scan(Scanner.java:48)
at jdk.compiler/com.sun.source.util.TreeScanner.visitExpressionStatement(TreeScanner.java:504)
at com.google.errorprone.scanner.ErrorProneScanner.visitExpressionStatement(ErrorProneScanner.java:775)
at com.google.errorprone.scanner.ErrorProneScanner.visitExpressionStatement(ErrorProneScanner.java:178)
at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCExpressionStatement.accept(JCTree.java:1655)
at jdk.compiler/com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:92)
at com.google.errorprone.scanner.Scanner.scan(Scanner.java:74)
at com.google.errorprone.scanner.Scanner.scan(Scanner.java:48)
at jdk.compiler/com.sun.source.util.TreeScanner.scan(TreeScanner.java:110)
at jdk.compiler/com.sun.source.util.TreeScanner.visitBlock(TreeScanner.java:271)
at com.google.errorprone.scanner.ErrorProneScanner.visitBlock(ErrorProneScanner.java:621)
at com.google.errorprone.scanner.ErrorProneScanner.visitBlock(ErrorProneScanner.java:178)
at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:1148)
at jdk.compiler/com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:92)
at com.google.errorprone.scanner.Scanner.scan(Scanner.java:74)
at com.google.errorprone.scanner.Scanner.scan(Scanner.java:48)
at jdk.compiler/com.sun.source.util.TreeScanner.scanAndReduce(TreeScanner.java:95)
at jdk.compiler/com.sun.source.util.TreeScanner.visitMethod(TreeScanner.java:223)
at com.google.errorprone.scanner.ErrorProneScanner.visitMethod(ErrorProneScanner.java:882)
at com.google.errorprone.scanner.ErrorProneScanner.visitMethod(ErrorProneScanner.java:178)
at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:992)
at jdk.compiler/com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:92)
at com.google.errorprone.scanner.Scanner.scan(Scanner.java:74)
at com.google.errorprone.scanner.Scanner.scan(Scanner.java:48)
at jdk.compiler/com.sun.source.util.TreeScanner.scanAndReduce(TreeScanner.java:95)
at jdk.compiler/com.sun.source.util.TreeScanner.scan(TreeScanner.java:110)
at jdk.compiler/com.sun.source.util.TreeScanner.scanAndReduce(TreeScanner.java:118)
at jdk.compiler/com.sun.source.util.TreeScanner.visitClass(TreeScanner.java:202)
at com.google.errorprone.scanner.ErrorProneScanner.visitClass(ErrorProneScanner.java:649)
at com.google.errorprone.scanner.ErrorProneScanner.visitClass(ErrorProneScanner.java:178)
at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCClassDecl.accept(JCTree.java:899)
at jdk.compiler/com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:92)
at com.google.errorprone.scanner.Scanner.scan(Scanner.java:74)
at com.google.errorprone.scanner.Scanner.scan(Scanner.java:48)
at jdk.compiler/com.sun.source.util.TreeScanner.scan(TreeScanner.java:110)
at jdk.compiler/com.sun.source.util.TreeScanner.scanAndReduce(TreeScanner.java:118)
at jdk.compiler/com.sun.source.util.TreeScanner.visitCompilationUnit(TreeScanner.java:151)
at com.google.errorprone.scanner.ErrorProneScanner.visitCompilationUnit(ErrorProneScanner.java:661)
at com.google.errorprone.scanner.ErrorProneScanner.visitCompilationUnit(ErrorProneScanner.java:178)
at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCCompilationUnit.accept(JCTree.java:627)
at jdk.compiler/com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:66)
at com.google.errorprone.scanner.Scanner.scan(Scanner.java:58)
at com.google.errorprone.scanner.ErrorProneScannerTransformer.apply(ErrorProneScannerTransformer.java:43)
at com.google.errorprone.ErrorProneAnalyzer.finished(ErrorProneAnalyzer.java:231)
at jdk.compiler/com.sun.tools.javac.api.MultiTaskListener.finished(MultiTaskListener.java:133)
at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.flow(JavaCompiler.java:1423)
at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.flow(JavaCompiler.java:1370)
at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:955)
at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.lambda$doCall$0(JavacTaskImpl.java:104)
at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.invocationHelper(JavacTaskImpl.java:152)
at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:100)
at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:94)
at org.gradle.internal.compiler.java.IncrementalCompileTask.call(IncrementalCompileTask.java:92)
at org.gradle.api.internal.tasks.compile.AnnotationProcessingCompileTask.call(AnnotationProcessingCompileTask.java:94)
at org.gradle.api.internal.tasks.compile.ResourceCleaningCompilationTask.call(ResourceCleaningCompilationTask.java:57)
at org.gradle.api.internal.tasks.compile.JdkJavaCompiler.execute(JdkJavaCompiler.java:83)
at org.gradle.api.internal.tasks.compile.JdkJavaCompiler.execute(JdkJavaCompiler.java:50)
at org.gradle.api.internal.tasks.compile.daemon.AbstractIsolatedCompilerWorkerExecutor$CompilerWorkAction.execute(AbstractIsolatedCompilerWorkerExecutor.java:79)
at org.gradle.workers.internal.DefaultWorkerServer.execute(DefaultWorkerServer.java:68)
at org.gradle.workers.internal.AbstractClassLoaderWorker$1.create(AbstractClassLoaderWorker.java:54)
at org.gradle.workers.internal.AbstractClassLoaderWorker$1.create(AbstractClassLoaderWorker.java:48)
at org.gradle.internal.classloader.ClassLoaderUtils.executeInClassloader(ClassLoaderUtils.java:100)
at org.gradle.workers.internal.AbstractClassLoaderWorker.executeInClassLoader(AbstractClassLoaderWorker.java:48)
at org.gradle.workers.internal.FlatClassLoaderWorker.run(FlatClassLoaderWorker.java:32)
at org.gradle.workers.internal.FlatClassLoaderWorker.run(FlatClassLoaderWorker.java:22)
at org.gradle.workers.internal.WorkerDaemonServer.run(WorkerDaemonServer.java:108)
at org.gradle.workers.internal.WorkerDaemonServer.run(WorkerDaemonServer.java:77)
at org.gradle.process.internal.worker.request.WorkerAction.lambda$run$1(WorkerAction.java:150)
at org.gradle.process.internal.worker.child.WorkerLogEventListener.withWorkerLoggingProtocol(WorkerLogEventListener.java:41)
at org.gradle.process.internal.worker.request.WorkerAction.lambda$run$2(WorkerAction.java:150)
at org.gradle.internal.operations.CurrentBuildOperationRef.with(CurrentBuildOperationRef.java:84)
at org.gradle.process.internal.worker.request.WorkerAction.run(WorkerAction.java:142)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at java.base/java.lang.reflect.Method.invoke(Method.java:565)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:182)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:164)
at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:414)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:47)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1090)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:614)
at java.base/java.lang.Thread.run(Thread.java:1474)
Related problem
Originally, the signature of flatMap was PECSified, i.e.:
<U extends @Nullable Object> AsyncTask<U> flatMap(
Function<? super T, ? extends AsyncTask<U>> mapper
);which did not cause a crash but did cause a false positive with the code above:
MinExample.java:9: error: [NullAway] incompatible types: AsyncTask<Void> [] cannot be converted to AsyncTask<@Nullable Void> []
tasks.flatMap(readyTasks -> consume(readyTasks));
^
(see http://t.uber.com/nullaway )
1 error
which also seems invalid(?) (although I may be misreading the spec).
coderabbitai
Metadata
Metadata
Assignees
Labels
crashjspecifyRelated to support for jspecify standard (see jspecify.dev)Related to support for jspecify standard (see jspecify.dev)