Error-prone: Compilation crash with ambigous overloads

Created on 22 Feb 2018  路  12Comments  路  Source: google/error-prone

Please answer these questions before submitting your issue. Thanks!

What version of Error Prone are you using?

2.1.3 still exists in 2.2.0

Does this issue reproduce with the latest release?

yes

What did you do?

compiling this class.
This gist contains a version of the class that did fail compiling and a version that the compiler crashed on, the only change is the name of an overloaded method.

What did you expect to see?

It should compile normally, just like the normal javac compiler

What did you see instead?

It crashed with this stacktrace:

java.lang.AssertionError
    at com.sun.tools.javac.util.Assert.error(Assert.java:155)
    at com.sun.tools.javac.util.Assert.check(Assert.java:46)
    at com.sun.tools.javac.code.Flags.asFlagSet(Flags.java:69)
    at com.google.errorprone.bugpatterns.UnsafeFinalization.matchMethodInvocation(UnsafeFinalization.java:65)
    at com.google.errorprone.scanner.ErrorProneScanner.visitMethodInvocation(ErrorProneScanner.java:907)
    at com.google.errorprone.scanner.ErrorProneScanner.visitMethodInvocation(ErrorProneScanner.java:146)
    at com.sun.tools.javac.tree.JCTree$JCMethodInvocation.accept(JCTree.java:1644)
    at com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:82)
    at com.google.errorprone.scanner.Scanner.scan(Scanner.java:82)
    at com.google.errorprone.scanner.Scanner.scan(Scanner.java:42)
    at com.sun.source.util.TreeScanner.scanAndReduce(TreeScanner.java:90)
    at com.sun.source.util.TreeScanner.scan(TreeScanner.java:105)
    at com.sun.source.util.TreeScanner.scanAndReduce(TreeScanner.java:113)
    at com.sun.source.util.TreeScanner.visitMethodInvocation(TreeScanner.java:509)
    at com.google.errorprone.scanner.ErrorProneScanner.visitMethodInvocation(ErrorProneScanner.java:913)
    at com.google.errorprone.scanner.ErrorProneScanner.visitMethodInvocation(ErrorProneScanner.java:146)
    at com.sun.tools.javac.tree.JCTree$JCMethodInvocation.accept(JCTree.java:1644)
    at com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:82)
    at com.google.errorprone.scanner.Scanner.scan(Scanner.java:82)
    at com.google.errorprone.scanner.Scanner.scan(Scanner.java:42)
    at com.sun.source.util.TreeScanner.visitMemberSelect(TreeScanner.java:680)
    at com.google.errorprone.scanner.ErrorProneScanner.visitMemberSelect(ErrorProneScanner.java:878)
    at com.google.errorprone.scanner.ErrorProneScanner.visitMemberSelect(ErrorProneScanner.java:146)
    at com.sun.tools.javac.tree.JCTree$JCFieldAccess.accept(JCTree.java:2112)
    at com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:82)
    at com.google.errorprone.scanner.Scanner.scan(Scanner.java:82)
    at com.google.errorprone.scanner.Scanner.scan(Scanner.java:42)
    at com.sun.source.util.TreeScanner.scanAndReduce(TreeScanner.java:90)
    at com.sun.source.util.TreeScanner.visitMethodInvocation(TreeScanner.java:508)
    at com.google.errorprone.scanner.ErrorProneScanner.visitMethodInvocation(ErrorProneScanner.java:913)
    at com.google.errorprone.scanner.ErrorProneScanner.visitMethodInvocation(ErrorProneScanner.java:146)
    at com.sun.tools.javac.tree.JCTree$JCMethodInvocation.accept(JCTree.java:1644)
    at com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:82)
    at com.google.errorprone.scanner.Scanner.scan(Scanner.java:82)
    at com.google.errorprone.scanner.Scanner.scan(Scanner.java:42)
    at com.sun.source.util.TreeScanner.visitReturn(TreeScanner.java:469)
    at com.google.errorprone.scanner.ErrorProneScanner.visitReturn(ErrorProneScanner.java:1021)
    at com.google.errorprone.scanner.ErrorProneScanner.visitReturn(ErrorProneScanner.java:146)
    at com.sun.tools.javac.tree.JCTree$JCReturn.accept(JCTree.java:1548)
    at com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:82)
    at com.google.errorprone.scanner.Scanner.scan(Scanner.java:82)
    at com.google.errorprone.scanner.Scanner.scan(Scanner.java:42)
    at com.sun.source.util.TreeScanner.scan(TreeScanner.java:105)
    at com.sun.source.util.TreeScanner.visitBlock(TreeScanner.java:248)
    at com.google.errorprone.scanner.ErrorProneScanner.visitBlock(ErrorProneScanner.java:530)
    at com.google.errorprone.scanner.ErrorProneScanner.visitBlock(ErrorProneScanner.java:146)
    at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:1026)
    at com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:82)
    at com.google.errorprone.scanner.Scanner.scan(Scanner.java:82)
    at com.google.errorprone.scanner.Scanner.scan(Scanner.java:42)
    at com.sun.source.util.TreeScanner.scanAndReduce(TreeScanner.java:90)
    at com.sun.source.util.TreeScanner.visitMethod(TreeScanner.java:206)
    at com.google.errorprone.scanner.ErrorProneScanner.visitMethod(ErrorProneScanner.java:898)
    at com.google.errorprone.scanner.ErrorProneScanner.visitMethod(ErrorProneScanner.java:146)
    at com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:898)
    at com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:82)
    at com.google.errorprone.scanner.Scanner.scan(Scanner.java:82)
    at com.google.errorprone.scanner.Scanner.scan(Scanner.java:42)
    at com.sun.source.util.TreeScanner.scanAndReduce(TreeScanner.java:90)
    at com.sun.source.util.TreeScanner.scan(TreeScanner.java:105)
    at com.sun.source.util.TreeScanner.scanAndReduce(TreeScanner.java:113)
    at com.sun.source.util.TreeScanner.visitClass(TreeScanner.java:187)
    at com.google.errorprone.scanner.ErrorProneScanner.visitClass(ErrorProneScanner.java:590)
    at com.google.errorprone.scanner.ErrorProneScanner.visitClass(ErrorProneScanner.java:146)
    at com.sun.tools.javac.tree.JCTree$JCClassDecl.accept(JCTree.java:808)
    at com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:82)
    at com.google.errorprone.scanner.Scanner.scan(Scanner.java:82)
    at com.google.errorprone.scanner.Scanner.scan(Scanner.java:42)
    at com.sun.source.util.TreeScanner.scan(TreeScanner.java:105)
    at com.sun.source.util.TreeScanner.scanAndReduce(TreeScanner.java:113)
    at com.sun.source.util.TreeScanner.visitCompilationUnit(TreeScanner.java:144)
    at com.google.errorprone.scanner.ErrorProneScanner.visitCompilationUnit(ErrorProneScanner.java:605)
    at com.google.errorprone.scanner.ErrorProneScanner.visitCompilationUnit(ErrorProneScanner.java:146)
    at com.sun.tools.javac.tree.JCTree$JCCompilationUnit.accept(JCTree.java:591)
    at com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:56)
    at com.google.errorprone.scanner.Scanner.scan(Scanner.java:64)
    at com.google.errorprone.scanner.ErrorProneScannerTransformer.apply(ErrorProneScannerTransformer.java:41)
    at com.google.errorprone.ErrorProneAnalyzer.finished(ErrorProneAnalyzer.java:152)
    at com.sun.tools.javac.api.MultiTaskListener.finished(MultiTaskListener.java:120)
    at com.sun.tools.javac.main.JavaCompiler.flow(JavaCompiler.java:1425)
    at com.sun.tools.javac.main.JavaCompiler.flow(JavaCompiler.java:1374)
    at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:973)
    at com.sun.tools.javac.api.JavacTaskImpl.lambda$doCall$0(JavacTaskImpl.java:100)
    at com.sun.tools.javac.api.JavacTaskImpl.handleExceptions(JavacTaskImpl.java:142)
    at com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:96)
    at com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:90)
    at com.google.errorprone.BaseErrorProneCompiler.run(BaseErrorProneCompiler.java:137)
    at com.google.errorprone.BaseErrorProneCompiler.run(BaseErrorProneCompiler.java:108)
    at com.google.errorprone.ErrorProneCompiler.run(ErrorProneCompiler.java:118)
    at com.google.errorprone.ErrorProneCompiler.compile(ErrorProneCompiler.java:65)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at net.ltgt.gradle.errorprone.ErrorProneCompiler.execute(ErrorProneCompiler.java:66)
    at net.ltgt.gradle.errorprone.ErrorProneCompiler.execute(ErrorProneCompiler.java:23)
    at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.delegateAndHandleErrors(NormalizingJavaCompiler.java:98)
    at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.execute(NormalizingJavaCompiler.java:51)
    at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.execute(NormalizingJavaCompiler.java:37)
    at org.gradle.api.internal.tasks.compile.CleaningJavaCompilerSupport.execute(CleaningJavaCompilerSupport.java:35)
    at org.gradle.api.internal.tasks.compile.CleaningJavaCompilerSupport.execute(CleaningJavaCompilerSupport.java:25)
    at org.gradle.api.internal.tasks.compile.incremental.IncrementalCompilationFinalizer.execute(IncrementalCompilationFinalizer.java:39)
    at org.gradle.api.internal.tasks.compile.incremental.IncrementalCompilationFinalizer.execute(IncrementalCompilationFinalizer.java:24)
    at org.gradle.api.tasks.compile.JavaCompile.performCompilation(JavaCompile.java:207)
    at org.gradle.api.tasks.compile.JavaCompile.compile(JavaCompile.java:133)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73)
    at org.gradle.api.internal.project.taskfactory.IncrementalTaskAction.doExecute(IncrementalTaskAction.java:46)
    at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:39)
    at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:26)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$1.run(ExecuteActionsTaskExecuter.java:121)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:110)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:92)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:70)
    at org.gradle.api.internal.tasks.execution.OutputDirectoryCreatingTaskExecuter.execute(OutputDirectoryCreatingTaskExecuter.java:51)
    at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:62)
    at org.gradle.api.internal.tasks.execution.ResolveTaskOutputCachingStateExecuter.execute(ResolveTaskOutputCachingStateExecuter.java:54)
    at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:60)
    at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:97)
    at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:87)
    at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:52)
    at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
    at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:54)
    at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
    at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:34)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker$1.run(DefaultTaskGraphExecuter.java:248)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:241)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:230)
    at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.processTask(DefaultTaskPlanExecutor.java:123)
    at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.access$200(DefaultTaskPlanExecutor.java:79)
    at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:104)
    at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:98)
    at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.execute(DefaultTaskExecutionPlan.java:626)
    at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.executeWithTask(DefaultTaskExecutionPlan.java:581)
    at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.run(DefaultTaskPlanExecutor.java:98)
    at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
    at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
    at java.lang.Thread.run(Thread.java:748)

