Skip to content

Commit

Permalink
[Switch Expression][Sealed types] Switching on sealed interface insta…
Browse files Browse the repository at this point in the history
…nce compiles even when the switch expression does not cover all possible input values (#2621)

* Fixes #2503
  • Loading branch information
srikanth-sankaran committed Jun 24, 2024
1 parent 2feaa74 commit 61ab97e
Show file tree
Hide file tree
Showing 5 changed files with 314 additions and 247 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,8 @@

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.function.IntPredicate;
Expand Down Expand Up @@ -1431,7 +1429,6 @@ private boolean checkAndFlagDefaultRecord(BlockScope skope, CompilerOptions comp
return false;
}
private boolean isExhaustiveWithCaseTypes(List<ReferenceBinding> allAllowedTypes, List<TypeBinding> listedTypes) {
// first KISS (Keep It Simple Stupid)
int pendingTypes = allAllowedTypes.size();
for (ReferenceBinding pt : allAllowedTypes) {
/* Per JLS 14.11.1.1: A type T that names an abstract sealed class or sealed interface is covered
Expand All @@ -1450,63 +1447,7 @@ private boolean isExhaustiveWithCaseTypes(List<ReferenceBinding> allAllowedTypes
}
}
}
if (pendingTypes == 0)
return true;
// else - #KICKME (Keep It Complicated Keep Me Employed)"
List<TypeBinding> coveredTypes = new ArrayList<>(listedTypes);
List<ReferenceBinding> remainingTypes = new ArrayList<>(allAllowedTypes);
remainingTypes.removeAll(coveredTypes);

Map<TypeBinding, List<TypeBinding>> impliedTypes = new HashMap<>();

for (ReferenceBinding type : remainingTypes) {
impliedTypes.put(type, new ArrayList<>());
List<ReferenceBinding> typesToAdd = new ArrayList<>();
for (ReferenceBinding impliedType : allAllowedTypes) {
if (impliedType.equals(type)) continue;
if (type.isClass()) {
if (impliedType.isAbstract() && type.superclass().equals(impliedType)) {
typesToAdd.add(impliedType);
}
if (Arrays.asList(type.superInterfaces()).contains(impliedType))
typesToAdd.add(impliedType);
} else if (type.isInterface()) {
if (Arrays.asList(impliedType.superInterfaces()).contains(type))
typesToAdd.add(impliedType);
}
}
if (!typesToAdd.isEmpty()) {
impliedTypes.get(type).addAll(typesToAdd);
}
}
boolean delta = true;
while (delta) {
delta = false;
List<ReferenceBinding> typesToAdd = new ArrayList<>();
for (ReferenceBinding type : remainingTypes) {
boolean add = false;
if (type.isClass()) {
for (TypeBinding tb : impliedTypes.get(type)) {
if (coveredTypes.contains(tb)) {
add = true;
break;
}
}
} else if (type.isInterface()) {
add = coveredTypes.containsAll(impliedTypes.get(type));
}
if (add) {
typesToAdd.add(type);
}
}
if (!typesToAdd.isEmpty()) {
remainingTypes.removeAll(typesToAdd);
coveredTypes.addAll(typesToAdd);
typesToAdd.clear();
delta = true;
}
}
return remainingTypes.isEmpty();
return pendingTypes == 0;
}
private boolean needPatternDispatchCopy() {
if (this.containsPatterns || (this.switchBits & QualifiedEnum) != 0)
Expand Down

This file was deleted.

Loading

0 comments on commit 61ab97e

Please sign in to comment.