Skip to content

Commit 450e16c

Browse files
committed
Fix unchecked conversion not failed compilation
Detect when any explicit type argument is a raw type Adds regression test testGH4957 reproducing the Comparator.comparing + raw Comparable scenario (issue #4957) and asserting the expected warnings/errors. With this fix testGH4957 passes.
1 parent 006800c commit 450e16c

2 files changed

Lines changed: 74 additions & 2 deletions

File tree

org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
* Bug 434483 - [1.8][compiler][inference] Type inference not picked up with method reference
2727
* Bug 446442 - [1.8] merge null annotations from super methods
2828
* Bug 457079 - Regression: type inference
29+
* Christoph Rueger GH4957 - ECJ compiles fine but Java does not: unchecked conversion
2930
*******************************************************************************/
3031
package org.eclipse.jdt.internal.compiler.lookup;
3132

@@ -75,8 +76,17 @@ public static MethodBinding computeCompatibleMethod(MethodBinding originalMethod
7576
// incompatible due to wrong arity
7677
return new ProblemMethodBinding(originalMethod, originalMethod.selector, substitutes, ProblemReasons.TypeParameterArityMismatch);
7778
}
78-
methodSubstitute = environment.createParameterizedGenericMethod(originalMethod, substitutes);
79-
break computeSubstitutes;
79+
// JLS 15.12.2.6: Check if any explicit type argument is raw.
80+
boolean usesUncheckedConversion = false;
81+
for (int i = 0; i < typeVariables.length; i++) {
82+
if (substitutes[i].isRawType()) {
83+
usesUncheckedConversion = true;
84+
break;
85+
}
86+
}
87+
methodSubstitute = environment.createParameterizedGenericMethod(originalMethod, substitutes,
88+
usesUncheckedConversion, false, null);
89+
break computeSubstitutes;
8090
}
8191
// perform type argument inference (15.12.2.7)
8292
// initializes the map of substitutes (var --> type[][]{ equal, extends, super}

org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_9.java

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2295,6 +2295,68 @@ public static <T> Iterable<T> concat(Iterable<? extends Iterable<? extends T>> e
22952295
runner.javacTestOptions = JavacHasABug.JavacBug8016207;
22962296
runner.runNegativeTest();
22972297
}
2298+
/**
2299+
* https://github.com/eclipse-jdt/eclipse.jdt.core/issues/4957Eclipse
2300+
* 2026-03 compiles fine but Java does not: unchecked conversion with Comparator.comparing + raw Comparable
2301+
*/
2302+
public void testGH4957() {
2303+
this.runNegativeTest(
2304+
new String[] {
2305+
"Snippet.java",
2306+
"import java.util.Comparator;\n"
2307+
+ "import java.util.Map;\n"
2308+
+ "\n"
2309+
+ "public class Snippet {\n"
2310+
+ "\n"
2311+
+ " public static void main(String[] args) {\n"
2312+
+ "\n"
2313+
+ " Comparator<Map<String, Object>> eventComparator = Comparator\n"
2314+
+ " .<Map<String, Object>, Comparable>comparing(e -> (Comparable) e.get(\"event_date\"),\n"
2315+
+ " Comparator.nullsLast(Comparator.naturalOrder()))\n"
2316+
+ " .thenComparing(e -> (String) e.get(\"event_type\"));\n"
2317+
+ " }\n"
2318+
+ "\n"
2319+
+ "}",
2320+
},
2321+
// related to https://docs.oracle.com/javase/specs/jls/se21/html/jls-15.html#jls-15.12.2.6
2322+
// Eclipse was incorrectly accepting this without warnings/errors;
2323+
// javac reports unchecked conversion because raw Comparable is used
2324+
// and the resulting Comparator is a raw Comparator (not Comparator<Map<String,Object>>),
2325+
// causing thenComparing to operate on raw type Object.
2326+
"----------\n" +
2327+
"1. WARNING in Snippet.java (at line 8)\n" +
2328+
" Comparator<Map<String, Object>> eventComparator = Comparator\n" +
2329+
" .<Map<String, Object>, Comparable>comparing(e -> (Comparable) e.get(\"event_date\"),\n" +
2330+
" Comparator.nullsLast(Comparator.naturalOrder()))\n" +
2331+
" .thenComparing(e -> (String) e.get(\"event_type\"));\n" +
2332+
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
2333+
"Type safety: The method thenComparing(Function) belongs to the raw type Comparator. References to generic type Comparator<T> should be parameterized\n" +
2334+
"----------\n" +
2335+
"2. WARNING in Snippet.java (at line 8)\n" +
2336+
" Comparator<Map<String, Object>> eventComparator = Comparator\n" +
2337+
" .<Map<String, Object>, Comparable>comparing(e -> (Comparable) e.get(\"event_date\"),\n" +
2338+
" Comparator.nullsLast(Comparator.naturalOrder()))\n" +
2339+
" .thenComparing(e -> (String) e.get(\"event_type\"));\n" +
2340+
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
2341+
"Type safety: The expression of type Comparator needs unchecked conversion to conform to Comparator<Map<String,Object>>\n" +
2342+
"----------\n" +
2343+
"3. WARNING in Snippet.java (at line 9)\n" +
2344+
" .<Map<String, Object>, Comparable>comparing(e -> (Comparable) e.get(\"event_date\"),\n" +
2345+
" ^^^^^^^^^^\n" +
2346+
"Comparable is a raw type. References to generic type Comparable<T> should be parameterized\n" +
2347+
"----------\n" +
2348+
"4. WARNING in Snippet.java (at line 9)\n" +
2349+
" .<Map<String, Object>, Comparable>comparing(e -> (Comparable) e.get(\"event_date\"),\n" +
2350+
" ^^^^^^^^^^\n" +
2351+
"Comparable is a raw type. References to generic type Comparable<T> should be parameterized\n" +
2352+
"----------\n" +
2353+
"5. ERROR in Snippet.java (at line 11)\n" +
2354+
" .thenComparing(e -> (String) e.get(\"event_type\"));\n" +
2355+
" ^^^\n" +
2356+
"The method get(String) is undefined for the type Object\n" +
2357+
"----------\n");
2358+
}
2359+
22982360
public static Class<GenericsRegressionTest_9> testClass() {
22992361
return GenericsRegressionTest_9.class;
23002362
}

0 commit comments

Comments
 (0)