Most helpful comment

@cushon I have a simple reproducer here https://github.com/BrentDouglas/error-prone-949

public class Main {

    public static void main(final String... args) {
        thing((Integer it) -> "");
    }

    interface X1 extends Function<Integer, String> {}
    interface X2 extends Function<Short, String> {}

    static void thing(final X1 x) {}
    static void thing(final X2 x) {}
}

All 12 comments

Thanks for the report. Do you have a small, self-contained example that reproduces the crash?

@cushon The gist mentioned in the original description contains such an example, just remove the package name at the top and it should work

I'm not seeing a crash. Can you provide a complete repro?

$ curl https://gist.githubusercontent.com/RoiEXLab/e828b23dbbbf7fbbc73e4ef6f921159d/raw/e5d22de041259c904dbdaf0c649bb7f33708454c/MutableProperty.crash.java > MutableProperty.java
$ java -Xbootclasspath/p:$PWD/error_prone_ant-2.2.0.jar com.google.errorprone.ErrorProneCompiler \
  -cp jsr305-3.0.0.jar -Xep:UnsafeFinalization:ERROR MutableProperty.java

@cushon Sorry, I made a false assumption there. The class seems to compile fine, however the code calling one of the static of methods failed to compile. It's going to be hard to extract a case for that, but I'll try doing this today.
In the meantime you can checkout the workaround I had to make to temporarily workaround this: https://github.com/triplea-game/triplea/commit/3b109d85df251013973ba539327c6df717b687c5
If you don't mind downloading a Gigabyte of data, you can of course just clone the repository and checkout the parent commit of this fix and run ./gradlew check or something, not sure if you have time for this though.

