Bug 472663 - [null][1.8] Wrong warning for method reference


Change-Id: Ib3e72958228daa6b857e65cfa61d044084e0deed
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java
index 99d085f..ae6e3d7 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java
@@ -8336,4 +8336,63 @@
 		options,

 		"");

 }

+public void testBug472663() {

+	runConformTestWithLibs(

+		new String[] {

+			"test/Callee.java",

+			"package test;\n" + 

+			"\n" + 

+			"import org.eclipse.jdt.annotation.NonNullByDefault;\n" + 

+			"\n" + 

+			"@NonNullByDefault\n" + 

+			"public class Callee {\n" + 

+			"	public static String staticOtherClass(String foo) {\n" + 

+			"		return foo;\n" + 

+			"	}\n" + 

+			"\n" + 

+			"	public String instanceOtherClass(String foo) {\n" + 

+			"		return foo;\n" + 

+			"	}\n" + 

+			"}\n"

+		},

+		getCompilerOptions(),

+		"");

+	// and now consume Callee.class:

+	runConformTestWithLibs(

+			new String[] {

+				"test/Caller.java",

+				"package test;\n" + 

+				"\n" + 

+				"import java.util.function.Function;\n" + 

+				"\n" + 

+				"import org.eclipse.jdt.annotation.NonNullByDefault;\n" + 

+				"\n" + 

+				"@NonNullByDefault\n" + 

+				"public class Caller {\n" + 

+				"	public void foo(final Callee callee) {\n" + 

+				"		Function<String, String> function;\n" + 

+				"\n" + 

+				"		// assignments with warnings (wrong):\n" + 

+				"		function = Callee::staticOtherClass;\n" + 

+				"		function = callee::instanceOtherClass;\n" + 

+				"\n" + 

+				"		// assignments with no warnings (ok):\n" + 

+				"		function = foo -> Callee.staticOtherClass(foo);\n" + 

+				"		function = foo -> callee.instanceOtherClass(foo);\n" + 

+				"		function = Caller::staticSameClass;\n" + 

+				"		function = this::instanceSameClass;\n" + 

+				"	}\n" + 

+				"\n" + 

+				"	public static String staticSameClass(String foo) {\n" + 

+				"		return foo;\n" + 

+				"	}\n" + 

+				"\n" + 

+				"	public String instanceSameClass(String foo) {\n" + 

+				"		return foo;\n" + 

+				"	}\n" + 

+				"}\n"

+			},

+			getCompilerOptions(),

+			"");

+	}

 }

diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java
index ad77677..845d662 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java
@@ -66,6 +66,7 @@
 import org.eclipse.jdt.internal.compiler.lookup.Binding;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
+import org.eclipse.jdt.internal.compiler.lookup.ImplicitNullAnnotationVerifier;
 import org.eclipse.jdt.internal.compiler.lookup.InferenceContext18;
 import org.eclipse.jdt.internal.compiler.lookup.IntersectionTypeBinding18;
 import org.eclipse.jdt.internal.compiler.lookup.InvocationSite;
@@ -741,8 +742,14 @@
 	}
 
 	protected void checkNullAnnotations(BlockScope scope) {
-		if (scope.compilerOptions().isAnnotationBasedNullAnalysisEnabled) {
+		CompilerOptions compilerOptions = scope.compilerOptions();
+		if (compilerOptions.isAnnotationBasedNullAnalysisEnabled) {
         	if (this.expectedType == null || !NullAnnotationMatching.hasContradictions(this.expectedType)) { // otherwise assume it has been reported and we can do nothing here
+        		if ((this.binding.tagBits & TagBits.IsNullnessKnown) == 0) {
+        			// not interested in reporting problems against this.binding:
+        			new ImplicitNullAnnotationVerifier(scope.environment(), compilerOptions.inheritNullAnnotations)
+        					.checkImplicitNullAnnotations(this.binding, null/*srcMethod*/, false, scope);
+        		}
 	        	// TODO: simplify by using this.freeParameters?
 	        	int len;
 	        	int expectedlen = this.binding.parameters.length;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/NonNullDefaultAwareTypeAnnotationWalker.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/NonNullDefaultAwareTypeAnnotationWalker.java
index aafe24b..9fa7cbf 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/NonNullDefaultAwareTypeAnnotationWalker.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/NonNullDefaultAwareTypeAnnotationWalker.java
@@ -116,14 +116,14 @@
 
 	@Override
 	public ITypeAnnotationWalker toMethodParameter(short index) {
-		// don't set nextIsDefaultLocation, because signature-level nullness is handled by ImplicitNullAnnotationVerifier
+		// don't set nextIsDefaultLocation, because signature-level nullness is handled by ImplicitNullAnnotationVerifier (triggered per invocation via MessageSend.resolveType() et al)
 		if (this.isEmpty) return restrict(this.matches, this.pathPtr);
 		return super.toMethodParameter(index);
 	}
 
 	@Override
 	public ITypeAnnotationWalker toMethodReturn() {
-		// don't set nextIsDefaultLocation, because signature-level nullness is handled by ImplicitNullAnnotationVerifier
+		// don't set nextIsDefaultLocation, because signature-level nullness is handled by ImplicitNullAnnotationVerifier (triggered per invocation via MessageSend.resolveType() et al)
 		if (this.isEmpty) return restrict(this.matches, this.pathPtr);
 		return super.toMethodReturn();
 	}