diff --git a/checker/jtreg/nullness/MethodReceiverTypeErrorMessageTest.java b/checker/jtreg/nullness/MethodReceiverTypeErrorMessageTest.java new file mode 100644 index 00000000000..bdadce69135 --- /dev/null +++ b/checker/jtreg/nullness/MethodReceiverTypeErrorMessageTest.java @@ -0,0 +1,20 @@ +/* + * @test + * @summary Test case for method receiver type in error message. If it is a non-raw type, it should be printed as such. + * + * @compile/fail/ref=MethodReceiverTypeErrorMessageTest.out -XDrawDiagnostics -processor org.checkerframework.checker.nullness.NullnessChecker MethodReceiverTypeErrorMessageTest.java + */ +public class MethodReceiverTypeErrorMessageTest { + + MethodReceiverTypeErrorMessageTest() { + foo(); + } + + void foo() {} +} + +class sub extends MethodReceiverTypeErrorMessageTest { + sub() { + foo(); + } +} diff --git a/checker/jtreg/nullness/MethodReceiverTypeErrorMessageTest.out b/checker/jtreg/nullness/MethodReceiverTypeErrorMessageTest.out new file mode 100644 index 00000000000..8ebbd6ab47d --- /dev/null +++ b/checker/jtreg/nullness/MethodReceiverTypeErrorMessageTest.out @@ -0,0 +1,7 @@ +MethodReceiverTypeErrorMessageTest.java:10:12: compiler.err.proc.messager: [method.invocation.invalid] call to foo() not allowed on the given receiver. +found : @UnderInitialization(MethodReceiverTypeErrorMessageTest.class) MethodReceiverTypeErrorMessageTest +required: @Initialized MethodReceiverTypeErrorMessageTest +MethodReceiverTypeErrorMessageTest.java:18:12: compiler.err.proc.messager: [method.invocation.invalid] call to foo() not allowed on the given receiver. +found : @UnderInitialization(sub.class) sub +required: @Initialized MethodReceiverTypeErrorMessageTest<@Initialized String> +2 errors diff --git a/checker/tests/nullness/ReceiverTypeArgs.java b/checker/tests/nullness/ReceiverTypeArgs.java new file mode 100644 index 00000000000..796ee301592 --- /dev/null +++ b/checker/tests/nullness/ReceiverTypeArgs.java @@ -0,0 +1,19 @@ +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; + +public class ReceiverTypeArgs { + static class Box { + T item; + + public Box(T item) { + this.item = item; + } + + void test(Box<@NonNull T> this) {} + } + + private static void foo(Box<@Nullable String> box) { + // :: error: (method.invocation.invalid) + box.test(); + } +} diff --git a/framework/src/main/java/org/checkerframework/common/basetype/BaseTypeVisitor.java b/framework/src/main/java/org/checkerframework/common/basetype/BaseTypeVisitor.java index 6cb489b93f6..ff8e8697901 100644 --- a/framework/src/main/java/org/checkerframework/common/basetype/BaseTypeVisitor.java +++ b/framework/src/main/java/org/checkerframework/common/basetype/BaseTypeVisitor.java @@ -3772,8 +3772,8 @@ protected void checkMethodInvocability( return; } - AnnotatedTypeMirror methodReceiver = method.getReceiverType().getErased(); - AnnotatedTypeMirror treeReceiver = methodReceiver.shallowCopy(false); + AnnotatedDeclaredType methodReceiver = method.getReceiverType(); + AnnotatedDeclaredType treeReceiver = methodReceiver.shallowCopy(false); AnnotatedTypeMirror rcv = atypeFactory.getReceiverType(tree); treeReceiver.addAnnotations(rcv.getEffectiveAnnotations()); @@ -3782,10 +3782,10 @@ protected void checkMethodInvocability( // The diagnostic can be a bit misleading because the check is of the receiver but // `tree` is the entire method invocation (where the receiver might be implicit). commonAssignmentCheckStartDiagnostic(methodReceiver, treeReceiver, tree); - boolean success = typeHierarchy.isSubtype(treeReceiver, methodReceiver); - commonAssignmentCheckEndDiagnostic(success, null, methodReceiver, treeReceiver, tree); + boolean success = typeHierarchy.isSubtype(rcv, methodReceiver); + commonAssignmentCheckEndDiagnostic(success, null, methodReceiver, rcv, tree); if (!success) { - reportMethodInvocabilityError(tree, treeReceiver, methodReceiver); + reportMethodInvocabilityError(tree, rcv, methodReceiver); } } } diff --git a/javacutil/src/main/java/org/checkerframework/javacutil/TreeUtils.java b/javacutil/src/main/java/org/checkerframework/javacutil/TreeUtils.java index 6fbd74259f5..575adebce94 100644 --- a/javacutil/src/main/java/org/checkerframework/javacutil/TreeUtils.java +++ b/javacutil/src/main/java/org/checkerframework/javacutil/TreeUtils.java @@ -253,7 +253,7 @@ public static boolean isSelfAccess(ExpressionTree tree) { * @param tree an expression tree * @return the outermost non-parenthesized tree enclosed by the given tree */ - @SuppressWarnings("interning:return.type.incompatible") // pol ymorphism implementation + @SuppressWarnings("interning:return.type.incompatible") // polymorphism implementation public static @PolyInterned ExpressionTree withoutParens(@PolyInterned ExpressionTree tree) { ExpressionTree t = tree; while (t.getKind() == Tree.Kind.PARENTHESIZED) {