@cushon I have a simple reproducer here https://github.com/BrentDouglas/error-prone-949

public class Main {

    public static void main(final String... args) {
        thing((Integer it) -> "");
    }

    interface X1 extends Function<Integer, String> {}
    interface X2 extends Function<Short, String> {}

    static void thing(final X1 x) {}
    static void thing(final X2 x) {}
}

In com/sun/tools/javac/code/Flags.java POTENTIALLY_AMBIGUOUS is declared as a constant but it isn't included in the enum Flags which is being iterated over.

@BrentDouglas thanks for the repro! I can work around this with the following patch, with indicates the underlying problem is similar to the one discussed in #781.

diff --git a/pom.xml b/pom.xml
index 9452958..a58cf45 100644
--- a/pom.xml
+++ b/pom.xml
@@ -20,6 +20,7 @@
                     <source>8</source>
                     <target>8</target>
                     <compilerArgument>-Xlint:all</compilerArgument>
+                    <compilerArgument>-XDcompilePolicy=simple</compilerArgument>
                 </configuration>
                 <dependencies>
                     <dependency>
@@ -36,4 +37,4 @@
             </plugin>
         </plugins>
     </build>

Oh nice. Renaming the method so that it is no longer ambiguous as @RoiEXLab did in the previous example also works.

