Skip to content

Commit

Permalink
Wrong diagnostic about switch expression being inexhaustive (#3041)
Browse files Browse the repository at this point in the history
  • Loading branch information
srikanth-sankaran authored Oct 2, 2024
1 parent b88a5b3 commit 3357118
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1410,10 +1410,7 @@ private boolean checkAndFlagDefaultSealed(BlockScope skope, CompilerOptions comp
ReferenceBinding ref = (ReferenceBinding) this.expression.resolvedType;
if (!(ref.isClass() || ref.isInterface() || ref.isTypeVariable() || ref.isIntersectionType()))
return false;
if (ref instanceof TypeVariableBinding) {
TypeVariableBinding tvb = (TypeVariableBinding) ref;
ref = tvb.firstBound instanceof ReferenceBinding ? (ReferenceBinding) tvb.firstBound : ref;
}

if (ref.isRecord()) {
boolean isRecordPattern = false;
for (Pattern pattern : this.caseLabelElements) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2552,7 +2552,7 @@ public List<ReferenceBinding> getAllEnumerableReferenceTypes() {
return Collections.emptyList();

Set<ReferenceBinding> permSet = new HashSet<>(Arrays.asList(permittedTypes()));
if (isClass() && (!isAbstract()))
if (isClass() && canBeInstantiated())
permSet.add(this);
Set<ReferenceBinding> oldSet = new HashSet<>(permSet);
do {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,18 @@
package org.eclipse.jdt.internal.compiler.lookup;

import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.NullAnnotationMatching;
import org.eclipse.jdt.internal.compiler.ast.NullAnnotationMatching.CheckMode;
import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.ast.Wildcard;
import org.eclipse.jdt.internal.compiler.ast.NullAnnotationMatching.CheckMode;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants.BoundCheckStatus;
Expand Down Expand Up @@ -154,7 +155,7 @@ private TypeConstants.BoundCheckStatus internalBoundCheck(Substitution substitut
return BoundCheckStatus.OK;

BoundCheckStatus nullStatus = BoundCheckStatus.OK;
boolean checkNullAnnotations = scope.environment().usesNullTypeAnnotations() && (location == null || (location.bits & ASTNode.InsideJavadoc) == 0);
boolean checkNullAnnotations = scope != null && scope.environment().usesNullTypeAnnotations() && (location == null || (location.bits & ASTNode.InsideJavadoc) == 0);

if (argumentType.kind() == Binding.WILDCARD_TYPE) {
WildcardBinding wildcard = (WildcardBinding) argumentType;
Expand Down Expand Up @@ -744,6 +745,29 @@ public boolean isSealed() {
return false;
}


@Override
public ReferenceBinding[] permittedTypes() {
Set<ReferenceBinding> permittedTypes = new HashSet<>();
if (this.superclass != null && this.superclass.isSealed()) {
for (ReferenceBinding pt : this.superclass.permittedTypes()) {
if (boundCheck(null, pt, null, null) != BoundCheckStatus.MISMATCH)
permittedTypes.add(pt);
}
}
if (this.superInterfaces != null && this.superInterfaces != Binding.NO_SUPERINTERFACES) {
for (int i = 0, length = this.superInterfaces.length; i < length; i++) {
if (this.superInterfaces[i].isSealed()) {
for (ReferenceBinding pt : this.superInterfaces[i].permittedTypes()) {
if (boundCheck(null, pt, null, null) != BoundCheckStatus.MISMATCH)
permittedTypes.add(pt);
}
}
}
}
return permittedTypes.toArray(new ReferenceBinding[0]);
}

// /**
// * Returns the original type variable for a given variable.
// * Only different from receiver for type variables of generic methods of parameterized types
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8747,4 +8747,74 @@ public static void main(String[] args) {
},
"4200");
}

// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/2719
// [Switch expression + Sealed Types] Suspect diagnostic about switch expression being inexhaustive
public void testIssue2719() {
runConformTest(
new String[] {
"X.java",
"""
public interface X {
static <T extends Object & AbstractSealedInterface> Integer get(T object) {
return switch (object) {
case ClassC ignored -> 4200;
};
}
public abstract sealed interface AbstractSealedInterface permits InterfaceB {
}
public sealed interface InterfaceB extends AbstractSealedInterface permits ClassC {
}
final class ClassC implements InterfaceB {}
public static void main(String[] args) {
System.out.println(get(new ClassC()));
}
}
"""
},
"4200");
}

// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/2719
// [Switch expression + Sealed Types] Suspect diagnostic about switch expression being inexhaustive
public void testIssue2719_2() {
runConformTest(
new String[] {
"X.java",
"""
public interface X {
static <T extends Object & I1 & I2> Integer get(T object) {
return switch (object) {
case AB ignored -> 42;
case BA ignored -> 420;
};
}
public abstract sealed interface I1 permits A, AB, BA {
}
public abstract sealed interface I2 permits B, AB, BA {
}
final class A implements I1 {}
final class B implements I2 {}
final class AB implements I1, I2 {}
final class BA implements I1, I2 {}
public static void main(String[] args) {
System.out.println(get(new AB()));
System.out.println(get(new BA()));
}
}
"""
},
"42\n420");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public static Class[] getAllTestClasses() {
}

public static Test suite() {
TestSuite ts = new TestSuite(RunVariousSwitchTests.class.getName());
TestSuite ts = new TestSuite(RunVariousSealedTypeTests.class.getName());

Class[] testClasses = getAllTestClasses();
addTestsToSuite(ts, testClasses);
Expand Down

0 comments on commit 3357118

Please sign in to comment.