From e1e6a710eed4e2cfb5574d3778df6b5a63e1555b Mon Sep 17 00:00:00 2001 From: Srikanth Sankaran Date: Thu, 14 Nov 2024 05:59:16 +0530 Subject: [PATCH] Verify error with primitive patterns involving boxed types * Fixes https://github.com/eclipse-jdt/eclipse.jdt.core/issues/3129 * Fixes https://github.com/eclipse-jdt/eclipse.jdt.core/issues/3181 --- .../compiler/ast/IGenerateTypeCheck.java | 9 ++-- .../compiler/ast/InstanceOfExpression.java | 2 +- .../internal/compiler/ast/RecordPattern.java | 2 +- .../internal/compiler/ast/TypePattern.java | 4 +- .../regression/PrimitiveInPatternsTest.java | 50 +++++++++++++++++++ 5 files changed, 57 insertions(+), 10 deletions(-) diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/IGenerateTypeCheck.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/IGenerateTypeCheck.java index 5565d8a5fb1..7d42dc22559 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/IGenerateTypeCheck.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/IGenerateTypeCheck.java @@ -14,7 +14,6 @@ package org.eclipse.jdt.internal.compiler.ast; import org.eclipse.jdt.internal.compiler.ast.Pattern.PrimitiveConversionRoute; -import org.eclipse.jdt.internal.compiler.codegen.BranchLabel; import org.eclipse.jdt.internal.compiler.codegen.CodeStream; import org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; @@ -25,7 +24,7 @@ */ interface IGenerateTypeCheck { - default void generateTypeCheck(TypeBinding providedType, TypeReference expectedTypeRef, BlockScope scope, CodeStream codeStream, BranchLabel falseLabel, PrimitiveConversionRoute route) { + default void generateTypeCheck(TypeBinding providedType, TypeReference expectedTypeRef, BlockScope scope, CodeStream codeStream, PrimitiveConversionRoute route) { switch (route) { case IDENTITY_CONVERSION -> { consumeProvidedValue(providedType, codeStream); @@ -46,8 +45,7 @@ default void generateTypeCheck(TypeBinding providedType, TypeReference expectedT } case WIDENING_REFERENCE_AND_UNBOXING_COVERSION, WIDENING_REFERENCE_AND_UNBOXING_COVERSION_AND_WIDENING_PRIMITIVE_CONVERSION -> { - codeStream.ifnull(falseLabel); - codeStream.iconst_1(); + codeStream.instance_of(scope.getJavaLangObject()); setPatternIsTotalType(); } case NARROWING_AND_UNBOXING_CONVERSION -> { @@ -56,8 +54,7 @@ default void generateTypeCheck(TypeBinding providedType, TypeReference expectedT } case UNBOXING_CONVERSION, UNBOXING_AND_WIDENING_PRIMITIVE_CONVERSION -> { - codeStream.ifnull(falseLabel); - codeStream.iconst_1(); + codeStream.instance_of(scope.getJavaLangObject()); setPatternIsTotalType(); } case NO_CONVERSION_ROUTE -> { diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java index 1972bd87b09..352210da4d3 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java @@ -179,7 +179,7 @@ public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStr route = this.testContextRecord.route(); providedType = this.testContextRecord.right(); } - generateTypeCheck(providedType, this.type, currentScope, codeStream, internalFalseLabel, route); + generateTypeCheck(providedType, this.type, currentScope, codeStream, route); if (this.pattern != null) { codeStream.ifeq(internalFalseLabel); diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/RecordPattern.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/RecordPattern.java index bc26d4f3489..883202e4099 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/RecordPattern.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/RecordPattern.java @@ -251,7 +251,7 @@ original record instance as receiver - leaving the stack drained. if (!p.isUnnamed()) codeStream.dup(componentType); // lastComponent ? named ? ([C, C] : [R, C, C]) : ([C] : [R, C]) if (p instanceof TypePattern) { - ((TypePattern) p).generateTypeCheck(currentScope, codeStream, matchFailLabel); + ((TypePattern) p).generateTypeCheck(currentScope, codeStream); } else { codeStream.instance_of(p.resolvedType); // lastComponent ? named ? ([C, boolean] : [R, C, boolean]) : ([boolean] : [R, boolean]) } diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/TypePattern.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/TypePattern.java index 4716fde7211..dfbb068495f 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/TypePattern.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/TypePattern.java @@ -110,8 +110,8 @@ public void generateCode(BlockScope currentScope, CodeStream codeStream, BranchL } } - public void generateTypeCheck(BlockScope scope, CodeStream codeStream, BranchLabel internalFalseLabel) { - generateTypeCheck(this.outerExpressionType, getType(), scope, codeStream, internalFalseLabel, + public void generateTypeCheck(BlockScope scope, CodeStream codeStream) { + generateTypeCheck(this.outerExpressionType, getType(), scope, codeStream, Pattern.findPrimitiveConversionRoute(this.resolvedType, this.accessorMethod.returnType, scope)); } 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 7c782c38245..93c368e72d9 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 @@ -7281,6 +7281,56 @@ public static void main(String[] args) { }, "int:30"); } + + // https://github.com/eclipse-jdt/eclipse.jdt.core/issues/3181 + // VerifyError during conversion between T extends Long and double + public void testGH3181() { + runConformTest(new String[] { + "X.java", + """ + record Record(T t) { + } + + public class X { + public static double foo(Record s) { + return switch (s) { + case Record(double s1) -> s1 + 1.0; + default -> 0; + }; + } + + public static void main(String[] args) { + System.out.println(foo(new Record<>(42L))); + } + } + """ + }, + "43.0"); + } + + // https://github.com/eclipse-jdt/eclipse.jdt.core/issues/3129 + // VerifyError with instanceof record patterns with conversion from double to Long + public void testGH3129() { + runConformTest(new String[] { + "X.java", + """ + record Record(Long i) { + } + + public class X { + public static double convert(Record r) { + return r instanceof Record(double d) ? d + 1.0 : 0; + } + + public static void main(String[] args) { + System.out.println(convert(new Record(42L))); + } + } + """ + }, + "43.0"); + } + public void _testSpec00X() { runNegativeTest(new String[] { "X.java",