After looking at this a bit more I'm still confused: changing other javac flags that should have no effect on the output (e.g. -verbose) also works around the crash. There may be some non-determinism in javac here, I'm still looking.

Never mind: the bug only reproduces with -Xlint:all, which enables a code path that causes POTENTIALLY_AMBIGUOUS to be set. When I added additional <compilerArgument> apparently they override the previous ones, maybe <compilerArgs> is the right way to do that.

Anyway, it is easy to reproduce outside of maven:

javac -XDcompilePolicy=simple -processorpath error_prone_ant-2.3.1.jar -Xplugin:ErrorProne -Xlint:all  ./src/main/java/Main.java
...
./src/main/java/Main.java:15: warning: [overloads] thing(X1) in Main is potentially ambiguous with thing(X2) in Main
    static void thing(final X1 x) {}
                ^
./src/main/java/Main.java:9: error: An unhandled exception was thrown by the Error Prone static analysis plugin.
        thing((Integer it) -> "");
             ^
     Please report this at https://github.com/google/error-prone/issues/new and include the following:

     error-prone version: 2.3.1
     BugPattern: UnsafeFinalization
     Stack Trace:
     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.check(Assert.java:46)
    at jdk.compiler/com.sun.tools.javac.code.Flags.asFlagSet(Flags.java:69)
    at com.google.errorprone.bugpatterns.UnsafeFinalization.matchMethodInvocation(UnsafeFinalization.java:65)
    at com.google.errorprone.scanner.ErrorProneScanner.visitMethodInvocation(ErrorProneScanner.java:904)
    at com.google.errorprone.scanner.ErrorProneScanner.visitMethodInvocation(ErrorProneScanner.java:145)
    at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCMethodInvocation.accept(JCTree.java:1644)

Closing since -XDcompilePolicy=simple works around this

Shouldn't this be fixed without the flag anyway as https://github.com/openjdk/jdk/commit/9c60728a281ac4e2a5ffeaa87fe2db74a1f701a1 adds the missing enum constant?

Was this page helpful?
0 / 5 - 0 ratings