Skip to content

Commit

Permalink
VerifyError in switch expression on double
Browse files Browse the repository at this point in the history
  • Loading branch information
srikanth-sankaran committed Apr 25, 2024
1 parent a7a65eb commit fcb3de9
Show file tree
Hide file tree
Showing 3 changed files with 351 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,7 @@ public class SwitchStatement extends Expression {
public final static int NullCase = ASTNode.Bit2;
public final static int TotalPattern = ASTNode.Bit3;
public final static int Exhaustive = ASTNode.Bit4;
public final static int Enhanced = ASTNode.Bit5;
public final static int QualifiedEnum = ASTNode.Bit6;
public final static int QualifiedEnum = ASTNode.Bit5;

// for switch on strings
private static final char[] SecretStringVariableName = " switchDispatchString".toCharArray(); //$NON-NLS-1$
Expand Down Expand Up @@ -1113,7 +1112,7 @@ public void resolve(BlockScope upperScope) {
isStringSwitch = true;
break checkType;
}
if (!JavaFeature.PATTERN_MATCHING_IN_SWITCH.isSupported(compilerOptions)) {
if (!JavaFeature.PATTERN_MATCHING_IN_SWITCH.isSupported(compilerOptions) || (expressionType.isBaseType() && expressionType.id != T_null && expressionType.id != T_void)) {
upperScope.problemReporter().incorrectSwitchType(this.expression, expressionType);
expressionType = null; // fault-tolerance: ignore type mismatch from constants from hereon
} else {
Expand Down Expand Up @@ -1308,9 +1307,7 @@ private boolean isCaseStmtNullOnly(CaseStatement caseStmt) {
private boolean isExhaustive() {
return (this.switchBits & SwitchStatement.Exhaustive) != 0;
}
public boolean isEnhanced() {
return (this.switchBits & SwitchStatement.Enhanced) != 0;
}

private boolean checkAndSetEnhanced(BlockScope upperScope, TypeBinding expressionType) {
if (JavaFeature.PATTERN_MATCHING_IN_SWITCH.isSupported(upperScope.compilerOptions())
&& expressionType != null && !(this instanceof SwitchExpression )) {
Expand All @@ -1321,6 +1318,11 @@ private boolean checkAndSetEnhanced(BlockScope upperScope, TypeBinding expressio
case TypeIds.T_byte:
case TypeIds.T_short:
case TypeIds.T_int:
case TypeIds.T_long:
case TypeIds.T_double:
case TypeIds.T_boolean:
case TypeIds.T_float:
case TypeIds.T_void:
case TypeIds.T_JavaLangCharacter:
case TypeIds.T_JavaLangByte:
case TypeIds.T_JavaLangShort:
Expand All @@ -1329,7 +1331,6 @@ private boolean checkAndSetEnhanced(BlockScope upperScope, TypeBinding expressio
acceptableType = false;
}
if (acceptableType || this.containsPatterns || this.containsNull) {
this.switchBits |= SwitchStatement.Enhanced;
return true;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7467,4 +7467,341 @@ public static void main(String[] args) {
},
"42");
}

// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/2382
// VerifyError in switch expression on double
public void testIssue2382() {
if (this.complianceLevel < ClassFileConstants.JDK14)
return;
this.runNegativeTest(
new String[] {
"X.java",
"""
public class X {
public static void main(String[] args) {
double d = 3;
double r = switch (d) {
case 1.0 -> 0.2;
case 2.0 -> 0.5;
case 8.0 -> 2;
case 9.0 -> 3;
default -> 3;
};
System.out.println(r);
}
X() {}
}
"""
},
"----------\n"
+ "1. ERROR in X.java (at line 6)\n"
+ " double r = switch (d) {\n"
+ " ^\n"
+ "Cannot switch on a value of type double. Only convertible int values, strings or enum variables are permitted\n"
+ "----------\n");
}
// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/2382
// VerifyError in switch expression on double
public void testIssue2382_2() {
if (this.complianceLevel < ClassFileConstants.JDK14)
return;
this.runNegativeTest(
new String[] {
"X.java",
"""
public class X {
public static void main(String[] args) {
long d = 3;
double r = switch (d) {
case 1.0 -> 0.2;
case 2.0 -> 0.5;
case 8.0 -> 2;
case 9.0 -> 3;
default -> 3;
};
System.out.println(r);
}
X() {}
}
"""
},
"----------\n"
+ "1. ERROR in X.java (at line 6)\n"
+ " double r = switch (d) {\n"
+ " ^\n"
+ "Cannot switch on a value of type long. Only convertible int values, strings or enum variables are permitted\n"
+ "----------\n");
}
// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/2382
// VerifyError in switch expression on double
public void testIssue2382_3() {
if (this.complianceLevel < ClassFileConstants.JDK14)
return;
this.runNegativeTest(
new String[] {
"X.java",
"""
public class X {
public static void main(String[] args) {
float d = 3;
double r = switch (d) {
case 1.0 -> 0.2;
case 2.0 -> 0.5;
case 8.0 -> 2;
case 9.0 -> 3;
default -> 3;
};
System.out.println(r);
}
X() {}
}
"""
},
"----------\n"
+ "1. ERROR in X.java (at line 6)\n"
+ " double r = switch (d) {\n"
+ " ^\n"
+ "Cannot switch on a value of type float. Only convertible int values, strings or enum variables are permitted\n"
+ "----------\n");
}
// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/2382
// VerifyError in switch expression on double
public void testIssue2382_4() {
if (this.complianceLevel < ClassFileConstants.JDK14)
return;
this.runNegativeTest(
new String[] {
"X.java",
"""
public class X {
public static void main(String[] args) {
boolean d = true;
double r = switch (d) {
default -> 3;
};
System.out.println(r);
}
X() {}
}
"""
},
"----------\n"
+ "1. ERROR in X.java (at line 6)\n"
+ " double r = switch (d) {\n"
+ " ^\n"
+ "Cannot switch on a value of type boolean. Only convertible int values, strings or enum variables are permitted\n"
+ "----------\n");
}
// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/2382
// VerifyError in switch expression on double
public void testIssue2382_5() {
if (this.complianceLevel < ClassFileConstants.JDK14)
return;
this.runNegativeTest(
new String[] {
"X.java",
"""
public class X {
public static void main(String[] args) {
double d = 3;
switch (d) {
case 1.0 -> System.out.println(d);
};
}
X() {}
}
"""
},
"----------\n"
+ "1. ERROR in X.java (at line 6)\n"
+ " switch (d) {\n"
+ " ^\n"
+ "Cannot switch on a value of type double. Only convertible int values, strings or enum variables are permitted\n"
+ "----------\n");
}
// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/2382
// VerifyError in switch expression on double
public void testIssue2382_6() {
if (this.complianceLevel < ClassFileConstants.JDK14)
return;
this.runNegativeTest(
new String[] {
"X.java",
"""
public class X {
static void foo() {}
public static void main(String[] args) {
double d = 3;
switch (foo()) {
case 1.0 -> System.out.println(d);
};
}
X() {}
}
"""
},
this.complianceLevel < ClassFileConstants.JDK21 ?
"----------\n"
+ "1. ERROR in X.java (at line 7)\n"
+ " switch (foo()) {\n"
+ " ^^^^^\n"
+ "Cannot switch on a value of type void. Only convertible int values, strings or enum variables are permitted\n"
+ "----------\n" :
"----------\n"
+ "1. ERROR in X.java (at line 8)\n"
+ " case 1.0 -> System.out.println(d);\n"
+ " ^^^\n"
+ "Type mismatch: cannot convert from double to void\n"
+ "----------\n");
}
// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/2382
// VerifyError in switch expression on double
public void testIssue2382_7() {
if (this.complianceLevel < ClassFileConstants.JDK14)
return;
this.runNegativeTest(
new String[] {
"X.java",
"""
public class X {
static void foo() {}
public static void main(String[] args) {
double d = 3;
switch (null) {
case null -> System.out.println(d);
};
}
X() {}
}
"""
},
this.complianceLevel < ClassFileConstants.JDK21 ?
"----------\n"
+ "1. ERROR in X.java (at line 7)\n"
+ " switch (null) {\n"
+ " ^^^^\n"
+ "Cannot switch on a value of type null. Only convertible int values, strings or enum variables are permitted\n"
+ "----------\n"
+ "2. ERROR in X.java (at line 8)\n"
+ " case null -> System.out.println(d);\n"
+ " ^^^^\n"
+ "The Java feature 'Pattern Matching in Switch' is only available with source level 21 and above\n"
+ "----------\n" :
"----------\n"
+ "1. ERROR in X.java (at line 7)\n"
+ " switch (null) {\n"
+ " ^^^^\n"
+ "An enhanced switch statement should be exhaustive; a default label expected\n"
+ "----------\n");
}
// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/2382
// VerifyError in switch expression on double
public void testIssue2382_8() {
if (this.complianceLevel < ClassFileConstants.JDK21)
return;
this.runConformTest(
new String[] {
"X.java",
"""
public class X {
static void foo() {}
public static void main(String[] args) {
double d = 3;
switch (null) {
case null -> System.out.println(d);
default -> System.out.println("Default");
};
}
X() {}
}
"""
},
"3.0");
}
// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/2382
// VerifyError in switch expression on double
public void testIssue2382_9() {
if (this.complianceLevel < ClassFileConstants.JDK14)
return;
this.runNegativeTest(
new String[] {
"X.java",
"""
public class X {
static void foo() {}
public static void main(String[] args) {
double d = 3;
switch (foo()) {
case null -> System.out.println(d);
};
}
X() {}
}
"""
},
this.complianceLevel < ClassFileConstants.JDK21 ?
"----------\n"
+ "1. ERROR in X.java (at line 7)\n"
+ " switch (foo()) {\n"
+ " ^^^^^\n"
+ "Cannot switch on a value of type void. Only convertible int values, strings or enum variables are permitted\n"
+ "----------\n"
+ "2. ERROR in X.java (at line 8)\n"
+ " case null -> System.out.println(d);\n"
+ " ^^^^\n"
+ "The Java feature 'Pattern Matching in Switch' is only available with source level 21 and above\n"
+ "----------\n" :
"----------\n" +
"1. ERROR in X.java (at line 7)\n" +
" switch (foo()) {\n" +
" ^^^^^\n" +
"An enhanced switch statement should be exhaustive; a default label expected\n" +
"----------\n" +
"2. ERROR in X.java (at line 8)\n" +
" case null -> System.out.println(d);\n" +
" ^^^^\n" +
"Type mismatch: cannot convert from null to void\n" +
"----------\n");
}
}
Loading

0 comments on commit fcb3de9

Please sign in to comment.