JDK-8203679 : AssertionError in DeferredAttr with parenthesized method reference
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 9,10,11
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2018-05-23
  • Updated: 2019-10-28
  • Resolved: 2018-06-12
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 11
11 b18Fixed
Related Reports
Relates :  
Relates :  
Description
The following ill-formed program crashes javac 11-ea+14. Removing the extra parens around `(I::v)` works around the crash and allows an error to be reported.

```
import java.util.Arrays;
import java.util.stream.Collectors;
import java.util.stream.Stream;

class Test {

  interface I {
    String k();

    String v();
  }

  void f(Stream<I> xs) {
    xs.collect(Collectors.toMap(I::k, Arrays.asList((I::v))));
  }
}
```

```
javac -fullversion Test.java
javac full version "11-ea+14"
An exception has occurred in the compiler (11-ea). Please file a bug against the Java compiler via the Java bug reporting page (http://bugreport.java.com) after checking the Bug Database (http://bugs.java.com) for duplicates. Include your program and the following diagnostic in your report. Thank you.
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.DeferredAttr$DeferredAttrNode$StructuralStuckChecker.visitReference(DeferredAttr.java:882)
        at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCMemberReference.accept(JCTree.java:2190)
        at jdk.compiler/com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
        at jdk.compiler/com.sun.tools.javac.tree.TreeScanner.visitParens(TreeScanner.java:264)
        at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCParens.accept(JCTree.java:1847)
        at jdk.compiler/com.sun.tools.javac.comp.DeferredAttr$DeferredAttrNode$StructuralStuckChecker.complete(DeferredAttr.java:795)
        at jdk.compiler/com.sun.tools.javac.comp.DeferredAttr$DeferredType.check(DeferredAttr.java:327)
        at jdk.compiler/com.sun.tools.javac.comp.DeferredAttr$DeferredType.access$000(DeferredAttr.java:198)
```
Comments
My understanding of the crash is that: * DeferredAttr makes two copies of the parenthesized method reference. * ArgumentAttr#visitParens wraps the trees as a 'ParensType'. * ArgumentAttr#argumentTypeCache caches the result of processing the ParensType. It only visits the method reference in the first one, and the second is a cache hit. This is the step that calls setOverloadKind, so the kind is only set for one of the copies. Registering a new local cache when ArgumentAttr#processArg calls attribSpeculative works around the crash, confirming it's related to the caching. (That change to the caching would also significantly regress performance, I'm not suggesting it as a fix.)
09-06-2018