Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Record patterns exhaustiveness check problems #455

Closed
kriegaex opened this issue Oct 7, 2022 · 4 comments
Closed

Record patterns exhaustiveness check problems #455

kriegaex opened this issue Oct 7, 2022 · 4 comments
Labels
bug Something isn't working compiler Eclipse Java Compiler (ecj) related issues

Comments

@kriegaex
Copy link
Contributor

kriegaex commented Oct 7, 2022

This might be related to #450 (not sure). The following code compiles fine with Javac:

public class RecordPatternsJava19ExhaustivenessOK {
  static Pair<A> p1 = new Pair<>(new A(), new B());
  static Pair<I> p2 = new Pair<>(new C(), new D());

  public static void main(String[] args) {
    exhaustiveSwitch();
  }

  static void exhaustiveSwitch() {
    switch (p2) {
      case Pair<I>(I i,C c) -> System.out.println("x");
      case Pair<I>(I i,D d) -> System.out.println("y");
    }

    switch (p2) {
      case Pair<I>(C c,I i) -> System.out.println("a");
      case Pair<I>(D d,C c) -> System.out.println("b");
      case Pair<I>(D d1,D d2) -> System.out.println("c");
    }
  }

  static class A { }
  static class B extends A { }
  sealed interface I permits C, D { }
  static final class C implements I { }
  static final class D implements I { }
  record Pair<T>(T x, T y) { }

}
$ javac -J-Duser.language=en --enable-preview --release 19 -nowarn -d target/classes src/main/java/RecordPatternsJava19ExhaustivenessOK.java
Note: src\main\java\RecordPatternsJava19ExhaustivenessOK.java uses preview features of Java SE 19.
Note: Recompile with -Xlint:preview for details.

$ java --enable-preview -cp target/classes RecordPatternsJava19ExhaustivenessOK
y
a

But with ECJ it says (from my AspectJ Maven build):

[ERROR] RecordPatternsJava19ExhaustivenessOK.java:10:0::0 An enhanced switch statement should be exhaustive; a default label expected
[ERROR] error at switch (p2) {
[ERROR]
[ERROR] RecordPatternsJava19ExhaustivenessOK.java:15:0::0 An enhanced switch statement should be exhaustive; a default label expected

The negative test:

public class RecordPatternsJava19ExhaustivenessError {
  static Pair<I> p2 = new Pair<>(new C(), new D());

  public static void main(String[] args) {
    exhaustiveSwitch();
  }

  static void exhaustiveSwitch() {
    switch (p2) {
      case Pair<I>(C fst, D snd) -> System.out.println("a");
      case Pair<I>(D fst, C snd) -> System.out.println("b");
      case Pair<I>(I fst, C snd) -> System.out.println("c");
    }
  }

  static class A { }
  static class B extends A { }
  sealed interface I permits C, D { }
  static final class C implements I { }
  static final class D implements I { }
  record Pair<T>(T x, T y) { }

}
$ javac -J-Duser.language=en --enable-preview --release 19 -nowarn -d target/classes src/main/java/RecordPatternsJava19ExhaustivenessError.java
src\main\java\RecordPatternsJava19ExhaustivenessError.java:9: error: the switch statement does not cover all possible input values
    switch (p2) {
    ^
Note: src\main\java\RecordPatternsJava19ExhaustivenessError.java uses preview features of Java SE 19.
Note: Recompile with -Xlint:preview for details.
1 error

ECJ says:

[ERROR] RecordPatternsJava19ExhaustivenessError.java:9:0::0 An enhanced switch statement should be exhaustive; a default label expected
[ERROR] error at switch (p2) {

I am not sure if ECJ gets it right by chance or accidentally. Better double-check, please. Ideally, the error message should be adjusted to be similar to Javac's, too.

@kriegaex
Copy link
Contributor Author

kriegaex commented Dec 2, 2022

I just re-tested with ECJ 4.26 RC2. The issue persists.

@kriegaex
Copy link
Contributor Author

kriegaex commented Dec 21, 2022

Here is an additional finding: When adding redundant default -> System.out.println("z"); clauses to both switch statements in the sample code in order to make it compile with ECJ, this will cause a runtime error when trying to execute the compiled code:

$ "/c/Program Files/Java/jdk-19/bin/java" -jar ecj-I20221220-1800.jar --release 19 --enable-preview -nowarn RecordPatternsJava19ExhaustivenessOK.java

$ "/c/Program Files/Java/jdk-19/bin/java" --enable-preview RecordPatternsJava19ExhaustivenessOK
Exception in thread "main" java.lang.NoSuchMethodError: 'RecordPatternsJava19ExhaustivenessOK$I RecordPatternsJava19ExhaustivenessOK$Pair.x()'
        at RecordPatternsJava19ExhaustivenessOK.exhaustiveSwitch(RecordPatternsJava19ExhaustivenessOK.java:11)
        at RecordPatternsJava19ExhaustivenessOK.main(RecordPatternsJava19ExhaustivenessOK.java:6)

As you can see, it compiles fine after adding the default clauses, but the byte code generated seems to be wrong. Please note that I tried the latest integration build I20221220-1800.

I also tried moving the inner classes and records out of the class, but it does not help either, only the class name in the error message is slightly different, of course:

$ "/c/Program Files/Java/jdk-19/bin/java" --enable-preview RecordPatternsJava19ExhaustivenessOK
Exception in thread "main" java.lang.NoSuchMethodError: 'I Pair.x()'
        at RecordPatternsJava19ExhaustivenessOK.exhaustiveSwitch(RecordPatternsJava19ExhaustivenessOK.java:11)
        at RecordPatternsJava19ExhaustivenessOK.main(RecordPatternsJava19ExhaustivenessOK.java:6)

So this issue is not just about faulty exhaustiveness checks but about byte code generation as well.

@kriegaex
Copy link
Contributor Author

kriegaex commented Mar 28, 2023

@jarthana, @mpalat: After the Java 20 merge into the main branch, the erroneous exhaustiveness check still persists and needs to be fixed. But at least the workaround of adding a redundant default clause, as described in the previous comment, now works and no longer generates faulty byte code.

@trancexpress trancexpress added bug Something isn't working compiler Eclipse Java Compiler (ecj) related issues labels Apr 3, 2023
@kriegaex
Copy link
Contributor Author

This seems to be fixed, closing issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working compiler Eclipse Java Compiler (ecj) related issues
Projects
None yet
Development

No branches or pull requests

2 participants