diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/CastExpression.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/CastExpression.java index 3e0a80a70a6..cdfab2ee490 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/CastExpression.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/CastExpression.java @@ -655,10 +655,12 @@ public TypeBinding resolveType(BlockScope scope) { } TypeBinding expressionType = this.expression.resolveType(scope); TypeBinding originalExpressionType = expressionType; + boolean isPolymorphicMethod = false; if (this.expression instanceof MessageSend) { MessageSend messageSend = (MessageSend) this.expression; MethodBinding methodBinding = messageSend.binding; if (methodBinding != null && methodBinding.isPolymorphic()) { + isPolymorphicMethod = true; messageSend.binding = scope.environment().updatePolymorphicMethodReturnType((PolymorphicMethodBinding) methodBinding, castType); if (TypeBinding.notEquals(expressionType, castType)) { expressionType = castType; @@ -681,6 +683,8 @@ public TypeBinding resolveType(BlockScope scope) { } boolean isLegal = checkCastTypesCompatibility(scope, castType, originalExpressionType, this.expression, true); if (isLegal) { + if (isPolymorphicMethod) + this.bits &= ~ASTNode.GenerateCheckcast; this.expression.computeConversion(scope, castType, expressionType); if ((this.bits & ASTNode.UnsafeCast) != 0) { // unsafe cast if (scope.compilerOptions().reportUnavoidableGenericTypeProblems diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PolymorphicSignatureTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PolymorphicSignatureTest.java index 05a12f573ef..c5e7388bab4 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PolymorphicSignatureTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PolymorphicSignatureTest.java @@ -13,8 +13,10 @@ *******************************************************************************/ package org.eclipse.jdt.core.tests.compiler.regression; +import java.io.IOException; import junit.framework.Test; import org.eclipse.jdt.core.tests.compiler.regression.AbstractRegressionTest.JavacTestOptions.JavacHasABug; +import org.eclipse.jdt.core.util.ClassFormatException; @SuppressWarnings({ "rawtypes" }) public class PolymorphicSignatureTest extends AbstractRegressionTest { @@ -118,11 +120,9 @@ public void testBug475996() { "}\n" }); } - public void testGH3651() { + public void testGH3651() throws ClassFormatException, IOException { Runner runner = new Runner(); - runner.testFiles = new String[] { - "VarHandleCast.java", - """ + String source = """ import java.lang.invoke.VarHandle; class VarHandleCast { VarHandle vh; @@ -130,8 +130,8 @@ V method(Object obj) { return (V)vh.getAndSet(this, obj); } } - """ - }; + """; + runner.testFiles = new String[] { "VarHandleCast.java", source }; runner.expectedCompilerLog = """ ---------- 1. WARNING in VarHandleCast.java (at line 5) @@ -142,5 +142,72 @@ V method(Object obj) { """; runner.javacTestOptions = JavacHasABug.JavacBug8343286; runner.runWarningTest(); + + String expectedOutput = """ + // Method descriptor #19 (Ljava/lang/Object;)Ljava/lang/Object; + // Signature: (Ljava/lang/Object;)TV; + // Stack: 3, Locals: 2 + java.lang.Object method(java.lang.Object obj); + 0 aload_0 [this] + 1 getfield VarHandleCast.vh : java.lang.invoke.VarHandle [22] + 4 aload_0 [this] + 5 aload_1 [obj] + 6 invokevirtual java.lang.invoke.VarHandle.getAndSet(VarHandleCast, java.lang.Object) : java.lang.Object [24] + 9 areturn + Line numbers: + [pc: 0, line: 5] + Local variable table: + [pc: 0, pc: 10] local: this index: 0 type: VarHandleCast + [pc: 0, pc: 10] local: obj index: 1 type: java.lang.Object + Local variable type table: + [pc: 0, pc: 10] local: this index: 0 type: VarHandleCast + """; + checkClassFile("VarHandleCast", source, expectedOutput); + } + public void testGH3651_noCheckcast() throws ClassFormatException, IOException { + String source = """ + import java.lang.invoke.MethodHandle; + import java.util.function.Function; + + public class CheckCast { + static Function createValueGetter(MethodHandle methodHandle) { + return a -> { + try { + return (String) methodHandle.invokeExact(a); // CHECKCAST String added + } catch (Throwable e) { + throw new IllegalStateException(e); + } + }; + } + } + """; + runConformTest(new String[] { "CheckCast.java", source }); + String expectedOutput = """ + // Method descriptor #24 (Ljava/lang/invoke/MethodHandle;Ljava/lang/Object;)Ljava/lang/String; + // Stack: 3, Locals: 3 + private static synthetic java.lang.String lambda$0(java.lang.invoke.MethodHandle arg0, java.lang.Object a); + 0 aload_0 [arg0] + 1 aload_1 [a] + 2 invokevirtual java.lang.invoke.MethodHandle.invokeExact(java.lang.Object) : java.lang.String [25] + 5 areturn + 6 astore_2 [e] + 7 new java.lang.IllegalStateException [31] + 10 dup + 11 aload_2 [e] + 12 invokespecial java.lang.IllegalStateException(java.lang.Throwable) [33] + 15 athrow + Exception Table: + [pc: 0, pc: 5] -> 6 when : java.lang.Throwable + Line numbers: + [pc: 0, line: 8] + [pc: 6, line: 9] + [pc: 7, line: 10] + Local variable table: + [pc: 0, pc: 16] local: a index: 1 type: java.lang.Object + [pc: 7, pc: 16] local: e index: 2 type: java.lang.Throwable + Stack map table: number of frames 1 + [pc: 6, same_locals_1_stack_item, stack: {java.lang.Throwable}] + """; + checkClassFile("CheckCast", source, expectedOutput); } }