Skip to content

Commit

Permalink
Fix for problem reported by Jay introduced by the fix for
Browse files Browse the repository at this point in the history
  • Loading branch information
srikanth-sankaran committed Mar 5, 2024
1 parent 78955db commit 7c77997
Show file tree
Hide file tree
Showing 5 changed files with 208 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ public void generateCode(BlockScope currentScope, CodeStream codeStream, BranchL
cst == Constant.NotAConstant);
}

@Override
public boolean matchFailurePossible() {
return !isAlwaysTrue() || this.primaryPattern.matchFailurePossible();
}

@Override
public boolean isAlwaysTrue() {
Constant cst = this.condition.optimizedBooleanConstant();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ public boolean coversType(TypeBinding type) {
return (type.isSubtypeOf(this.resolvedType, false));
}

// Given a non-null instance of appropriate type, would the pattern always match ?
public boolean matchFailurePossible() {
return false;
}

public boolean isAlwaysTrue() {
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,14 @@ private ReferenceBinding inferRecordParameterization(BlockScope scope, Reference
}
}

@Override
public boolean matchFailurePossible() {
return this.patterns.length != 0; // if no deconstruction is involved, no failure is possible.
}

@Override
public boolean isAlwaysTrue() {
return this.patterns.length == 0;
return false;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -980,7 +980,7 @@ private void generateCodePatternCaseEpilogue(CodeStream codeStream, int caseInde
Pattern pattern = (Pattern) caseStatement.constantExpressions[caseStatement.patternIndex];
if (caseStatement.falseLabel != null)
caseStatement.falseLabel.place();
if (!pattern.isAlwaysTrue()) {
if (pattern.matchFailurePossible()) {
/* We are generating a "thunk"/"trampoline" of sorts now, that flow analysis has no clue about.
We need to manage the live variables manually. Pattern bindings are not definitely
assigned here as we are in the else region.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7275,6 +7275,7 @@ public class X {
public static void main(String[] args) {
Object o = null;
foo(new R());
foo(new S());
}
@SuppressWarnings("preview")
public static void foo(Object o) {
Expand All @@ -7294,32 +7295,214 @@ record S() {}
"""
},
"R Only\n" +
"Either S or an R\n" +
"Either S or an R");

String expectedOutput =
" // Method descriptor #22 (Ljava/lang/Object;)V\n" +
" // Stack: 2, Locals: 3\n" +
" public static void foo(java.lang.Object o);\n" +
" 0 aload_0 [o]\n" +
" 1 dup\n" +
" 2 invokestatic java.util.Objects.requireNonNull(java.lang.Object) : java.lang.Object [27]\n" +
" 2 invokestatic java.util.Objects.requireNonNull(java.lang.Object) : java.lang.Object [30]\n" +
" 5 pop\n" +
" 6 astore_1\n" +
" 7 iconst_0\n" +
" 8 istore_2\n" +
" 9 aload_1\n" +
" 10 iload_2\n" +
" 11 invokedynamic 0 typeSwitch(java.lang.Object, int) : int [33]\n" +
" 11 invokedynamic 0 typeSwitch(java.lang.Object, int) : int [36]\n" +
" 16 tableswitch default: 56\n" +
" case 0: 40\n" +
" case 1: 48\n" +
" 40 getstatic java.lang.System.out : java.io.PrintStream [37]\n" +
" 43 ldc <String \"R Only\"> [43]\n" +
" 45 invokevirtual java.io.PrintStream.println(java.lang.String) : void [45]\n" +
" 48 getstatic java.lang.System.out : java.io.PrintStream [37]\n" +
" 51 ldc <String \"Either S or an R\"> [51]\n" +
" 53 invokevirtual java.io.PrintStream.println(java.lang.String) : void [45]\n" +
" 40 getstatic java.lang.System.out : java.io.PrintStream [40]\n" +
" 43 ldc <String \"R Only\"> [46]\n" +
" 45 invokevirtual java.io.PrintStream.println(java.lang.String) : void [48]\n" +
" 48 getstatic java.lang.System.out : java.io.PrintStream [40]\n" +
" 51 ldc <String \"Either S or an R\"> [54]\n" +
" 53 invokevirtual java.io.PrintStream.println(java.lang.String) : void [48]\n" +
" 56 return\n";

SwitchPatternTest.verifyClassFile(expectedOutput, "X.class", ClassFileBytesDisassembler.SYSTEM);
}
// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/773
// [20][pattern switch] unnecessary code generated
public void testIssue773_2() throws Exception {
runConformTest(
new String[] {
"X.java",
"""
interface I {}
record R (I i, I j) {}
class A implements I {}
class B implements I {}
public class X {
static int swtch(Object o) {
return switch (o) {
case R(A a1, A a2) -> 1;
case R(B b1, B b2) -> 2;
case Object obj -> 3;
};
}
public static void main(String argv[]) {
Object o = new R(new A(), new A());
System.out.print(swtch(o));
o = new R(new B(), new B());
System.out.print(swtch(o));
o = new R(new I() {}, new I() {});
System.out.println(swtch(o));
}
}
"""
},
"123");
}
// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/773
// [20][pattern switch] unnecessary code generated
public void testIssue773_3() throws Exception {
runConformTest(
new String[] {
"X.java",
"""
interface I {}
record R (I i, I j) {}
class A implements I {}
class B implements I {}
public class X {
static int swtch(Object o) {
return switch (o) {
case R(A a1, A a2) when o == null -> 1;
case R(B b1, B b2) when o == null -> 2;
case Object obj -> 3;
};
}
public static void main(String argv[]) {
Object o = new R(new A(), new A());
System.out.print(swtch(o));
o = new R(new B(), new B());
System.out.print(swtch(o));
o = new R(new I() {}, new I() {});
System.out.println(swtch(o));
}
}
"""
},
"333");
}
// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/773
// [20][pattern switch] unnecessary code generated
public void testIssue773_4() throws Exception {
runConformTest(
new String[] {
"X.java",
"""
interface I {}
record R (I i, I j) {}
class A implements I {}
class B implements I {}
public class X {
static int swtch(Object o) {
return switch (o) {
case R(A a1, A a2) when o != null -> 1;
case R(B b1, B b2) when o != null -> 2;
case Object obj -> 3;
};
}
public static void main(String argv[]) {
Object o = new R(new A(), new A());
System.out.print(swtch(o));
o = new R(new B(), new B());
System.out.print(swtch(o));
o = new R(new I() {}, new I() {});
System.out.println(swtch(o));
}
}
"""
},
"123");
}
// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/773
// [20][pattern switch] unnecessary code generated
public void testIssue773_5() throws Exception {
runConformTest(
new String[] {
"X.java",
"""
interface I {}
record R (I i, I j) {}
class A implements I {}
class B implements I {}
public class X {
static int swtch(Object o) {
return switch (o) {
case R(A a1, A a2) when o != null -> 1;
case R(B b1, B b2) when o == null -> 2;
case Object obj -> 3;
};
}
public static void main(String argv[]) {
Object o = new R(new A(), new A());
System.out.print(swtch(o));
o = new R(new B(), new B());
System.out.print(swtch(o));
o = new R(new I() {}, new I() {});
System.out.println(swtch(o));
}
}
"""
},
"133");
}
// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/773
// [20][pattern switch] unnecessary code generated
public void testIssue773_6() throws Exception {
runConformTest(
new String[] {
"X.java",
"""
public class X {
record CoffeeBreak() {}
public int recharge(CoffeeBreak c) {
int energyLevel = 0;
switch (c) {
case CoffeeBreak( ) -> {
energyLevel = 3;
}
default->{
energyLevel = -3;
}
}
return energyLevel;
}
public static void main(String argv[]) {
X t = new X();
CoffeeBreak c = new CoffeeBreak();
if (t.recharge(c) == 3) {
System.out.println("OK!");
} else {
System.out.println("!OK!");
}
}
}
"""
},
"OK!");
}

}

0 comments on commit 7c77997

Please sign in to comment.