Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1029,16 +1029,12 @@ void gatherLabelExpression(LabelExpression labelExpression) {
public void resolve(BlockScope upperScope) {
try {
TypeBinding expressionType = this.expression.resolveType(upperScope);
if (expressionType != null && !expressionType.isValidBinding())
expressionType = null; // fault-tolerance: ignore further type mismatch from label expressions
CompilerOptions compilerOptions = upperScope.compilerOptions();
if (expressionType != null) {
this.expression.computeConversion(upperScope, expressionType, expressionType);
checkType: {

if (!expressionType.isValidBinding()) {
expressionType = null; // fault-tolerance: ignore type mismatch from constants from hereon
break checkType;
}

if (expressionType.isBaseType()) {
if (JavaFeature.PRIMITIVES_IN_PATTERNS.isSupported(compilerOptions))
this.isPrimitiveSwitch = true;
Expand All @@ -1047,28 +1043,25 @@ public void resolve(BlockScope upperScope) {
if (expressionType.isCompatibleWith(TypeBinding.INT))
break checkType;
}

if (expressionType.id == TypeIds.T_JavaLangString || expressionType.isEnum() || upperScope.isBoxingCompatibleWith(expressionType, TypeBinding.INT))
break checkType;

if (!JavaFeature.PATTERN_MATCHING_IN_SWITCH.isSupported(compilerOptions) || (expressionType.isBaseType() && expressionType.id != T_null && expressionType.id != T_void)) {
if (JavaFeature.PATTERN_MATCHING_IN_SWITCH.isSupported(compilerOptions) && (!expressionType.isBaseType() || expressionType.id == T_null || expressionType.id == T_void)) {
this.isNonTraditional = true;
} else {
if (!this.isPrimitiveSwitch) { // when isPrimitiveSwitch is set it is approved above
upperScope.problemReporter().incorrectSwitchType(this.expression, expressionType);
expressionType = null; // fault-tolerance: ignore type mismatch from constants from hereon
}
} else {
this.isNonTraditional = true;
}
}
}

this.scope = new BlockScope(upperScope);
if (expressionType != null)
reserveSecretVariablesSlots();
reserveSecretVariablesSlot();
else
this.switchBits |= InvalidSelector;


if (this.statements != null) {
preprocess(); // make a pass over the switch block and allocate vectors.
LocalVariableBinding[] patternVariables = NO_VARIABLES;
Expand Down Expand Up @@ -1096,18 +1089,10 @@ public void resolve(BlockScope upperScope) {

if (expressionType != null) {
if (!expressionType.isBaseType() && upperScope.isBoxingCompatibleWith(expressionType, TypeBinding.INT)) {
if (this.containsPatterns || this.containsNull) {
if (!JavaFeature.PATTERN_MATCHING_IN_SWITCH.isSupported(compilerOptions) || (expressionType.isBaseType() && expressionType.id != T_null && expressionType.id != T_void)) {
if (!this.isPrimitiveSwitch) { // when isPrimitiveSwitch is set it is approved above
upperScope.problemReporter().incorrectSwitchType(this.expression, expressionType);
this.switchBits |= InvalidSelector;
expressionType = null; // fault-tolerance: ignore type mismatch from constants from hereon
}
}
} else
if (!this.containsPatterns && !this.containsNull)
this.expression.computeConversion(upperScope, TypeBinding.INT, expressionType);
}
releaseUnusedSecretVariables();
releaseUnusedSecretVariable();
complainIfNotExhaustiveSwitch(upperScope, expressionType, compilerOptions);
}

Expand Down Expand Up @@ -1148,12 +1133,10 @@ private void complainIfNotExhaustiveSwitch(BlockScope upperScope, TypeBinding se
}

if (this.defaultCase == null) {
if (this instanceof SwitchExpression // complained about elsewhere, don't also bark here
|| compilerOptions.getSeverity(CompilerOptions.MissingDefaultCase) == ProblemSeverities.Ignore) {
if (this instanceof SwitchExpression || compilerOptions.getSeverity(CompilerOptions.MissingDefaultCase) == ProblemSeverities.Ignore) // complained about elsewhere, don't also bark here
upperScope.methodScope().hasMissingSwitchDefault = true;
} else {
else
upperScope.problemReporter().missingDefaultCase(this, true, selectorType);
}
}
return;
}
Expand Down Expand Up @@ -1311,21 +1294,21 @@ private boolean needPatternDispatchCopy() {
return !(eType.isPrimitiveOrBoxedPrimitiveType() || eType.isEnum() || eType.id == TypeIds.T_JavaLangString); // classic selectors
}

private void reserveSecretVariablesSlots() { // may be released later if unused.
private void reserveSecretVariablesSlot() { // may be released later if unused.
this.selector = new LocalVariableBinding(SecretSelectorVariableName, this.scope.getJavaLangObject(), ClassFileConstants.AccDefault, false);
this.scope.addLocalVariable(this.selector);
this.selector.setConstant(Constant.NotAConstant);
}

private void releaseUnusedSecretVariables() {
private void releaseUnusedSecretVariable() {
if (this.selector != null) {
if (this.expression.resolvedType.id == T_JavaLangString && !this.isNonTraditional) {
this.selector.useFlag = LocalVariableBinding.USED;
this.selector.type = this.scope.getJavaLangString();
} else if (needPatternDispatchCopy()) {
this.selector.useFlag = LocalVariableBinding.USED;
this.selector.type = this.expression.resolvedType;
}
} // else gets released by virtue of not being tagged USED.
}
}
protected void reportMissingEnumConstantCase(BlockScope upperScope, FieldBinding enumConstant) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3624,6 +3624,111 @@ String unreachableCode(String arg) {
"----------\n");
}

// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/3379
// [Enhanced Switch] Wrong error message: Cannot switch on a value of type Integer... at levels that don't support enhanced switch
public void testIssue3379() throws Exception {
if (this.complianceLevel < ClassFileConstants.JDK14)
return; // uses switch rules.
String [] sources = new String[] {
"X.java",
"""
public class X {
public static void main(String[] args) {
Integer i = 42;
switch (i) {
case null -> System.out.println("Null");
default -> System.out.println("Default: " + i);
}
}
}
""",
};

if (this.complianceLevel < ClassFileConstants.JDK21) {
this.runNegativeTest(sources,
"----------\n" +
"1. ERROR in X.java (at line 5)\n" +
" case null -> System.out.println(\"Null\");\n" +
" ^^^^\n" +
"The Java feature 'Pattern Matching in Switch' is only available with source level 21 and above\n" +
"----------\n");
} else {
this.runConformTest(sources, "Default: 42");
}
}

// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/3379
// [Enhanced Switch] Wrong error message: Cannot switch on a value of type Integer... at levels that don't support enhanced switch
public void testIssue3379_2() throws Exception {
if (this.complianceLevel < ClassFileConstants.JDK14)
return; // uses switch rules.
String [] sources = new String[] {
"X.java",
"""
public class X {
public static void main(String[] args) {
Long i = 42l;
switch (i) {
case null -> System.out.println("Null");
default -> System.out.println("Default: " + i);
}
}
}
""",
};

if (this.complianceLevel < ClassFileConstants.JDK21) {
this.runNegativeTest(sources,
"----------\n" +
"1. ERROR in X.java (at line 4)\n" +
" switch (i) {\n" +
" ^\n" +
"Cannot switch on a value of type Long. Only convertible int values, strings or enum variables are permitted\n" +
"----------\n" +
"2. ERROR in X.java (at line 5)\n" +
" case null -> System.out.println(\"Null\");\n" +
" ^^^^\n" +
"The Java feature 'Pattern Matching in Switch' is only available with source level 21 and above\n" +
"----------\n");
} else {
this.runConformTest(sources, "Default: 42");
}
}

// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/3379
// [Enhanced Switch] Wrong error message: Cannot switch on a value of type Integer... at levels that don't support enhanced switch
public void testIssue3379_3() throws Exception {
if (this.complianceLevel < ClassFileConstants.JDK14)
return; // uses switch rules.

String [] sources = new String[] {
"X.java",
"""
public class X {
public static void main(String[] args) {
Short i = 42;
switch (i) {
case null -> System.out.println("Null");
default -> System.out.println("Default: " + i);
}
}
}
""",
};

if (this.complianceLevel < ClassFileConstants.JDK21) {
this.runNegativeTest(sources,
"----------\n" +
"1. ERROR in X.java (at line 5)\n" +
" case null -> System.out.println(\"Null\");\n" +
" ^^^^\n" +
"The Java feature 'Pattern Matching in Switch' is only available with source level 21 and above\n" +
"----------\n");
} else {
this.runConformTest(sources, "Default: 42");
}
}

public static Class testClass() {
return SwitchTest.class;
}
Expand Down
Loading