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

compiler should infer method but I get: ambiguous methods error

    Details

    • Type: Bug
    • Status: Closed
    • Priority: P3
    • Resolution: Not an Issue
    • Affects Version/s: 8u25
    • Fix Version/s: None
    • Component/s: tools
    • Labels:
    • Subcomponent:
    • CPU:
      x86_64
    • OS:
      windows_7

      Description

      FULL PRODUCT VERSION :
      java version "1.8.0_25"
      Java(TM) SE Runtime Environment (build 1.8.0_25-b18)
      Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Window 7 64 bit

      A DESCRIPTION OF THE PROBLEM :
      When I try to compile attached piece of code I get error that call of method is ambiguous, but this is not true. Proper method should be inferred with ease. In java 1.7 this compiles without any error.

      Test case is in attached code, and I have also repo on github with this bug:

      https://github.com/wjtk/java8-inference-bug



      REGRESSION. Last worked in version 7u71

      ADDITIONAL REGRESSION INFORMATION:
      java version "1.7.0_71"
      Java(TM) SE Runtime Environment (build 1.7.0_71-b14)
      Java HotSpot(TM) 64-Bit Server VM (build 24.71-b01, mixed mode)


      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      package pl.wkr.j8.inferencebug;

      import org.junit.Test;

      import java.util.Iterator;

      import static pl.wkr.j8.inferencebug.A.*;
      import static pl.wkr.j8.inferencebug.B.*;

      class A {
          public static <T> void methodA(Iterable<T> actual) {}
          public static <T> void methodA(Iterator<T> actual) {}
          public static void methodA(Throwable actual) {}
      }

      class B {
          public static <E extends Throwable> E methodB() {
              return null;
          }
      }


      public class InferenceBugTest {

          @Test
          public void should_infer_method() {
              methodA(methodB());
              /* ^^^
              Java 1.7 compiles this, but in 1.8(1.8.0_25) I get error:

                error: reference to methodA is ambiguous
                      methodA(methodB());
                      ^
                both method <T#1>methodA(Iterator<T#1>) in A and method <T#2>methodA(Iterable<T#2>) in A match
                where T#1,T#2 are type-variables:
                  T#1 extends Object declared in method <T#1>methodA(Iterator<T#1>)
                  T#2 extends Object declared in method <T#2>methodA(Iterable<T#2>)

                -------------
                 (change 'sourceCompatibility' in build.gradle to see behavior in java 1.7 and 1.8)
               */
          }
      }




      ---------- END SOURCE ----------

        Activity

        Hide
        pardesha Pardeep Sharma added a comment -
        Tested this with JDK 7u72, 8u25, and 8u45 and couldn't reproduce. The code compiled fine without any error. Closing this as Incomplete while seeking more information from the submitter.
        Show
        pardesha Pardeep Sharma added a comment - Tested this with JDK 7u72, 8u25, and 8u45 and couldn't reproduce. The code compiled fine without any error. Closing this as Incomplete while seeking more information from the submitter.
        Hide
        pardesha Pardeep Sharma added a comment -
        The user claim to be able to reproduce this issue with JDK 8u25:
        "I try to compile only with javac, and I got the same error:

        InferenceBugTest.java:28: error: reference to methodA is ambiguous
                methodA(methodB());
                ^
          both method <T#1>methodA(Iterator<T#1>) in A and method
        <T#2>methodA(Iterable<T#2>) in A match
          where T#1,T#2 are type-variables:
            T#1 extends Object declared in method <T#1>methodA(Iterator<T#1>)
            T#2 extends Object declared in method <T#2>methodA(Iterable<T#2>)


        java version "1.8.0_25"
        Java(TM) SE Runtime Environment (build 1.8.0_25-b18)
        Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)

        but In 1.7 this compiles without any error, version:

        java version "1.7.0_71"
        Java(TM) SE Runtime Environment (build 1.7.0_71-b14)
        Java HotSpot(TM) 64-Bit Server VM (build 24.71-b01, mixed mode)

        I even try to compile this on travis, and there is same error:
        https://travis-ci.org/wjtk/java8-inference-bug
        This is build log of my test-case repo:

        https://github.com/wjtk/java8-inference-bug
        So I think that problem still remains."

        Re-opened for further evaluation.
        Show
        pardesha Pardeep Sharma added a comment - The user claim to be able to reproduce this issue with JDK 8u25: "I try to compile only with javac, and I got the same error: InferenceBugTest.java:28: error: reference to methodA is ambiguous         methodA(methodB());         ^   both method <T#1>methodA(Iterator<T#1>) in A and method <T#2>methodA(Iterable<T#2>) in A match   where T#1,T#2 are type-variables:     T#1 extends Object declared in method <T#1>methodA(Iterator<T#1>)     T#2 extends Object declared in method <T#2>methodA(Iterable<T#2>) java version "1.8.0_25" Java(TM) SE Runtime Environment (build 1.8.0_25-b18) Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode) but In 1.7 this compiles without any error, version: java version "1.7.0_71" Java(TM) SE Runtime Environment (build 1.7.0_71-b14) Java HotSpot(TM) 64-Bit Server VM (build 24.71-b01, mixed mode) I even try to compile this on travis, and there is same error: https://travis-ci.org/wjtk/java8-inference-bug This is build log of my test-case repo: https://github.com/wjtk/java8-inference-bug So I think that problem still remains." Re-opened for further evaluation.
        Hide
        mcimadamore Maurizio Cimadamore added a comment -
        This is not a bug, but rather a consequence of more powerful inference; in JDK 7 inference of the innermost method (methodB) is independent from the context - meaning that methodB is inferred as returning Throwable - which then drives overload selection of the outer method (methodA) so that methodA(Throwable) is chosen. This behavior is still reproducible with the compilation flag -source 7.

        In JDK 8, inference does not have to instantiate inference variables eagerly - meaning that the innermost call to methodB is indeed compatible with all the methodA signature:

        methodA(Iterable<T>) --> inferred return type for methodB is Throwable & Iterable<Object>
        methodA(Iterator<T>) --> inferred return type for methodB is Throwable & Iterator<Object>
        methodA(Throwable) --> inferred return type for methodB is Throwable

        So, the next question is: given all methods are applicable, which one is the most specific? Unfortunately, since the three methodA overloads accept unrelated interfaces, the answer is that no method is most specific, hence the ambiguity error.
        Show
        mcimadamore Maurizio Cimadamore added a comment - This is not a bug, but rather a consequence of more powerful inference; in JDK 7 inference of the innermost method (methodB) is independent from the context - meaning that methodB is inferred as returning Throwable - which then drives overload selection of the outer method (methodA) so that methodA(Throwable) is chosen. This behavior is still reproducible with the compilation flag -source 7. In JDK 8, inference does not have to instantiate inference variables eagerly - meaning that the innermost call to methodB is indeed compatible with all the methodA signature: methodA(Iterable<T>) --> inferred return type for methodB is Throwable & Iterable<Object> methodA(Iterator<T>) --> inferred return type for methodB is Throwable & Iterator<Object> methodA(Throwable) --> inferred return type for methodB is Throwable So, the next question is: given all methods are applicable, which one is the most specific? Unfortunately, since the three methodA overloads accept unrelated interfaces, the answer is that no method is most specific, hence the ambiguity error.
        Hide
        pardesha Pardeep Sharma added a comment -
        Comment from the original submitter:
        "I think that maybe inference algorithm in java 1.8 should be improved. It's more natural that in this case inference result would be as in 1.7.

        Of course result type of methodB could be Throwable that implement Iterable or Iterator interface (or any other interface), but I don't see sense to analyze such corner cases. Inference algorithm should
        make things easier and explicit casting is worse situation than was before."
        Show
        pardesha Pardeep Sharma added a comment - Comment from the original submitter: "I think that maybe inference algorithm in java 1.8 should be improved. It's more natural that in this case inference result would be as in 1.7. Of course result type of methodB could be Throwable that implement Iterable or Iterator interface (or any other interface), but I don't see sense to analyze such corner cases. Inference algorithm should make things easier and explicit casting is worse situation than was before."

          People

          • Assignee:
            Unassigned
            Reporter:
            webbuggrp Webbug Group
          • Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: