From e4fb2348ae6f07bcad8c2cd1c23b3cf731235aa0 Mon Sep 17 00:00:00 2001 From: Stephan Herrmann Date: Sat, 17 Aug 2024 21:00:05 +0200 Subject: [PATCH] ClassCastException with array as wildcard generic parameter avoid the bogus cast fixes https://github.com/eclipse-jdt/eclipse.jdt.core/issues/2817 --- .../compiler/lookup/CaptureBinding.java | 10 +++++----- .../lookup/IntersectionTypeBinding18.java | 13 ++++++++---- .../compiler/lookup/ReferenceBinding.java | 6 ++++-- .../compiler/lookup/TypeVariableBinding.java | 4 ++-- .../regression/GenericsRegressionTest_9.java | 20 +++++++++++++++++++ 5 files changed, 40 insertions(+), 13 deletions(-) diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.java index c7723579ac1..0bd7494f47b 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.java @@ -284,7 +284,7 @@ public void initializeBounds(Scope scope, ParameterizedTypeBinding capturedParam } } @Override - public ReferenceBinding upwardsProjection(Scope scope, TypeBinding[] mentionedTypeVariables) { + public TypeBinding upwardsProjection(Scope scope, TypeBinding[] mentionedTypeVariables) { if (enterRecursiveProjectionFunction()) { try { for (TypeBinding mentionedTypeVariable : mentionedTypeVariables) { @@ -292,7 +292,7 @@ public ReferenceBinding upwardsProjection(Scope scope, TypeBinding[] mentionedTy TypeBinding upperBoundForProjection = this.upperBoundForProjection(); if (upperBoundForProjection == null) upperBoundForProjection = scope.getJavaLangObject(); - return ((ReferenceBinding)upperBoundForProjection).upwardsProjection(scope, mentionedTypeVariables); + return upperBoundForProjection.upwardsProjection(scope, mentionedTypeVariables); } } return this; @@ -535,13 +535,13 @@ public TypeBinding uncapture(Scope scope) { } @Override - public ReferenceBinding downwardsProjection(Scope scope, TypeBinding[] mentionedTypeVariables) { - ReferenceBinding result = null; + public TypeBinding downwardsProjection(Scope scope, TypeBinding[] mentionedTypeVariables) { + TypeBinding result = null; if (enterRecursiveProjectionFunction()) { for (TypeBinding mentionedTypeVariable : mentionedTypeVariables) { if (TypeBinding.equalsEquals(this, mentionedTypeVariable)) { if (this.lowerBound != null) { - result = (ReferenceBinding) this.lowerBound.downwardsProjection(scope, mentionedTypeVariables); + result = this.lowerBound.downwardsProjection(scope, mentionedTypeVariables); } break; } diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/IntersectionTypeBinding18.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/IntersectionTypeBinding18.java index b002c03e3e3..93ced431ac0 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/IntersectionTypeBinding18.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/IntersectionTypeBinding18.java @@ -348,7 +348,11 @@ void collectInferenceVariables(Set variables) { public ReferenceBinding upwardsProjection(Scope scope, TypeBinding[] mentionedTypeVariables) { ReferenceBinding[] projectedTypes = new ReferenceBinding[this.intersectingTypes.length]; for (int i = 0; i < this.intersectingTypes.length; ++i) { - projectedTypes[i] = this.intersectingTypes[i].upwardsProjection(scope, mentionedTypeVariables); + TypeBinding projected = this.intersectingTypes[i].upwardsProjection(scope, mentionedTypeVariables); + if (projected instanceof ReferenceBinding refBinding) + projectedTypes[i] = refBinding; + else + return null; } return (ReferenceBinding) scope.environment().createIntersectionType18(projectedTypes); } @@ -357,10 +361,11 @@ public ReferenceBinding upwardsProjection(Scope scope, TypeBinding[] mentionedTy public ReferenceBinding downwardsProjection(Scope scope, TypeBinding[] mentionedTypeVariables) { ReferenceBinding[] projectedTypes = new ReferenceBinding[this.intersectingTypes.length]; for (int i = 0; i < this.intersectingTypes.length; ++i) { - ReferenceBinding projected = this.intersectingTypes[i].downwardsProjection(scope, mentionedTypeVariables); - if (projected == null) + TypeBinding projected = this.intersectingTypes[i].downwardsProjection(scope, mentionedTypeVariables); + if (projected instanceof ReferenceBinding refBind) + projectedTypes[i] = refBind; + else return null; - projectedTypes[i] = projected; } return (ReferenceBinding) scope.environment().createIntersectionType18(projectedTypes); } diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java index 0d4b2c04984..3753052c368 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java @@ -2054,7 +2054,8 @@ public char[] sourceName() { * @return Upwards type projection of 'this', or null if downwards projection is undefined */ @Override -public ReferenceBinding upwardsProjection(Scope scope, TypeBinding[] mentionedTypeVariables) { +public TypeBinding upwardsProjection(Scope scope, TypeBinding[] mentionedTypeVariables) { + // Note: return type remains as TypeBinding, because subclass CaptureBinding may return an ArrayBinding :( return this; } @@ -2065,7 +2066,8 @@ public ReferenceBinding upwardsProjection(Scope scope, TypeBinding[] mentionedTy * @return Downwards type projection of 'this', or null if downwards projection is undefined */ @Override -public ReferenceBinding downwardsProjection(Scope scope, TypeBinding[] mentionedTypeVariables) { +public TypeBinding downwardsProjection(Scope scope, TypeBinding[] mentionedTypeVariables) { + // Note: return type remains as TypeBinding, because subclass CaptureBinding may return an ArrayBinding :( return this; } diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java index 6ebe5afe165..d61b7108cc9 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java @@ -1205,12 +1205,12 @@ public boolean isFreeTypeVariable() { } @Override - public ReferenceBinding upwardsProjection(Scope scope, TypeBinding[] mentionedTypeVariables) { + public TypeBinding upwardsProjection(Scope scope, TypeBinding[] mentionedTypeVariables) { return this; } @Override - public ReferenceBinding downwardsProjection(Scope scope, TypeBinding[] mentionedTypeVariables) { + public TypeBinding downwardsProjection(Scope scope, TypeBinding[] mentionedTypeVariables) { return this; } diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_9.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_9.java index 15bab7385bc..6a652d49038 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_9.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_9.java @@ -1007,6 +1007,26 @@ public void foo() { + "----------\n", null, true, options); } +public void testGH2817() { + Runner runner = new Runner(); + runner.testFiles = new String[] { + "Test.java", + """ + class A {} + class B {} + + public interface Test { + void use(T t, B b); + B> create(); + + default void test() { + use(new A(), create()); + } + } + """ + }; + runner.runConformTest(); +} public static Class testClass() { return GenericsRegressionTest_9.class; }