eclipse-jdt / eclipse.jdt.core

Eclipse Public License 2.0
168 stars 133 forks source link

[Switch Expressions] ECJ vs javac difference compiling method invocation involving switch expressions with poly type result expressions #3205

Open srikanth-sankaran opened 1 month ago

srikanth-sankaran commented 1 month ago

This program is by javac (X.java:18: error: reference to foo is ambiguous) while ECJ happily compiles it:

interface I {
    void foo();
}
interface J {
    void foo();
}

public class X {

    public static void foo(Object o, J j) {
        System.out.println("Object");
    }
    public static void foo(String s, I i) {
        System.out.println("String");
    }

 public static void main(String[] args) {
   foo("Hello", switch (args.length) {
        case 0 -> () -> System.out.println("empty arguments vector");
        default -> () -> System.out.println("non-empty arguments vector");
 });
 }
}
srikanth-sankaran commented 1 month ago

To check which compiler is right.

srikanth-sankaran commented 1 month ago

Here is a snippet showing interesting behavior:

interface I {
    void foo();
}

interface J {
    void foo();
}

public class X implements I, J {

    public void foo() {
    }

    static void doit() {}

    static void ii(I i) {

    }

    static void jj(J j) {

    }

    public static void foo(Object o, J j) {
        System.out.println("Object");
    }

    static <T> T gM() {
        return null;
    }

    public static void foo(String s, I i) {
        System.out.println("String");
    }

    public static void main(String[] args) {

        ii(gM());
        jj(gM());

        // Compiles with both ECJ and javac
        foo("Testing:", () -> {});

        // Compiles with both ECJ and javac
        foo("Testing:", args == null ? () -> {} : () -> {});

        // Compiles with both ECJ and javac
        foo("Testing:", X::doit);

        // Rejected by both ECJ and javac.
        foo("Testing:", gM());

        // Rejected by both ECJ and javac.
        foo("Testing:", new X());

        // Rejected by javac, accepted by ECJ.
        foo("Hello", switch (0) {
                        case 0 -> () -> {};
                        default -> () -> {};
        });
    }
}
srikanth-sankaran commented 1 month ago

@stephan-herrmann - one more case of difference, My initial analysis says defect is in javac,

stephan-herrmann commented 1 month ago

Nitpick: the original example would be easier to analyze, if different method names were used where it's possible without changing the semantics. When it says "foo is ambiguous", where should I look in a forest of lots of foos? (Just like bug reports relating to generics tend to have at least 49 type parameters called <T>).