Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8026329

Regression: Type Inferencer can return incorrect type signatures

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: P3
    • Resolution: Not an Issue
    • Affects Version/s: 8
    • Fix Version/s: 8
    • Component/s: tools
    • Labels:
    • Subcomponent:
    • OS:
      os_x

      Description

      FULL PRODUCT VERSION :
      openjdk version "1.8.0-jdk8-b108"
      OpenJDK Runtime Environment (build 1.8.0-jdk8-b108-20130923)
      OpenJDK 64-Bit Server VM (build 25.0-b50, mixed mode)


      ADDITIONAL OS VERSION INFORMATION :
      Darwin Stormbringer.local 12.5.0 Darwin Kernel Version 12.5.0: Sun Sep 29 13:33:47 PDT 2013; root:xnu-2050.48.12~1/RELEASE_X86_64 x86_64

      A DESCRIPTION OF THE PROBLEM :
      When compiled under Java 8, the sample project found [1] fails to compile. This small project is extracted from a larger commercial project and compiles fine under Java 7, but fails under Java 8.

      As originally reported on the jdk8-dev/compiler-dev mailing lists [2], the sample project which uses the popular FEST-Assert testing library now fails to compile it's second test method, with javac reporting that the method 'hasSize' can not be found.

      As the FEST-Assert library employs a fairly deep class hierarchy, and also employing some complex generics magic to provide some recursive 'self types' I'm finding it difficult to extract a totally standalone test case that triggers the observed regression.

      It would appear, that somewhere along the call chain, the generic 'S' type on FEST's AbstractAssertion class is being returned as itself (AbstractAssertion) rather than the subclass that the method was actually invoked upon (ListAssertion).

      So far my method of testing this, is to run "mvn clean compile" under both JDK7 and JDK8, and calling javac directly.

      [1] https://github.com/talios/jdk8-covariantfail
      [2] http://mail.openjdk.java.net/pipermail/jdk8-dev/2013-September/003226.html

      REGRESSION. Last worked in version 7u40

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1. Clone the sample project

      $ git clone git@github.com:talios/jdk8-covariantfail.git
      $ cd jdk8-covariantfail

      2. Build with Apache Maven under JDK8

      $ JAVA_HOME=~/j2sdk-image mvn clean test



      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      I would expect the code to compile, and tests to run as expected.
      ACTUAL -
      ~/D/covariantfail (master|???) $ /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/bin/java -version
      java version "1.8.0-ea"
      Java(TM) SE Runtime Environment (build 1.8.0-ea-b106)
      Java HotSpot(TM) 64-Bit Server VM (build 25.0-b48, mixed mode)

      ~/D/covariantfail (master|???) $ /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/bin/javac -version
      javac 1.8.0-ea

      /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/bin/javac -d /Users/amrk/Dropbox/covariantfail/target/test-classes -classpath /Users/amrk/Dropbox/covariantfail/target/test-classes:/Users/amrk/Dropbox/covariantfail/target/classes:/Users/amrk/.m2/repository/org/testng/testng/6.8.5/testng-6.8.5.jar:/Users/amrk/.m2/repository/junit/junit/4.10/junit-4.10.jar:/Users/amrk/.m2/repository/org/hamcrest/hamcrest-core/1.1/hamcrest-core-1.1.jar:/Users/amrk/.m2/repository/org/beanshell/bsh/2.0b4/bsh-2.0b4.jar:/Users/amrk/.m2/repository/com/beust/jcommander/1.27/jcommander-1.27.jar:/Users/amrk/.m2/repository/org/yaml/snakeyaml/1.6/snakeyaml-1.6.jar:/Users/amrk/.m2/repository/org/easytesting/fest-assert-core/2.0M10/fest-assert-core-2.0M10.jar:/Users/amrk/.m2/repository/org/easytesting/fest-util/1.2.5/fest-util-1.2.5.jar: -sourcepath /Users/amrk/Dropbox/covariantfail/src/test/java: /Users/amrk/Dropbox/covariantfail/src/test/java/com/talios/RegexMatch.java /Users/amrk/Dropbox/covariantfail/src/test/java/com/talios/AppTest.java -g -nowarn -target 1.5 -source 1.5 -encoding UTF-8
      /Users/amrk/Dropbox/covariantfail/src/test/java/com/talios/AppTest.java:37: error: cannot find symbol
                      .hasSize(3);
                      ^
        symbol: method hasSize(int)
        location: class AbstractAssert
      Note: /Users/amrk/Dropbox/covariantfail/src/test/java/com/talios/AppTest.java uses unchecked or unsafe operations.
      Note: Recompile with -Xlint:unchecked for details.
      1 error


      REPRODUCIBILITY :
      This bug can be reproduced always.

      CUSTOMER SUBMITTED WORKAROUND :
      Don't use Java 8 sadly :(

        Issue Links

          Activity

          Hide
          ksrini Kumar Srinivasan added a comment -
          Show
          ksrini Kumar Srinivasan added a comment - Use this workaround suggested here: http://mail.openjdk.java.net/pipermail/compiler-dev/2013-October/007586.html
          Hide
          vromero Vicente Arturo Romero Zaldivar added a comment - - edited
          I have created this test, not minimal version, that should recreate the same conditions of the original report:

          import java.util.*;

          abstract class GenericAssert<S, A> {
              public S describedAs(String description) {
                  return null;
              }
          }

          abstract class GroupAssert<S, A> extends GenericAssert<S, A> {
              public final S isNotEmpty() {
                  return null;
              }

              public final S hasSize(int expected) {
                  return null;
              }

              S has(Condition<? super A> matcher) {
                  return null;
              }

              S doesNotHave(Condition<? super A> matcher) {
                  return null;
              }
          }

          class ListAssert extends GroupAssert<ListAssert, List<?>> {}

          abstract class Condition<T> {
              public abstract boolean matches(T value);
          }

          class RegexMatch extends Condition {

              public static RegexMatch regexMatch(String pattern) {
                  return null;
              }

              @Override
              public boolean matches(Object value) {
                  return true;
              }
          }

          public class Test {
              public static void testHasReturns() {
                  List<String> strings = Arrays.asList("one", "two", "three");
                  assertThat(strings)
                          .describedAs("test")
                          .isNotEmpty()
                          .has(RegexMatch.regexMatch("th.*"))
                          .doesNotHave(RegexMatch.regexMatch("moo.*"))
                          .hasSize(3);
              }

              public static <T> ListAssert assertThat(List<T> actual) {
                  return null;
              }
          }

          I have traversed the different definitions in the fest library getting the original code. The code compiles with jdk8 TL, with warnings but compiles, so I will change the state of this bug to can't reproduce.
          Show
          vromero Vicente Arturo Romero Zaldivar added a comment - - edited I have created this test, not minimal version, that should recreate the same conditions of the original report: import java.util.*; abstract class GenericAssert<S, A> {     public S describedAs(String description) {         return null;     } } abstract class GroupAssert<S, A> extends GenericAssert<S, A> {     public final S isNotEmpty() {         return null;     }     public final S hasSize(int expected) {         return null;     }     S has(Condition<? super A> matcher) {         return null;     }     S doesNotHave(Condition<? super A> matcher) {         return null;     } } class ListAssert extends GroupAssert<ListAssert, List<?>> {} abstract class Condition<T> {     public abstract boolean matches(T value); } class RegexMatch extends Condition {     public static RegexMatch regexMatch(String pattern) {         return null;     }     @Override     public boolean matches(Object value) {         return true;     } } public class Test {     public static void testHasReturns() {         List<String> strings = Arrays.asList("one", "two", "three");         assertThat(strings)                 .describedAs("test")                 .isNotEmpty()                 .has(RegexMatch.regexMatch("th.*"))                 .doesNotHave(RegexMatch.regexMatch("moo.*"))                 .hasSize(3);     }     public static <T> ListAssert assertThat(List<T> actual) {         return null;     } } I have traversed the different definitions in the fest library getting the original code. The code compiles with jdk8 TL, with warnings but compiles, so I will change the state of this bug to can't reproduce.
          Hide
          vromero Vicente Arturo Romero Zaldivar added a comment -
          See [1] to find a detailed explanation of why this is not a bug.

          [1] http://mail.openjdk.java.net/pipermail/compiler-dev/2013-November/008038.html
          Show
          vromero Vicente Arturo Romero Zaldivar added a comment - See [1] to find a detailed explanation of why this is not a bug. [1] http://mail.openjdk.java.net/pipermail/compiler-dev/2013-November/008038.html

            People

            • Assignee:
              vromero Vicente Arturo Romero Zaldivar
              Reporter:
              aefimov Aleksej Efimov
            • Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: