diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java
index 3cb973bdf94..856b4d5f0c1 100644
--- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java
+++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java
@@ -208,8 +208,12 @@ public ParameterizedTypeBinding capture(Scope scope, int start, int end) {
if (wildcard.boundKind == Wildcard.SUPER && wildcard.bound.id == TypeIds.T_JavaLangObject) {
capturedArguments[i] = wildcard.bound;
} else {
- capturedArguments[i] = this.environment.createCapturedWildcard(wildcard, contextType, start, end, cud, compilationUnitScope::nextCaptureID);
- freshCaptures[i] = true;
+ if (wildcard.boundKind == Wildcard.EXTENDS && wildcard.otherBounds == null && wildcard.bound instanceof CaptureBinding) {
+ capturedArguments[i] = wildcard.bound;
+ } else {
+ capturedArguments[i] = this.environment.createCapturedWildcard(wildcard, contextType, start, end, cud, compilationUnitScope::nextCaptureID);
+ freshCaptures[i] = true;
+ }
}
} else {
capturedArguments[i] = argument;
diff --git a/org.eclipse.jdt.core.tests.compiler/META-INF/MANIFEST.MF b/org.eclipse.jdt.core.tests.compiler/META-INF/MANIFEST.MF
index fac3896ca24..5b4a64c99a3 100644
--- a/org.eclipse.jdt.core.tests.compiler/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.core.tests.compiler/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.jdt.core.tests.compiler;singleton:=true
-Bundle-Version: 3.13.1100.qualifier
+Bundle-Version: 3.13.1200.qualifier
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Export-Package: org.eclipse.jdt.core.tests.compiler,
diff --git a/org.eclipse.jdt.core.tests.compiler/pom.xml b/org.eclipse.jdt.core.tests.compiler/pom.xml
index 970f8759212..21ba83b32e7 100644
--- a/org.eclipse.jdt.core.tests.compiler/pom.xml
+++ b/org.eclipse.jdt.core.tests.compiler/pom.xml
@@ -19,7 +19,7 @@
../tests-pom/
org.eclipse.jdt.core.tests.compiler
- 3.13.1100-SNAPSHOT
+ 3.13.1200-SNAPSHOT
eclipse-test-plugin
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java
index de5fdf4918e..1a432243c88 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java
@@ -10964,4 +10964,32 @@ > void foo2(Y y1) {
"The method bar(One>) in the type Bug is not applicable for the arguments (One>)\n" +
"----------\n");
}
+ // https://github.com/eclipse-jdt/eclipse.jdt.core/issues/4867
+ public void testGH4867() {
+ runConformTest(
+ new String[] {
+ "MessageExpressionVoterTests.java",
+ """
+ public class MessageExpressionVoterTests {
+ MessageMatcher> matcher = new MessageMatcher() {
+ };
+
+ public boolean voteGranted() {
+ return this.matcher.matcher(ArgumentMatchers.any());
+ }
+ }
+ interface MessageMatcher {
+ default boolean matcher(Message extends T> message) {
+ return true;
+ }
+ }
+ interface Message {}
+ class ArgumentMatchers {
+ public static T any() {
+ return null;
+ }
+ }
+ """
+ });
+ }
}