diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/Pattern.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/Pattern.java index 52cd3074810..be5c2c11427 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/Pattern.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/Pattern.java @@ -27,6 +27,7 @@ import org.eclipse.jdt.internal.compiler.lookup.Scope; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; +import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding; import org.eclipse.jdt.internal.compiler.lookup.VoidTypeBinding; public abstract class Pattern extends Expression { @@ -83,6 +84,8 @@ public boolean coversType(TypeBinding type, Scope scope) { return false; if (type == null || this.resolvedType == null) return false; + if (type instanceof TypeVariableBinding && type.superclass().isBoxedPrimitiveType()) + type = type.superclass(); // when a boxing type is in supers it must be superclass, because all boxing types are classes if (type.isPrimitiveOrBoxedPrimitiveType()) { PrimitiveConversionRoute route = Pattern.findPrimitiveConversionRoute(this.resolvedType, type, scope); switch (route) { @@ -235,7 +238,6 @@ public static PrimitiveConversionRoute findPrimitiveConversionRoute(TypeBinding } else if (expressionType.isBoxedPrimitiveType() && destinationIsBaseType) { TypeBinding unboxedExpressionType = scope.environment().computeBoxingType(expressionType); - //TODO: a narrowing reference conversion that is checked followed by an unboxing conversion //an unboxing conversion (5.1.8) if (TypeBinding.equalsEquals(destinationType, unboxedExpressionType)) return PrimitiveConversionRoute.UNBOXING_CONVERSION; @@ -243,8 +245,8 @@ public static PrimitiveConversionRoute findPrimitiveConversionRoute(TypeBinding if (BaseTypeBinding.isWidening(destinationType.id, unboxedExpressionType.id)) return PrimitiveConversionRoute.UNBOXING_AND_WIDENING_PRIMITIVE_CONVERSION; } else if (destinationIsBaseType) { - if (expressionType.erasure().isBoxedPrimitiveType()) { // / ... - int boxId = expressionType.erasure().id; + if (expressionType instanceof TypeVariableBinding && expressionType.superclass().isBoxedPrimitiveType()) { // / ... + int boxId = expressionType.superclass().id; int exprPrimId = TypeIds.box2primitive(boxId); if (exprPrimId == destinationType.id) return PrimitiveConversionRoute.WIDENING_REFERENCE_AND_UNBOXING_COVERSION; @@ -252,6 +254,8 @@ public static PrimitiveConversionRoute findPrimitiveConversionRoute(TypeBinding return PrimitiveConversionRoute.WIDENING_REFERENCE_AND_UNBOXING_COVERSION_AND_WIDENING_PRIMITIVE_CONVERSION; } TypeBinding boxedDestinationType = scope.environment().computeBoxingType(destinationType); + // a narrowing reference conversion that is checked followed by an unboxing conversion + // TODO: check relevance of 'checked', as well as use of erasure() below if (boxedDestinationType.isCompatibleWith(expressionType.erasure())) return PrimitiveConversionRoute.NARROWING_AND_UNBOXING_CONVERSION; } diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PrimitiveInPatternsTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PrimitiveInPatternsTest.java index 63bc424b59b..0d85bd6ba61 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PrimitiveInPatternsTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PrimitiveInPatternsTest.java @@ -7042,6 +7042,46 @@ public static void main(String argv[]) { "1.0\n" + "100.0"); } + public void testIssue2937_1() { + runConformTest(new String[] { + "X.java", + """ + record Record(T t) {} + public class X { + public static short foo(Record s) { + return switch (s) { + case Record(short s1) -> s1; + default -> 0; + }; + } + public static void main(String[] args) { + System.out.print(foo(new Record((short) 2))); + } + } + """ + }, + "2"); + } + public void testIssue2937_2() { + runConformTest(new String[] { + "X.java", + """ + record Record(T t) {} + public class X { + public static short foo(Record s) { + return switch (s) { + case Record(short s1) -> s1; + default -> 0; + }; + } + public static void main(String[] args) { + System.out.print(foo(new Record((short) 2))); + } + } + """ + }, + "2"); + } // test from spec public void _testSpec001() { runConformTest(new String[] {