Skip to content

Commit d41a4f2

Browse files
NPE in TypeBinding.getSingleAbstractMethod() (eclipse-jdt#4014)
* Fixes eclipse-jdt#3956 * Fixes eclipse-jdt#4009
1 parent fe4d99c commit d41a4f2

File tree

2 files changed

+90
-1
lines changed

2 files changed

+90
-1
lines changed

org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -887,7 +887,7 @@ CompatibilityResult internalIsCompatibleWith(TypeBinding targetType, Scope skope
887887

888888
// copy here is potentially compatible with the target type and has its shape fully computed: i.e value/void compatibility is determined and result expressions have been gathered.
889889
targetType = findGroundTargetType(this.enclosingScope, targetType, targetType, argumentsTypeElided());
890-
MethodBinding sam = targetType.getSingleAbstractMethod(this.enclosingScope, true);
890+
MethodBinding sam = targetType == null ? null : targetType.getSingleAbstractMethod(this.enclosingScope, true);
891891
if (sam == null || sam.problemId() == ProblemReasons.NoSuchSingleAbstractMethod) {
892892
return CompatibilityResult.INCOMPATIBLE;
893893
}

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

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10473,6 +10473,95 @@ public static void main(String[] strArr) {
1047310473
"----------\n");
1047410474
}
1047510475

10476+
// https://github.com/eclipse-jdt/eclipse.jdt.core/issues/3956
10477+
// NPE in TypeBinding.getSingleAbstractMethod()
10478+
public void testIssue3956() {
10479+
this.runNegativeTest(
10480+
new String[] {
10481+
"TestMe.java",
10482+
"""
10483+
import java.util.concurrent.CompletableFuture;
10484+
10485+
public class TestMe {
10486+
public String id;
10487+
private CompletableFuture<Action> active;
10488+
10489+
public void test() {
10490+
CompletableFuture<Void> future;
10491+
if (id == null) {
10492+
future = active.thenAcceptAsync(recording -> {
10493+
recording.stop().run();
10494+
recording.process();
10495+
});
10496+
} else {
10497+
future = active.thenComposeAsync(recording -> {
10498+
recording.stop().run();
10499+
// This code (should) have compile errors but instead triggers ClassCastException
10500+
10501+
return update().handleAsync(() -> recording.process());
10502+
10503+
// Deleting the line and using this code would work
10504+
// return update().handleAsync((a, b) -> {
10505+
// recording.process();
10506+
// return null;
10507+
// });
10508+
});
10509+
}
10510+
}
10511+
10512+
public synchronized CompletableFuture<?> update() {
10513+
return null;
10514+
}
10515+
10516+
private static final class Action {
10517+
10518+
public Runnable stop() {
10519+
return () -> {
10520+
};
10521+
}
10522+
10523+
public void process() {
10524+
10525+
}
10526+
10527+
}
10528+
}
10529+
"""
10530+
},
10531+
"----------\n" +
10532+
"1. ERROR in TestMe.java (at line 15)\n" +
10533+
" future = active.thenComposeAsync(recording -> {\n" +
10534+
" recording.stop().run();\n" +
10535+
"// This code (should) have compile errors but instead triggers ClassCastException\n" +
10536+
"\n" +
10537+
" return update().handleAsync(() -> recording.process());\n" +
10538+
"\n" +
10539+
"// Deleting the line and using this code would work\n" +
10540+
"// return update().handleAsync((a, b) -> {\n" +
10541+
"// recording.process();\n" +
10542+
"// return null;\n" +
10543+
"// });\n" +
10544+
" });\n" +
10545+
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
10546+
"Type mismatch: cannot convert from CompletableFuture<Object> to CompletableFuture<Void>\n" +
10547+
"----------\n" +
10548+
"2. ERROR in TestMe.java (at line 19)\n" +
10549+
" return update().handleAsync(() -> recording.process());\n" +
10550+
" ^^^^^^^^^^^\n" +
10551+
"The method handleAsync(BiFunction<? super capture#1-of ?,Throwable,? extends U>) in the type CompletableFuture<capture#1-of ?> is not applicable for the arguments (() -> {})\n" +
10552+
"----------\n" +
10553+
"3. ERROR in TestMe.java (at line 19)\n" +
10554+
" return update().handleAsync(() -> recording.process());\n" +
10555+
" ^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
10556+
"Lambda expression's signature does not match the signature of the functional interface method apply(? super capture#1-of ?, Throwable)\n" +
10557+
"----------\n" +
10558+
"4. ERROR in TestMe.java (at line 19)\n" +
10559+
" return update().handleAsync(() -> recording.process());\n" +
10560+
" ^^^^^^^^^^^^^^^^^^^\n" +
10561+
"Cannot return a void result\n" +
10562+
"----------\n");
10563+
}
10564+
1047610565
public static Class testClass() {
1047710566
return NegativeLambdaExpressionsTest.class;
1047810567
}

0 commit comments

Comments
 (0)