eclipse-jdt / eclipse.jdt.core

Eclipse Public License 2.0
164 stars 130 forks source link

[switch][sealed types] ECJ fails to signal a completely dominated case arm #3035

Closed srikanth-sankaran closed 3 weeks ago

srikanth-sankaran commented 1 month ago

The following program is accepted by ECJ but rejected by javac with X.java:18: error: this case label is dominated by a preceding case label

abstract sealed class J<T1, T2> permits X.S, A {
}

final class A extends J<Integer, String> {
}

public class X {

    sealed class S<T, U> extends J<T, U> permits SS {
    }

    final class SS<T, U> extends S<U, T> {}

    int testExhaustive(J<Integer, String> ji) {
        return switch (ji) { // Exhaustive!
        case A a -> 42;
        case S<Integer, String> e -> 4200;
        case SS<String, Integer> e -> 420;
        };
    }

    public static void main(String[] args) {
        S<Integer, String> xs = null;
        System.out.println(new X().testExhaustive(new X().new S<Integer, String>()));
        J<Integer, String> ji = new X().new SS<String, Integer>();
    }
}

Indeed running the ECJ compiled program produces:

4200
4200

showing the domination.

srikanth-sankaran commented 3 weeks ago

14.30.3 Properties of Patterns

A pattern p is said to dominate another pattern q if every value that matches q also matches p, and is defined as follows: • A pattern p dominates a type pattern that declares a pattern variable of type T if p is unconditional for T. • A pattern p dominates a record pattern with type R if p is unconditional for R. • A record pattern with type R and component pattern list L dominates another record pattern with type S and component pattern list M if (i) R and S name the same record class, and (ii) every component pattern, if any, in L dominates the corresponding component pattern in M. • A pattern p dominates a match-all pattern with type T if p is unconditional for T.

A pattern p is said to be unconditional for a type T if it can be determined at compile time that every value of type T will match p, and so the run time, testing aspect of pattern matching could be elided. It is defined as follows: • A type pattern that declares a pattern variable of a reference type S is unconditional for a reference type T if the erasure of T is a subtype of the erasure of S. • A type pattern that declares a pattern variable of a primitive type P is unconditional for the type P. • A match-all pattern is unconditional for every type T. Note that no record pattern is unconditional because the null reference does not match any record pattern.