Releng: update jdt.core to I20160317-0200 for 4.6 M6

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 f13a31b2..91d907f 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 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.jdt.core.tests.compiler;singleton:=true
-Bundle-Version: 3.12.100.qualifier
+Bundle-Version: 3.12.200.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 1bfc96a..34d0158 100644
--- a/org.eclipse.jdt.core.tests.compiler/pom.xml
+++ b/org.eclipse.jdt.core.tests.compiler/pom.xml
@@ -20,7 +20,7 @@
   </parent>
   <groupId>org.eclipse.jdt</groupId>
   <artifactId>org.eclipse.jdt.core.tests.compiler</artifactId>
-  <version>3.12.100-SNAPSHOT</version>
+  <version>3.12.200-SNAPSHOT</version>
   <packaging>eclipse-test-plugin</packaging>
 
   <properties>
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/CompletionParserTest18.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/CompletionParserTest18.java
index e14509c..7ffbefb 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/CompletionParserTest18.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/CompletionParserTest18.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2013, 2014 IBM Corporation and others.
+ * Copyright (c) 2013, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -2278,4 +2278,46 @@
 		expectedReplacedSource,
 		"diet ast");
 }
+//https://bugs.eclipse.org/bugs/show_bug.cgi?id=473008
+public void test473008() {
+	String string = 
+			"interface FooFunctional {\n" +
+			"   void function();\n" +
+			"}\n" +
+			"public class Foo {\n" +
+			"    public void bar() {\n" +
+			"      private FooFunctional lambda = this::bar;\n" +
+			"      new StringBuffer(" +
+			"    }\n" +
+			"}\n";
+	String completeBehind = "StringBuffer(";
+	int cursorLocation = string.indexOf(completeBehind) + completeBehind.length() - 1;
+
+	String expectedCompletionNodeToString = "<CompleteOnAllocationExpression:new StringBuffer()>";
+	String expectedParentNodeToString = "<NONE>";
+	String completionIdentifier = "";
+	String expectedReplacedSource = "";
+	String expectedUnitDisplayString =
+			"interface FooFunctional {\n" + 
+			"  void function();\n" + 
+			"}\n" + 
+			"public class Foo {\n" + 
+			"  public Foo() {\n" + 
+			"  }\n" + 
+			"  public void bar() {\n" + 
+			"    private FooFunctional lambda;\n" + 
+			"    <CompleteOnAllocationExpression:new StringBuffer()>;\n" + 
+			"  }\n" + 
+			"}\n";
+
+	checkMethodParse(
+		string.toCharArray(),
+		cursorLocation,
+		expectedCompletionNodeToString,
+		expectedParentNodeToString,
+		expectedUnitDisplayString,
+		completionIdentifier,
+		expectedReplacedSource,
+		"diet ast");
+}
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/ExplicitConstructorInvocationSelectionTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/ExplicitConstructorInvocationSelectionTest.java
index e0abec8..6ea595b 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/ExplicitConstructorInvocationSelectionTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/ExplicitConstructorInvocationSelectionTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -49,7 +49,7 @@
 		"  }\n" +
 		"  public class SubInnerBar extends InnerBar {\n" +
 		"    SubInnerBar() {\n" +
-		"      super(<SelectOnMessageSend:fred()>);\n" +
+		"      Bar.super(<SelectOnMessageSend:fred()>);\n" +
 		"    }\n" +
 		"  }\n" +
 		"  static Bar x;\n" +
@@ -98,7 +98,7 @@
 		"  }\n" +
 		"  public class SubInnerBar extends InnerBar {\n" +
 		"    SubInnerBar() {\n" +
-		"      this(<SelectOnMessageSend:fred()>);\n" +
+		"      Bar.this(<SelectOnMessageSend:fred()>);\n" +
 		"    }\n" +
 		"  }\n" +
 		"  static Bar x;\n" +
@@ -147,7 +147,7 @@
 		"  }\n" +
 		"  public class SubInnerBar extends InnerBar {\n" +
 		"    SubInnerBar(Bar x) {\n" +
-		"      super(<SelectOnMessageSend:fred()>);\n" +
+		"      primary().super(<SelectOnMessageSend:fred()>);\n" +
 		"    }\n" +
 		"  }\n" +
 		"  static Bar x;\n" +
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/SelectionParserTest18.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/SelectionParserTest18.java
index 9166a00..852c395 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/SelectionParserTest18.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/SelectionParserTest18.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2013 IBM Corporation and others.
+ * Copyright (c) 2013, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -176,4 +176,77 @@
 			expectedReplacedSource,
 			testName);
 }
-}
\ No newline at end of file
+//https://bugs.eclipse.org/bugs/show_bug.cgi?id=476693
+public void test476693() throws JavaModelException {
+	String string = 
+			"import static java.util.stream.Collectors.toList;\n" +
+			"import java.util.List;\n" +
+			"import java.util.Spliterator;\n" +
+			"import java.util.stream.Stream;\n" +
+			"interface Seq<T> extends Stream<T>, Iterable<T> {\n" +
+			"    @Override\n" +
+			"    default Spliterator<T> spliterator() {\n" +
+			"        return Iterable.super.spliterator();\n" +
+			"    }\n" +
+			"}\n" +
+			"interface Tuple2<T1, T2> {}\n" +
+			"interface Tuple3<T1, T2, T3> {}\n" +
+			"\n" +
+			"public class Test<T1, T2, T3> {\n" +
+			"    <T1, T2> Seq<Tuple2<T1, T2>> m(Stream<T1> arg1, Stream<T2> arg2) {\n" +
+			"        System.out.println(\"m1\"); return null;\n" +
+			"    }\n" +
+			"    <T1, T2> Seq<Tuple2<T1, T2>> m(Seq<T1> arg1, Seq<T2> arg2){\n" +
+			"        System.out.println(\"m3\"); return null;\n" +
+			"    }\n" +
+			"    <T1, T2, T3> void m(Seq<T1> c1, Seq<T2> c2, Seq<T3> c3) {\n" +
+			"            // Click F3 on the m() call. This will jump to m1, erroneously\n" +
+			"            List<Tuple2<T1, T2>> l = m(c1, c2).collect(toList());\n" +
+			"            System.out.println(\"Hello\"); // This shouldn't appear in the selection parse tree\n" +
+			"    }\n" +
+			"}";
+
+	String expectedCompletionNodeToString = "<SelectOnMessageSend:m(c1, c2)>";
+
+	String completionIdentifier = "m";
+	String expectedUnitDisplayString =
+					"import static java.util.stream.Collectors.toList;\n" +
+					"import java.util.List;\n" +
+					"import java.util.Spliterator;\n" +
+					"import java.util.stream.Stream;\n" +
+					"interface Seq<T> extends Stream<T>, Iterable<T> {\n" +
+					"  default @Override Spliterator<T> spliterator() {\n" +
+					"  }\n" +
+					"}\n" +
+					"interface Tuple2<T1, T2> {\n" +
+					"}\n" +
+					"interface Tuple3<T1, T2, T3> {\n" +
+					"}\n" +
+					"public class Test<T1, T2, T3> {\n" +
+					"  public Test() {\n" +
+					"  }\n" +
+					"  <T1, T2>Seq<Tuple2<T1, T2>> m(Stream<T1> arg1, Stream<T2> arg2) {\n" +
+					"  }\n" +
+					"  <T1, T2>Seq<Tuple2<T1, T2>> m(Seq<T1> arg1, Seq<T2> arg2) {\n" +
+					"  }\n" +
+					"  <T1, T2, T3>void m(Seq<T1> c1, Seq<T2> c2, Seq<T3> c3) {\n" +
+					"    List<Tuple2<T1, T2>> l = <SelectOnMessageSend:m(c1, c2)>.collect(toList());\n" +
+					"  }\n" +
+					"}\n";
+	String expectedReplacedSource = "m(c1, c2)";
+	String testName = "<select>";
+
+	int selectionStart = string.indexOf("m(c1, c2)");
+	int selectionEnd = selectionStart;
+
+	this.checkMethodParse(
+			string.toCharArray(),
+			selectionStart,
+			selectionEnd,
+			expectedCompletionNodeToString,
+			expectedUnitDisplayString,
+			completionIdentifier,
+			expectedReplacedSource,
+			testName);
+}
+}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractNullAnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractNullAnnotationTest.java
index f2eea51..d2e1072 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractNullAnnotationTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractNullAnnotationTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2010, 2014 GK Software AG and others.
+ * Copyright (c) 2010, 2016 GK Software AG and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -16,6 +16,7 @@
 import org.eclipse.core.runtime.FileLocator;
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.osgi.framework.Bundle;
 
 @SuppressWarnings({ "unchecked", "rawtypes" })
@@ -97,6 +98,10 @@
 
 			// enable null annotations:
 			defaultOptions.put(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED);
+
+			defaultOptions.put(CompilerOptions.OPTION_PessimisticNullAnalysisForFreeTypeVariables, JavaCore.ERROR);
+			defaultOptions.put(CompilerOptions.OPTION_ReportNonNullTypeVariableFromLegacyInvocation, JavaCore.WARNING);
+			
 			// leave other new options at these defaults:
 //			defaultOptions.put(CompilerOptions.OPTION_ReportNullContractViolation, JavaCore.ERROR);
 //			defaultOptions.put(CompilerOptions.OPTION_ReportPotentialNullContractViolation, JavaCore.ERROR);
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AssignmentTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AssignmentTest.java
index be896d9..357958e 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AssignmentTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AssignmentTest.java
@@ -2098,6 +2098,52 @@
 			"Hello World!");
 	}
 }
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=486908
+public void testBug486908_A(){
+	if (this.complianceLevel >= ClassFileConstants.JDK1_7) {
+	this.runConformTest(new String[] {
+			"Random.java",
+			"import java.util.ArrayList;\n" + 
+			"import java.util.List;\n" + 
+			"public class Random {\n" + 
+			"	private final List<Object> values;\n" + 
+			"	public Random() {\n" + 
+			"		values = new ArrayList<>();\n" + 
+			"	}\n" + 
+			"	public Random(Object arg) {\n" + 
+			"		if(arg instanceof Random) {\n" + 
+			"			values = ((Random)(arg)).values; //Compile error here.\n" + 
+			"		} else {\n" + 
+			"			throw new IllegalArgumentException(\"arg is not instance of Random\");\n" + 
+			"		}\n" + 
+			"	}\n" + 
+			"	public static void foo() {\n" + 
+			"		return;\n" + 
+			"	}\n" + 
+			"	public static void main(String[] args){\n" + 
+			"		foo();\n" + 
+			"	}\n" + 
+			"}\n"
+	});
+}
+}
+public void testBug486908_B() {
+	this.runConformTest(new String[] {
+			"Sample.java",
+			"public class Sample {\n" + 
+			"	public final String value;\n" + 
+			"	public Sample() {\n" + 
+			"		this.value = new Sample().value;\n" + 
+			"	}\n" + 
+			"	public static void foo() {\n" + 
+			"		return;\n" + 
+			"	}\n" + 
+			"	public static void main(String[] args) {\n" + 
+			"		foo();\n" + 
+			"	}\n" + 
+			"}\n"
+	});
+}
 public static Class testClass() {
 	return AssignmentTest.class;
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java
index 4524048..3c5e188 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -2077,6 +2077,7 @@
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion\" value=\"warning\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral\" value=\"ignore\"/>\n" +
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped\" value=\"warning\"/>\n" +
+			"		<option key=\"org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation\" value=\"warning\"/>\n" +
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict\" value=\"error\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.nullReference\" value=\"warning\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.nullSpecViolation\" value=\"error\"/>\n" + 
@@ -2084,6 +2085,7 @@
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.overridingMethodWithoutSuperInvocation\" value=\"ignore\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod\" value=\"warning\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.parameterAssignment\" value=\"ignore\"/>\n" + 
+			"		<option key=\"org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables\" value=\"warning\"/>\n" +
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment\" value=\"ignore\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.potentialNullReference\" value=\"ignore\"/>\n" + 
 			"		<option key=\"org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable\" value=\"ignore\"/>\n" + 
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java
index 773ddb6..19da8f2 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2006, 2015 IBM Corporation and others.
+ * Copyright (c) 2006, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -841,6 +841,8 @@
 		expectedProblemAttributes.put("NonNullMessageSendComparisonYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
 		expectedProblemAttributes.put("NonNullSpecdFieldComparisonYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
 		expectedProblemAttributes.put("NonNullLocalVariableComparisonYieldsFalse", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
+		expectedProblemAttributes.put("NonNullTypeVariableFromLegacyMethod", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
+		expectedProblemAttributes.put("NonNullMethodTypeVariableFromLegacyMethod", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
 		expectedProblemAttributes.put("NonStaticAccessToStaticField", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
 		expectedProblemAttributes.put("NonStaticAccessToStaticMethod", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
 		expectedProblemAttributes.put("NonStaticContextForEnumMemberType", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
@@ -941,6 +943,7 @@
 		expectedProblemAttributes.put("ReferenceExpressionReturnNullRedef", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
 		expectedProblemAttributes.put("ReferenceExpressionReturnNullRedefUnchecked", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
 		expectedProblemAttributes.put("ReferenceToForwardField", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
+		expectedProblemAttributes.put("RequiredNonNullButProvidedFreeTypeVariable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
 		expectedProblemAttributes.put("RequiredNonNullButProvidedNull", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
 		expectedProblemAttributes.put("RequiredNonNullButProvidedPotentialNull", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
 		expectedProblemAttributes.put("RequiredNonNullButProvidedSpecdNullable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
@@ -1009,6 +1012,7 @@
 		expectedProblemAttributes.put("TypeMissingDeprecatedAnnotation", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
 		expectedProblemAttributes.put("TypeParameterHidingType", new ProblemAttributes(CategorizedProblem.CAT_NAME_SHADOWING_CONFLICT));
 		expectedProblemAttributes.put("UnboxingConversion", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
+		expectedProblemAttributes.put("UncheckedAccessOfValueOfFreeTypeVariable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
 		expectedProblemAttributes.put("UnclosedCloseable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
 		expectedProblemAttributes.put("UnclosedCloseableAtExit", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
 		expectedProblemAttributes.put("UndefinedAnnotationMember", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
@@ -1032,6 +1036,8 @@
 		expectedProblemAttributes.put("UnhandledWarningToken", new ProblemAttributes(CategorizedProblem.CAT_UNNECESSARY_CODE));
 		expectedProblemAttributes.put("UninitializedBlankFinalField", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
 		expectedProblemAttributes.put("UninitializedBlankFinalFieldHintMissingDefault", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
+		expectedProblemAttributes.put("UninitializedFreeTypeVariableField", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
+		expectedProblemAttributes.put("UninitializedFreeTypeVariableFieldHintMissingDefault", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
 		expectedProblemAttributes.put("UninitializedLocalVariable", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
 		expectedProblemAttributes.put("UninitializedLocalVariableHintMissingDefault", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
 		expectedProblemAttributes.put("UninitializedNonNullField", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
@@ -1752,6 +1758,8 @@
 		expectedProblemAttributes.put("NonNullSpecdFieldComparisonYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
 		expectedProblemAttributes.put("NonNullLocalVariableComparisonYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
 		expectedProblemAttributes.put("NonNullMessageSendComparisonYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
+		expectedProblemAttributes.put("NonNullTypeVariableFromLegacyMethod", new ProblemAttributes(JavaCore.COMPILER_PB_NONNULL_TYPEVAR_FROM_LEGACY_INVOCATION));
+		expectedProblemAttributes.put("NonNullMethodTypeVariableFromLegacyMethod", new ProblemAttributes(JavaCore.COMPILER_PB_NONNULL_TYPEVAR_FROM_LEGACY_INVOCATION));
 		expectedProblemAttributes.put("NonStaticAccessToStaticField", new ProblemAttributes(JavaCore.COMPILER_PB_STATIC_ACCESS_RECEIVER));
 		expectedProblemAttributes.put("NonStaticAccessToStaticMethod", new ProblemAttributes(JavaCore.COMPILER_PB_STATIC_ACCESS_RECEIVER));
 		expectedProblemAttributes.put("NonStaticContextForEnumMemberType", SKIP);
@@ -1768,7 +1776,7 @@
 		expectedProblemAttributes.put("NullableFieldReference", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_REFERENCE));
 		expectedProblemAttributes.put("NullAnnotationUnsupportedLocation", SKIP);
 		expectedProblemAttributes.put("NullAnnotationUnsupportedLocationAtType", SKIP);
-		expectedProblemAttributes.put("NullityMismatchAgainstFreeTypeVariable", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_SPECIFICATION_VIOLATION));
+		expectedProblemAttributes.put("NullityMismatchAgainstFreeTypeVariable", new ProblemAttributes(JavaCore.COMPILER_PB_PESSIMISTIC_NULL_ANALYSIS_FOR_FREE_TYPE_VARIABLES));
 		expectedProblemAttributes.put("NullityMismatchingTypeAnnotation", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_SPECIFICATION_VIOLATION));
 		expectedProblemAttributes.put("NullityMismatchingTypeAnnotationSuperHint", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_SPECIFICATION_VIOLATION));
 		expectedProblemAttributes.put("NullityMismatchTypeArgument", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_SPECIFICATION_VIOLATION));
@@ -1778,7 +1786,7 @@
 		expectedProblemAttributes.put("NullLocalVariableComparisonYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
 		expectedProblemAttributes.put("NullLocalVariableInstanceofYieldsFalse", new ProblemAttributes(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK));
 		expectedProblemAttributes.put("NullLocalVariableReference", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_REFERENCE));
-		expectedProblemAttributes.put("NullNotCompatibleToFreeTypeVariable", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_SPECIFICATION_VIOLATION));
+		expectedProblemAttributes.put("NullNotCompatibleToFreeTypeVariable", new ProblemAttributes(JavaCore.COMPILER_PB_PESSIMISTIC_NULL_ANALYSIS_FOR_FREE_TYPE_VARIABLES));
 		expectedProblemAttributes.put("NullSourceString", SKIP);
 		expectedProblemAttributes.put("NullUnboxing", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_REFERENCE));
 		expectedProblemAttributes.put("NumericValueOutOfRange", SKIP);
@@ -1858,6 +1866,7 @@
 		expectedProblemAttributes.put("RepeatableAnnotationTypeTargetMismatch", SKIP);
 		expectedProblemAttributes.put("RepeatableAnnotationWithRepeatingContainerAnnotation", SKIP);
 		expectedProblemAttributes.put("RepeatedAnnotationWithContainerAnnotation", SKIP);
+		expectedProblemAttributes.put("RequiredNonNullButProvidedFreeTypeVariable", new ProblemAttributes(JavaCore.COMPILER_PB_PESSIMISTIC_NULL_ANALYSIS_FOR_FREE_TYPE_VARIABLES));
 		expectedProblemAttributes.put("RequiredNonNullButProvidedNull", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_SPECIFICATION_VIOLATION));
 		expectedProblemAttributes.put("RequiredNonNullButProvidedPotentialNull", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_ANNOTATION_INFERENCE_CONFLICT));
 		expectedProblemAttributes.put("RequiredNonNullButProvidedUnknown", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_UNCHECKED_CONVERSION));
@@ -1920,6 +1929,7 @@
 		expectedProblemAttributes.put("TypeMissingDeprecatedAnnotation", new ProblemAttributes(JavaCore.COMPILER_PB_MISSING_DEPRECATED_ANNOTATION));
 		expectedProblemAttributes.put("TypeParameterHidingType", new ProblemAttributes(JavaCore.COMPILER_PB_TYPE_PARAMETER_HIDING));
 		expectedProblemAttributes.put("UnboxingConversion", new ProblemAttributes(JavaCore.COMPILER_PB_AUTOBOXING));
+		expectedProblemAttributes.put("UncheckedAccessOfValueOfFreeTypeVariable", new ProblemAttributes(JavaCore.COMPILER_PB_PESSIMISTIC_NULL_ANALYSIS_FOR_FREE_TYPE_VARIABLES));
 		expectedProblemAttributes.put("UnclosedCloseable", new ProblemAttributes(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE));
 		expectedProblemAttributes.put("UnclosedCloseableAtExit", new ProblemAttributes(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE));
 		expectedProblemAttributes.put("UndefinedAnnotationMember", SKIP);
@@ -1943,6 +1953,8 @@
 		expectedProblemAttributes.put("UnhandledWarningToken", new ProblemAttributes(JavaCore.COMPILER_PB_UNHANDLED_WARNING_TOKEN));
 		expectedProblemAttributes.put("UninitializedBlankFinalField", SKIP);
 		expectedProblemAttributes.put("UninitializedBlankFinalFieldHintMissingDefault", SKIP);
+		expectedProblemAttributes.put("UninitializedFreeTypeVariableField", SKIP);
+		expectedProblemAttributes.put("UninitializedFreeTypeVariableFieldHintMissingDefault", SKIP);
 		expectedProblemAttributes.put("UninitializedLocalVariable", SKIP);
 		expectedProblemAttributes.put("UninitializedLocalVariableHintMissingDefault", SKIP);
 		expectedProblemAttributes.put("UninitializedNonNullField", SKIP);
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ExpressionContextTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ExpressionContextTests.java
index c0763a3..6cc0ae1 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ExpressionContextTests.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ExpressionContextTests.java
@@ -65,7 +65,7 @@
 }
 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=399773, [1.8][compiler] Cast expression should allow for additional bounds to form intersection types
 public void test002() {
-	this.runNegativeTest(
+	this.runConformTest(
 			new String[] {
 				"X.java",
 				"interface I {\n" +
@@ -79,13 +79,7 @@
 				"public class X {\n" +
 				"	Object p = (I & J) () -> {};\n" +
 				"}\n" ,
-			},
-			"----------\n" + 
-			"1. ERROR in X.java (at line 10)\n" + 
-			"	Object p = (I & J) () -> {};\n" + 
-			"	                   ^^^^^\n" +
-			"The target type of this expression is not a functional interface: more than one of the intersecting interfaces are functional\n" + 
-			"----------\n");
+			});
 }
 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=399773, [1.8][compiler] Cast expression should allow for additional bounds to form intersection types
 public void test003() {
@@ -257,7 +251,7 @@
 			"3. ERROR in X.java (at line 10)\n" + 
 			"	Object p = (@Marker java.lang. @Readonly String & I & J) () -> {};\n" + 
 			"	                                                         ^^^^^\n" +
-			"The target type of this expression is not a functional interface: more than one of the intersecting interfaces are functional\n" + 
+			"The target type of this expression must be a functional interface\n" + 
 			"----------\n");
 }
 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=399773, [1.8][compiler] Cast expression should allow for additional bounds to form intersection types
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java
index acc8216..ce08ab4 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java
@@ -50222,7 +50222,9 @@
 			"1. ERROR in X.java (at line 9)\n" + 
 			"	Integer j = ffi.bar(ffi, new Foo());\n" + 
 			"	            ^^^^^^^^^^^^^^^^^^^^^^^\n" + 
-			"Type mismatch: cannot convert from Foo<Integer> to Integer\n" + 
+			(this.complianceLevel < ClassFileConstants.JDK1_8
+			? "Type mismatch: cannot convert from Foo<Integer> to Integer\n"
+			: "Type mismatch: cannot convert from Foo to Integer\n") +
 			"----------\n" + 
 			"2. WARNING in X.java (at line 9)\n" + 
 			"	Integer j = ffi.bar(ffi, new Foo());\n" + 
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_7.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_7.java
index c5df191..805dd10 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_7.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_7.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2011, 2015 IBM Corporation.
+ * Copyright (c) 2011, 2016 IBM Corporation.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -3034,6 +3034,38 @@
 			"----------\n");
 	}
 }
+public void testBug488649_JDK6791481_ex1() {
+	int count = 1;
+	runNegativeTest(
+		new String[] {
+			"Test.java",
+			"class Test<X> {\n" + 
+			"	X m(Class<X> c) {return null;}\n" + 
+			"	X x = m((Class)String.class);\n" + 
+			"}\n"
+		},
+		"----------\n" + 
+		(this.complianceLevel >= ClassFileConstants.JDK1_8
+			?
+		(count++)+". ERROR in Test.java (at line 3)\n" + 
+		"	X x = m((Class)String.class);\n" + 
+		"	      ^^^^^^^^^^^^^^^^^^^^^^\n" + 
+		"Type mismatch: cannot convert from Object to X\n" + // <- want to see this error, but at 1.7- we keep javac compatibility
+		"----------\n"
+			:
+		""
+		)+
+		(count++)+". WARNING in Test.java (at line 3)\n" +
+		"	X x = m((Class)String.class);\n" +
+		"	        ^^^^^^^^^^^^^^^^^^^\n" + 
+		"Type safety: The expression of type Class needs unchecked conversion to conform to Class<X>\n" + 
+		"----------\n" + 
+		(count++)+". WARNING in Test.java (at line 3)\n" +
+		"	X x = m((Class)String.class);\n" + 
+		"	         ^^^^^\n" + 
+		"Class is a raw type. References to generic type Class<T> should be parameterized\n" + 
+		"----------\n");
+}
 public static Class testClass() {
 	return GenericsRegressionTest_1_7.class;
 }
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 c62cebf..4167aa3 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
@@ -5829,4 +5829,242 @@
 			"}\n"
 		});
 }
+public void testBug483228a() {
+	runNegativeTest(
+		new String[] {
+			"X.java",
+			"interface UnaryOp<T> { T apply(T arg); }\n" + 
+			"interface IntegerToNumber { Number apply(Integer arg); }\n" + 
+			"\n" + 
+			"public class X {\n" + 
+			"\n" + 
+			"  <T> void m(UnaryOp<T> f) {}\n" + 
+			"  void m(IntegerToNumber f) {}\n" + 
+			"\n" + 
+			"  void test() {\n" + 
+			"    m((Integer i) -> i);\n" + 
+			"  } \n" + 
+			"}\n"
+		},
+		"----------\n" + 
+		"1. ERROR in X.java (at line 10)\n" + 
+		"	m((Integer i) -> i);\n" + 
+		"	^\n" + 
+		"The method m(UnaryOp<Integer>) is ambiguous for the type X\n" + 
+		"----------\n");
+}
+public void testBug449824a() {
+	runNegativeTest(
+		new String[] {
+			"X.java",
+			"public class X {\n" + 
+			"	interface FI1<T> {\n" + 
+			"		public T get(X x, T n);\n" + 
+			"	}\n" + 
+			"	interface FI2 {\n" + 
+			"		public Integer get(X x, Integer t);\n" + 
+			"	}\n" + 
+			"	void m(FI1<Number> fi) { }\n" + 
+			"	void m(FI2 fi) { }\n" + 
+			"	Integer id(Number n) {\n" + 
+			"		return null;\n" + 
+			"	}\n" + 
+			"	void test() {\n" + 
+			"		m(X::id);\n" + 
+			"	}\n" + 
+			"}\n"
+		},
+		"----------\n" + 
+		"1. ERROR in X.java (at line 14)\n" + 
+		"	m(X::id);\n" + 
+		"	^\n" + 
+		"The method m(X.FI1<Number>) is ambiguous for the type X\n" + 
+		"----------\n");
+}
+public void testBug449824b() {
+	runNegativeTest(
+		new String[] {
+			"X.java",
+			"public class X {\n" + 
+			"	interface FI1<T> {\n" + 
+			"		public T get(T... n);\n" + 
+			"	}\n" + 
+			"	interface FI2 {\n" + 
+			"		public Integer get(Integer... t);\n" + 
+			"	}\n" + 
+			"	void m(FI1<Number> fi) { }\n" + 
+			"	void m(FI2 fi) { }\n" + 
+			"	Integer id(Number[] n) {\n" + 
+			"		return null;\n" + 
+			"	}\n" + 
+			"	void test() {\n" + 
+			"		m(this::id);\n" + 
+			"	}\n" + 
+			"}\n"
+		},
+		"----------\n" + 
+		"1. WARNING in X.java (at line 3)\n" + 
+		"	public T get(T... n);\n" + 
+		"	                  ^\n" + 
+		"Type safety: Potential heap pollution via varargs parameter n\n" +
+		"----------\n" + 
+		"2. ERROR in X.java (at line 14)\n" + 
+		"	m(this::id);\n" + 
+		"	^\n" + 
+		"The method m(X.FI1<Number>) is ambiguous for the type X\n" +
+		"----------\n");
+}
+public void testBug487746_comment2() {
+	runConformTest(
+		new String[] {
+			"Example.java",
+			"\n" + 
+			"import java.time.Instant;\n" + 
+			"import java.util.Comparator;\n" + 
+			"import java.util.stream.Collectors;\n" + 
+			"\n" + 
+			"public class Example {\n" + 
+			"   public void test1() {\n" + 
+			"      // Returns Collector<Something,?,Something> - CORRECT\n" + 
+			"      Collectors.collectingAndThen(\n" + 
+			"            Collectors.<Something>toList(),\n" + 
+			"            list -> list.stream().sorted(Comparator.comparing(Something::getTime)).limit(1).findAny().orElse(null)\n" + 
+			"      );\n" + 
+			"   }\n" + 
+			"   \n" + 
+			"   public void test2() {\n" + 
+			"         Collectors.collectingAndThen(\n" + 
+			"            Collectors.<Something>toList(),\n" + 
+			"            list -> list.stream().collect(Collectors.groupingBy(Something::getSize,\n" + 
+			"                     // Returns Collector<Something,?,Object> - INCORRECT!\n" + 
+			"                     Collectors.collectingAndThen(\n" + 
+			"                        Collectors.<Something>toList(),\n" + 
+			"                        list2 -> list2.stream().sorted(Comparator.comparing(Something::getTime)).limit(1).findAny().orElse(null)\n" + 
+			"                     )\n" + 
+			"                  )));\n" + 
+			"   }\n" +
+			"   private interface Something {\n" + 
+			"      public int getSize();\n" + 
+			"      public Instant getTime();\n" + 
+			"  }\n" + 
+			"}\n"
+		});
+}
+public void _testBug487746_comment9() { // FIXME: still reports an unexpected error
+	runConformTest(
+		new String[] {
+			"Example.java",
+			"\n" + 
+			"import java.time.Instant;\n" + 
+			"import java.util.Comparator;\n" + 
+			"import java.util.List;\n" + 
+			"import java.util.stream.Collectors;\n" + 
+			"\n" + 
+			"public class Example {\n" + 
+			"	public void doesntCompile(List<Something> things) {\n" + 
+			"   	things.stream()\n" + 
+			"       	.filter(thing -> thing.getSize() > 100)\n" + 
+			"       	.collect(Collectors.collectingAndThen(\n" + 
+			"        	 	Collectors.<Something>toList(),\n" + 
+			"         		list -> list.stream().collect(Collectors.groupingBy(Something::getSize,\n" + 
+			"           	       	Collectors.collectingAndThen(\n" + 
+			"               	      Collectors.<Something>toList(),\n" + 
+			"                   	  list2 -> list2.stream().sorted(Comparator.comparing(Something::getTime)).limit(1).findAny().orElse(null)\n" + 
+			"                  		)\n" + 
+			"               ))))\n" + 
+			"   		.forEach((size, thing) -> {\n" + 
+			"       		System.out.println(thing.getSize());   // Compile error because Eclipse thinks 'thing' is Object\n" + 
+			"   		});\n" + 
+			"	}\n" + 
+			"   private interface Something {\n" + 
+			"      public int getSize();\n" + 
+			"      public Instant getTime();\n" + 
+			"  }\n" + 
+			"}\n"
+		});
+}
+public void testBug480075() {
+	runConformTest(
+		new String[] {
+			"X.java",
+			"import java.util.stream.*;\n" +
+			"public class X {\n" +
+			"	void test() {\n" +
+			"		IntStream.of(42).mapToObj(i -> i > 42 ? \"gt\" : i < 42 ? \"lt\" : \"42\").findFirst();\n" + 
+			"\n" + 
+			"		Stream.generate(Object::new).map(o -> o != null ? o : o == null ? o : o).findAny();\n" + 
+			"\n" + 
+			"	}\n" +
+			"}\n"
+		});
+}
+public void testBug488649() {
+	runNegativeTest(
+		new String[] {
+			"X.java",
+			"class A<T> {}\n" +
+			"public class X {\n" +
+			"	static <U> U get(A<U> a) { return null; }\n" +
+			"	void test(A a) {\n" +
+			"		get(a).missing();\n" +
+			"	}\n" +
+			"}\n"
+		},
+		"----------\n" + 
+		"1. WARNING in X.java (at line 4)\n" + 
+		"	void test(A a) {\n" + 
+		"	          ^\n" + 
+		"A is a raw type. References to generic type A<T> should be parameterized\n" + 
+		"----------\n" + 
+		"2. WARNING in X.java (at line 5)\n" + 
+		"	get(a).missing();\n" + 
+		"	^^^^^^\n" + 
+		"Type safety: Unchecked invocation get(A) of the generic method get(A<U>) of type X\n" + 
+		"----------\n" + 
+		"3. WARNING in X.java (at line 5)\n" + 
+		"	get(a).missing();\n" + 
+		"	    ^\n" + 
+		"Type safety: The expression of type A needs unchecked conversion to conform to A<Object>\n" + 
+		"----------\n" + 
+		"4. ERROR in X.java (at line 5)\n" + 
+		"	get(a).missing();\n" + 
+		"	       ^^^^^^^\n" + 
+		"The method missing() is undefined for the type Object\n" + 
+		"----------\n");
+}
+public void testBug488672() {
+	runConformTest(
+		new String[] {
+			"X.java",
+			"import java.util.*;\n" + 
+			"\n" + 
+			"public class X {\n" + 
+			"	void foo(Manager manager) {\n" + 
+			"		HashSet<String> activeBindings = new HashSet<>(manager.getActiveBindingsDisregardingContextFlat());\n" + 
+			"	}\n" + 
+			"}\n" + 
+			"\n" + 
+			"class Manager {\n" + 
+			"	Collection getActiveBindingsDisregardingContextFlat() {\n" + 
+			"		return null;\n" + 
+			"	}\n" + 
+			"}\n"
+		});
+}
+public void testBug488795() {
+	runConformTest(
+		new String[] {
+			"X.java",
+			"interface Parameter {}\n" +
+			"interface Parameters<S extends Parameters<S, T>, T extends Parameter> extends Iterable<T> {\n" +
+			"	S get();\n" +
+			"}\n" +
+			"public class X {\n" +
+			"	void test(Parameters<?,?> parameters) {\n" +
+			"		for(Parameter p : parameters.get())\n" +
+			"			System.out.println(p);\n" +
+			"	}\n" +
+			"}\n"
+		});
+}
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InnerEmulationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InnerEmulationTest.java
index f525875..ade8bf4 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InnerEmulationTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InnerEmulationTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2006, 2015 IBM Corporation and others.
+ * Copyright (c) 2006, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JSR335ClassFileTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JSR335ClassFileTest.java
index af65cdd..ec7fd34 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JSR335ClassFileTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JSR335ClassFileTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2013, 2014 Jesper Steen Moller, IBM and others.
+ * Copyright (c) 2013, 2016 Jesper Steen Moller, IBM and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -3212,7 +3212,7 @@
 				"}\n" +
 				"interface J {\n" +
 				"  public void foo();\n" +
-				"  public void bar();\n" +
+				"  public default void bar() {}\n" +
 				"}\n" +
 				"interface K {\n" +
 				"  public void foo();\n" +
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaExpressionsTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaExpressionsTest.java
index b426473..fc03010 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaExpressionsTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaExpressionsTest.java
@@ -24,6 +24,7 @@
 import org.eclipse.jdt.core.util.IClassFileReader;
 import org.eclipse.jdt.core.util.IMethodInfo;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.core.util.BootstrapMethodsAttribute;
 
 import junit.framework.Test;
 
@@ -4969,14 +4970,14 @@
 				"        SerializableFunction<List<String>, List<String>> f = X::foo;\n" +
 				"        Method[] methods = X.class.getDeclaredMethods();\n" +
 				"        for (Method m : methods) {\n" +
-				"        	if (m.getName().contains(\"lambda\")) {\n" +
+				"        	if (m.getName().contains(\"foo\")) {\n" +
 				"        		System.out.println(\"- \" + m.getGenericReturnType() + \" \" + m.getName() + \"(\" + Arrays.asList(m.getGenericParameterTypes()) + \")\");\n" +
 				"        	}\n" +
 				"        }\n" +
 				"    }\n" +
 				"}\n"
 			},
-			"- java.util.List<java.lang.String> lambda$0([java.util.List<java.lang.String>])");
+			"- java.util.List<java.lang.String> foo([java.util.List<java.lang.String>])");
 }
 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=447119, [1.8][compiler] method references lost generic type information (4.4 -> 4.4.1 regression) 
 public void test447119d() {
@@ -5017,9 +5018,9 @@
 				"	}\n" +
 				"}\n"
 			},
-			"Lambda binds to: X.lambda$0\n" + 
+			"Lambda binds to: X.noop\n" + 
 			"Methods (with generics):\n" + 
-			"[- java.util.List<java.lang.String> lambda$0(java.util.List<java.lang.String>), - java.util.List<java.lang.String> noop(java.util.List<java.lang.String>)]",
+			"[- java.util.List<java.lang.String> noop(java.util.List<java.lang.String>)]",
 			null,
 			true,
 			new String [] { "-Ddummy" }); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
@@ -5882,6 +5883,168 @@
 	},
 	"10");
 }
+public void testBug487586() {
+	runNegativeTest(
+		new String[] {
+			"X.java",
+			"\n" + 
+			"interface Calculator {\n" + 
+			"    public int calculate(int a, int b);\n" + 
+			"}\n" + 
+			"\n" + 
+			"interface Sumator {\n" + 
+			"    public int test();\n" + 
+			"\n" + 
+			"    public int test3(int a, int b);\n" + 
+			"}\n" + 
+			"\n" + 
+			"// intersection of both types\n" + 
+			"interface Both extends Sumator, Calculator {\n" + 
+			"\n" + 
+			"}\n" + 
+			"public class X {\n" + 
+			"  public static void main(String[] args) {\n" + 
+			"    Calculator test = (Calculator & Sumator) (a, b) -> a + b;\n" + 
+			"    System.out.println(test.calculate(2, 3));\n" + 
+			"\n" + 
+			"    Sumator sumator = (Calculator & Sumator) (a, b) -> a + b; // does compile, but throws an Exception\n" + 
+			"    sumator.test();\n" + 
+			"\n" + 
+			"    Both both = (Both) (a, b) -> a + b; // does not compile\n" + 
+			"  }\n" + 
+			"}\n"
+		},
+		"----------\n" + 
+		"1. ERROR in X.java (at line 18)\n" + 
+		"	Calculator test = (Calculator & Sumator) (a, b) -> a + b;\n" + 
+		"	                                         ^^^^^^^^^^^^^^^\n" + 
+		"The target type of this expression must be a functional interface\n" + 
+		"----------\n" + 
+		"2. ERROR in X.java (at line 21)\n" + 
+		"	Sumator sumator = (Calculator & Sumator) (a, b) -> a + b; // does compile, but throws an Exception\n" + 
+		"	                                         ^^^^^^^^^^^^^^^\n" + 
+		"The target type of this expression must be a functional interface\n" + 
+		"----------\n" + 
+		"3. ERROR in X.java (at line 24)\n" + 
+		"	Both both = (Both) (a, b) -> a + b; // does not compile\n" + 
+		"	                   ^^^^^^^^^^^^^^^\n" + 
+		"The target type of this expression must be a functional interface\n" + 
+		"----------\n");
+}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=452587 Java 8: Method references to the same method do not share BootstrapMethod
+public void testBug452587() {
+	this.runConformTest(
+		new String[] {
+			"Test.java",
+			" public class Test {\n" + 
+			"    public static void main(String[] args) {\n" + 
+			"      Runnable m = Test::m;\n" + 
+			"      Runnable n = Test::m;\n" + 
+			"      Runnable o = Test::m;\n" + 
+			"      Runnable p = Test::m;\n" + 
+			"      Runnable q = Test::m;\n" + 
+			"    }\n" + 
+			"    public static void m() {}\n" + 
+			"  }\n"
+	});
+	IClassFileReader classFileReader = ToolFactory.createDefaultClassFileReader(OUTPUT_DIR + File.separator + "Test.class", IClassFileReader.ALL);
+	BootstrapMethodsAttribute bootstrapMethodsAttribute = null;
+	IClassFileAttribute[] attrs = classFileReader.getAttributes();
+	for (int i=0,max=attrs.length;i<max;i++) {
+		if (new String(attrs[i].getAttributeName()).equals("BootstrapMethods")) {
+			bootstrapMethodsAttribute = (BootstrapMethodsAttribute)attrs[i];
+			break;
+		}
+	}
+	assertNotNull("BootstrapMethods attribute not found", bootstrapMethodsAttribute);
+	int bmaLength = bootstrapMethodsAttribute.getBootstrapMethodsLength();
+	assertEquals("Incorrect number of bootstrap methods found", 1, bmaLength);
+}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=485529 [1.8][compiler] Verify error with constructor reference to nested class constructor
+public void testBug485529() {
+	this.runConformTest(
+		new String[] {
+			"X.java",
+			"interface I {\n" + 
+			"	X makeX(int x);\n" + 
+			"}\n" + 
+			"public class X {\n" + 
+			"		class Y extends X {\n" + 
+			"			class Z extends X  {\n" + 
+			"				private Z(int z) {\n" + 
+			"				}\n" + 
+			"				private Z() {}\n" + 
+			"			}\n" + 
+			"			private Y(int y) {\n" + 
+			"			}\n" + 
+			"			 Y() {\n" + 
+			"			}\n" + 
+			"		}\n" + 
+			"		I i = Y :: new;\n" + 
+			"	private X(int x) {\n" + 
+			"	}\n" + 
+			"	\n" + 
+			"	X() {\n" + 
+			"	}\n" + 
+			"	public static void main(String[] args) {\n" + 
+			"		new X();\n" + 
+			"		\n" + 
+			"	}\n" + 
+			"}"
+	},
+	"");
+}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=479284 [1.8][inference] fail to resolve matching types for lambda and method reference + NPE at build
+public void testBug479284() {
+	runNegativeTest(
+		new String[] {
+			"BadInferenceMars451.java",
+			"package bug.report;\n" + 
+			"import java.util.ArrayList;\n" + 
+			"import java.util.Arrays;\n" + 
+			"import java.util.List;\n" + 
+			"import java.util.Map;\n" + 
+			"import java.util.function.BinaryOperator;\n" + 
+			"import java.util.function.Function;\n" + 
+			"import java.util.stream.Collectors;\n" + 
+			"/**\n" + 
+			" * Problem is valid on Version: Mars.1 Release (4.5.1) Build id: 20150924-1200\n" + 
+			" */\n" + 
+			"public class BadInferenceMars451 {\n" + 
+			"	public static Map<Object, List<X>> BadInferenceMars451Casus1() {\n" + 
+			"		List<X> stuff = new ArrayList<>();\n" + 
+			"		return stuff.stream().collect(Collectors.toMap(Function.identity(), t -> Arrays.asList(t), BadInferenceMars451::sum));\n" + 
+			"	}\n" + 
+			"	public static Map<Object, List<X>> BadInferenceMars451Casus1Fixed1() {\n" + 
+			"		List<X> stuff = new ArrayList<>();\n" + 
+			"		return stuff.stream().collect(Collectors.toMap(Function.identity(), t -> Arrays.asList(t), (BinaryOperator<List<X>>) BadInferenceMars451::sum));\n" + 
+			"	}\n" + 
+			"	public static Map<Object, List<X>> BadInferenceMars451Casus1Fixed2() {\n" + 
+			"		List<X> stuff = new ArrayList<>();\n" + 
+			"		return stuff.stream().collect(Collectors.toMap(Function.identity(), t -> Arrays.<X> asList(t), BadInferenceMars451::sum));\n" + 
+			"	}\n" + 
+			"	/* \n" + 
+			"	 * Uncomment this to see eclipse crash at build\n" + 
+			"	 * this doesnt work but it should not crash the ide\n" + 
+			"	 */ \n" + 
+			"	public static Map<Object, List<X>> BadInferenceMars451Casus1Crash() {\n" + 
+			"		List<X> stuff = new ArrayList<>();\n" + 
+			"		return stuff.stream().collect(Collectors.toMap(Function.identity(), t -> Arrays.asList(t), BadInferenceMars451<X>::sum));\n" + 
+			"	}\n" + 
+			"	public static <T> List<T> sum(List<T> l1, List<T> l2) {\n" + 
+			"		return null;\n" + 
+			"	}\n" + 
+			"	public static class X {\n" + 
+			"	}\n" + 
+			"}\n"
+		},
+		"----------\n" + 
+		"1. ERROR in BadInferenceMars451.java (at line 31)\n" + 
+		"	return stuff.stream().collect(Collectors.toMap(Function.identity(), t -> Arrays.asList(t), BadInferenceMars451<X>::sum));\n" + 
+		"	                                                                                           ^^^^^^^^^^^^^^^^^^^\n" + 
+		"The type BadInferenceMars451 is not generic; it cannot be parameterized with arguments <BadInferenceMars451.X>\n" + 
+		"----------\n");
+}
 public static Class testClass() {
 	return LambdaExpressionsTest.class;
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaRegressionTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaRegressionTest.java
index 0078f71..369f46d 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaRegressionTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaRegressionTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2016 IBM Corporation and others.
+ * Copyright (c) 2015, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -409,6 +409,11 @@
 	"	fl.call(each -> each.doSomething()); // fails\n" + 
 	"	   ^^^^\n" + 
 	"The method call(X.RightHand<? super X.Target>) is ambiguous for the type X.Concrete<X.Target>\n" + 
+	"----------\n" + 
+	"2. ERROR in X.java (at line 6)\n" + 
+	"	fl.call(Target::doSomething); // succeeds in Eclipse 4.5M3 and 4.4.1\n" + 
+	"	   ^^^^\n" + 
+	"The method call(X.RightHand<? super X.Target>) is ambiguous for the type X.Concrete<X.Target>\n" + 
 	"----------\n");
 }
 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=448954, [1.8][compiler] Suspect error: "The method foo(String, String, X::goo) is undefined for the type X"
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NegativeLambdaExpressionsTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NegativeLambdaExpressionsTest.java
index 85c739b..10131d7 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NegativeLambdaExpressionsTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NegativeLambdaExpressionsTest.java
@@ -7311,9 +7311,7 @@
 
 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=420598, [1.8][compiler] Incorrect error about intersection cast type not being a functional interface. 
 public void testIntersectionCast() {
-		this.runNegativeTest(
-			true /* skipJavac */,
-			JavacTestOptions.EclipseHasABug.EclipseBug424410,
+		this.runConformTest(
 			new String[] {
 					"X.java", 
 					"import java.io.Serializable;\n" +
@@ -7328,23 +7326,18 @@
 					"interface L {\n" +
 					"	void foo();\n" +
 					"}\n" +
+					"interface All extends J, I, K, L {}\n" +
 					"public class X {\n" +
 					"	public static void main(String[] args) {\n" +
 					"		I i = (I & Serializable) () -> {};\n" +
 					"		i = (I & J & K) () -> {};\n" +
 					"		i = (J & I & K) () -> {};  \n" +
 					"		i = (J & I & K & L) () -> {};  \n" +
+					"		i = (All) () -> {};\n" +
 					"	}\n" +
-					"}\n" + 
-					""
+					"}\n"
 			},
-			"----------\n" + 
-			"1. ERROR in X.java (at line 18)\n" + 
-			"	i = (J & I & K & L) () -> {};  \n" + 
-			"	                    ^^^^^\n" + 
-			"The target type of this expression is not a functional interface: more than one of the intersecting interfaces are functional\n" + 
-			"----------\n"
-		);
+			"");
 }
 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=421711, [1.8][compiler] '_' as identifier for a lambda parameter should be rejected.
 public void testUnderScoreParameter() {
@@ -9051,11 +9044,16 @@
 	    "	     ^^^^^^^^\n" +
 	    "The method removeIf(Predicate<? super Process>) in the type Collection<Process> is not applicable for the arguments ((int x) -> {})\n" +
 	    "----------\n" +
-	    "2. ERROR in X.java (at line 3)\n" +
-	    "	list.removeIf((int x) -> \"\");\n" +
-	    "	              ^^^^^^^^^^^^^\n" +
-	    "The target type of this expression is not a well formed parameterized type due to bound(s) mismatch\n" +
-	    "----------\n");
+	    "2. ERROR in X.java (at line 3)\n" + 
+		"	list.removeIf((int x) -> \"\");\n" + 
+		"	               ^^^\n" + 
+		"Lambda expression\'s parameter x is expected to be of type Process\n" + 
+		"----------\n" + 
+		"3. ERROR in X.java (at line 3)\n" + 
+		"	list.removeIf((int x) -> \"\");\n" + 
+		"	                         ^^\n" + 
+		"Type mismatch: cannot convert from String to boolean\n" + 
+		"----------\n");
 }
 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=424154,  [1.8][compiler] PolyTypeBinding must not render the full lambda body in error messages
 //Variations where return types or arguments mismatch or both.
@@ -9863,6 +9861,168 @@
 		"The blank final field s may not have been initialized\n" + 
 		"----------\n");
 }
+public void testBug487390() {
+	runNegativeTest(
+		new String[] {
+			"X.java",
+			"interface ConsumeN {\n" + 
+			"	void consume(String.. strings); // syntax error here\n" + 
+			"}\n" + 
+			"public class X {\n" + 
+			"\n" + 
+			"	void consu(ConsumeN c) { }\n" + 
+			"	void test() {\n" + 
+			"		consu((String... s) -> System.out.print(s.length));\n" + 
+			"	}\n" + 
+			"}"
+		},
+		"----------\n" + 
+		"1. ERROR in X.java (at line 2)\n" + 
+		"	void consume(String.. strings); // syntax error here\n" + 
+		"	                    ^\n" + 
+		"Syntax error on token \".\", Identifier expected\n" + 
+		"----------\n" + 
+		"2. ERROR in X.java (at line 8)\n" + 
+		"	consu((String... s) -> System.out.print(s.length));\n" + 
+		"	^^^^^\n" + 
+		"The method consu(ConsumeN) in the type X is not applicable for the arguments ((String... s) -> {})\n" + 
+		"----------\n" + 
+		"3. ERROR in X.java (at line 8)\n" + 
+		"	consu((String... s) -> System.out.print(s.length));\n" + 
+		"	      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
+		"Lambda expression\'s signature does not match the signature of the functional interface method consume()\n" + 
+		"----------\n");
+}
+public void testBug487390b() {
+	runNegativeTest(
+		new String[] {
+			"X.java",
+			"interface ConsumeN {\n" + 
+			"	void consume();\n" + 
+			"}\n" + 
+			"public class X {\n" + 
+			"\n" + 
+			"	void consu(ConsumeN c) { }\n" + 
+			"	void test() {\n" + 
+			"		consu((String... s) -> System.out.print(s.length));\n" + 
+			"	}\n" + 
+			"}"
+		},
+		"----------\n" + 
+		"1. ERROR in X.java (at line 8)\n" + 
+		"	consu((String... s) -> System.out.print(s.length));\n" + 
+		"	^^^^^\n" + 
+		"The method consu(ConsumeN) in the type X is not applicable for the arguments ((String... s) -> {})\n" + 
+		"----------\n" + 
+		"2. ERROR in X.java (at line 8)\n" + 
+		"	consu((String... s) -> System.out.print(s.length));\n" + 
+		"	      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
+		"Lambda expression\'s signature does not match the signature of the functional interface method consume()\n" + 
+		"----------\n");
+}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=458332, [1.8][compiler] only 409 method references/lambda expressions per class possible
+public void testBug458332() {
+	runNegativeTest(
+		new String[] {
+			"Test.java",
+			"import java.io.Serializable;\n" + 
+			"import java.util.function.Consumer;\n" + 
+			"public class Test {\n" + 
+			"	public static void main(String[] args) {\n" + 
+			"		System.out.println(Data.part1().length);\n" + 
+			"		System.out.println(Data.part2().length);\n" + 
+			"	}\n" + 
+			"	@FunctionalInterface\n" + 
+			"	private static interface MethodRef extends Consumer<String[]>, Serializable {}\n" + 
+			"	private static class Data {\n" + 
+			"		static MethodRef[] part1() {\n" + 
+			"			return new MethodRef[] {\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"				};\n" + 
+			"		}\n" + 
+			"		static MethodRef[] part2() {\n" + 
+			"			return new MethodRef[] {\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"					Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main, Test::main,\n" + 
+			"				};\n" + 
+			"		}\n" + 
+			"	}\n" + 
+			"}\n"
+		},
+		"----------\n" + 
+		"1. ERROR in Test.java (at line 10)\n" + 
+		"	private static class Data {\n" + 
+		"	                     ^^^^\n" + 
+		"The code of method $deserializeLambda$(SerializedLambda) is exceeding the 65535 bytes limit\n" + 
+		"----------\n");
+}
 public static Class testClass() {
 	return NegativeLambdaExpressionsTest.class;
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NonFatalErrorTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NonFatalErrorTest.java
index e7d516a..434ea2c 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NonFatalErrorTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NonFatalErrorTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -12,6 +12,7 @@
 
 import java.util.Map;
 
+import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 
@@ -297,4 +298,213 @@
 				// compiler results
 				null /* do not check error string */);
 	}
+	public void testImportUnresolved() {
+		Map<String,String> options = getCompilerOptions();
+		options.put(JavaCore.COMPILER_PB_UNUSED_IMPORT, JavaCore.ERROR);
+		runNegativeTest(
+			true, // flush dir
+			new String[] {
+				"X.java",
+				"import com.bogus.Missing;\n" +
+				"public class X {\n" +
+				"	public static void main(String[] args) {\n" +
+				"		new X().test();\n" +
+				"	}\n" +
+				"	void test() {\n" +
+				"		System.out.println(\"OK\");\n" +
+				"	}\n" +
+				"}\n"
+			},
+			null, // libs
+			options,
+			"----------\n" + 
+			"1. ERROR in X.java (at line 1)\n" + 
+			"	import com.bogus.Missing;\n" + 
+			"	       ^^^^^^^^^\n" + 
+			"The import com.bogus cannot be resolved\n" + 
+			"----------\n",
+			"OK",
+			"",
+			JavacTestOptions.SKIP);
+	}
+	public void testImportUnresolved_fatal() {
+		Map<String,String> options = getCompilerOptions();
+		options.put(JavaCore.COMPILER_PB_UNUSED_IMPORT, JavaCore.ERROR);
+		options.put(JavaCore.COMPILER_PB_FATAL_OPTIONAL_ERROR, JavaCore.ENABLED);
+		runNegativeTest(
+			true, // flush dir
+			new String[] {
+				"p/Z.java",
+				"package p;\n" +
+				"public class Z {\n" +
+				"	public static void main(String[] args) throws Exception {\n" +
+				"		try {\n" +
+				"			Class.forName(\"X\").newInstance();\n" + // forward reference, workaround by using reflection
+				"		} catch (java.lang.Error e) {\n" +
+				"			System.err.println(e.getMessage());\n" +
+				"		}\n" +
+				"	}\n" +
+				"}\n",
+				"X.java",
+				"import com.bogus.Missing;\n" +
+				"public class X {\n" +
+				"	public static void main(String[] args) {\n" +
+				"		new X().test();\n" +
+				"	}\n" +
+				"	void test() {\n" +
+				"		System.out.println(\"OK\");\n" +
+				"	}\n" +
+				"}\n"
+			},
+			null, // libs
+			options,
+			"----------\n" + 
+			"1. ERROR in X.java (at line 1)\n" + 
+			"	import com.bogus.Missing;\n" + 
+			"	       ^^^^^^^^^\n" + 
+			"The import com.bogus cannot be resolved\n" + 
+			"----------\n",
+			"",
+			"Unresolved compilation problem: \n" + 
+			"	The import com.bogus cannot be resolved",
+			JavacTestOptions.SKIP);
+	}
+	public void testPackageConflict() {
+		runNegativeTest(
+			true, // flush dir
+			new String[] {
+				"p/z.java",
+				"package p;\n" +
+				"public class z {\n" +
+				"	public static void main(String[] args) throws Exception {\n" +
+				"		try {\n" +
+				"			Class.forName(\"p.z.X\").newInstance();\n" +
+				"		} catch (ClassNotFoundException e) {\n" +
+				"			System.out.println(e.getClass().getName());\n" +
+				"		}\n" +
+				"	}\n" +
+				"}\n",
+				"p/z/X.java",
+				"package p.z;\n" +
+				"public class X {\n" +
+				"	public X() {\n" +
+				"		System.out.println(\"OK\");\n" +
+				"	}\n" +
+				"}\n",
+			},
+			null, // libs
+			getCompilerOptions(),
+			"----------\n" + 
+			"1. ERROR in p\\z\\X.java (at line 1)\n" + 
+			"	package p.z;\n" + 
+			"	        ^^^\n" + 
+			"The package p.z collides with a type\n" + 
+			"----------\n",
+			"java.lang.ClassNotFoundException", // cannot generate code in presence of the above error
+			"",
+			JavacTestOptions.SKIP);
+	}
+	public void testImportVariousProblems() {
+		runNegativeTest(
+			true, // flush dir
+			new String[] {
+				"p/Z.java",
+				"package p;\n" +
+				"public class Z {\n" +
+				"	public static void main(String[] args) throws Exception {\n" +
+				"		try {\n" +
+				"			Class.forName(\"X\").newInstance();\n" + // forward reference, workaround by using reflection
+				"		} catch (ClassNotFoundException e) {\n" +
+				"			System.out.println(e.getClass().getName());\n" +
+				"		}\n" +
+				"	}\n" +
+				"}\n",
+				"p1/Y.java",
+				"package p1;\n" +
+				"public class Y {}\n",
+				"p2/Y.java",
+				"package p2;\n" +
+				"public class Y {}\n",
+				"X.java",
+				"import java.util;\n" +
+				"import p.Z;\n" +
+				"import p1.Y;\n" +
+				"import p2.Y;\n" +
+				"public class X {\n" +
+				"	public X() {\n" +
+				"		System.out.println(\"OK\");\n" +
+				"	}\n" +
+				"}\n" +
+				"class Z {}\n"
+			},
+			null, // libs
+			getCompilerOptions(),
+			"----------\n" + 
+			"1. ERROR in X.java (at line 1)\n" + 
+			"	import java.util;\n" + 
+			"	       ^^^^^^^^^\n" + 
+			"Only a type can be imported. java.util resolves to a package\n" + 
+			"----------\n" + 
+			"2. ERROR in X.java (at line 2)\n" + 
+			"	import p.Z;\n" + 
+			"	       ^^^\n" + 
+			"The import p.Z conflicts with a type defined in the same file\n" + 
+			"----------\n" + 
+			"3. ERROR in X.java (at line 4)\n" + 
+			"	import p2.Y;\n" + 
+			"	       ^^^^\n" + 
+			"The import p2.Y collides with another import statement\n" + 
+			"----------\n",
+			"OK",
+			"",
+			JavacTestOptions.SKIP);
+	}
+	public void testImportStaticProblems() {
+		if (this.complianceLevel < ClassFileConstants.JDK1_5) return; // uses static imports
+		runNegativeTest(
+			true, // flush dir
+			new String[] {
+				"p/Z.java",
+				"package p;\n" +
+				"public class Z {\n" +
+				"	public static void main(String[] args) throws Exception {\n" +
+				"		try {\n" +
+				"			Class.forName(\"X\").newInstance();\n" + // forward reference, workaround by using reflection
+				"		} catch (ClassNotFoundException e) {\n" +
+				"			System.out.println(e.getClass().getName());\n" +
+				"		}\n" +
+				"	}\n" +
+				"}\n",
+				"p1/Y.java",
+				"package p1;\n" +
+				"public class Y {\n" +
+				"	static int f;\n" +
+				"}\n",
+				"X.java",
+				"import static p1.Y;\n" +
+				"import static p1.Y.f;\n" +
+				"public class X {\n" +
+				"	public X() {\n" +
+				"		System.out.println(\"OK\");\n" +
+				"	}\n" +
+				"}\n" +
+				"class Z {}\n"
+			},
+			null, // libs
+			getCompilerOptions(),
+			"----------\n" + 
+			"1. ERROR in X.java (at line 1)\n" + 
+			"	import static p1.Y;\n" + 
+			"	              ^^^^\n" + 
+			"The static import p1.Y must be a field or member type\n" + 
+			"----------\n" + 
+			"2. ERROR in X.java (at line 2)\n" + 
+			"	import static p1.Y.f;\n" + 
+			"	              ^^^^^^\n" + 
+			"The field Y.p1.Y.f is not visible\n" + 
+			"----------\n",
+			"OK",
+			"",
+			JavacTestOptions.SKIP);
+	}
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java
index 792f9e2..64b32ce 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java
@@ -8115,7 +8115,11 @@
 		"Null type safety: The expression of type \'T\' needs unchecked conversion to conform to \'@NonNull T\'\n" + 
 		"----------\n"
 		:
-		""));
+		"3. WARNING in EclipseBug.java (at line 10)\n" + 
+		"	return commandType.newInstance();\n" + 
+		"	       ^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
+		"Unsafe interpretation of method return type as \'@NonNull\' based on the receiver type \'@NonNull Class<T extends @NonNull String>\'. Type \'Class<T>\' doesn\'t seem to be designed with null type annotations in mind\n" + 
+		"----------\n"));
 }
 public void testBug459967_Enum_valueOf() {
 	runConformTestWithLibs(
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullChecksTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullChecksTests.java
new file mode 100644
index 0000000..68677dd
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullChecksTests.java
@@ -0,0 +1,313 @@
+package org.eclipse.jdt.core.tests.compiler.regression;
+
+import java.util.Map;
+
+import org.eclipse.jdt.core.JavaCore;
+
+import junit.framework.Test;
+
+public class NullChecksTests extends AbstractNullAnnotationTest {
+
+	public NullChecksTests(String name) {
+		super(name);
+	}
+
+	// Static initializer to specify tests subset using TESTS_* static variables
+	// All specified tests which do not belong to the class are skipped...
+	static {
+//			TESTS_NAMES = new String[] { "testAssertNonNull1" };
+//			TESTS_NUMBERS = new int[] { 561 };
+//			TESTS_RANGE = new int[] { 1, 2049 };
+	}
+
+	public static Test suite() {
+		return buildMinimalComplianceTestSuite(testClass(), F_1_8);
+	}
+
+	public static Class<NullChecksTests> testClass() {
+		return NullChecksTests.class;
+	}
+
+	public void testAssertNonNull1() {
+		runConformTestWithLibs(
+			new String[] {
+				"X.java",
+				"import org.eclipse.jdt.annotation.*;\n" +
+				"import static org.eclipse.jdt.annotation.Checks.*;\n" +
+				"public class X {\n" +
+				"	@SuppressWarnings(\"null\")\n" +
+				"	static @NonNull String hide(String some) {\n" +
+				"		return some;\n" +
+				"	}\n" +
+				"	public static void main(String... args) {\n" +
+				"		@NonNull String myHiddenNull = hide(null);\n" +
+				"		try {\n" +
+				"			assertNonNull(\"foo\", myHiddenNull);\n" +
+				"		} catch (NullPointerException npe) {\n" +
+				"			System.out.println(npe.getMessage());\n" +
+				"		}\n" +
+				"		try {\n" +
+				"			assertNonNullWithMessage(\"Shouldn't!\", \"foo\", myHiddenNull);\n" +
+				"		} catch (NullPointerException npe) {\n" +
+				"			System.out.println(npe.getMessage());\n" +
+				"		}\n" +
+				"	}\n" +
+				"}\n"
+			},
+			getCompilerOptions(),
+			"",
+			"Value in position 1 must not be null\n" + 
+			"Shouldn\'t!");
+	}
+
+	public void testAssertNonNullElements() {
+		runConformTestWithLibs(
+			new String[] {
+				"X.java",
+				"import org.eclipse.jdt.annotation.*;\n" +
+				"import static org.eclipse.jdt.annotation.Checks.*;\n" +
+				"import java.util.*;\n" +
+				"public class X {\n" +
+				"	@SuppressWarnings(\"null\")\n" +
+				"	static @NonNull String hide(String some) {\n" +
+				"		return some;\n" +
+				"	}\n" +
+				"	public static void main(String... args) {\n" +
+				"		@NonNull List<String> myList = new ArrayList<>();\n" +
+				"		myList.add(\"foo\");\n" +
+				"		myList.add(null);\n" +
+				"		try {\n" +
+				"			assertNonNullElements(myList);\n" +
+				"		} catch (NullPointerException npe) {\n" +
+				"			System.out.println(npe.getMessage());\n" +
+				"		}\n" +
+				"		@NonNull List<@NonNull String> myList2 = new ArrayList<>();\n" +
+				"		myList2.add(\"foo\");\n" +
+				"		myList2.add(hide(null));\n" +
+				"		try {\n" +
+				"			assertNonNullElements(myList2, \"Shouldn't!\");\n" +
+				"		} catch (NullPointerException npe) {\n" +
+				"			System.out.println(npe.getMessage());\n" +
+				"		}\n" +
+				"	}\n" +
+				"}\n"
+			},
+			getCompilerOptions(),
+			"",
+			"Value in position 1 must not be null\n" + 
+			"Shouldn\'t!");
+	}
+
+	public void testRequireNonNull() {
+		runConformTestWithLibs(
+			new String[] {
+				"X.java",
+				"import org.eclipse.jdt.annotation.*;\n" +
+				"import static org.eclipse.jdt.annotation.Checks.*;\n" +
+				"public class X {\n" +
+				"	@SuppressWarnings(\"null\")\n" +
+				"	static @NonNull String hide(String some) {\n" +
+				"		return some;\n" +
+				"	}\n" +
+				"	static void test(@Nullable String str, @Nullable X x) {\n" +
+				"		@NonNull String nnStr;\n" +
+				"		@NonNull X nnX;\n" +
+				"		try {\n" +
+				"			nnStr = requireNonNull(str);\n" +
+				"			nnX = requireNonNull(null, \"Shouldn\'t!\");\n" +
+				"		} catch (NullPointerException npe) {\n" +
+				"			System.out.println(npe.getMessage());\n" +
+				"		}\n" +
+				"	}\n" +
+				"	public static void main(String... args) {\n" +
+				"		test(\"foo\", null);\n" +
+				"	}\n" +
+				"}\n"
+			},
+			getCompilerOptions(),
+			"",
+			"Shouldn\'t!");
+	}
+
+	public void testRequireNonEmptyString() {
+		runConformTestWithLibs(
+			new String[] {
+				"X.java",
+				"import org.eclipse.jdt.annotation.*;\n" +
+				"import static org.eclipse.jdt.annotation.Checks.*;\n" +
+				"public class X {\n" +
+				"	@SuppressWarnings(\"null\")\n" +
+				"	static @NonNull String hide(String some) {\n" +
+				"		return some;\n" +
+				"	}\n" +
+				"	static void test(@Nullable String str1, @Nullable String str2) {\n" +
+				"		@NonNull String nnStr;\n" +
+				"		try {\n" +
+				"			nnStr = requireNonEmpty(str1);\n" +
+				"		} catch (NullPointerException npe) {\n" +
+				"			System.out.println(\"npe:\"+npe.getMessage());\n" +
+				"		}\n" +
+				"		try {\n" +
+				"			nnStr = requireNonEmpty(str2, \"Shouldn't!\");\n" +
+				"		} catch (NullPointerException npe) {\n" +
+				"			System.out.println(\"npe\"+npe.getMessage());\n" +
+				"		} catch (IllegalArgumentException iae) {\n" +
+				"			System.out.println(iae.getMessage());\n" +
+				"		}\n" +
+				"	}\n" +
+				"	public static void main(String... args) {\n" +
+				"		test(null, \"\");\n" +
+				"	}\n" +
+				"}\n"
+			},
+			getCompilerOptions(),
+			"",
+			"npe:null\n" +
+			"Shouldn\'t!");
+	}
+
+	public void testRequireNonEmptyCollection() {
+		runConformTestWithLibs(
+			new String[] {
+				"X.java",
+				"import java.util.*;\n" +
+				"import org.eclipse.jdt.annotation.*;\n" +
+				"import static org.eclipse.jdt.annotation.Checks.*;\n" +
+				"public class X {\n" +
+				"	static void test(@Nullable Collection<String> strs, @Nullable Collection<String> strs1, Collection<String> strs2) {\n" +
+				"		@NonNull Collection<String> nnStrs;\n" +
+				"		try {\n" +
+				"			nnStrs = requireNonEmpty(strs);\n" +
+				"		} catch (NullPointerException npe) {\n" +
+				"			System.out.println(\"NPE:\"+npe.getMessage());\n" +
+				"		}\n" +
+				"		try {\n" +
+				"			nnStrs = requireNonEmpty(strs1);\n" +
+				"		} catch (NullPointerException npe) {\n" +
+				"			System.out.println(\"npe:\"+npe.getMessage());\n" +
+				"		}\n" +
+				"		try {\n" +
+				"			nnStrs = requireNonEmpty(strs2, \"Shouldn't!\");\n" +
+				"		} catch (NullPointerException npe) {\n" +
+				"			System.out.println(\"npe\"+npe.getMessage());\n" +
+				"		} catch (IllegalArgumentException iae) {\n" +
+				"			System.out.println(iae.getMessage());\n" +
+				"		}\n" +
+				"	}\n" +
+				"	public static void main(String... args) {\n" +
+				"		test(Collections.singletonList(\"good\"), null, Collections.emptyList());\n" +
+				"	}\n" +
+				"}\n"
+			},
+			getCompilerOptions(),
+			"",
+			"npe:null\n" +
+			"Shouldn\'t!");
+	}
+	
+	public void testIsNull() {
+		Map<String, String> compilerOptions = getCompilerOptions();
+		compilerOptions.put(JavaCore.COMPILER_PB_SUPPRESS_OPTIONAL_ERRORS, JavaCore.ENABLED);
+		runConformTestWithLibs(
+			new String[] {
+				"X.java",
+				"import org.eclipse.jdt.annotation.*;\n" +
+				"import static org.eclipse.jdt.annotation.Checks.*;\n" +
+				"public class X {\n" +
+				"	@SuppressWarnings(\"null\")\n" +
+				"	static <T> @NonNull T hide(T some) {\n" +
+				"		return some;\n" +
+				"	}\n" +
+				"	static void test(@NonNull X x1, @NonNull X x2, @NonNull X x3) {\n" +
+				"		if (isNull(x1))\n" +
+				"			System.out.println(\"IS NULL\");\n" +
+				"		if (isAnyNull(x2, x1))\n" +
+				"			System.out.println(\"IS ANY NULL 1\");\n" +
+				"		if (isAnyNull(x2, x3))\n" +
+				"			System.out.println(\"IS ANY NULL 2\");\n" +
+				"	}\n" +
+				"	public static void main(String... args) {\n" +
+				"		test(hide(null), new X(), new X());\n" +
+				"	}\n" +
+				"}\n"					
+			},
+			compilerOptions,
+			"",
+			"IS NULL\n" +
+			"IS ANY NULL 1");
+	}
+	
+	public void testAsNullable() {
+		runConformTestWithLibs(
+			new String[] {
+				"X.java",
+				"import java.util.*;\n" +
+				"import static org.eclipse.jdt.annotation.Checks.*;\n" +
+				"public class X {\n" +
+				"	static void test(Optional<X> xopt) {\n" +
+				"		if (xopt != null) {\n" +
+				"			X x = asNullable(xopt);\n" +
+				"			if (x == null)\n" +
+				"				System.out.println(\"NULL\");\n" +
+				"		}\n" +
+				"	}\n" +
+				"	public static void main(String... args) {\n" +
+				"		test(Optional.ofNullable(null));\n" +
+				"	}\n" +
+				"}\n"					
+			},
+			getCompilerOptions(),
+			"",
+			"NULL");
+	}
+	
+	public void testNonNullElse() {
+		runConformTestWithLibs(
+			new String[] {
+				"X.java",
+				"import java.util.function.*;\n" +
+				"import org.eclipse.jdt.annotation.*;\n" +
+				"import static org.eclipse.jdt.annotation.Checks.*;\n" +
+				"public class X {\n" +
+				"	static void test(String str, String noStr, @NonNull Supplier<@NonNull String> prov) {\n" +
+				"		System.out.println(nonNullElse(str, \"ELSE1\"));\n" +
+				"		System.out.println(nonNullElse(noStr, \"ELSE2\"));\n" +
+				"		System.out.println(nonNullElseGet(str, () -> \"ELSE3\"));\n" +
+				"		System.out.println(nonNullElseGet(noStr, prov));\n" +
+				"	}\n" +
+				"	public static void main(String... args) {\n" +
+				"		test(\"good\", null, () -> \"ELSE4\");\n" +
+				"	}\n" +
+				"}\n"					
+			},
+			getCompilerOptions(),
+			"",
+			"good\n" +
+			"ELSE2\n" +
+			"good\n" +
+			"ELSE4");
+	}
+	
+	public void _testIfNonNull() { // FIXME: see https://bugs.eclipse.org/489609 - [1.8][null] null annotation on wildcard is dropped during inference
+		runConformTestWithLibs(
+			new String[] {
+				"X.java",
+				"import org.eclipse.jdt.annotation.*;\n" +
+				"import static org.eclipse.jdt.annotation.Checks.*;\n" +
+				"public class X {\n" +
+				"	static void test(@Nullable String str) {\n" +
+				"		ifNonNull(str, s -> print(s));\n" +
+				"	}\n" +
+				"	static void print(@NonNull String s) {\n" +
+				"		System.out.print(s);\n" +
+				"	}\n" +
+				"	public static void main(String... args) {\n" +
+				"		test(\"good\");\n" +
+				"	}\n" +
+				"}\n"					
+			},
+			getCompilerOptions(),
+			"",
+			"good");
+	}
+}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java
index 10401b2..14d4d19 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java
@@ -10251,11 +10251,16 @@
 			"    }\n" +
 			"  }\n" +
 			"}\n"},
-		"----------\n" +
-		"1. ERROR in X.java (at line 7)\n" +
-		"	if (a == null) {\n" +
-		"	    ^\n" +
-		"Redundant null check: The variable a can only be null at this location\n" +
+		"----------\n" + 
+		"1. ERROR in X.java (at line 6)\n" + 
+		"	a = null;\n" + 
+		"	^\n" + 
+		"Redundant assignment: The variable a can only be null at this location\n" + 
+		"----------\n" + 
+		"2. ERROR in X.java (at line 7)\n" + 
+		"	if (a == null) {\n" + 
+		"	    ^\n" + 
+		"Redundant null check: The variable a can only be null at this location\n" + 
 		"----------\n",
 	    JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
 }
@@ -10281,18 +10286,23 @@
 			"    }\n" +
 			"  }\n" +
 			"}\n"},
-		"----------\n" +
-		"1. ERROR in X.java (at line 7)\n" +
-		"	if (a == null) {\n" +
-		"	    ^\n" +
-		"Redundant null check: The variable a can only be null at this location\n" +
-		"----------\n" +
-		"2. ERROR in X.java (at line 13)\n" +
-		"	if (a == null) {\n" +
-		"	    ^\n" +
-		"Null comparison always yields false: The variable a cannot be null at this location\n" +
-		"----------\n" +
-		"3. WARNING in X.java (at line 13)\n" + 
+		"----------\n" + 
+		"1. ERROR in X.java (at line 6)\n" + 
+		"	a = null;\n" + 
+		"	^\n" + 
+		"Redundant assignment: The variable a can only be null at this location\n" + 
+		"----------\n" + 
+		"2. ERROR in X.java (at line 7)\n" + 
+		"	if (a == null) {\n" + 
+		"	    ^\n" + 
+		"Redundant null check: The variable a can only be null at this location\n" + 
+		"----------\n" + 
+		"3. ERROR in X.java (at line 13)\n" + 
+		"	if (a == null) {\n" + 
+		"	    ^\n" + 
+		"Null comparison always yields false: The variable a cannot be null at this location\n" + 
+		"----------\n" + 
+		"4. WARNING in X.java (at line 13)\n" + 
 		"	if (a == null) {\n" + 
 		"      System.out.println();\n" + 
 		"    }\n" + 
@@ -13335,7 +13345,10 @@
 }
 // variation with nested loops.
 public void testBug321926l() {
-	this.runConformTest(
+	Map options = getCompilerOptions();
+	options.put(JavaCore.COMPILER_PB_REDUNDANT_NULL_CHECK, JavaCore.WARNING);
+
+	this.runTest(
 		new String[] {
 			"X.java",
 			"import java.io.IOException;\n" +
@@ -13374,7 +13387,22 @@
 			"	 }\n" +
 			"  }\n" +
 			"}"},
-		"Compiler good Compiler good");
+		 false,
+		 "----------\n" + 
+		"1. WARNING in X.java (at line 8)\n" + 
+		"	someVariable = null;\n" + 
+		"	^^^^^^^^^^^^\n" + 
+		"Redundant assignment: The variable someVariable can only be null at this location\n" + 
+		"----------\n",
+		"Compiler good Compiler good", 
+		"",
+		true, // force execution
+		null, // classlibs
+		true, // flush output,
+		null, // vm args
+		options,	
+		null,
+		null);
 }
 public void testBug321926m() {
 	this.runConformTest(
@@ -17681,4 +17709,269 @@
 		"Potential null pointer access: The variable s may be null at this location\n" + 
 		"----------\n");
 }
+public void testBug486912KnownNullInLoop() {
+	runNegativeTest(
+		new String[] {
+			"test/KnownNullInLoop.java",
+			"package test;\n" +
+			"\n" +
+			"public class KnownNullInLoop {\n" +
+			"	public void testDoWhile() {\n" +
+			"		Object o1 = null;\n" +
+			"		do {\n" +
+			"			o1.hashCode(); // ERROR1: known null, but no problem reported.\n" +
+			"		} while (false);\n" +
+			"	}\n" +
+			"\n" +
+			"	public void testWhileWithBreak() {\n" +
+			"		Object o1 = null;\n" +
+			"		while (true) {\n" +
+			"			o1.hashCode(); // ERROR2: known null, but no problem reported.\n" +
+			"			break;\n" +
+			"		}\n" +
+			"	}\n" +
+			"}\n" +
+			"",
+		}, 
+		"----------\n" + 
+		"1. ERROR in test\\KnownNullInLoop.java (at line 7)\n" + 
+		"	o1.hashCode(); // ERROR1: known null, but no problem reported.\n" + 
+		"	^^\n" + 
+		"Null pointer access: The variable o1 can only be null at this location\n" + 
+		"----------\n" + 
+		"2. ERROR in test\\KnownNullInLoop.java (at line 14)\n" + 
+		"	o1.hashCode(); // ERROR2: known null, but no problem reported.\n" + 
+		"	^^\n" + 
+		"Null pointer access: The variable o1 can only be null at this location\n" + 
+		"----------\n"
+	);
+}
+public void testBug486912PotNullInLoop_orig() {
+	runNegativeTest(
+		new String[] {
+			"test/PotNullInLoop.java",
+			"package test;\n" +
+			"\n" +
+			"public class PotNullInLoop {\n" +
+			"	boolean b;\n" +
+			"\n" +
+			"	public void testDoWhile1() {\n" +
+			"		Object o1 = null;\n" +
+			"		Object o2 = new Object();\n" +
+			"		Object potNonNull = b ? o2 : o2;\n" + // actually: def nn
+			"		Object potNull = b ? o1 : o1;\n" +	  // actually: def n
+			"		Object ponNullOrNonNull = b ? potNull : potNonNull;\n" +
+			"		do {\n" +
+			"			potNonNull.hashCode(); // OK\n" +
+			"			potNull.hashCode(); // ERROR 1: pot null, but nothing reported\n" +
+			"			ponNullOrNonNull.hashCode(); // ERROR 2: pot null, but nothing reported\n" +
+			"		} while (false);\n" +
+			"	}\n" +
+			"\n" +
+			"	public void testWhileWithBreak() {\n" +
+			"		Object o1 = null;\n" +
+			"		Object o2 = new Object();\n" +
+			"		Object potNonNull = b ? o2 : o2;\n" +
+			"		Object potNull = b ? o1 : o1;\n" +
+			"		Object ponNullOrNonNull = b ? potNull : potNonNull;\n" +
+			"		while (b) {\n" +
+			"			potNonNull.hashCode(); // OK\n" +
+			"			potNull.hashCode(); // ERROR 3 : pot null, but nothing reported\n" +
+			"			ponNullOrNonNull.hashCode(); // ERROR 4: pot null, but nothing reported\n" +
+			"			break;\n" +
+			"		}\n" +
+			"	}\n" +
+			"\n" +
+			"	public void testWhile() {\n" +
+			"		Object o1 = null;\n" +
+			"		Object o2 = new Object();\n" +
+			"		Object potNonNull = b ? o2 : o2;\n" +
+			"		Object potNull = b ? o1 : o1;\n" +
+			"		Object ponNullOrNonNull = b ? potNull : potNonNull;\n" +
+			"		while (b) {\n" +
+			"			potNonNull.hashCode(); // OK\n" +
+			"			potNull.hashCode(); // OK: pot null, is reported\n" +
+			"			ponNullOrNonNull.hashCode(); // OK: pot null, is reported\n" +
+			"		}\n" +
+			"	}\n" +
+			"\n" +
+			"	public void testFor() {\n" +
+			"		Object o1 = null;\n" +
+			"		Object o2 = new Object();\n" +
+			"		Object potNonNull = b ? o2 : o2;\n" +
+			"		Object potNull = b ? o1 : o1;\n" +
+			"		Object ponNullOrNonNull = b ? potNull : potNonNull;\n" +
+			"		for (int i = 0; i < 1; i++) {\n" +
+			"			potNonNull.hashCode(); // OK\n" +
+			"			potNull.hashCode(); // OK: pot null, is reported\n" +
+			"			ponNullOrNonNull.hashCode(); // OK: pot null, is reported\n" +
+			"		}\n" +
+			"	}\n" +
+			"\n" +
+			"	public void testForEach() {\n" +
+			"		Object o1 = null;\n" +
+			"		Object o2 = new Object();\n" +
+			"		Object potNonNull = b ? o2 : o2;\n" +
+			"		Object potNull = b ? o1 : o1;\n" +
+			"		Object ponNullOrNonNull = b ? potNull : potNonNull;\n" +
+			"		for (int i = 0; i < 1; i++) {\n" +
+			"			potNonNull.hashCode(); // OK\n" +
+			"			potNull.hashCode(); // OK: pot null, is reported\n" +
+			"			ponNullOrNonNull.hashCode(); // OK: pot null, is reported\n" +
+			"		}\n" +
+			"	}\n" +
+			"\n" +
+			"}\n" +
+			"",
+		}, 
+		"----------\n" + 
+		"1. ERROR in test\\PotNullInLoop.java (at line 14)\n" + 
+		"	potNull.hashCode(); // ERROR 1: pot null, but nothing reported\n" + 
+		"	^^^^^^^\n" + 
+		"Null pointer access: The variable potNull can only be null at this location\n" + 
+		"----------\n" + 
+		"2. ERROR in test\\PotNullInLoop.java (at line 15)\n" + 
+		"	ponNullOrNonNull.hashCode(); // ERROR 2: pot null, but nothing reported\n" + 
+		"	^^^^^^^^^^^^^^^^\n" + 
+		"Potential null pointer access: The variable ponNullOrNonNull may be null at this location\n" + 
+		"----------\n" + 
+		"3. ERROR in test\\PotNullInLoop.java (at line 27)\n" + 
+		"	potNull.hashCode(); // ERROR 3 : pot null, but nothing reported\n" + 
+		"	^^^^^^^\n" + 
+		"Null pointer access: The variable potNull can only be null at this location\n" + 
+		"----------\n" + 
+		"4. ERROR in test\\PotNullInLoop.java (at line 28)\n" + 
+		"	ponNullOrNonNull.hashCode(); // ERROR 4: pot null, but nothing reported\n" + 
+		"	^^^^^^^^^^^^^^^^\n" + 
+		"Potential null pointer access: The variable ponNullOrNonNull may be null at this location\n" + 
+		"----------\n" + 
+		"5. ERROR in test\\PotNullInLoop.java (at line 41)\n" + 
+		"	potNull.hashCode(); // OK: pot null, is reported\n" + 
+		"	^^^^^^^\n" + 
+		"Null pointer access: The variable potNull can only be null at this location\n" + 
+		"----------\n" + 
+		"6. ERROR in test\\PotNullInLoop.java (at line 42)\n" + 
+		"	ponNullOrNonNull.hashCode(); // OK: pot null, is reported\n" + 
+		"	^^^^^^^^^^^^^^^^\n" + 
+		"Potential null pointer access: The variable ponNullOrNonNull may be null at this location\n" + 
+		"----------\n" + 
+		"7. ERROR in test\\PotNullInLoop.java (at line 54)\n" + 
+		"	potNull.hashCode(); // OK: pot null, is reported\n" + 
+		"	^^^^^^^\n" + 
+		"Null pointer access: The variable potNull can only be null at this location\n" + 
+		"----------\n" + 
+		"8. ERROR in test\\PotNullInLoop.java (at line 55)\n" + 
+		"	ponNullOrNonNull.hashCode(); // OK: pot null, is reported\n" + 
+		"	^^^^^^^^^^^^^^^^\n" + 
+		"Potential null pointer access: The variable ponNullOrNonNull may be null at this location\n" + 
+		"----------\n" + 
+		"9. ERROR in test\\PotNullInLoop.java (at line 67)\n" + 
+		"	potNull.hashCode(); // OK: pot null, is reported\n" + 
+		"	^^^^^^^\n" + 
+		"Null pointer access: The variable potNull can only be null at this location\n" + 
+		"----------\n" + 
+		"10. ERROR in test\\PotNullInLoop.java (at line 68)\n" + 
+		"	ponNullOrNonNull.hashCode(); // OK: pot null, is reported\n" + 
+		"	^^^^^^^^^^^^^^^^\n" + 
+		"Potential null pointer access: The variable ponNullOrNonNull may be null at this location\n" + 
+		"----------\n"
+	);
+}
+// variant of testBug486912PotNullInLoop_orig spiced up with potentiality from an 'unknown' o0:
+public void testBug486912PotNullInLoop() {
+	runNegativeTest(
+		new String[] {
+			"test/PotNullInLoop.java",
+			"package test;\n" +
+			"\n" +
+			"public class PotNullInLoop {\n" +
+			"	boolean b;\n" +
+			"\n" +
+			"	public void testDoWhile1(Object o0) {\n" +
+			"		Object o1 = null;\n" +
+			"		Object o2 = new Object();\n" +
+			"		Object potNonNull = b ? o2 : o0;\n" +
+			"		Object potNull = b ? o1 : o0;\n" +
+			"		do {\n" +
+			"			potNonNull.hashCode(); // OK\n" +
+			"			potNull.hashCode(); // ERROR 1: pot null, but nothing reported\n" +
+			"		} while (false);\n" +
+			"	}\n" +
+			"\n" +
+			"	public void testWhileWithBreak(Object o0) {\n" +
+			"		Object o1 = null;\n" +
+			"		Object o2 = new Object();\n" +
+			"		Object potNonNull = b ? o2 : o0;\n" +
+			"		Object potNull = b ? o1 : o0;\n" +
+			"		while (b) {\n" +
+			"			potNonNull.hashCode(); // OK\n" +
+			"			potNull.hashCode(); // ERROR 3 : pot null, but nothing reported\n" +
+			"			break;\n" +
+			"		}\n" +
+			"	}\n" +
+			"\n" +
+			"	public void testWhile(Object o0) {\n" +
+			"		Object o1 = null;\n" +
+			"		Object o2 = new Object();\n" +
+			"		Object potNonNull = b ? o2 : o0;\n" +
+			"		Object potNull = b ? o1 : o0;\n" +
+			"		while (b) {\n" +
+			"			potNonNull.hashCode(); // OK\n" +
+			"			potNull.hashCode(); // OK: pot null, is reported\n" +
+			"		}\n" +
+			"	}\n" +
+			"\n" +
+			"	public void testFor(Object o0) {\n" +
+			"		Object o1 = null;\n" +
+			"		Object o2 = new Object();\n" +
+			"		Object potNonNull = b ? o2 : o0;\n" +
+			"		Object potNull = b ? o1 : o0;\n" +
+			"		for (int i = 0; i < 1; i++) {\n" +
+			"			potNonNull.hashCode(); // OK\n" +
+			"			potNull.hashCode(); // OK: pot null, is reported\n" +
+			"		}\n" +
+			"	}\n" +
+			"\n" +
+			"	public void testForEach(Object o0) {\n" +
+			"		Object o1 = null;\n" +
+			"		Object o2 = new Object();\n" +
+			"		Object potNonNull = b ? o2 : o0;\n" +
+			"		Object potNull = b ? o1 : o0;\n" +
+			"		for (int i = 0; i < 1; i++) {\n" +
+			"			potNonNull.hashCode(); // OK\n" +
+			"			potNull.hashCode(); // OK: pot null, is reported\n" +
+			"		}\n" +
+			"	}\n" +
+			"\n" +
+			"}\n" +
+			"",
+		}, 
+		"----------\n" + 
+		"1. ERROR in test\\PotNullInLoop.java (at line 13)\n" + 
+		"	potNull.hashCode(); // ERROR 1: pot null, but nothing reported\n" + 
+		"	^^^^^^^\n" + 
+		"Potential null pointer access: The variable potNull may be null at this location\n" + 
+		"----------\n" + 
+		"2. ERROR in test\\PotNullInLoop.java (at line 24)\n" + 
+		"	potNull.hashCode(); // ERROR 3 : pot null, but nothing reported\n" + 
+		"	^^^^^^^\n" + 
+		"Potential null pointer access: The variable potNull may be null at this location\n" + 
+		"----------\n" + 
+		"3. ERROR in test\\PotNullInLoop.java (at line 36)\n" + 
+		"	potNull.hashCode(); // OK: pot null, is reported\n" + 
+		"	^^^^^^^\n" + 
+		"Potential null pointer access: The variable potNull may be null at this location\n" + 
+		"----------\n" + 
+		"4. ERROR in test\\PotNullInLoop.java (at line 47)\n" + 
+		"	potNull.hashCode(); // OK: pot null, is reported\n" + 
+		"	^^^^^^^\n" + 
+		"Potential null pointer access: The variable potNull may be null at this location\n" + 
+		"----------\n" + 
+		"5. ERROR in test\\PotNullInLoop.java (at line 58)\n" + 
+		"	potNull.hashCode(); // OK: pot null, is reported\n" + 
+		"	^^^^^^^\n" + 
+		"Potential null pointer access: The variable potNull may be null at this location\n" + 
+		"----------\n"
+	);
+}
 }
\ No newline at end of file
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 f92be0a..5c75171 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
@@ -177,9 +177,16 @@
 				  "@Target({METHOD,PARAMETER,LOCAL_VARIABLE,TYPE_USE})\n" +
 				  "public @interface Dummy {\n" +
 				  "}\n",
+				"p/List.java",
+				  "package p;\n" +
+				  "public interface List<T> {\n" +
+				  "	T get(int i);\n" + // avoid IProblem.NonNullTypeVariableFromLegacyMethod against unannotated j.u.List
+				  " void add(T e);\n" +
+				  " void add(int i, T e);\n" +
+				  "}\n",
 				"X.java",
 				  "import org.eclipse.jdt.annotation.*;\n" +
-				  "import java.util.List;\n" +
+				  "import p.List;\n" +
 				  "public class X {\n" +
 				  "    void foo(@Nullable List<@NonNull Object> l) {\n" +
 				  "        System.out.print(l.get(0).toString()); // problem: l may be null\n" +
@@ -189,7 +196,7 @@
 				  "        System.out.print(l.get(0).toString()); // problem: l may be null\n" +
 				  "        l.add(0, null); // problem: cannot insert 'null' into this list\n" +
 				  "    }\n" +
-				  "    void bar2(@Dummy java.util.@Nullable List<java.lang.@NonNull Object> l2) {\n" +
+				  "    void bar2(@Dummy p.@Nullable List<java.lang.@NonNull Object> l2) {\n" +
 				  "        System.out.print(l2.get(0).toString()); // problem: l2 may be null\n" +
 				  "        l2.add(0, null); // problem: cannot insert 'null' into this list\n" +
 				  "    }\n" +
@@ -198,7 +205,7 @@
 			"1. ERROR in X.java (at line 5)\n" + 
 			"	System.out.print(l.get(0).toString()); // problem: l may be null\n" + 
 			"	                 ^\n" + 
-			"Potential null pointer access: this expression has a '@Nullable' type\n" + 
+			"Potential null pointer access: this expression has a \'@Nullable\' type\n" + 
 			"----------\n" + 
 			"2. ERROR in X.java (at line 6)\n" + 
 			"	l.add(null); // problem: cannot insert \'null\' into this list\n" + 
@@ -208,7 +215,7 @@
 			"3. ERROR in X.java (at line 9)\n" + 
 			"	System.out.print(l.get(0).toString()); // problem: l may be null\n" + 
 			"	                 ^\n" + 
-			"Potential null pointer access: this expression has a '@Nullable' type\n" + 
+			"Potential null pointer access: this expression has a \'@Nullable\' type\n" + 
 			"----------\n" + 
 			"4. ERROR in X.java (at line 10)\n" + 
 			"	l.add(0, null); // problem: cannot insert \'null\' into this list\n" + 
@@ -218,7 +225,7 @@
 			"5. ERROR in X.java (at line 13)\n" + 
 			"	System.out.print(l2.get(0).toString()); // problem: l2 may be null\n" + 
 			"	                 ^^\n" + 
-			"Potential null pointer access: this expression has a '@Nullable' type\n" + 
+			"Potential null pointer access: this expression has a \'@Nullable\' type\n" + 
 			"----------\n" + 
 			"6. ERROR in X.java (at line 14)\n" + 
 			"	l2.add(0, null); // problem: cannot insert \'null\' into this list\n" + 
@@ -240,18 +247,21 @@
 				  "        public X foo(Y l) {\n" +
 				  "            return anX;\n" +
 				  "        }\n" +
+				  "        public I(X x) {\n" +
+				  "            anX = x;\n" +
+				  "        }\n" +
 				  "    }\n" +
 				  "    void bar(A<@Nullable Object>.I<@NonNull Object> i) {\n" + // legal instantiation
 				  "        @NonNull Object o = i.foo(null); // problems: argument and assignment violate null contracts\n" +
 				  "    }\n" +
 				  "}\n"},
 			"----------\n" + 
-			"1. ERROR in A.java (at line 10)\n" + 
+			"1. ERROR in A.java (at line 13)\n" + 
 			"	@NonNull Object o = i.foo(null); // problems: argument and assignment violate null contracts\n" + 
 			"	                    ^^^^^^^^^^^\n" + 
 			"Null type mismatch (type annotations): required '@NonNull Object' but this expression has type '@Nullable Object'\n" + 
 			"----------\n" + 
-			"2. ERROR in A.java (at line 10)\n" + 
+			"2. ERROR in A.java (at line 13)\n" + 
 			"	@NonNull Object o = i.foo(null); // problems: argument and assignment violate null contracts\n" + 
 			"	                          ^^^^\n" + 
 			"Null type mismatch: required \'@NonNull Object\' but the provided value is null\n" + 
@@ -353,7 +363,7 @@
 			"1. ERROR in B.java (at line 4)\n" + 
 			"	ai.foo(null); // problems: ai can be null, arg must not be null\n" + 
 			"	^^\n" + 
-			"Potential null pointer access: this expression has a '@Nullable' type\n" + 
+			"Potential null pointer access: this expression has a \'@Nullable\' type\n" + 
 			"----------\n" + 
 			"2. ERROR in B.java (at line 4)\n" + 
 			"	ai.foo(null); // problems: ai can be null, arg must not be null\n" + 
@@ -417,6 +427,7 @@
 				"Wrapper.java",
 				  "public class Wrapper<T> {\n" +
 				  "	T content;" +
+				  "	public Wrapper(T t) { content = t; }\n" +
 				  "	public T content() { return content; }\n" +
 				  "}\n",
 				"A.java",
@@ -451,6 +462,7 @@
 				"Wrapper.java",
 				  "public class Wrapper<T> {\n" +
 				  "	T content;" +
+				  "	public Wrapper(T t) { content = t; }\n" +
 				  "	public T content() { return content; }\n" +
 				  "}\n",
 				"A.java",
@@ -522,7 +534,7 @@
     		"4. ERROR in A.java (at line 15)\n" + 
     		"	string = maybeStringArray[0]; // problems: indexing nullable array & unchecked conversion\n" + 
     		"	         ^^^^^^^^^^^^^^^^\n" + 
-    		"Potential null pointer access: this expression has a '@Nullable' type\n" + 
+    		"Potential null pointer access: this expression has a \'@Nullable\' type\n" + 
     		"----------\n" + 
     		"5. WARNING in A.java (at line 15)\n" + 
     		"	string = maybeStringArray[0]; // problems: indexing nullable array & unchecked conversion\n" + 
@@ -532,7 +544,7 @@
     		"6. ERROR in A.java (at line 17)\n" + 
     		"	maybeStringArray[0] = null; 	 // problem: indexing nullable array\n" + 
     		"	^^^^^^^^^^^^^^^^\n" + 
-    		"Potential null pointer access: this expression has a '@Nullable' type\n" + 
+    		"Potential null pointer access: this expression has a \'@Nullable\' type\n" + 
 			"----------\n");
 	}
 
@@ -1048,7 +1060,7 @@
 				"1. ERROR in Y1.java (at line 4)\n" + 
 				"	System.out.println(p.X1.f1.length);\n" + 
 				"	                        ^^\n" + 
-				"Potential null pointer access: this expression has a '@Nullable' type\n" + 
+				"Potential null pointer access: this expression has a \'@Nullable\' type\n" + 
 				"----------\n" + 
 				"2. ERROR in Y1.java (at line 5)\n" + 
 				"	System.out.println(X1.f2[0].length);\n" + 
@@ -1308,9 +1320,16 @@
 		customOptions.put(JavaCore.COMPILER_PB_MISSING_SERIAL_VERSION, JavaCore.IGNORE);
 		runConformTestWithLibs(
 				new String[] {
+					"p/List.java",
+					"package p;\n" +
+					"@org.eclipse.jdt.annotation.NonNullByDefault\n" +
+					"public interface List<T> {\n" +
+					"	T get(int i);\n" + // avoid IProblem.NonNullTypeVariableFromLegacyMethod against unannotated j.u.List
+					"}\n",
 					"p/X1.java",
 					"package p;\n" +
-					"import java.util.*;\n" +
+					"import java.util.Map;\n" +
+					"import p.List;\n" +
 					"import org.eclipse.jdt.annotation.*;\n" +
 					"import static java.lang.annotation.ElementType.*;\n" +
 					"import java.lang.annotation.*;\n" +
@@ -2438,6 +2457,8 @@
 	
 	// poly-null method
 	public void testNullTypeInference1() {
+		Map compilerOptions = getCompilerOptions();
+		compilerOptions.put(CompilerOptions.OPTION_ReportNonNullTypeVariableFromLegacyInvocation, CompilerOptions.IGNORE);
 		runNegativeTestWithLibs(
 			new String[] {
 				"X.java",
@@ -2459,7 +2480,7 @@
 				"	}\n" +
 				"}\n"
 			},
-			getCompilerOptions(),
+			compilerOptions,
 			"----------\n" + 
 			"1. ERROR in X.java (at line 9)\n" + 
 			"	return polyNullMethod(strings).get(0);\n" + 
@@ -3078,6 +3099,11 @@
 			"	ls.add(null);\n" + 
 			"	       ^^^^\n" + 
 			"Null type mismatch: required \'@NonNull ? extends @NonNull String\' but the provided value is null\n" + 
+			"----------\n" + 
+			"3. WARNING in X.java (at line 10)\n" + 
+			"	@NonNull String s = ls.get(0);\n" + 
+			"	                    ^^^^^^^^^\n" + 
+			"Unsafe interpretation of method return type as \'@NonNull\' based on the receiver type \'List<@NonNull capture#of ? extends @NonNull String>\'. Type \'List<E>\' doesn\'t seem to be designed with null type annotations in mind\n" + 
 			"----------\n");
 	}
 
@@ -3400,12 +3426,17 @@
 			},
 			getCompilerOptions(),
 			"----------\n" + 
-			"1. WARNING in X.java (at line 10)\n" + 
+			"1. WARNING in X.java (at line 6)\n" + 
+			"	return l.get(0);\n" + 
+			"	       ^^^^^^^^\n" + 
+			"Unsafe interpretation of method return type as \'@NonNull\' based on the receiver type \'@NonNull List<@NonNull T>\'. Type \'List<E>\' doesn\'t seem to be designed with null type annotations in mind\n" + 
+			"----------\n" + 
+			"2. WARNING in X.java (at line 10)\n" + 
 			"	s.foo(new ArrayList<String>()); // (1)\n" + 
 			"	      ^^^^^^^^^^^^^^^^^^^^^^^\n" + 
 			"Null type safety (type annotations): The expression of type \'ArrayList<String>\' needs unchecked conversion to conform to \'@NonNull List<@NonNull String>\', corresponding supertype is 'List<String>'\n" + 
 			"----------\n" + 
-			"2. ERROR in X.java (at line 11)\n" + 
+			"3. ERROR in X.java (at line 11)\n" + 
 			"	s.foo(null); // (2)\n" + 
 			"	      ^^^^\n" + 
 			"Null type mismatch: required \'@NonNull List<@NonNull String>\' but the provided value is null\n" + 
@@ -3736,15 +3767,15 @@
 			},
 			getCompilerOptions(),
 			"----------\n" + 
-			"1. WARNING in X.java (at line 4)\n" + 
+			"1. ERROR in X.java (at line 4)\n" + 
 			"	consume(t); // error, t can be null\n" + 
 			"	        ^\n" + 
-			"Null type safety (type annotations): The expression of type \'T\' needs unchecked conversion to conform to \'@NonNull T\'\n" + 
+			"Null type safety: required \'@NonNull\' but this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" + 
 			"----------\n" + 
-			"2. WARNING in X.java (at line 5)\n" + 
+			"2. ERROR in X.java (at line 5)\n" + 
 			"	consumeObject(t); // error, t can be null\n" + 
 			"	              ^\n" + 
-			"Null type safety (type annotations): The expression of type \'T\' needs unchecked conversion to conform to \'@NonNull Object\'\n" + 
+			"Null type safety: required \'@NonNull\' but this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" + 
 			"----------\n" + 
 			"3. ERROR in X.java (at line 8)\n" + 
 			"	consume(t); // error, both sides explicit, mismatch\n" + 
@@ -3794,15 +3825,15 @@
 			},
 			getCompilerOptions(),
 			"----------\n" + 
-			"1. WARNING in X.java (at line 4)\n" + 
+			"1. ERROR in X.java (at line 4)\n" + 
 			"	consume(t); // error, t can be null\n" + 
 			"	        ^\n" + 
-			"Null type safety (type annotations): The expression of type \'T extends Number\' needs unchecked conversion to conform to \'@NonNull T extends Number\'\n" + 
+			"Null type safety: required \'@NonNull\' but this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" + 
 			"----------\n" + 
-			"2. WARNING in X.java (at line 5)\n" + 
+			"2. ERROR in X.java (at line 5)\n" + 
 			"	consumeObject(t); // error, t can be null\n" + 
 			"	              ^\n" + 
-			"Null type safety (type annotations): The expression of type \'T extends Number\' needs unchecked conversion to conform to \'@NonNull Object\'\n" + 
+			"Null type safety: required \'@NonNull\' but this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" + 
 			"----------\n" + 
 			"3. ERROR in X.java (at line 8)\n" + 
 			"	consume(t); // error, both sides explicit, mismatch\n" + 
@@ -4404,27 +4435,32 @@
 		"	        ^^^^\n" + 
 		"Null type mismatch: required \'? extends @NonNull A\' but the provided value is null\n" + 
 		"----------\n" + 
-		"2. ERROR in C.java (at line 15)\n" + 
+		"2. WARNING in C.java (at line 14)\n" + 
+		"	return la1.get(0); // OK\n" + 
+		"	       ^^^^^^^^^^\n" + 
+		"Unsafe interpretation of method return type as \'@NonNull\' based on the receiver type \'List<capture#of ? extends @NonNull A>\'. Type \'List<E>\' doesn\'t seem to be designed with null type annotations in mind\n" + 
+		"----------\n" + 
+		"3. ERROR in C.java (at line 15)\n" + 
 		"	la1 = lb2; // ERR2\n" + 
 		"	      ^^^\n" + 
 		"Null type mismatch (type annotations): required \'List<? extends @NonNull A>\' but this expression has type \'List<@Nullable B>\'\n" + 
 		"----------\n" + 
-		"3. ERROR in C.java (at line 17)\n" + 
+		"4. ERROR in C.java (at line 17)\n" + 
 		"	la2.add(null); // ERR3\n" + 
 		"	        ^^^^\n" + 
 		"Null type mismatch: required \'? extends @Nullable A\' but the provided value is null\n" + 
 		"----------\n" + 
-		"4. ERROR in C.java (at line 19)\n" + 
+		"5. ERROR in C.java (at line 19)\n" + 
 		"	return la2.get(0); // ERR4\n" + 
 		"	       ^^^^^^^^^^\n" + 
 		"Null type mismatch (type annotations): required \'@NonNull A\' but this expression has type \'capture#of ? extends @Nullable A\'\n" + 
 		"----------\n" + 
-		"5. ERROR in C.java (at line 25)\n" + 
+		"6. ERROR in C.java (at line 25)\n" + 
 		"	<T extends @Nullable A> T mExtends1(List<T> t) { return null; /*ERR5*/ }\n" + 
 		"	                                                        ^^^^\n" + 
 		"Null type mismatch: required \'T extends @Nullable A\' but the provided value is null\n" + 
 		"----------\n" + 
-		"6. ERROR in C.java (at line 26)\n" + 
+		"7. ERROR in C.java (at line 26)\n" + 
 		"	<T extends @NonNull A> T mExtends2(List<T> t) { return null; /*ERR6*/ }\n" + 
 		"	                                                       ^^^^\n" + 
 		"Null type mismatch: required \'T extends @NonNull A\' but the provided value is null\n" + 
@@ -4734,12 +4770,12 @@
 		"1. ERROR in X.java (at line 6)\n" + 
 		"	in.add(null); // NOK, cannot assume nullable\n" + 
 		"	       ^^^^\n" + 
-		"Null type mismatch (type annotations): \'null\' is not compatible to the free type variable '? extends Number'\n" + 
+		"Null type mismatch (type annotations): \'null\' is not compatible to the free type variable \'? extends Number\'\n" + 
 		"----------\n" + 
-		"2. WARNING in X.java (at line 7)\n" + 
+		"2. ERROR in X.java (at line 7)\n" + 
 		"	needNN(in.get(0)); // NOK, cannot assume nonnull\n" + 
 		"	       ^^^^^^^^^\n" + 
-		"Null type safety (type annotations): The expression of type \'capture#of ? extends Number\' needs unchecked conversion to conform to \'@NonNull Number\'\n" + 
+		"Null type safety: required \'@NonNull\' but this expression has type \'capture#2-of ? extends java.lang.Number\', a free type variable that may represent a \'@Nullable\' type\n" + 
 		"----------\n" + 
 		"3. ERROR in X.java (at line 8)\n" + 
 		"	return new ArrayList<@Nullable T>(); // NOK, cannot assume nullable for T in List<T>\n" + 
@@ -4947,17 +4983,22 @@
 		},
 		getCompilerOptions(),
 		"----------\n" + 
-		"1. ERROR in X.java (at line 9)\n" + 
+		"1. WARNING in X.java (at line 8)\n" + 
+		"	@NonNull Number n = l.get(0); // OK\n" + 
+		"	                    ^^^^^^^^\n" + 
+		"Unsafe interpretation of method return type as \'@NonNull\' based on the receiver type \'List<capture#of ? extends @NonNull Number>\'. Type \'List<E>\' doesn\'t seem to be designed with null type annotations in mind\n" + 
+		"----------\n" + 
+		"2. ERROR in X.java (at line 9)\n" + 
 		"	return null; // ERR\n" + 
 		"	       ^^^^\n" + 
 		"Null type mismatch: required \'T extends @NonNull Number\' but the provided value is null\n" + 
 		"----------\n" + 
-		"2. WARNING in X.java (at line 13)\n" + 
+		"3. WARNING in X.java (at line 13)\n" + 
 		"	@NonNull Number nnn = inner.process(Integer.valueOf(3), new ArrayList<@Nullable Integer>()); // WARN on 1. arg; ERR on 2. arg\n" + 

 		"	                                    ^^^^^^^^^^^^^^^^^^\n" + 

 		"Null type safety (type annotations): The expression of type \'Integer\' needs unchecked conversion to conform to \'@NonNull Integer\'\n" + 

 		"----------\n" + 
-		"3. ERROR in X.java (at line 13)\n" + 
+		"4. ERROR in X.java (at line 13)\n" + 
 		"	@NonNull Number nnn = inner.process(Integer.valueOf(3), new ArrayList<@Nullable Integer>()); // WARN on 1. arg; ERR on 2. arg\n" + 

 		"	                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
 		"Null type mismatch (type annotations): required \'List<? extends @NonNull Number>\' but this expression has type \'ArrayList<@Nullable Integer>\', corresponding supertype is \'List<@Nullable Integer>\'\n" + 
@@ -5971,6 +6012,8 @@
 }
 // top-level annotation is overridden at use-site, details remain - parameterized type
 public void testTypeVariable19() {
+	Map compilerOptions = getCompilerOptions();
+	compilerOptions.put(CompilerOptions.OPTION_ReportNonNullTypeVariableFromLegacyInvocation, CompilerOptions.IGNORE);
 	runNegativeTestWithLibs(
 		new String[] {
 			"X.java",
@@ -5999,7 +6042,7 @@
 			"	}\n" + 
 			"}\n"
 		},
-		getCompilerOptions(),
+		compilerOptions,
 		"----------\n" + 
 		"1. ERROR in X.java (at line 15)\n" + 
 		"	case 0 : return i1.get0().get(0).toUpperCase(); // problem at detail\n" + 
@@ -6491,10 +6534,10 @@
 		},
 		getCompilerOptions(),
 		"----------\n" + 
-		"1. WARNING in X.java (at line 5)\n" + 
+		"1. ERROR in X.java (at line 5)\n" + 
 		"	@NonNull T localT = t; // err#1\n" + 
 		"	                    ^\n" + 
-		"Null type safety (type annotations): The expression of type \'T\' needs unchecked conversion to conform to \'@NonNull T\'\n" + 
+		"Null type safety: required \'@NonNull\' but this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" + 
 		"----------\n" + 
 		"2. ERROR in X.java (at line 6)\n" + 
 		"	return null; // err must mention free type variable, not @NonNull\n" + 
@@ -6521,10 +6564,10 @@
 		},
 		getCompilerOptions(),
 		"----------\n" + 
-		"1. WARNING in X.java (at line 8)\n" + 
+		"1. ERROR in X.java (at line 8)\n" + 
 		"	@NonNull T localT = t; // err#1\n" + 
 		"	                    ^\n" + 
-		"Null type safety (type annotations): The expression of type \'T\' needs unchecked conversion to conform to \'@NonNull T\'\n" + 
+		"Null type safety: required \'@NonNull\' but this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" + 
 		"----------\n" + 
 		"2. ERROR in X.java (at line 9)\n" + 
 		"	return null; // err must mention free type variable, not @NonNull\n" + 
@@ -6667,7 +6710,17 @@
 		},
 		getCompilerOptions(),
 		"----------\n" + 
-		"1. ERROR in Foo.java (at line 20)\n" + 
+		"1. WARNING in Foo.java (at line 17)\n" + 
+		"	return requireNonNull(foos).get(0);\n" + 
+		"	       ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
+		"Unsafe interpretation of method return type as \'@NonNull\' based on the receiver type \'@NonNull List<capture#of ? extends @NonNull Foo>\'. Type \'List<E>\' doesn\'t seem to be designed with null type annotations in mind\n" + 
+		"----------\n" + 
+		"2. WARNING in Foo.java (at line 20)\n" + 
+		"	return requireNonNull(foos.get(0)).get(0);\n" + 
+		"	       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
+		"Unsafe interpretation of method return type as \'@NonNull\' based on the receiver type \'List<@NonNull Foo>\'. Type \'List<E>\' doesn\'t seem to be designed with null type annotations in mind\n" + 
+		"----------\n" + 
+		"3. ERROR in Foo.java (at line 20)\n" + 
 		"	return requireNonNull(foos.get(0)).get(0);\n" + 
 		"	                      ^^^^\n" + 
 		"Potential null pointer access: this expression has a \'@Nullable\' type\n" + 
@@ -6732,7 +6785,7 @@
 		},
 		options,
 		"");
-	runConformTestWithLibs(
+	runNegativeTestWithLibs(
 		new String[] {
 			"UnequalBinaryNode.java",
 			"public class UnequalBinaryNode<L extends ExtendedNode, R extends ExtendedNode>\n" +
@@ -6748,7 +6801,17 @@
 			"}\n"
 		},
 		options,
-		"");
+		"----------\n" + 
+		"1. ERROR in UnequalBinaryNode.java (at line 8)\n" + 
+		"	left.setParent(this);\n" + 
+		"	^^^^\n" + 
+		"Potential null pointer access: this expression has type \'L\', a free type variable that may represent a \'@Nullable\' type\n" + 
+		"----------\n" + 
+		"2. ERROR in UnequalBinaryNode.java (at line 9)\n" + 
+		"	right.setParent(this); // error on this line without fix\n" + 
+		"	^^^^^\n" + 
+		"Potential null pointer access: this expression has type \'R\', a free type variable that may represent a \'@Nullable\' type\n" + 
+		"----------\n");
 }
 //https://bugs.eclipse.org/bugs/show_bug.cgi?id=434582,
 //[1.8][compiler][null] @Nullable annotation in type parameter causes NullPointerException in JDT core
@@ -7709,6 +7772,7 @@
 public void testBug448709() {
 	Map compilerOptions = getCompilerOptions();
 	compilerOptions.put(JavaCore.COMPILER_PB_NULL_SPECIFICATION_VIOLATION, JavaCore.WARNING); // ensure program is runnable
+	compilerOptions.put(JavaCore.COMPILER_PB_PESSIMISTIC_NULL_ANALYSIS_FOR_FREE_TYPE_VARIABLES, JavaCore.WARNING); // ensure program is runnable
 	runConformTestWithLibs(
 		new String[] {
 			"Test.java",
@@ -7761,22 +7825,27 @@
 		},
 		compilerOptions,
 		"----------\n" + 
-		"1. WARNING in Test.java (at line 39)\n" + 
+		"1. WARNING in Test.java (at line 21)\n" + 
+		"	final U result = mapper.apply(source);\n" + 
+		"	                              ^^^^^^\n" + 
+		"Null type safety: required \'@NonNull\' but this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" + 
+		"----------\n" + 
+		"2. WARNING in Test.java (at line 39)\n" + 
 		"	map(optNullableString, testMethodRef);\n" + 
 		"	                       ^^^^^^^^^^^^^\n" + 
 		"Contradictory null annotations: method was inferred as \'@NonNull Optional<@NonNull Integer> map(@NonNull Optional<@Nullable String>, Function<@NonNull ? super @Nullable String,? extends @NonNull Integer>)\', but only one of \'@NonNull\' and \'@Nullable\' can be effective at any location\n" + 
 		"----------\n" + 
-		"2. WARNING in Test.java (at line 41)\n" + 
+		"3. WARNING in Test.java (at line 41)\n" + 
 		"	map(optNullableString, Test::testMethod); // Error: Null type mismatch at parameter 1: required \'@NonNull String\' but provided \'@Nullable String\' via method descriptor Function<String,Integer>.apply(String)\n" + 
 		"	                       ^^^^^^^^^^^^^^^^\n" + 
 		"Contradictory null annotations: method was inferred as \'@NonNull Optional<@NonNull Integer> map(@NonNull Optional<@Nullable String>, Function<@NonNull ? super @Nullable String,? extends @NonNull Integer>)\', but only one of \'@NonNull\' and \'@Nullable\' can be effective at any location\n" + 
 		"----------\n" + 
-		"3. WARNING in Test.java (at line 43)\n" + 
+		"4. WARNING in Test.java (at line 43)\n" + 
 		"	map(optNullableString, (s) -> Test.testMethod(s));\n" + 
 		"	                       ^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
 		"Contradictory null annotations: method was inferred as \'@NonNull Optional<@NonNull Integer> map(@NonNull Optional<@Nullable String>, Function<@NonNull ? super @Nullable String,? extends @NonNull Integer>)\', but only one of \'@NonNull\' and \'@Nullable\' can be effective at any location\n" + 
 		"----------\n" + 
-		"4. WARNING in Test.java (at line 43)\n" + 
+		"5. WARNING in Test.java (at line 43)\n" + 
 		"	map(optNullableString, (s) -> Test.testMethod(s));\n" + 
 		"	                                              ^\n" + 
 		"Null type mismatch (type annotations): required \'@NonNull String\' but this expression has type \'@Nullable String\'\n" + 
@@ -7785,6 +7854,28 @@
 		"1->2\n" +
 		"1->2");
 }
+public void testBug448709b() {
+	runConformTestWithLibs(
+		new String[] {
+			"Test.java",
+			"import java.util.*;\n" + 
+			"import java.util.function.*;\n" + 
+			"import org.eclipse.jdt.annotation.*;\n" + 
+			"\n" + 
+			"public class Test {\n" + 
+			"\n" + 
+			"  public static final <T,U> void map(final @NonNull Optional<T> optional, final Function<@NonNull ? super T,? extends U> mapper) {\n" + 
+			"    final T source = optional.get();\n" +
+			"    if (source != null) {\n" + 
+			"      final U result = mapper.apply(source);\n" +
+			"      System.out.println(source+\"->\"+result);\n" + 
+			"    }\n" + 
+			"  }\n" + 
+			"}\n"
+		},
+		getCompilerOptions(),
+		"");
+}
 public void testBug459967_Array_constructor() {

 	runConformTestWithLibs(

 		new String[] {

@@ -7994,6 +8085,11 @@
     		"	@NonNull GenericType gt = cwru.method().get(0);\n" + 
     		"	         ^^^^^^^^^^^\n" + 
     		"GenericType is a raw type. References to generic type GenericType<T> should be parameterized\n" + 
+    		"----------\n" + 
+    		"2. WARNING in projB\\ClassThatImports.java (at line 7)\n" + 
+    		"	@NonNull GenericType gt = cwru.method().get(0);\n" + 
+    		"	                          ^^^^^^^^^^^^^^^^^^^^\n" + 
+    		"Unsafe interpretation of method return type as \'@NonNull\' based on the receiver type \'@NonNull List<@NonNull GenericType>\'. Type \'List<E>\' doesn\'t seem to be designed with null type annotations in mind\n" + 
     		"----------\n");
 }
 
@@ -8270,6 +8366,8 @@
 		getCompilerOptions(), "");
 }
 public void testBug456584() {
+	Map compilerOptions = getCompilerOptions();
+	compilerOptions.put(JavaCore.COMPILER_PB_PESSIMISTIC_NULL_ANALYSIS_FOR_FREE_TYPE_VARIABLES, JavaCore.WARNING);
 	runConformTestWithLibs(
 		new String[] {
 			"Test.java",
@@ -8286,12 +8384,17 @@
 			"\n" + 
 			"}\n"
 		},
-		getCompilerOptions(),
+		compilerOptions,
 		"----------\n" + 
 		"1. WARNING in Test.java (at line 9)\n" + 
 		"	return Objects.requireNonNull(function.apply(input));\n" + 
+		"	       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
+		"Unsafe interpretation of method return type as \'@NonNull\' based on substitution \'T=@NonNull capture#of ? extends R\'. Declaring type \'Objects\' doesn\'t seem to be designed with null type annotations in mind\n" + 
+		"----------\n" + 
+		"2. WARNING in Test.java (at line 9)\n" + 
+		"	return Objects.requireNonNull(function.apply(input));\n" + 
 		"	                              ^^^^^^^^^^^^^^^^^^^^^\n" + 
-		"Null type safety (type annotations): The expression of type \'capture#of ? extends R\' needs unchecked conversion to conform to \'@NonNull capture#of ? extends R\'\n" + 
+		"Null type safety: required \'@NonNull\' but this expression has type \'capture#2-of ? extends R\', a free type variable that may represent a \'@Nullable\' type\n" + 
 		"----------\n");
 }
 public void testBug447661() {
@@ -8894,13 +8997,20 @@
 		},
 		getCompilerOptions(),
 		"----------\n" + 
-		"1. ERROR in X.java (at line 12)\n" + 
+		"1. ERROR in X.java (at line 9)\n" + 
+		"	return list.get(0);\n" + 
+		"	       ^^^^\n" + 
+		"Potential null pointer access: this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" + 
+		"----------\n" + 
+		"2. ERROR in X.java (at line 12)\n" + 
 		"	public class X extends Super<@NonNull String, List<@Nullable String>> {\n" + 
 		"	                                              ^^^^\n" + 
 		"Null constraint mismatch: The type \'List<@Nullable String>\' is not a valid substitute for the type parameter \'T extends List<S>\'\n" + 
 		"----------\n");
 }
 public void testBug477719() {
+	Map compilerOptions = getCompilerOptions();
+	compilerOptions.put(CompilerOptions.OPTION_ReportNonNullTypeVariableFromLegacyInvocation, CompilerOptions.IGNORE);
 	runConformTestWithLibs(
 		new String[] {
 			"X.java",
@@ -8915,7 +9025,7 @@
 			"	}\n" +
 			"}\n"
 		},
-		getCompilerOptions(),
+		compilerOptions,
 		"");
 }
 public void testBug482247() {
@@ -8951,6 +9061,23 @@
 		"Null type safety (type annotations): The expression of type \'String[]\' needs unchecked conversion to conform to \'@NonNull String @NonNull[]\'\n" + 
 		"----------\n");
 }
+public void testBug482247_comment5() {
+	runConformTestWithLibs(
+		new String[] {
+			"Snippet.java",
+			"import org.eclipse.jdt.annotation.*;\n" +
+			"public class Snippet {\n" + 
+			"	@NonNull String[] s1 = new String[0]; // No warning\n" + 
+			"	public void handleIncidentBeforeCreate() {\n" + 
+			"		@NonNull String[] s = new String[0]; // Warning\n" +
+			"		String [] @NonNull[] s2 = new String[0][];\n" +
+			"		String [] @NonNull[] @Nullable[] s3 = new String[0][][];\n" +
+			"	}\n" + 
+			"}"
+		},
+		getCompilerOptions(),
+		"");
+}
 public void testBug483146() {
 	runConformTestWithLibs(
 		new String[] {
@@ -9078,12 +9205,17 @@
 		},
 		getCompilerOptions(),
 		"----------\n" + 
-		"1. ERROR in X.java (at line 14)\n" + 
+		"1. ERROR in X.java (at line 9)\n" + 
+		"	return list.get(0);\n" + 
+		"	       ^^^^\n" + 
+		"Potential null pointer access: this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" + 
+		"----------\n" + 
+		"2. ERROR in X.java (at line 14)\n" + 
 		"	<T extends List<@Nullable String>> @NonNull String pick(T list) {\n" + 
 		"	 ^\n" + 
 		"Cannot redefine null constraints of type variable \'T extends List<@NonNull String>\' declared in \'Super<String>.pick(T)\'\n" + 
 		"----------\n" + 
-		"2. ERROR in X.java (at line 15)\n" + 
+		"3. ERROR in X.java (at line 15)\n" + 
 		"	return super.pick(list);\n" + 
 		"	       ^^^^^^^^^^^^^^^^\n" + 
 		"Null constraint mismatch: The type \'T extends List<@Nullable String>\' is not a valid substitute for the type parameter \'T extends List<@NonNull String>\'\n" + 
@@ -9512,9 +9644,14 @@
 	customOptions.put(JavaCore.COMPILER_PB_MISSING_SERIAL_VERSION, JavaCore.IGNORE);
 	runNegativeTestWithLibs(
 			new String[] {
+				"p/List.java",
+				"package p;\n" +
+				"public interface List<T> {\n" +
+				"	T get(int i);\n" + // avoid IProblem.NonNullTypeVariableFromLegacyMethod against unannotated j.u.List
+				"}\n",
 				"p/X1.java",
 				"package p;\n" +
-				"import java.util.*;\n" +
+				"import java.util.Map;\n" +
 				"import org.eclipse.jdt.annotation.*;\n" +
 				"import static java.lang.annotation.ElementType.*;\n" +
 				"import java.lang.annotation.*;\n" +
@@ -9587,17 +9724,22 @@
 		"	                    ^\n" + 
 		"Null type mismatch (type annotations): required \'@NonNull Object\' but this expression has type \'T1 extends @Nullable Number\'\n" + 
 		"----------\n" + 
-		"3. ERROR in x\\C.java (at line 13)\n" + 
+		"3. ERROR in x\\C.java (at line 10)\n" + 
+		"	return t.toString(); // legal???\n" + 
+		"	       ^\n" + 
+		"Potential null pointer access: this expression has type \'T1\', a free type variable that may represent a \'@Nullable\' type\n" + 
+		"----------\n" + 
+		"4. ERROR in x\\C.java (at line 13)\n" + 
 		"	consume(null);  // illegal - OK\n" + 
 		"	        ^^^^\n" + 
 		"Null type mismatch: required \'T1 extends @Nullable Number\' but the provided value is null\n" + 
 		"----------\n" + 
-		"4. ERROR in x\\C.java (at line 14)\n" + 
+		"5. ERROR in x\\C.java (at line 14)\n" + 
 		"	@NonNull Object t = provide();  // error, should warn?\n" + 
 		"	                    ^^^^^^^^^\n" + 
 		"Null type mismatch (type annotations): required \'@NonNull Object\' but this expression has type \'T1 extends @Nullable Number\'\n" + 
 		"----------\n" + 
-		"5. ERROR in x\\C.java (at line 18)\n" + 
+		"6. ERROR in x\\C.java (at line 18)\n" + 
 		"	return null; // error, should warn?\n" + 
 		"	       ^^^^\n" + 
 		"Null type mismatch: required \'T1 extends @Nullable Number\' but the provided value is null\n" + 
@@ -9957,20 +10099,20 @@
 		}, 
 		getCompilerOptions(), 
 		"----------\n" + 
-		"1. WARNING in test\\TestInterdepInvokeNN.java (at line 48)\n" + 
+		"1. ERROR in test\\TestInterdepInvokeNN.java (at line 48)\n" + 
 		"	return f2(e); // error 1 expected\n" + 
 		"	          ^\n" + 
-		"Null type safety (type annotations): The expression of type \'E21 extends T21\' needs unchecked conversion to conform to \'@NonNull E21 extends T21\'\n" + 
+		"Null type safety: required '@NonNull' but this expression has type 'E21', a free type variable that may represent a '@Nullable' type\n" + 
 		"----------\n" + 
-		"2. WARNING in test\\TestInterdepInvokeNN.java (at line 66)\n" + 
+		"2. ERROR in test\\TestInterdepInvokeNN.java (at line 66)\n" + 
 		"	return f3(e); // error 2 expected\n" + 
 		"	          ^\n" + 
-		"Null type safety (type annotations): The expression of type \'E31 extends T31\' needs unchecked conversion to conform to \'@NonNull E31 extends T31\'\n" + 
+		"Null type safety: required '@NonNull' but this expression has type 'E31', a free type variable that may represent a '@Nullable' type\n" + 
 		"----------\n" + 
-		"3. WARNING in test\\TestInterdepInvokeNN.java (at line 84)\n" + 
+		"3. ERROR in test\\TestInterdepInvokeNN.java (at line 84)\n" + 
 		"	return f4(e); // error 3 expected\n" + 
 		"	          ^\n" + 
-		"Null type safety (type annotations): The expression of type \'E41 extends T41\' needs unchecked conversion to conform to \'@NonNull E41 extends T41\'\n" + 
+		"Null type safety: required '@NonNull' but this expression has type 'E41', a free type variable that may represent a '@Nullable' type\n" + 
 		"----------\n"
 	);
 }
@@ -10346,4 +10488,891 @@
 		"----------\n"
 	);	
 }
+public void testBug485030() {
+	runConformTestWithLibs(new String[] {
+			"SomeAnnotation.java",
+			"import static java.lang.annotation.ElementType.TYPE_USE;\n" + 
+			"import java.lang.annotation.Target;\n" + 
+
+			"@Target({ TYPE_USE })\n" + 
+			"@interface SomeAnnotation {\n" + 
+			"}\n", 
+
+			"TestContradictoryOnGenericArray.java",
+			"import java.io.Serializable;\n" +
+
+			"import org.eclipse.jdt.annotation.NonNullByDefault;\n" +
+			"import org.eclipse.jdt.annotation.Nullable;\n" +
+
+			"@NonNullByDefault\n" +
+			"public class TestContradictoryOnGenericArray {\n" +
+			"	public <@SomeAnnotation Q extends Serializable> void f() {\n" +
+			"		final @Nullable Q[] array = null;\n" +
+			"	}\n" +
+			"}\n"
+	}, getCompilerOptions(), "");
+}
+public void testBug485302() {
+	runNegativeTestWithLibs(
+		new String[] {
+		"WildCardNullable.java",
+			"package test;\n" +
+			"\n" +
+			"import org.eclipse.jdt.annotation.NonNull;\n" +
+			"import org.eclipse.jdt.annotation.Nullable;\n" +
+			"\n" +
+			"public class WildCardNullable {\n" +
+			"	static class A<T> {\n" +
+			"		@Nullable\n" +
+			"		T returnNull() {\n" +
+			"			return null;\n" +
+			"		}\n" +
+			"\n" +
+			"		void acceptNonNullT(@NonNull T t) {\n" +
+			"		}\n" +
+			"\n" +
+			"		void acceptNonNullObject(@NonNull Object x) {\n" +
+			"		}\n" +
+			"	}\n" +
+			"\n" +
+			"	static @NonNull Number g(A<? extends @NonNull Number> a) {\n" +
+			"		return a.returnNull(); // error 1 expected\n" +
+			"	}\n" +
+			"\n" +
+			"	public static final <T> void map(final A<@NonNull ? super T> a, T t) {\n" +
+			"		a.acceptNonNullT(t); // warning 2 expected\n" +
+			"		a.acceptNonNullObject(t); // warning 3 expected\n" +
+			"	}\n" +
+			"}\n" +
+			""
+		}, 
+		getCompilerOptions(),
+		"----------\n" + 
+		"1. ERROR in WildCardNullable.java (at line 21)\n" + 
+		"	return a.returnNull(); // error 1 expected\n" + 
+		"	       ^^^^^^^^^^^^^^\n" + 
+		"Null type mismatch (type annotations): required \'@NonNull Number\' but this expression has type \'@Nullable capture#of ? extends Number\'\n" + 
+		"----------\n" + 
+		"2. ERROR in WildCardNullable.java (at line 25)\n" + 
+		"	a.acceptNonNullT(t); // warning 2 expected\n" + 
+		"	                 ^\n" + 
+		"Null type safety: required '@NonNull' but this expression has type 'T', a free type variable that may represent a '@Nullable' type\n" + 
+		"----------\n" + 
+		"3. ERROR in WildCardNullable.java (at line 26)\n" + 
+		"	a.acceptNonNullObject(t); // warning 3 expected\n" + 
+		"	                      ^\n" + 
+		"Null type safety: required '@NonNull' but this expression has type 'T', a free type variable that may represent a '@Nullable' type\n" + 
+		"----------\n"
+	);
+}
+
+public void testBug485027() {
+	runConformTestWithLibs(new String[] {
+			"SomeAnnotation.java",
+			"import static java.lang.annotation.ElementType.TYPE_USE;\n" + 
+			"import java.lang.annotation.Retention;\n" + 
+			"import java.lang.annotation.RetentionPolicy;\n" + 
+			"import java.lang.annotation.Target;\n" + 
+
+			"@Retention(RetentionPolicy.CLASS)\n" + 
+			"@Target({ TYPE_USE })\n" + 
+			"@interface SomeAnnotation {\n" + 
+			"}\n", 
+
+			"Base.java",
+			"import java.io.Serializable;\n" +
+
+			"import org.eclipse.jdt.annotation.NonNullByDefault;\n" +
+			"import org.eclipse.jdt.annotation.Nullable;\n" +
+
+			"@NonNullByDefault\n" +
+			"public class Base {\n" +
+			"	public <@SomeAnnotation Q extends Serializable> void setValuesArray(Q @Nullable [] value) {\n" +
+			"	}\n" +
+			"}\n"
+	}, getCompilerOptions(), "");
+			
+	runConformTestWithLibs(new String[] {
+			"Derived.java",
+			"import java.io.Serializable;\n" +
+
+			"import org.eclipse.jdt.annotation.NonNullByDefault;\n" +
+			"import org.eclipse.jdt.annotation.Nullable;\n" +
+
+			"@NonNullByDefault\n" +
+			"public class Derived extends Base {\n" +
+			"	@Override\n" +
+			"	public final <@SomeAnnotation Q1 extends Serializable> void setValuesArray(Q1 @Nullable [] value) {\n" +
+			"	}\n" +
+			"}"
+	}, getCompilerOptions(), "");
+}
+public void testBug485565() {
+	runConformTestWithLibs(
+			new String[] {
+			"test2/ClassWithRegistry.java",
+			"package test2;\n" +
+			"\n" +
+			"import java.rmi.registry.Registry;\n" +
+			"\n" +
+			"import org.eclipse.jdt.annotation.Nullable;\n" +
+			"\n" +
+			"public class ClassWithRegistry {\n" +
+			"    @Nullable\n" +
+			"    public Registry registry;\n" +
+			"}\n"
+			}, 
+			getCompilerOptions(),
+			""
+		);
+		runConformTestWithLibs(
+			new String[] {
+			"test1/ClassWithLambda.java",
+			"package test1;\n" +
+			"\n" +
+			"import test2.ClassWithRegistry;\n" +
+			"\n" +
+			"// must be compiled before ZClassWithBug\n" +
+			"public class ClassWithLambda {\n" +
+			"	interface Lambda {\n" +
+			"		void f();\n" +
+			"	}\n" +
+			"\n" +
+			"	public static void invoke(Lambda lambda) {\n" +
+			"		lambda.f();\n" +
+			"	}\n" +
+			"\n" +
+			"	public void f() {\n" +
+			"		new ClassWithRegistry(); // must be accessed as class file\n" +
+			"		invoke(() -> java.rmi.registry.Registry.class.hashCode());\n" +
+			"	}\n" +
+			"}\n",
+			"test1/ZClassWithBug.java",
+			"package test1;\n" +
+			"\n" +
+			"import java.rmi.registry.Registry;\n" +
+			"\n" +
+			"import org.eclipse.jdt.annotation.NonNullByDefault;\n" +
+			"import org.eclipse.jdt.annotation.Nullable;\n" +
+			"\n" +
+			"@NonNullByDefault\n" +
+			"public abstract class ZClassWithBug {\n" +
+			"\n" +
+			"	@Nullable\n" +
+			"	public Registry rmiregistry;\n" +
+			"}\n"
+		}, 
+		getCompilerOptions(),
+		""
+	);
+}
+public void testBug485814() {
+	runConformTestWithLibs(
+		new String[] {
+			"test/ExplainedResult.java",
+			"package test;\n" +
+			"\n" +
+			"import org.eclipse.jdt.annotation.NonNullByDefault;\n" +
+			"\n" +
+			"@NonNullByDefault\n" +
+			"public class ExplainedResult<V2> extends Result<V2> {\n" +
+			"\n" +
+			"	public ExplainedResult(int score, V2 extractedValue2) {\n" +
+			"		super(score, extractedValue2);\n" +
+			"	}\n" +
+			"\n" +
+			"	@Override\n" +
+			"	public <OtherV2> ExplainedResult<OtherV2> withValue(OtherV2 otherValue2) {\n" +
+			"		return new ExplainedResult<OtherV2>(this.score, otherValue2);\n" +
+			"	}\n" +
+			"}\n" +
+			"",
+			"test/Result.java",
+			"package test;\n" +
+			"\n" +
+			"import org.eclipse.jdt.annotation.NonNullByDefault;\n" +
+			"\n" +
+			"@NonNullByDefault\n" +
+			"public class Result<V1> {\n" +
+			"\n" +
+			"	public final int score;\n" +
+			"\n" +
+			"	public final V1 extractedValue;\n" +
+			"\n" +
+			"	public Result(int score, V1 extractedValue1) {\n" +
+			"		this.score = score;\n" +
+			"		this.extractedValue = extractedValue1;\n" +
+			"	}\n" +
+			"\n" +
+			"	public <OtherV1> Result<OtherV1> withValue(OtherV1 otherValue1) {\n" +
+			"		return new Result<OtherV1>(score, otherValue1);\n" +
+			"	}\n" +
+			"}\n" +
+			""
+		}, 
+		getCompilerOptions(),
+		""
+	);			
+}
+public void testBug485581() {
+	runConformTestWithLibs(
+		new String[] {
+		"test/MatchResult.java",
+			"package test;\n" +
+			"\n" +
+			"import org.eclipse.jdt.annotation.NonNullByDefault;\n" +
+			"\n" +
+			"@NonNullByDefault\n" +
+			"public class MatchResult<V> implements Comparable<MatchResult<?>> {\n" +
+			"	public final int score;\n" +
+			"	public final V value;\n" +
+			"\n" +
+			"	public MatchResult(int score, V value) {\n" +
+			"		this.score = score;\n" +
+			"		this.value = value;\n" +
+			"	}\n" +
+			"\n" +
+			"	@Override\n" +
+			"	public int compareTo(MatchResult<?> o) {\n" +
+			"		return score - o.score;\n" +
+			"	}\n" +
+			"}\n"
+		},
+		getCompilerOptions(),
+		""
+	);
+	runConformTestWithLibs(
+		new String[] {
+			"test/FVEHandler.java",
+			"package test;\n" +
+			"\n" +
+			"import org.eclipse.jdt.annotation.NonNullByDefault;\n" +
+			"\n" +
+			"@NonNullByDefault\n" +
+			"public class FVEHandler {\n" +
+			"	public static void process(MatchResult<?> matchResult) {\n" +
+			"		if (matchResult.value != null) {\n" +
+			"		}\n" +
+			"	}\n" +
+			"}\n",
+		}, 
+		getCompilerOptions(),
+		""
+	);
+}
+public void testBug485374() {
+	runConformTestWithLibs(
+		new String[] {
+			"test/I.java",
+			"package test;\n" +
+			"public interface I<W> {\n" +
+			"    public class Nested {\n" +
+			"    }\n" +
+			"}\n" +
+			"",
+			"test/D.java",
+			"package test;\n" +
+			"import org.eclipse.jdt.annotation.NonNull;\n" +
+			"\n" +
+			"public class D implements I<I.@NonNull Nested> {\n" +
+			"}\n" +
+			""
+		}, 
+		getCompilerOptions(),
+		""
+	);
+	runNegativeTestWithLibs(
+			new String[] {
+			"test2/Import.java",
+				"package test2;\n" +
+				"import test.D;\n" +
+				"class Import {}\n"
+			}, 
+			getCompilerOptions(),
+			"----------\n" + 
+			"1. WARNING in test2\\Import.java (at line 2)\n" + 
+			"	import test.D;\n" + 
+			"	       ^^^^^^\n" + 
+			"The import test.D is never used\n" + 
+			"----------\n"
+		);
+}
+
+public void testBug466556a() {
+	runNegativeTestWithLibs(
+		new String[] {
+			"test/C.java",
+			"package test;\n" +
+			"class C<T extends Number> {\n" +
+			"    int consume(T t) {\n" +
+			"        return t.intValue(); // NOT OK since T could be nullable\n" +
+			"    }\n" +
+			"    T provide() {\n" +
+			"        return null;         // NOT OK since T could require nonnull\n" +
+			"    }\n" +
+			"}\n",
+		}, 
+		getCompilerOptions(),
+		"----------\n" + 
+		"1. ERROR in test\\C.java (at line 4)\n" + 
+		"	return t.intValue(); // NOT OK since T could be nullable\n" + 
+		"	       ^\n" + 
+		"Potential null pointer access: this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" + 
+		"----------\n" + 
+		"2. ERROR in test\\C.java (at line 7)\n" + 
+		"	return null;         // NOT OK since T could require nonnull\n" + 
+		"	       ^^^^\n" + 
+		"Null type mismatch (type annotations): \'null\' is not compatible to the free type variable \'T\'\n" + 
+		"----------\n"
+	);
+}
+public void testBug466556nonfree() {
+	runNegativeTestWithLibs(
+		new String[] {
+			"test/C.java",
+			"package test;\n" +
+			"class C<T extends @org.eclipse.jdt.annotation.NonNull Number> {\n" +
+			"    int consume(T t) {\n" +
+			"        return t.intValue(); // OK since T has upper bound with @NonNull\n" +
+			"    }\n" +
+			"    T provide() {\n" +
+			"        return null;         // NOT OK since T could require nonnull\n" +
+			"    }\n" +
+			"}\n",
+		}, 
+		getCompilerOptions(),
+		"----------\n" + 
+		"1. ERROR in test\\C.java (at line 7)\n" + 
+		"	return null;         // NOT OK since T could require nonnull\n" + 
+		"	       ^^^^\n" + 
+		"Null type mismatch: required \'T extends @NonNull Number\' but the provided value is null\n" + 
+		"----------\n"
+	);
+}
+public void testBug466556b() {
+	runNegativeTestWithLibs(
+		new String[] {
+			"test/C.java",
+			"package test;\n" +
+			"\n" +
+			"import java.util.function.Supplier;\n" +
+			"\n" +
+			"class C<T> {\n" +
+			"	int consume(T t) {\n" +
+			"		return t.hashCode();\n" +
+			"	}\n" +
+			"	void consume2(Supplier<T> s) {\n" +
+			"		s.get().hashCode();\n" +
+			"	}\n" +
+			"}\n",
+		}, 
+		getCompilerOptions(),
+		"----------\n" + 
+		"1. ERROR in test\\C.java (at line 7)\n" + 
+		"	return t.hashCode();\n" + 
+		"	       ^\n" + 
+		"Potential null pointer access: this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" + 
+		"----------\n" + 
+		"2. ERROR in test\\C.java (at line 10)\n" + 
+		"	s.get().hashCode();\n" + 
+		"	^^^^^^^\n" + 
+		"Potential null pointer access: this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" + 
+		"----------\n"
+	);
+}
+public void testBug466556c() {
+	runNegativeTestWithLibs(
+		new String[] {
+			"test/C.java",
+			"package test;\n" +
+			"\n" +
+			"import java.util.function.Supplier;\n" +
+			"\n" +
+			"class C<T extends Number> {\n" +
+			"	int consume(T t) {\n" +
+			"		Number n = t;\n" +
+			"		return n.intValue();\n" +
+			"	}\n" +
+			"\n" +
+			"	int consume2(Supplier<T> s) {\n" +
+			"		Number n = s.get();\n" +
+			"		return n.intValue();\n" +
+			"	}\n" +
+			"}\n",
+		}, 
+		getCompilerOptions(),
+		"----------\n" + 
+		"1. ERROR in test\\C.java (at line 8)\n" + 
+		"	return n.intValue();\n" + 
+		"	       ^\n" + 
+		"Potential null pointer access: The variable n may be null at this location\n" + 
+		"----------\n" + 
+		"2. ERROR in test\\C.java (at line 13)\n" + 
+		"	return n.intValue();\n" + 
+		"	       ^\n" + 
+		"Potential null pointer access: The variable n may be null at this location\n" + 
+		"----------\n"
+	);
+}
+public void testBug466556field() {
+	runNegativeTestWithLibs(
+		new String[] {
+			"test/D.java",
+			"package test;\n" +
+			"\n" +
+			"import org.eclipse.jdt.annotation.NonNull;\n" +
+			"import org.eclipse.jdt.annotation.Nullable;\n" +
+			"\n" +
+			"class E<T> {\n" +
+			"	T t;\n" +
+			"}\n" +
+			"\n" +
+			"class D<T> {\n" +
+			"	enum X {\n" +
+			"		x\n" +
+			"	};\n" +
+			"\n" +
+			"	T t1;\n" +
+			"	T t2;\n" +
+			"	T t3;\n" +
+			"	@Nullable\n" +
+			"	T t4;\n" +
+			"	@NonNull\n" +
+			"	T t5;\n" +
+			"	@NonNull\n" +
+			"	T t6;\n" +
+			"	@NonNull\n" +
+			"	T t7;\n" +
+			"\n" +
+			"	D(@NonNull T t) {\n" +
+			"		t2 = t;\n" +
+			"		switch (X.x) {\n" +
+			"		case x:\n" +
+			"			t1 = t;\n" +
+			"			t5 = t;\n" +
+			"		}\n" +
+			"		t6 = t;\n" +
+			"	}\n" +
+			"\n" +
+			"	void f() {\n" +
+			"		t1.hashCode();\n" +
+			"		t2.hashCode();\n" +
+			"		t3.hashCode();\n" +
+			"		t4.hashCode();\n" +
+			"		t5.hashCode();\n" +
+			"		t6.hashCode();\n" +
+			"		t7.hashCode();\n" +
+			"		T t = t1;\n" +
+			"		t.hashCode();\n" +
+			"	}\n" +
+			"	void g() {\n" +
+			"		if(t1 != null)\n" +
+			"			t1.hashCode();\n // problem report expected because syntactic null analysis for fields is off\n" +
+			"	}\n" +
+			"}\n" +
+			"",
+		}, 
+		getCompilerOptions(),
+		"----------\n" + 
+		"1. ERROR in test\\D.java (at line 7)\n" + 
+		"	T t;\n" + 
+		"	  ^\n" + 
+		"The field t may not have been initialized, whereas its type \'T\' is a free type variable that may represent a \'@NonNull\' type\n" + 
+		"----------\n" + 
+		"2. ERROR in test\\D.java (at line 27)\n" + 
+		"	D(@NonNull T t) {\n" + 
+		"	^^^^^^^^^^^^^^^\n" + 
+		"The field t1 may not have been initialized, whereas its type \'T\' is a free type variable that may represent a \'@NonNull\' type. Note that a problem regarding missing \'default:\' on \'switch\' has been suppressed, which is perhaps related to this problem\n" + 
+		"----------\n" + 
+		"3. ERROR in test\\D.java (at line 27)\n" + 
+		"	D(@NonNull T t) {\n" + 
+		"	^^^^^^^^^^^^^^^\n" + 
+		"The field t3 may not have been initialized, whereas its type \'T\' is a free type variable that may represent a \'@NonNull\' type. Note that a problem regarding missing \'default:\' on \'switch\' has been suppressed, which is perhaps related to this problem\n" + 
+		"----------\n" + 
+		"4. ERROR in test\\D.java (at line 27)\n" + 
+		"	D(@NonNull T t) {\n" + 
+		"	^^^^^^^^^^^^^^^\n" + 
+		"The @NonNull field t5 may not have been initialized. Note that a problem regarding missing \'default:\' on \'switch\' has been suppressed, which is perhaps related to this problem\n" + 
+		"----------\n" + 
+		"5. ERROR in test\\D.java (at line 27)\n" + 
+		"	D(@NonNull T t) {\n" + 
+		"	^^^^^^^^^^^^^^^\n" + 
+		"The @NonNull field t7 may not have been initialized. Note that a problem regarding missing \'default:\' on \'switch\' has been suppressed, which is perhaps related to this problem\n" + 
+		"----------\n" + 
+		"6. ERROR in test\\D.java (at line 38)\n" + 
+		"	t1.hashCode();\n" + 
+		"	^^\n" + 
+		"Potential null pointer access: this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" + 
+		"----------\n" + 
+		"7. ERROR in test\\D.java (at line 39)\n" + 
+		"	t2.hashCode();\n" + 
+		"	^^\n" + 
+		"Potential null pointer access: this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" + 
+		"----------\n" + 
+		"8. ERROR in test\\D.java (at line 40)\n" + 
+		"	t3.hashCode();\n" + 
+		"	^^\n" + 
+		"Potential null pointer access: this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" + 
+		"----------\n" + 
+		"9. ERROR in test\\D.java (at line 41)\n" + 
+		"	t4.hashCode();\n" + 
+		"	^^\n" + 
+		"Potential null pointer access: this expression has a \'@Nullable\' type\n" + 
+		"----------\n" + 
+		"10. ERROR in test\\D.java (at line 46)\n" + 
+		"	t.hashCode();\n" + 
+		"	^\n" + 
+		"Potential null pointer access: this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" + 
+		"----------\n" +
+		"11. ERROR in test\\D.java (at line 50)\n" + 
+		"	t1.hashCode();\n" + 
+		"	^^\n" + 
+		"Potential null pointer access: this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" + 
+		"----------\n"
+	);
+}
+public void testBug466556withRaw() {
+	runConformTestWithLibs(
+		new String[] {
+			"test/TestWithRaw.java",
+			"package test;\n" +
+			"\n" +
+			"public class TestWithRaw {\n" +
+			"	@SuppressWarnings({ \"unchecked\", \"rawtypes\" })\n" +
+			"	public static void uncheckedEnumValueOf(final Class<?> valueClass, final String value) {\n" +
+			"		Class valueClass2 = valueClass;\n" +
+			"		Enum.valueOf(valueClass2, value).name();\n" +
+			"	}\n" +
+			"}\n" +
+			"",
+		}, 
+		getCompilerOptions(),
+		""
+	);
+}
+public void testBug466556withPGMB() {
+	runNegativeTestWithLibs(
+		new String[] {
+			"test/TestWithParameterizedGenericMethodBinding.java",
+			"package test;\n" +
+			"\n" +
+			"public class TestWithParameterizedGenericMethodBinding {\n" +
+			"	static <T, E extends T> T f1(E e) {\n" +
+			"		return e;\n" +
+			"	}\n" +
+			"\n" +
+			"	static <T11, E11 extends T11> void g11(E11 e) {\n" +
+			"		f1(e).hashCode();\n" +
+			"	}\n" +
+			"}\n" +
+			"",
+		}, 
+		getCompilerOptions(),
+		"----------\n" + 
+		"1. ERROR in test\\TestWithParameterizedGenericMethodBinding.java (at line 9)\n" + 
+		"	f1(e).hashCode();\n" + 
+		"	^^^^^\n" + 
+		"Potential null pointer access: this expression has type \'E11\', a free type variable that may represent a \'@Nullable\' type\n" + 
+		"----------\n"
+	);
+}
+public void testBug466556captures() {
+	runNegativeTestWithLibs(
+		new String[] {
+			"test/TestCapture.java",
+			"package test;\n" +
+			"\n" +
+			"class I {\n" +
+			"	int i;\n" +
+			"\n" +
+			"	String s() {\n" +
+			"		return \"\";\n" +
+			"	}\n" +
+			"}\n" +
+			"\n" +
+			"class KE<E extends I> {\n" +
+			"	public final E e;\n" +
+			"\n" +
+			"	public E getE() {\n" +
+			"		return e;\n" +
+			"	}\n" +
+			"\n" +
+			"	public KE(E element) {\n" +
+			"		this.e = element;\n" +
+			"	}\n" +
+			"}\n" +
+			"\n" +
+			"class TestFreeTypeVariable<E2 extends I> {\n" +
+			"	public void test(KE<E2> ke) {\n" +
+			"		int i1 = ke.e.i; // error 1\n" +
+			"		ke.e.s().substring(i1); // error 2\n" +
+			"		int i2 = ke.getE().i; // error 3\n" +
+			"		ke.getE().s().substring(i2); // error 4\n" +
+			"	}\n" +
+			"}\n" +
+			"\n" +
+			"public class TestCapture {\n" +
+			"	public void test(KE<? extends I> ke) {\n" +
+			"		int i1 = ke.e.i; // error 5\n" +
+			"		ke.e.s().substring(i1); // error 6\n" +
+			"		int i2 = ke.getE().i; // error 7\n" +
+			"		ke.getE().s().substring(i2); // error 8\n" +
+			"	}\n" +
+			"}\n" +
+			"",
+		}, 
+		getCompilerOptions(),
+		"----------\n" + 
+		"1. ERROR in test\\TestCapture.java (at line 25)\n" + 
+		"	int i1 = ke.e.i; // error 1\n" + 
+		"	            ^\n" + 
+		"Potential null pointer access: this expression has type \'E2\', a free type variable that may represent a \'@Nullable\' type\n" + 
+		"----------\n" + 
+		"2. ERROR in test\\TestCapture.java (at line 26)\n" + 
+		"	ke.e.s().substring(i1); // error 2\n" + 
+		"	   ^\n" + 
+		"Potential null pointer access: this expression has type \'E2\', a free type variable that may represent a \'@Nullable\' type\n" + 
+		"----------\n" + 
+		"3. ERROR in test\\TestCapture.java (at line 27)\n" + 
+		"	int i2 = ke.getE().i; // error 3\n" + 
+		"	         ^^^^^^^^^\n" + 
+		"Potential null pointer access: this expression has type \'E2\', a free type variable that may represent a \'@Nullable\' type\n" + 
+		"----------\n" + 
+		"4. ERROR in test\\TestCapture.java (at line 28)\n" + 
+		"	ke.getE().s().substring(i2); // error 4\n" + 
+		"	^^^^^^^^^\n" + 
+		"Potential null pointer access: this expression has type \'E2\', a free type variable that may represent a \'@Nullable\' type\n" + 
+		"----------\n" + 
+		"5. ERROR in test\\TestCapture.java (at line 34)\n" + 
+		"	int i1 = ke.e.i; // error 5\n" + 
+		"	            ^\n" + 
+		"Potential null pointer access: this expression has type \'capture#1-of ? extends test.I\', a free type variable that may represent a \'@Nullable\' type\n" + 
+		"----------\n" + 
+		"6. ERROR in test\\TestCapture.java (at line 35)\n" + 
+		"	ke.e.s().substring(i1); // error 6\n" + 
+		"	   ^\n" + 
+		"Potential null pointer access: this expression has type \'capture#2-of ? extends test.I\', a free type variable that may represent a \'@Nullable\' type\n" + 
+		"----------\n" + 
+		"7. ERROR in test\\TestCapture.java (at line 36)\n" + 
+		"	int i2 = ke.getE().i; // error 7\n" + 
+		"	         ^^^^^^^^^\n" + 
+		"Potential null pointer access: this expression has type \'capture#3-of ? extends test.I\', a free type variable that may represent a \'@Nullable\' type\n" + 
+		"----------\n" + 
+		"8. ERROR in test\\TestCapture.java (at line 37)\n" + 
+		"	ke.getE().s().substring(i2); // error 8\n" + 
+		"	^^^^^^^^^\n" + 
+		"Potential null pointer access: this expression has type \'capture#4-of ? extends test.I\', a free type variable that may represent a \'@Nullable\' type\n" + 
+		"----------\n"
+	);
+}
+public void testBug466556Loops() {
+	runNegativeTestWithLibs(
+		new String[] {
+			"test/TestLoop.java",
+			"package test;\n" +
+			"\n" +
+			"import org.eclipse.jdt.annotation.NonNull;\n" +
+			"\n" +
+			"public class TestLoop<T> {\n" +
+			"	boolean b;\n" +
+			"\n" +
+			"	public static void nn(@NonNull Object value) {\n" +
+			"		assert value != null;\n" +
+			"	}\n" +
+			"\n" +
+			"	public void testDoWhile(T t1) {\n" +
+			"		nn(t1); // 1: unchecked warning\n" +
+			"		do {\n" +
+			"			nn(t1); // 2: unchecked warning\n" +
+			"			t1.hashCode(); // 3: Potential null pointer access...free type variable\n" +
+			"		} while (b);\n" +
+			"	}\n" +
+			"\n" +
+			"	public void testWhileWithBreak(T t1) {\n" +
+			"		while (true) {\n" +
+			"			nn(t1); // 4: unchecked warning\n" +
+			"			t1.hashCode(); // 5: Potential null pointer access...free type variable\n" +
+			"			if (b)\n" +
+			"				break;\n" +
+			"		}\n" +
+			"	}\n" +
+			"\n" +
+			"	public void testWhile(T t1) {\n" +
+			"		while (TestLoop.class.hashCode() == 4711) {\n" +
+			"			nn(t1); // 6: unchecked warning\n" +
+			"			t1.hashCode(); // 7: Potential null pointer access...free type variable\n" +
+			"		}\n" +
+			"	}\n" +
+			"\n" +
+			"	public void testFor(T t1) {\n" +
+			"		for (int i = 0; i < 1; i++) {\n" +
+			"			nn(t1); // 8: unchecked warning\n" +
+			"			t1.hashCode(); // 9: Potential null pointer access...free type variable\n" +
+			"		}\n" +
+			"	}\n" +
+			"\n" +
+			"	public void testForEach(T t1) {\n" +
+			"		for (int i = 0; i < 1; i++) {\n" +
+			"			nn(t1); // 10: unchecked warning\n" +
+			"			t1.hashCode(); // 11: Potential null pointer access: The variable t1 may be null at this location\n" +
+			"		}\n" +
+			"	}\n" +
+			"}\n" +
+			"",
+		}, 
+		getCompilerOptions(),
+		"----------\n" + 
+		"1. ERROR in test\\TestLoop.java (at line 13)\n" + 
+		"	nn(t1); // 1: unchecked warning\n" + 
+		"	   ^^\n" + 
+		"Null type safety: required \'@NonNull\' but this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" + 
+		"----------\n" + 
+		"2. ERROR in test\\TestLoop.java (at line 15)\n" + 
+		"	nn(t1); // 2: unchecked warning\n" + 
+		"	   ^^\n" + 
+		"Null type safety: required \'@NonNull\' but this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" + 
+		"----------\n" + 
+		"3. ERROR in test\\TestLoop.java (at line 16)\n" + 
+		"	t1.hashCode(); // 3: Potential null pointer access...free type variable\n" + 
+		"	^^\n" + 
+		"Potential null pointer access: this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" + 
+		"----------\n" + 
+		"4. ERROR in test\\TestLoop.java (at line 22)\n" + 
+		"	nn(t1); // 4: unchecked warning\n" + 
+		"	   ^^\n" + 
+		"Null type safety: required \'@NonNull\' but this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" + 
+		"----------\n" + 
+		"5. ERROR in test\\TestLoop.java (at line 23)\n" + 
+		"	t1.hashCode(); // 5: Potential null pointer access...free type variable\n" + 
+		"	^^\n" + 
+		"Potential null pointer access: this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" + 
+		"----------\n" + 
+		"6. ERROR in test\\TestLoop.java (at line 31)\n" + 
+		"	nn(t1); // 6: unchecked warning\n" + 
+		"	   ^^\n" + 
+		"Null type safety: required \'@NonNull\' but this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" + 
+		"----------\n" + 
+		"7. ERROR in test\\TestLoop.java (at line 32)\n" + 
+		"	t1.hashCode(); // 7: Potential null pointer access...free type variable\n" + 
+		"	^^\n" + 
+		"Potential null pointer access: this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" + 
+		"----------\n" + 
+		"8. ERROR in test\\TestLoop.java (at line 38)\n" + 
+		"	nn(t1); // 8: unchecked warning\n" + 
+		"	   ^^\n" + 
+		"Null type safety: required \'@NonNull\' but this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" + 
+		"----------\n" + 
+		"9. ERROR in test\\TestLoop.java (at line 39)\n" + 
+		"	t1.hashCode(); // 9: Potential null pointer access...free type variable\n" + 
+		"	^^\n" + 
+		"Potential null pointer access: this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" + 
+		"----------\n" + 
+		"10. ERROR in test\\TestLoop.java (at line 45)\n" + 
+		"	nn(t1); // 10: unchecked warning\n" + 
+		"	   ^^\n" + 
+		"Null type safety: required \'@NonNull\' but this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" + 
+		"----------\n" + 
+		"11. ERROR in test\\TestLoop.java (at line 46)\n" + 
+		"	t1.hashCode(); // 11: Potential null pointer access: The variable t1 may be null at this location\n" + 
+		"	^^\n" + 
+		"Potential null pointer access: this expression has type \'T\', a free type variable that may represent a \'@Nullable\' type\n" + 
+		"----------\n"
+	);
+}
+public void testBug461268() {
+	Map compilerOptions = getCompilerOptions();
+	compilerOptions.put(CompilerOptions.OPTION_ReportNonNullTypeVariableFromLegacyInvocation, JavaCore.ERROR);
+	compilerOptions.put(CompilerOptions.OPTION_PessimisticNullAnalysisForFreeTypeVariables, JavaCore.IGNORE);
+	runNegativeTestWithLibs(
+		new String[] {
+			"X.java",
+			"import java.util.List;\n" +
+			"import org.eclipse.jdt.annotation.*;\n" +
+			"public class X {\n" +
+			"	void test(List<@NonNull String> list) {\n" +
+			"		@NonNull String s = list.get(0);\n" +
+			"	}\n" +
+			"}\n"
+		},
+		compilerOptions,
+		"----------\n" + 
+		"1. ERROR in X.java (at line 5)\n" + 
+		"	@NonNull String s = list.get(0);\n" + 
+		"	                    ^^^^^^^^^^^\n" + 
+		"Unsafe interpretation of method return type as \'@NonNull\' based on the receiver type \'List<@NonNull String>\'. Type \'List<E>\' doesn\'t seem to be designed with null type annotations in mind\n" + 
+		"----------\n");
+}
+public void testBug461268invoke() {
+	Map compilerOptions = getCompilerOptions();
+	compilerOptions.put(CompilerOptions.OPTION_ReportNonNullTypeVariableFromLegacyInvocation, JavaCore.ERROR);
+	runNegativeTestWithLibs(
+		new String[] {
+			"X.java",
+			"import java.util.Map;\n" +
+			"import org.eclipse.jdt.annotation.*;\n" +
+			"public class X {\n" +
+			"	void test(Map<Object, @NonNull String> map) {\n" +
+			"		map.get(this).length();\n" +
+			"	}\n" +
+			"}\n"
+		},
+		compilerOptions,
+		"----------\n" + 
+		"1. ERROR in X.java (at line 5)\n" + 
+		"	map.get(this).length();\n" + 
+		"	^^^^^^^^^^^^^\n" + 
+		"Unsafe interpretation of method return type as \'@NonNull\' based on the receiver type \'Map<Object,@NonNull String>\'. Type \'Map<K,V>\' doesn\'t seem to be designed with null type annotations in mind\n" + 
+		"----------\n");
+}
+public void testBug461268nnbd() {
+	Map compilerOptions = getCompilerOptions();
+	compilerOptions.put(CompilerOptions.OPTION_ReportNonNullTypeVariableFromLegacyInvocation, JavaCore.ERROR);
+	runConformTestWithLibs(
+		new String[] {
+			"test2/Container.java",
+			"package test2;\n" +
+			"\n" +
+			"import org.eclipse.jdt.annotation.NonNullByDefault;\n" +
+			"\n" +
+			"@NonNullByDefault\n" +
+			"public class Container<T> {\n" +
+			"	public static <T> T getFrom(Container<T> container) {\n" +
+			"		return container.get();\n" +
+			"	}\n" +
+			"\n" +
+			"	private final T t;\n" +
+			"\n" +
+			"	public Container(T t) {\n" +
+			"		this.t = t;\n" +
+			"	}\n" +
+			"\n" +
+			"	private T get() {\n" + // we really mean 'T' unannotated, believe it due to @NonNullByDefault
+			"		return this.t;\n" +
+			"	}\n" +
+			"}\n",
+		}, 
+		getCompilerOptions(),
+		""
+	);
+	runConformTestWithLibs(
+		new String[] {
+			"test/Test.java",
+			"package test;\n" +
+			"\n" +
+			"import org.eclipse.jdt.annotation.NonNullByDefault;\n" +
+			"\n" +
+			"import test2.Container;\n" +
+			"\n" +
+			"@NonNullByDefault\n" +
+			"public class Test {\n" +
+			"	String f(Container<String> c) {\n" +
+			"		return Container.getFrom(c);\n" +
+			"	}\n" +
+			"}\n" +
+			"",
+		}, 
+		getCompilerOptions(),
+		""
+	);
+}
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SerializableLambdaTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SerializableLambdaTest.java
index e9111e8..86a4714 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SerializableLambdaTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SerializableLambdaTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2014 GoPivotal, Inc. All Rights Reserved.
+ * Copyright (c) 2014, 2016 GoPivotal, Inc. and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -15,6 +15,7 @@
  *        Olivier Tardieu tardieu@us.ibm.com - Contributions for
  *                          Bug 442416 - $deserializeLambda$ missing cases for nested lambdas
  *                          Bug 442418 - $deserializeLambda$ off-by-one error when deserializing the captured arguments of a lambda that also capture this
+ *        IBM Corporation - Additional tests
  *******************************************************************************/
 package org.eclipse.jdt.core.tests.compiler.regression;
 
@@ -1532,7 +1533,254 @@
 				null,true,
 				new String[]{"-Ddummy"}); // Not sure, unless we force the VM to not be reused by passing dummy vm argument, the generated program aborts midway through its execution.
 	}
-	
+
+	public void testbug479119() {
+		this.runConformTest(
+			new String[]{
+				"Testbed.java",
+				"import java.io.ObjectStreamClass;\n" + 
+				"import java.io.Serializable;\n" + 
+				"import java.lang.invoke.SerializedLambda;\n" + 
+				"import java.lang.reflect.Method;\n" + 
+				"import java.util.function.IntFunction;\n" + 
+				"import java.util.stream.Stream;\n" + 
+				"public class Testbed {\n" + 
+				"	public static void main(String[] args) {\n" + 
+				"		System.out.println(getMethod(Testbed::foo).equals(getMethod(Testbed::foo)));\n" + 
+				"	}\n" + 
+				"	private static void foo() { }\n" + 
+				"	static interface MethodRef extends Runnable, Serializable { }\n" + 
+				"	private static Method getMethod(MethodRef methodRef) {\n" + 
+				"		try {\n" + 
+				"			final Method invokeWriteReplaceMethod = ObjectStreamClass.class.getDeclaredMethod(\"invokeWriteReplace\", Object.class);\n" + 
+				"			invokeWriteReplaceMethod.setAccessible(true);\n" + 
+				"			final SerializedLambda l = (SerializedLambda)invokeWriteReplaceMethod.invoke(\n" + 
+				"					ObjectStreamClass.lookupAny(methodRef.getClass()),\n" + 
+				"					methodRef\n" + 
+				"				);\n" + 
+				"			System.out.println(\"Looking for \" + l.getImplClass() + \".\" + l.getImplMethodName());\n" + 
+				"			final Method[] methods = Stream.of(Class.forName(l.getImplClass()).getDeclaredMethods()).\n" + 
+				"				filter(m -> m.getName().equals(l.getImplMethodName())).\n" + 
+				"				toArray(Method[]::new);\n" + 
+				"			if(methods.length != 1) throw new AssertionError(\"TODO: check signature\");\n" + 
+				"			return methods[0];\n" + 
+				"		} catch(Exception e) {\n" + 
+				"			throw new RuntimeException(e);\n" + 
+				"		}\n" + 
+				"	}\n" + 
+				"}\n"
+		},
+		"Looking for Testbed.foo\n" +
+		"Looking for Testbed.foo\n" +
+		"true",
+		null,true,
+		new String[]{"-Ddummy"});
+		
+		String bootstrapEntries = printBootstrapMethodsAttribute(OUTPUT_DIR + File.separator + "Testbed.class");
+		String expectedOutput = 
+				"0: invokestatic java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;\n"+
+				"  Method arguments:\n"+
+				"    ()V\n"+
+				"    invokestatic Testbed.foo:()V\n"+
+				"    ()V\n"+
+				"    1\n"+
+				"1: invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;\n"+
+				"  Method arguments:\n"+
+				"    (Ljava/lang/Object;)Z\n"+
+				"    invokestatic Testbed.lambda$0:(Ljava/lang/invoke/SerializedLambda;Ljava/lang/reflect/Method;)Z\n"+
+				"    (Ljava/lang/reflect/Method;)Z\n"+
+				"2: invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;\n"+
+				"  Method arguments:\n"+
+				"    (I)Ljava/lang/Object;\n"+
+				"    invokestatic Testbed.lambda$1:(I)[Ljava/lang/reflect/Method;\n"+
+				"    (I)[Ljava/lang/reflect/Method;\n";
+
+		checkExpected(expectedOutput, bootstrapEntries);
+	}
+
+	public void testbug479119a() {
+		this.runConformTest(
+			new String[]{
+				"Testbed.java",
+				"import java.io.ObjectStreamClass;\n" + 
+				"import java.io.Serializable;\n" + 
+				"import java.lang.invoke.SerializedLambda;\n" + 
+				"import java.lang.reflect.Constructor;\n" + 
+				"import java.lang.reflect.Executable;\n" + 
+				"import java.lang.reflect.Method;\n" + 
+				"import java.util.function.IntFunction;\n" + 
+				"import java.util.stream.Stream;\n" + 
+				"public class Testbed {\n" + 
+				"	public static void main(String[] args) {\n" + 
+				"		System.out.println(getMethod(Testbed::foo).equals(getMethod(Testbed::foo)));\n" + 
+				"		System.out.println(getMethod(new Foo()::method).equals(getMethod(new Bar()::method)));\n" + 
+				"		System.out.println(getMethod(MethodRefImpl::new).equals(getMethod(MethodRefImpl::new)));\n" + 
+				"	}\n" + 
+				"	static class MethodRefImpl implements MethodRef {\n" + 
+				"		@Override\n" + 
+				"		public void run() {}\n" + 
+				"	}\n" + 
+				"	public static class Base {\n" + 
+				"        public void method () {}\n" + 
+				"    }\n" + 
+				"    public static class Foo extends Base {}\n" + 
+				"    public static class Bar extends Base {}\n" + 
+				"	private static void foo() { }\n" + 
+				"	static interface MethodRef extends Runnable, Serializable { }\n" + 
+				"	private static Executable getMethod(MethodRef methodRef) {\n" + 
+				"		try {\n" + 
+				"			final Method invokeWriteReplaceMethod = ObjectStreamClass.class.getDeclaredMethod(\"invokeWriteReplace\", Object.class);\n" + 
+				"			invokeWriteReplaceMethod.setAccessible(true);\n" + 
+				"			final SerializedLambda l = (SerializedLambda)invokeWriteReplaceMethod.invoke(\n" + 
+				"					ObjectStreamClass.lookupAny(methodRef.getClass()),\n" + 
+				"					methodRef\n" + 
+				"				);\n" + 
+				"			System.out.println(\"Looking for \" + l.getImplClass() + \".\" + l.getImplMethodName());\n" + 
+				"			boolean isConstructor = l.getImplMethodName().indexOf(\"<init>\") >= 0;\n" + 
+				"			final Executable[] methods = Stream.of(isConstructor ? Class.forName(l.getImplClass()).getDeclaredConstructors() : Class.forName(l.getImplClass()).getDeclaredMethods()).\n" + 
+				"				filter(m -> m.getName().equals(isConstructor ? l.getImplClass() : l.getImplMethodName())).\n" + 
+				"				toArray(isConstructor ? Constructor[]::new : Method[]::new);\n" + 
+				"			if(methods.length != 1) throw new AssertionError(\"TODO: check signature\");\n" + 
+				"			return methods[0];\n" + 
+				"		} catch(Exception e) {\n" + 
+				"			throw new RuntimeException(e);\n" + 
+				"		}\n" + 
+				"	}\n" + 
+				"}\n"
+		},
+		"Looking for Testbed.foo\n" +
+		"Looking for Testbed.foo\n" +
+		"true\n" +
+		"Looking for Testbed$Base.method\n" +
+		"Looking for Testbed$Base.method\n" +
+		"true\n" +
+		"Looking for Testbed$MethodRefImpl.<init>\n" +
+		"Looking for Testbed$MethodRefImpl.<init>\n" +
+		"true",
+		null,true,
+		new String[]{"-Ddummy"});
+	}
+
+	// Serializable reference expressions that share the same name
+	public void testbug479119b() {
+		this.runConformTest(
+			new String[]{
+				"X.java",
+				"import java.io.ByteArrayInputStream;\n" + 
+				"import java.io.ByteArrayOutputStream;\n" + 
+				"import java.io.IOException;\n" + 
+				"import java.io.ObjectInputStream;\n" + 
+				"import java.io.ObjectOutputStream;\n" + 
+				"import java.io.Serializable;\n" + 
+				"public class X {\n" + 
+				"    public static interface Consumer<T> extends Serializable {\n" + 
+				"        void accept(T t);\n" + 
+				"    }\n" + 
+				"    public static class Foo {\n" + 
+				"    	public void method () {\n" + 
+				"        	System.out.println(\"Foo\");\n" + 
+				"        }\n" + 
+				"    }\n" + 
+				"    public static class Bar {\n" + 
+				"    	public void method () {\n" + 
+				"        	System.out.println(\"Bar\");\n" + 
+				"        }\n" + 
+				"    }\n" + 
+				"    public static void main (String[] args) throws IOException, ClassNotFoundException {\n" + 
+				"        Consumer<Foo> foo = Foo::method;\n" + 
+				"        Consumer<Bar> bar = Bar::method;\n" + 
+				"        Consumer<Foo> baz = (b) -> {b.method();};\n" + 
+				"        ByteArrayOutputStream debug=new ByteArrayOutputStream();\n" + 
+				"		try(ObjectOutputStream oo=new ObjectOutputStream(debug)) {\n" + 
+				"			oo.writeObject(bar);\n" + 
+				"		}\n" + 
+				"		try(ObjectInputStream oi=new ObjectInputStream(new ByteArrayInputStream(debug.toByteArray()))) {\n" + 
+				"			Consumer<Bar> x = (Consumer)oi.readObject();\n" + 
+				"			x.accept(new Bar());\n" + 
+				"		}\n" + 
+				"		debug.reset();\n" + 
+				"		try(ObjectOutputStream oo=new ObjectOutputStream(debug)) {\n" + 
+				"			oo.writeObject(foo);\n" + 
+				"		}\n" + 
+				"		try(ObjectInputStream oi=new ObjectInputStream(new ByteArrayInputStream(debug.toByteArray()))) {\n" + 
+				"			Consumer<Foo> x = (Consumer)oi.readObject();\n" + 
+				"			x.accept(new Foo());\n" + 
+				"		}\n" + 
+				"    }\n" + 
+				"}\n"
+		},
+		"Bar\n" +
+		"Foo",
+		null,true,
+		new String[]{"-Ddummy"});
+	}
+	public void testbug479119_comment20() {
+		this.runConformTest(
+			new String[]{
+				"Testbed.java",
+				"import java.io.ByteArrayInputStream;\n" + 
+				"import java.io.ByteArrayOutputStream;\n" + 
+				"import java.io.IOException;\n" + 
+				"import java.io.ObjectInputStream;\n" + 
+				"import java.io.ObjectOutputStream;\n" + 
+				"import java.io.Serializable;\n" + 
+				"interface FI extends Serializable{\n" + 
+				"	void run(Testbed args);\n" + 
+				"}\n" + 
+				"interface IF extends Serializable{\n" + 
+				"	void run();\n" + 
+				"}\n" + 
+				"public class Testbed implements Serializable{\n" + 
+				"	String f;\n" + 
+				"	Testbed(String str) {\n" + 
+				"		f = str;\n" + 
+				"	}\n" + 
+				"	void test() throws IOException, ClassNotFoundException {\n" + 
+				"		accept(Testbed::foo);\n" + 
+				"		accept(this::foo);		\n" + 
+				"	}\n" + 
+				"	void foo() {\n" + 
+				"		System.out.println(this.f);\n" + 
+				"	}\n" + 
+				"	void accept(FI fi) {\n" + 
+				"		fi.run(this);\n" + 
+				"	}\n" + 
+				"	void accept(IF i) {\n" + 
+				"		i.run();\n" + 
+				"	}\n" + 
+				"	public static void main(String[] args) throws ClassNotFoundException, IOException {\n" + 
+				"		Testbed t = new Testbed(\"IF\");\n" + 
+				"		Testbed t2 = new Testbed(\"FI\");\n" + 
+				"		IF i = t::foo;\n" + 
+				"		FI f = Testbed::foo;\n" + 
+				"		ByteArrayOutputStream debug=new ByteArrayOutputStream();\n" + 
+				"		try(ObjectOutputStream oo=new ObjectOutputStream(debug))\n" + 
+				"		{\n" + 
+				"			oo.writeObject(i);\n" + 
+				"		}\n" + 
+				"		try(ObjectInputStream oi=new ObjectInputStream(new ByteArrayInputStream(debug.toByteArray())))\n" + 
+				"		{\n" + 
+				"			IF x = (IF)oi.readObject();\n" + 
+				"			t.accept(x);\n" + 
+				"		}\n" + 
+				"		debug=new ByteArrayOutputStream();\n" + 
+				"		try(ObjectOutputStream oo=new ObjectOutputStream(debug))\n" + 
+				"		{\n" + 
+				"			oo.writeObject(f);\n" + 
+				"		}\n" + 
+				"		try(ObjectInputStream oi=new ObjectInputStream(new ByteArrayInputStream(debug.toByteArray())))\n" + 
+				"		{\n" + 
+				"			FI x = (FI)oi.readObject();\n" + 
+				"			t2.accept(x);\n" + 
+				"		}\n" + 
+				"	}\n" + 
+				"}"
+		},
+		"IF\n" +
+		"FI",
+		null,true,
+		new String[]{"-Ddummy"});
+	}
 	// ---
 	
 	private void checkExpected(String expected, String actual) {
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StaticImportTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StaticImportTest.java
index e10053f..012cffa 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StaticImportTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StaticImportTest.java
@@ -3226,5 +3226,36 @@
 				"}"
 			});
 	}
-}
-
+	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=442580
+	// Explicit static import after two wildcard imports is ambiguous (works in javac)
+	public void testBug442580() {
+		this.runConformTest(new String [] {
+				"a/A.java",
+				"package a;\n" + 
+				"\n" + 
+				"public class A {\n" + 
+				"	public static void foo() {\n" + 
+				"		System.out.println(\"A.foo\");\n" + 
+				"	}\n" + 
+				"}",
+				"b/B.java",
+				"package b;\n" + 
+				"\n" + 
+				"public class B {\n" + 
+				"	public static void foo() {\n" + 
+				"		System.out.println(\"B.foo\");\n" + 
+				"	}\n" + 
+				"}",
+				"Test.java",
+				"import static a.A.*;\n" + 
+				"import static b.B.*;\n" + 
+				"import static b.B.foo;\n" + 
+				"\n" + 
+				"public class Test {\n" + 
+				"	public static void main(String[] args) {\n" + 
+				"		foo();\n" + 
+				"	}\n" + 
+				"}"
+		});
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/META-INF/MANIFEST.MF b/org.eclipse.jdt.core.tests.model/META-INF/MANIFEST.MF
index c463de4..a48eb46 100644
--- a/org.eclipse.jdt.core.tests.model/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.core.tests.model/META-INF/MANIFEST.MF
@@ -1,7 +1,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.jdt.core.tests.model;singleton:=true
-Bundle-Version: 3.10.100.qualifier
+Bundle-Version: 3.10.200.qualifier
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
 Export-Package: org.eclipse.jdt.core.tests,
diff --git a/org.eclipse.jdt.core.tests.model/pom.xml b/org.eclipse.jdt.core.tests.model/pom.xml
index 66b2fb2..144082d 100644
--- a/org.eclipse.jdt.core.tests.model/pom.xml
+++ b/org.eclipse.jdt.core.tests.model/pom.xml
@@ -20,7 +20,7 @@
   </parent>
   <groupId>org.eclipse.jdt</groupId>
   <artifactId>org.eclipse.jdt.core.tests.model</artifactId>
-  <version>3.10.100-SNAPSHOT</version>
+  <version>3.10.200-SNAPSHOT</version>
   <packaging>eclipse-test-plugin</packaging>
 
   <properties>
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter18Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter18Test.java
index 03e0a71..f9f412f 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter18Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter18Test.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -5183,52 +5183,6 @@
 	IMethodBinding binding = lambdaExpression.resolveMethodBinding();
 	assertTrue("Should be a varargs", binding.isVarargs());
 }
-// 	https://bugs.eclipse.org/bugs/show_bug.cgi?id=463942
-public void testBug463942_001() throws JavaModelException {
-	String contents = 
-			"@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
-			"@interface Marker {\n" +
-			" 	String value() default \"\";\n" +
-			"}\n" +
-			"@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
-			"@interface Marker2 {\n" +
-			" 	String value() default \"22\";\n" +
-			"}\n" +
-			"public class X {\n" +
-			"   public String @Marker(\"i0\") @Marker2 [] [] @Marker(\"i1\") [] str = null;\n" +
-			"}";
-
-	this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true);
-	ASTNode node = buildAST(contents, this.workingCopy);
-	assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
-	CompilationUnit compilationUnit = (CompilationUnit) node;
-	assertProblemsSize(compilationUnit, 0);
-
-	/* public String @Marker("i0") @Marker2 [] [] @Marker("i1") [] str = null; */
-	node = getASTNode(compilationUnit, 2, 0);
-	assertTrue("Not a field declaration", node.getNodeType() == ASTNode.FIELD_DECLARATION);
-	FieldDeclaration field = (FieldDeclaration) node;
-	List fragments = field.fragments();
-	assertEquals("Incorrect no of fragments", 1, fragments.size());
-	VariableDeclarationFragment fragment = (VariableDeclarationFragment) fragments.get(0);
-	IVariableBinding variable = fragment.resolveBinding();
-	assertNotNull("Should not be null", variable);
-	ITypeBinding typeBinding = variable.getType();
-	assertNotNull("Should not be null", typeBinding);
-	IAnnotationBinding[][] dimAnnotations = typeBinding.getTypeAnnotationsOnDimensions();
-
-	assertEquals("Incorrect type annotations", 3, dimAnnotations.length);
-	IAnnotationBinding[] annotations = dimAnnotations[0];
-	assertTrue("Incorrect number of annotations", annotations.length == 2);
-	assertEquals("Incorrect type annotations", "@Marker(value = i0)", annotations[0].toString());
-	assertEquals("Incorrect type annotations", "@Marker2()", annotations[1].toString());
-	annotations = dimAnnotations[1];
-	assertTrue("Incorrect number of annotations", annotations.length == 0);
-	annotations = dimAnnotations[2];
-	assertTrue("Incorrect number of annotations", annotations.length == 1);
-	assertEquals("Incorrect type annotations", "@Marker(value = i1)", annotations[0].toString());
-
-}
 
 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=399792
 public void testBug470794_001() throws JavaModelException {
@@ -5245,7 +5199,7 @@
 			"}\n" +
 			"interface J {\n" +
 			"  public void foo();\n" +
-			"  public void bar();\n" +
+			"  public default void bar() {}\n" +
 			"}\n" +
 			"interface K {\n" +
 			"  public void foo();\n" +
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/TypeBindingTests308.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/TypeBindingTests308.java
index 0e046f7..20affbf 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/TypeBindingTests308.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/TypeBindingTests308.java
@@ -2569,4 +2569,87 @@
 			deleteFile("/Converter18/src/X.java");
 		}
 	}
+	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=487716
+	public void testBug487716() throws Exception {
+		try {
+			String contents =
+				"import java.lang.annotation.ElementType; \n" +
+				"import java.lang.annotation.Target; \n" +
+				"@Target({ElementType.TYPE_USE, ElementType.CONSTRUCTOR})\n" +
+				"@interface A {} \n" +
+				"class X {\n" +
+				"	@A X() {}\n" +
+				"	X _x_ = new X();\n" +
+				"}\n";
+
+			this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true/*resolve*/);
+			ASTNode node = buildAST(contents, this.workingCopy, false);
+			assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+			CompilationUnit compilationUnit = (CompilationUnit) node;
+
+			List types = compilationUnit.types();
+			TypeDeclaration typeDecl = (TypeDeclaration) types.get(1);
+
+			// On the Allocation expression type - new X()
+			FieldDeclaration field = typeDecl.getFields()[0];
+			VariableDeclarationFragment fragment = (VariableDeclarationFragment) field.fragments().get(0);
+			ITypeBinding type = fragment.getInitializer().resolveTypeBinding();
+			IAnnotationBinding[] annots = type.getTypeAnnotations();
+			assertEquals("Incorrect no of annotations", 1, annots.length);
+
+			// On constructor declaration - X()
+			MethodDeclaration method = typeDecl.getMethods()[0];
+			assertTrue("Should be a constructor", method.isConstructor());
+			IMethodBinding methodBinding = method.resolveBinding();
+			annots = methodBinding.getAnnotations();
+			assertEquals("Incorrect no of annotations", 1, annots.length);
+		} finally {
+			deleteFile("/Converter18/src/X.java");
+		}
+	}	
+	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=487716
+	public void testBug487716a() throws Exception {
+		try {
+			String contents =
+				"package p;\n" +
+				"import java.lang.annotation.ElementType; \n" +
+				"import java.lang.annotation.Target; \n" +
+				"@Target({ElementType.TYPE_USE})\n" +
+				"@interface A {} \n" +
+				"class X {\n" +
+				"	@A X() {}\n" +
+				"   class Y {\n" +
+				"		@A Y() {}\n" +
+				"		Y _y_ = new X().new Y();\n" +
+				"	}\n" +
+				"}\n";
+
+			this.workingCopy = getWorkingCopy("/Converter18/src/p/X.java", true/*resolve*/);
+			ASTNode node = buildAST(contents, this.workingCopy, false);
+			assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+			CompilationUnit compilationUnit = (CompilationUnit) node;
+
+			List types = compilationUnit.types();
+			TypeDeclaration typeDecl = (TypeDeclaration) types.get(1);
+			
+			assertEquals(1, typeDecl.getTypes().length);
+			typeDecl = typeDecl.getTypes()[0];
+			
+			// On the Qualified Allocation expression type - new X().new Y()
+			FieldDeclaration field = typeDecl.getFields()[0];
+			VariableDeclarationFragment fragment = (VariableDeclarationFragment) field.fragments().get(0);
+			ITypeBinding type = fragment.getInitializer().resolveTypeBinding();
+			IAnnotationBinding[] annots = type.getTypeAnnotations();
+			assertEquals("Incorrect no of annotations", 1, annots.length);
+
+			// On constructor declaration - Y()
+			MethodDeclaration method = typeDecl.getMethods()[0];
+			assertTrue("Should be a constructor", method.isConstructor());
+			IMethodBinding methodBinding = method.resolveBinding();
+			annots = methodBinding.getAnnotations();
+			assertEquals("Incorrect no of annotations", 0, annots.length);
+		} finally {
+			deleteFile("/Converter18/src/X.java");
+		}
+	}
 }
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java
index 7873823..fd7718e 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java
@@ -12342,4 +12342,15 @@
 		"}";
 	formatSource(source);
 }
+/**
+ * https://bugs.eclipse.org/487375 - [formatter] block comment in front of method signature effects too much indentation
+ */
+public void testBug487375() {
+	String source =
+		"public class Test {\r\n" + 
+		"	/* public */ void foo() {\r\n" + 
+		"	}\r\n" + 
+		"}";
+	formatSource(source);
+}
 }
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java
index d7ecc6e..2c7499a 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java
@@ -8038,6 +8038,7 @@
 	public void test558() {
 		Map options = DefaultCodeFormatterConstants.getJavaConventionsSettings();
 
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_ENUM_CONSTANT, null);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_FIELD, null);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_METHOD, null);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_PACKAGE, null);
@@ -8078,6 +8079,7 @@
 	 */
 	public void test559() {
 		Map options = DefaultCodeFormatterConstants.getJavaConventionsSettings();
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_ENUM_CONSTANT, null);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_FIELD, null);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_METHOD, null);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_PACKAGE, null);
@@ -8382,6 +8384,7 @@
 
 	public void test575() {
 		Map options = DefaultCodeFormatterConstants.getEclipseDefaultSettings();
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_ENUM_CONSTANT, null);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_FIELD, null);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_METHOD, null);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_PACKAGE, null);
@@ -10879,6 +10882,7 @@
  */
 public void test728() {
 	this.formatterPrefs = null;
+	this.formatterOptions.remove(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_ENUM_CONSTANT);
 	this.formatterOptions.remove(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_FIELD);
 	this.formatterOptions.remove(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_METHOD);
 	this.formatterOptions.remove(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_PACKAGE);
@@ -13302,4 +13306,561 @@
 		"}"
 	);
 }
+/**
+ * https://bugs.eclipse.org/487375 - [formatter] block comment in front of method signature effects too much indentation
+ */
+public void testBug486719() {
+	this.formatterPrefs.page_width = 80;
+	String source =
+		"public class Example {\n" + 
+		"	int foo(Object a, Object b, Object c) {\n" + 
+		"		if (a == b) return 1;if (a == c) return 2; //$IDENTITY-COMPARISON$\n" + 
+		"		boolean aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = a == b && a == c; //$IDENTITY-COMPARISON$\n" + 
+		"		return 3;\n" + 
+		"	}\n" + 
+		"}";
+	formatSource(source);
+}
+/**
+ * https://bugs.eclipse.org/432628 - [formatter] Add option "Insert new line after annotations on enum constants"
+ */
+public void testBug432628a() {
+	setComplianceLevel(CompilerOptions.VERSION_1_5);
+	this.formatterPrefs.insert_new_line_after_annotation_on_enum_constant = false;
+	String source =
+		"public enum SomeEnum {\n" + 
+		"	@XmlEnumValue(\"val1\") VAL_1(\"val1\"), @XmlEnumValue(\"val2\") VAL_2(\"val2\");\n" + 
+		"}";
+	formatSource(source);
+}
+/**
+ * https://bugs.eclipse.org/432628 - [formatter] Add option "Insert new line after annotations on enum constants"
+ */
+public void testBug432628b() {
+	setComplianceLevel(CompilerOptions.VERSION_1_5);
+	this.formatterPrefs.insert_new_line_after_annotation_on_enum_constant = true;
+	String source =
+		"public enum SomeEnum {\n" + 
+		"	@XmlEnumValue(\"val1\")\n" + 
+		"	VAL_1(\"val1\"), @XmlEnumValue(\"val2\")\n" + 
+		"	VAL_2(\"val2\");\n" + 
+		"}";
+	formatSource(source);
+}
+/**
+ * https://bugs.eclipse.org/432628 - [formatter] Add option "Insert new line after annotations on enum constants"
+ */
+public void testBug432628c() {
+	setComplianceLevel(CompilerOptions.VERSION_1_5);
+	this.formatterPrefs.insert_new_line_after_annotation_on_enum_constant = true;
+	this.formatterPrefs.alignment_for_enum_constants = Alignment.M_ONE_PER_LINE_SPLIT + Alignment.M_FORCE;
+	String source =
+		"public enum SomeEnum {\n" + 
+		"	@XmlEnumValue(\"val1\")\n" + 
+		"	VAL_1(\"val1\"),\n" + 
+		"	@XmlEnumValue(\"val2\")\n" + 
+		"	VAL_2(\"val2\");\n" + 
+		"}";
+	formatSource(source);
+}
+/**
+ * https://bugs.eclipse.org/432628 - [formatter] Add option "Insert new line after annotations on enum constants"
+ */
+public void testBug432628d() {
+	setComplianceLevel(CompilerOptions.VERSION_1_5);
+	this.formatterPrefs.insert_new_line_after_annotation_on_enum_constant = false;
+	this.formatterPrefs.alignment_for_enum_constants = Alignment.M_ONE_PER_LINE_SPLIT + Alignment.M_FORCE;
+	String source =
+		"public enum SomeEnum {\n" + 
+		"	@XmlEnumValue(\"val1\") VAL_1(\"val1\"),\n" + 
+		"	@XmlEnumValue(\"val2\") VAL_2(\"val2\");\n" + 
+		"}";
+	formatSource(source);
+}
+/**
+ * https://bugs.eclipse.org/118264 - [formatter] Enable wrapping of for loop setup
+ */
+public void testBug118264a() {
+	this.formatterPrefs.page_width = 50;
+	String source =
+		"class Example {\n" + 
+		"	int foo(int argument) {\n" + 
+		"		for (int counter = 0; counter < argument; counter++) {\n" + 
+		"			doSomething(counter);\n" + 
+		"		}\n" + 
+		"	}\n" + 
+		"}";
+	formatSource(source);
+}
+/**
+ * https://bugs.eclipse.org/118264 - [formatter] Enable wrapping of for loop setup
+ */
+public void testBug118264b() {
+	this.formatterPrefs.alignment_for_expressions_in_for_loop_header = Alignment.M_COMPACT_SPLIT;
+	this.formatterPrefs.page_width = 50;
+	String source =
+		"class Example {\n" + 
+		"	int foo(int argument) {\n" + 
+		"		for (int counter = 0; counter < argument; counter++) {\n" + 
+		"			doSomething(counter);\n" + 
+		"		}\n" + 
+		"	}\n" + 
+		"}";
+	formatSource(source,
+		"class Example {\n" + 
+		"	int foo(int argument) {\n" + 
+		"		for (int counter = 0; counter < argument;\n" + 
+		"				counter++) {\n" + 
+		"			doSomething(counter);\n" + 
+		"		}\n" + 
+		"	}\n" + 
+		"}"
+	);
+}
+/**
+ * https://bugs.eclipse.org/118264 - [formatter] Enable wrapping of for loop setup
+ */
+public void testBug118264c() {
+	this.formatterPrefs.alignment_for_expressions_in_for_loop_header = Alignment.M_ONE_PER_LINE_SPLIT + Alignment.M_FORCE;
+	String source =
+		"class Example {\n" + 
+		"	int foo(int argument) {\n" + 
+		"		for (int counter = 0; counter < argument; counter++) {\n" + 
+		"			doSomething(counter);\n" + 
+		"		}\n" + 
+		"	}\n" + 
+		"}";
+	formatSource(source,
+		"class Example {\n" + 
+		"	int foo(int argument) {\n" + 
+		"		for (\n" + 
+		"				int counter = 0;\n" + 
+		"				counter < argument;\n" + 
+		"				counter++) {\n" + 
+		"			doSomething(counter);\n" + 
+		"		}\n" + 
+		"	}\n" + 
+		"}"
+	);
+}
+/**
+ * https://bugs.eclipse.org/118264 - [formatter] Enable wrapping of for loop setup
+ */
+public void testBug118264d() {
+	this.formatterPrefs.alignment_for_expressions_in_for_loop_header = Alignment.M_ONE_PER_LINE_SPLIT + Alignment.M_FORCE;
+	String source =
+		"class Example {\n" + 
+		"	int foo(int argument) {\n" + 
+		"		for (int counter = 0; ; ) {\n" + 
+		"			doSomething(counter);\n" + 
+		"		}\n" + 
+		"	}\n" + 
+		"}";
+	formatSource(source,
+		"class Example {\n" + 
+		"	int foo(int argument) {\n" + 
+		"		for (\n" + 
+		"				int counter = 0;;) {\n" + 
+		"			doSomething(counter);\n" + 
+		"		}\n" + 
+		"	}\n" + 
+		"}"
+	);
+}
+/**
+ * https://bugs.eclipse.org/118264 - [formatter] Enable wrapping of for loop setup
+ */
+public void testBug118264e() {
+	this.formatterPrefs.alignment_for_expressions_in_for_loop_header = Alignment.M_ONE_PER_LINE_SPLIT + Alignment.M_FORCE;
+	String source =
+		"class Example {\n" + 
+		"	int foo(int argument) {\n" + 
+		"		for (;;argument--, argument--) {\n" + 
+		"			doSomething(counter);\n" + 
+		"		}\n" + 
+		"	}\n" + 
+		"}";
+	formatSource(source,
+		"class Example {\n" + 
+		"	int foo(int argument) {\n" + 
+		"		for (;;\n" + 
+		"				argument--, argument--) {\n" + 
+		"			doSomething(counter);\n" + 
+		"		}\n" + 
+		"	}\n" + 
+		"}"
+	);
+}
+/**
+ * https://bugs.eclipse.org/118264 - [formatter] Enable wrapping of for loop setup
+ */
+public void testBug118264f() {
+	this.formatterPrefs.alignment_for_expressions_in_for_loop_header = Alignment.M_ONE_PER_LINE_SPLIT + Alignment.M_FORCE;
+	String source =
+		"class Example {\n" + 
+		"	int foo(int argument) {\n" + 
+		"		for (;;) {\n" + 
+		"			doSomething(counter);\n" + 
+		"		}\n" + 
+		"	}\n" + 
+		"}";
+	formatSource(source);
+}
+/**
+ * https://bugs.eclipse.org/465910 - [formatter] add a 'wrap before operator' option for conditional expressions
+ */
+public void testBug465910() {
+	this.formatterPrefs.alignment_for_conditional_expression = Alignment.M_ONE_PER_LINE_SPLIT + Alignment.M_FORCE;
+	String source =
+		"class Example {\n" + 
+		"	Result foo(boolean argument) {\n" + 
+		"		return argument ? doOneThing() : doOtherThing();\n" + 
+		"	}\n" + 
+		"}";
+	formatSource(source,
+		"class Example {\n" + 
+		"	Result foo(boolean argument) {\n" + 
+		"		return argument\n" + 
+		"				? doOneThing()\n" + 
+		"				: doOtherThing();\n" + 
+		"	}\n" + 
+		"}"
+	);
+	this.formatterPrefs.wrap_before_conditional_operator = false;
+	formatSource(source,
+		"class Example {\n" + 
+		"	Result foo(boolean argument) {\n" + 
+		"		return argument ?\n" + 
+		"				doOneThing() :\n" + 
+		"				doOtherThing();\n" + 
+		"	}\n" + 
+		"}"
+	);
+}
+/**
+ * https://bugs.eclipse.org/325631 - [formatter] Code formatter Expressions > Assignments lacks "Wrap before operator" option
+ */
+public void testBug325631() {
+	this.formatterPrefs.alignment_for_assignment = Alignment.M_ONE_PER_LINE_SPLIT + Alignment.M_FORCE;
+	String source =
+		"class Example {\n" + 
+		"	String value = \"\";\n" + 
+		"	void foo(boolean argument) {\n" + 
+		"		if (\"test\".equals(value = artument))\n" + 
+		"			doSomething();\n" + 
+		"	}\n" + 
+		"}";
+	formatSource(source,
+		"class Example {\n" + 
+		"	String value =\n" + 
+		"			\"\";\n" + 
+		"\n" + 
+		"	void foo(boolean argument) {\n" + 
+		"		if (\"test\".equals(value =\n" + 
+		"				artument))\n" + 
+		"			doSomething();\n" + 
+		"	}\n" + 
+		"}");
+	this.formatterPrefs.wrap_before_assignment_operator = true;
+	formatSource(source,
+		"class Example {\n" + 
+		"	String value\n" + 
+		"			= \"\";\n" + 
+		"\n" + 
+		"	void foo(boolean argument) {\n" + 
+		"		if (\"test\".equals(value\n" + 
+		"				= artument))\n" + 
+		"			doSomething();\n" + 
+		"	}\n" + 
+		"}"
+	);
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540a() throws JavaModelException {
+	setComplianceLevel(CompilerOptions.VERSION_1_8);
+	String input = getCompilationUnit("Formatter", "", "test370540", "Example_in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test370540", "Example_out01.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540b() throws JavaModelException {
+	setComplianceLevel(CompilerOptions.VERSION_1_8);
+	this.formatterPrefs.parenthesis_positions_in_method_declaration = DefaultCodeFormatterConstants.SEPARATE_LINES_IF_NOT_EMPY;
+	String input = getCompilationUnit("Formatter", "", "test370540", "Example_in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test370540", "Example_out02.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540c() throws JavaModelException {
+	setComplianceLevel(CompilerOptions.VERSION_1_8);
+	this.formatterPrefs.parenthesis_positions_in_method_declaration = DefaultCodeFormatterConstants.SEPARATE_LINES_IF_WRAPPED;
+	String input = getCompilationUnit("Formatter", "", "test370540", "Example_in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test370540", "Example_out03.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540d() throws JavaModelException {
+	this.formatterPrefs.parenthesis_positions_in_method_declaration = DefaultCodeFormatterConstants.SEPARATE_LINES;
+	setComplianceLevel(CompilerOptions.VERSION_1_8);
+	String input = getCompilationUnit("Formatter", "", "test370540", "Example_in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test370540", "Example_out04.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540e() throws JavaModelException {
+	setComplianceLevel(CompilerOptions.VERSION_1_8);
+	this.formatterPrefs.parenthesis_positions_in_method_invocation = DefaultCodeFormatterConstants.SEPARATE_LINES_IF_NOT_EMPY;
+	String input = getCompilationUnit("Formatter", "", "test370540", "Example_in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test370540", "Example_out05.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540f() throws JavaModelException {
+	setComplianceLevel(CompilerOptions.VERSION_1_8);
+	this.formatterPrefs.parenthesis_positions_in_method_invocation = DefaultCodeFormatterConstants.SEPARATE_LINES_IF_WRAPPED;
+	this.formatterPrefs.parenthesis_positions_in_enum_constant_declaration = DefaultCodeFormatterConstants.SEPARATE_LINES;
+	String input = getCompilationUnit("Formatter", "", "test370540", "Example_in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test370540", "Example_out06.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540g() throws JavaModelException {
+	setComplianceLevel(CompilerOptions.VERSION_1_8);
+	this.formatterPrefs.parenthesis_positions_in_enum_constant_declaration = DefaultCodeFormatterConstants.SEPARATE_LINES_IF_NOT_EMPY;
+	this.formatterPrefs.parenthesis_positions_in_if_while_statement = DefaultCodeFormatterConstants.SEPARATE_LINES;
+	String input = getCompilationUnit("Formatter", "", "test370540", "Example_in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test370540", "Example_out07.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540h() throws JavaModelException {
+	setComplianceLevel(CompilerOptions.VERSION_1_8);
+	this.formatterPrefs.parenthesis_positions_in_if_while_statement = DefaultCodeFormatterConstants.SEPARATE_LINES_IF_WRAPPED;
+	this.formatterPrefs.parenthesis_positions_in_lambda_declaration = DefaultCodeFormatterConstants.SEPARATE_LINES_IF_NOT_EMPY;
+	String input = getCompilationUnit("Formatter", "", "test370540", "Example_in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test370540", "Example_out08.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540i() throws JavaModelException {
+	setComplianceLevel(CompilerOptions.VERSION_1_8);
+	this.formatterPrefs.parenthesis_positions_in_if_while_statement = DefaultCodeFormatterConstants.SEPARATE_LINES_IF_WRAPPED;
+	this.formatterPrefs.parenthesis_positions_in_method_invocation = DefaultCodeFormatterConstants.SEPARATE_LINES_IF_NOT_EMPY;
+	String input = getCompilationUnit("Formatter", "", "test370540", "Example_in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test370540", "Example_out09.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540j() throws JavaModelException {
+	setComplianceLevel(CompilerOptions.VERSION_1_8);
+	this.formatterPrefs.parenthesis_positions_in_try_clause = DefaultCodeFormatterConstants.SEPARATE_LINES;
+	this.formatterPrefs.parenthesis_positions_in_method_declaration = DefaultCodeFormatterConstants.PRESERVE_POSITIONS;
+	String input = getCompilationUnit("Formatter", "", "test370540", "Example_in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test370540", "Example_out10.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540k() throws JavaModelException {
+	setComplianceLevel(CompilerOptions.VERSION_1_8);
+	this.formatterPrefs.parenthesis_positions_in_catch_clause = DefaultCodeFormatterConstants.SEPARATE_LINES;
+	this.formatterPrefs.parenthesis_positions_in_if_while_statement = DefaultCodeFormatterConstants.PRESERVE_POSITIONS;
+	String input = getCompilationUnit("Formatter", "", "test370540", "Example_in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test370540", "Example_out11.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540l() throws JavaModelException {
+	setComplianceLevel(CompilerOptions.VERSION_1_8);
+	this.formatterPrefs.parenthesis_positions_in_for_statement = DefaultCodeFormatterConstants.SEPARATE_LINES_IF_WRAPPED;
+	this.formatterPrefs.parenthesis_positions_in_annotation = DefaultCodeFormatterConstants.SEPARATE_LINES_IF_NOT_EMPY;
+	String input = getCompilationUnit("Formatter", "", "test370540", "Example_in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test370540", "Example_out12.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540m() throws JavaModelException {
+	setComplianceLevel(CompilerOptions.VERSION_1_8);
+	this.formatterPrefs.parenthesis_positions_in_for_statement = DefaultCodeFormatterConstants.SEPARATE_LINES_IF_WRAPPED;
+	this.formatterPrefs.alignment_for_expressions_in_for_loop_header = Alignment.M_NEXT_PER_LINE_SPLIT + Alignment.M_FORCE;
+	String input = getCompilationUnit("Formatter", "", "test370540", "Example_in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test370540", "Example_out13.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540n() throws JavaModelException {
+	setComplianceLevel(CompilerOptions.VERSION_1_8);
+	this.formatterPrefs.parenthesis_positions_in_switch_statement = DefaultCodeFormatterConstants.SEPARATE_LINES;
+	this.formatterPrefs.parenthesis_positions_in_annotation = DefaultCodeFormatterConstants.SEPARATE_LINES;
+	String input = getCompilationUnit("Formatter", "", "test370540", "Example_in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test370540", "Example_out14.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540p() throws JavaModelException {
+	setComplianceLevel(CompilerOptions.VERSION_1_8);
+	this.formatterPrefs.parenthesis_positions_in_annotation = DefaultCodeFormatterConstants.SEPARATE_LINES;
+	this.formatterPrefs.parenthesis_positions_in_catch_clause = DefaultCodeFormatterConstants.SEPARATE_LINES;
+	this.formatterPrefs.parenthesis_positions_in_enum_constant_declaration = DefaultCodeFormatterConstants.SEPARATE_LINES;
+	this.formatterPrefs.parenthesis_positions_in_for_statement = DefaultCodeFormatterConstants.SEPARATE_LINES;
+	this.formatterPrefs.parenthesis_positions_in_if_while_statement = DefaultCodeFormatterConstants.SEPARATE_LINES;
+	this.formatterPrefs.parenthesis_positions_in_lambda_declaration = DefaultCodeFormatterConstants.SEPARATE_LINES;
+	this.formatterPrefs.parenthesis_positions_in_method_declaration = DefaultCodeFormatterConstants.SEPARATE_LINES;
+	this.formatterPrefs.parenthesis_positions_in_method_invocation = DefaultCodeFormatterConstants.SEPARATE_LINES;
+	this.formatterPrefs.parenthesis_positions_in_switch_statement = DefaultCodeFormatterConstants.SEPARATE_LINES;
+	this.formatterPrefs.parenthesis_positions_in_try_clause = DefaultCodeFormatterConstants.SEPARATE_LINES;
+	String input = getCompilationUnit("Formatter", "", "test370540", "Example_in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test370540", "Example_out15.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540q() throws JavaModelException {
+	this.formatterPrefs.parenthesis_positions_in_for_statement = DefaultCodeFormatterConstants.SEPARATE_LINES;
+	String source = 
+		"public class Test {\n" + 
+		"	void foo() {\n" + 
+		"		for (\n" + 
+		"			String s : Arrays.asList(\"aa\")\n" + 
+		"		) {\n" + 
+		"		}\n" + 
+		"	}\n" + 
+		"}";
+	formatSource(source);
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540r() throws JavaModelException {
+	this.formatterPrefs.parenthesis_positions_in_method_invocation = DefaultCodeFormatterConstants.SEPARATE_LINES;
+	String source = 
+		"public class Test extends Exception {\n" + 
+		"	Test instance = new Test(\n" + 
+		"			1\n" + 
+		"	);\n" + 
+		"\n" + 
+		"	Test(int a) {\n" + 
+		"		this(\n" + 
+		"				a, 0\n" + 
+		"		);\n" + 
+		"	}\n" + 
+		"\n" + 
+		"	Test(int a, int b) {\n" + 
+		"		super(\n" + 
+		"				a + \"=\" + b\n" + 
+		"		);\n" + 
+		"	}\n" + 
+		"\n" + 
+		"	public void printStackTrace() {\n" + 
+		"		super.printStackTrace(\n" + 
+		"		);\n" + 
+		"	}\n" + 
+		"}";
+	formatSource(source);
+}
+/**
+ * https://bugs.eclipse.org/370540 - [Formatter] New settings for parentheses positions
+ */
+public void testBug370540s() throws JavaModelException {
+	this.formatterPrefs.parenthesis_positions_in_method_invocation = DefaultCodeFormatterConstants.SEPARATE_LINES_IF_WRAPPED;
+	String source = 
+		"public class Test extends Exception {\n" + 
+		"	void foo() {\n" + 
+		"		new StringBuilder().append(\"aaaaaaaaa\" + \"bbbbbbbbbbbbbbb\" + \"cccccccccccccc\" + \"dddddddddd\")\n" + 
+		"				.append(\"aaaaaaa\" + \"bbbbbbbbbbbbb\" + \"cccccccccccccc\" + \"ddddddddd\");\n" + 
+		"	}\n" + 
+		"}";
+	formatSource(source);
+}
+/**
+ * https://bugs.eclipse.org/384959 - [formatter] Add line wrapping options for generics
+ */
+public void testBug384959a() throws JavaModelException {
+	setComplianceLevel(CompilerOptions.VERSION_1_8);
+	String input = getCompilationUnit("Formatter", "", "test384959", "A_in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test384959", "A_out1.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/384959 - [formatter] Add line wrapping options for generics
+ */
+public void testBug384959b() throws JavaModelException {
+	setComplianceLevel(CompilerOptions.VERSION_1_8);
+	this.formatterPrefs.alignment_for_parameterized_type_references = Alignment.M_ONE_PER_LINE_SPLIT + Alignment.M_FORCE;
+	String input = getCompilationUnit("Formatter", "", "test384959", "A_in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test384959", "A_out2.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/384959 - [formatter] Add line wrapping options for generics
+ */
+public void testBug384959c() throws JavaModelException {
+	setComplianceLevel(CompilerOptions.VERSION_1_8);
+	this.formatterPrefs.alignment_for_type_arguments = Alignment.M_ONE_PER_LINE_SPLIT + Alignment.M_FORCE;
+	String input = getCompilationUnit("Formatter", "", "test384959", "A_in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test384959", "A_out3.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/384959 - [formatter] Add line wrapping options for generics
+ */
+public void testBug384959d() throws JavaModelException {
+	setComplianceLevel(CompilerOptions.VERSION_1_8);
+	this.formatterPrefs.alignment_for_type_parameters = Alignment.M_ONE_PER_LINE_SPLIT + Alignment.M_FORCE;
+	String input = getCompilationUnit("Formatter", "", "test384959", "A_in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test384959", "A_out4.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/384959 - [formatter] Add line wrapping options for generics
+ */
+public void testBug384959e() throws JavaModelException {
+	setComplianceLevel(CompilerOptions.VERSION_1_8);
+	int policy = Alignment.M_NEXT_SHIFTED_SPLIT + Alignment.M_FORCE;
+	this.formatterPrefs.alignment_for_parameterized_type_references = policy;
+	this.formatterPrefs.alignment_for_type_arguments = policy;
+	this.formatterPrefs.alignment_for_type_parameters = policy;
+	String input = getCompilationUnit("Formatter", "", "test384959", "A_in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test384959", "A_out5.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/384959 - [formatter] Add line wrapping options for generics
+ */
+public void testBug384959f() throws JavaModelException {
+	setComplianceLevel(CompilerOptions.VERSION_1_8);
+	this.formatterPrefs.tab_char = DefaultCodeFormatterOptions.SPACE;
+	int policy = Alignment.M_NEXT_PER_LINE_SPLIT + Alignment.M_INDENT_ON_COLUMN + Alignment.M_FORCE;
+	this.formatterPrefs.alignment_for_parameterized_type_references = policy;
+	this.formatterPrefs.alignment_for_type_arguments = policy;
+	this.formatterPrefs.alignment_for_type_parameters = policy;
+	String input = getCompilationUnit("Formatter", "", "test384959", "A_in.java").getSource();
+	formatSource(input, getCompilationUnit("Formatter", "", "test384959", "A_out6.java").getSource());
+}
+/**
+ * https://bugs.eclipse.org/384959 - [formatter] Add line wrapping options for generics
+ */
+public void testBug384959g() throws JavaModelException {
+	setComplianceLevel(CompilerOptions.VERSION_1_8);
+	this.formatterPrefs.alignment_for_type_parameters = Alignment.M_COMPACT_SPLIT;
+	String source = 
+		"public interface IteratedDescribeLinkList<\n" + 
+		"		T extends IteratedDescribeLinkList<T, E, A, B, C, D, F, G, H, I, X, Y, Z, J, K>, E extends IteratedDescribeLink,\n" + 
+		"		A extends Iterated, B extends Iterated, C extends IteratedList<C, A, F, H, Y, J>,\n" + 
+		"		D extends IteratedList<D, B, G, I, Z, K>, F extends MasteredList<F, H, C, A, J, Y>,\n" + 
+		"		G extends MasteredList<G, I, D, B, K, Z>, H extends Mastered, I extends Mastered, X extends T, Y extends C,\n" + 
+		"		Z extends D, J extends F, K extends G> extends ObjectToObjectLinkList<T, E, A, B, C, D, X, Y, Z> {\n" + 
+		"}";
+	formatSource(source);
+}
 }
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests.java
index fcd1e49..2be5e05 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -4970,16 +4970,13 @@
     int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
     this.wc.codeComplete(cursorLocation, requestor, this.wcOwner);
 
-    int start = str.lastIndexOf(completeBehind);
-    int end = start + completeBehind.length();
-
     assertResults(
             "expectedTypesSignatures=null\n"+
             "expectedTypesKeys=null",
             requestor.getContext());
 
 	assertResults(
-            "testCompletionEmptyToken2[PACKAGE_REF]{testCompletionEmptyToken2, testCompletionEmptyToken2, null, null, null, ["+start+", "+end+"], " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_CASE + R_EXACT_NAME + R_NON_RESTRICTED) + "}",
+            "",
             requestor.getResults());
 }
 
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests18.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests18.java
index ccdb387..1131cb7 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests18.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests18.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2014, 2015 IBM Corporation and others.
+ * Copyright (c) 2014, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -22,7 +22,7 @@
 import org.eclipse.jdt.core.eval.IEvaluationContext;
 import org.eclipse.jdt.internal.codeassist.RelevanceConstants;
 
-@SuppressWarnings({"rawtypes", "unchecked"})
+//@SuppressWarnings({"rawtypes", "unchecked"})
 public class CompletionTests18 extends AbstractJavaModelCompletionTests {
 
 static {
@@ -1543,7 +1543,7 @@
 	int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length() + 1;
 	IJavaProject javaProject = getJavaProject("Completion");
 
-	Map options = javaProject.getOptions(true);
+	Map<String, String> options = javaProject.getOptions(true);
 	options.put(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED);
 	options.put(JavaCore.COMPILER_INHERIT_NULL_ANNOTATIONS, JavaCore.ENABLED);
 	javaProject.setOptions(options);
@@ -2662,4 +2662,83 @@
 													RelevanceConstants.R_INTERESTING + RelevanceConstants.R_NON_RESTRICTED +
 													RelevanceConstants.R_CASE) + "}", requestor.getResults());
 }
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=473008
+public void test473008a() throws JavaModelException {
+	this.workingCopies = new ICompilationUnit[1];
+	this.workingCopies[0] = getWorkingCopy(
+			"/Completion/src/Foo.java",
+			"interface FooFunctional {\n" +
+			"   void function();\n" +
+			"}\n" +
+			"public class Foo {\n" +
+			"    private FooFunctional lambda = this::bar;\n" +
+			"    public void bar() {\n" +
+			"      new StringBuffer" +
+			"    }\n" +
+			"}\n");
+
+	CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true, true, true, false);
+	requestor.allowAllRequiredProposals();
+	String str = this.workingCopies[0].getSource();
+	String completeBehind = "new StringBuffer";
+	int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
+	this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
+	int relevance = R_DEFAULT + R_RESOLVED + R_INTERESTING + R_NON_RESTRICTED + R_CASE;
+	assertResults(
+			"StringBufferInputStream[TYPE_REF]{java.io.StringBufferInputStream, java.io, Ljava.io.StringBufferInputStream;, null, null, null, null, [147, 159], " + relevance + "}\n" + 
+			"StringBuffer[TYPE_REF]{StringBuffer, java.lang, Ljava.lang.StringBuffer;, null, null, null, null, [147, 159], " + (relevance + R_UNQUALIFIED + R_EXACT_NAME) + "}"
+			, requestor.getResults());
+}
+public void test473008b() throws JavaModelException {
+	this.workingCopies = new ICompilationUnit[1];
+	this.workingCopies[0] = getWorkingCopy(
+			"/Completion/src/Foo.java",
+			"interface FooFunctional {\n" +
+			"   void function();\n" +
+			"}\n" +
+			"public class Foo {\n" +
+			"    public void bar() {\n" +
+			"      private FooFunctional lambda = this::bar;\n" +
+			"      new StringBuffer" +
+			"    }\n" +
+			"}\n");
+
+	CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true, true, true, false);
+	requestor.allowAllRequiredProposals();
+	String str = this.workingCopies[0].getSource();
+	String completeBehind = "new StringBuffer";
+	int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
+	this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
+	int relevance = R_DEFAULT + R_RESOLVED + R_INTERESTING + R_NON_RESTRICTED + R_CASE;
+	assertResults(
+			"StringBufferInputStream[TYPE_REF]{java.io.StringBufferInputStream, java.io, Ljava.io.StringBufferInputStream;, null, null, null, null, [149, 161], " + relevance + "}\n" + 
+			"StringBuffer[TYPE_REF]{StringBuffer, java.lang, Ljava.lang.StringBuffer;, null, null, null, null, [149, 161], " + (relevance + R_UNQUALIFIED + R_EXACT_NAME) + "}"
+			, requestor.getResults());
+}
+public void test473008c() throws JavaModelException {
+	this.workingCopies = new ICompilationUnit[1];
+	this.workingCopies[0] = getWorkingCopy(
+			"/Completion/src/Foo.java",
+			"interface FooFunctional {\n" +
+			"   void function();\n" +
+			"}\n" +
+			"public class Foo {\n" +
+			"    public void bar() {\n" +
+			"      private FooFunctional lambda = () -> bar();\n" +
+			"      new StringBuffer" +
+			"    }\n" +
+			"}\n");
+
+	CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true, true, true, false);
+	requestor.allowAllRequiredProposals();
+	String str = this.workingCopies[0].getSource();
+	String completeBehind = "new StringBuffer";
+	int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
+	this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
+	int relevance = R_DEFAULT + R_RESOLVED + R_INTERESTING + R_NON_RESTRICTED + R_CASE;
+	assertResults(
+			"StringBufferInputStream[TYPE_REF]{java.io.StringBufferInputStream, java.io, Ljava.io.StringBufferInputStream;, null, null, null, null, [151, 163], " + relevance + "}\n" + 
+			"StringBuffer[TYPE_REF]{StringBuffer, java.lang, Ljava.lang.StringBuffer;, null, null, null, null, [151, 163], " + (relevance + R_UNQUALIFIED + R_EXACT_NAME) + "}"
+			, requestor.getResults());
+}
 }
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests2.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests2.java
index 52a03b0..827681c 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests2.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests2.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -6445,4 +6445,48 @@
 			(RelevanceConstants.R_DEFAULT + RelevanceConstants.R_RESOLVED + RelevanceConstants.R_INTERESTING + RelevanceConstants.R_NON_RESTRICTED
 			+ RelevanceConstants.R_CASE + RelevanceConstants.R_UNQUALIFIED) + "}", requestor.getResults());
 }
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=479656
+public void test479656() throws Exception {
+	try {
+		IFile f = getFile("/Completion/bug479656.jar");
+		IJavaProject p = this.createJavaProject(
+			"P",
+			new String[]{"src"},
+			new String[]{"JCL_LIB"},
+			 "bin", "1.5");
+		this.createFile("/P/bug479656.jar", f.getContents());
+		this.addLibraryEntry(p, "/P/bug479656.jar", true);
+		this.createFolder("/P/src/com/google/gwt/event/shared");
+		this.createFile(
+			"/P/src/com/google/gwt/event/shared/GwtEvent.java",
+			"package com.google.gwt.event.shared;\n" +
+			"public abstract class GwtEvent<H>  {\n" +
+			"	public static class Type<H> {}\n" +
+			"}\n");
+		this.createFolder("/P/src/test");
+		this.createFile(
+			"/P/src/test/Test.java",
+			"package test;\n" +
+			"public class Test {\n" +
+			"	String value = \"\";\n" +
+			"	com.gtouch5.shared.data.store.event.StoreEvent<String> event = null;\n" +
+			"	public Test() {\n" +
+			"		value.toS\n" +
+			"	}\n" +
+			"}\n");
+		refresh(p);
+		waitUntilIndexesReady();
+		ICompilationUnit cu = getCompilationUnit("P", "src", "test", "Test.java");
+		String source = cu.getSource();
+		String completeBehind = "value.toS";
+		int cursorLocation = source.lastIndexOf(completeBehind) + completeBehind.length();
+		CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true, false, false, true, true);
+		cu.codeComplete(cursorLocation, requestor);
+		assertResults(
+				"toString[METHOD_REF]{toString(), Ljava.lang.Object;, ()Ljava.lang.String;, toString, null, 35}",
+				requestor.getResults());
+	} finally {
+		deleteProject("P");
+	}
+}
 }
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations18Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations18Test.java
index 19c8363..defb870 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations18Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations18Test.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2014, 2015 GK Software AG, and others.
+ * Copyright (c) 2014, 2016 GK Software AG, and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -56,6 +56,7 @@
 import org.eclipse.jdt.core.tests.util.Util;
 import org.eclipse.jdt.core.util.ExternalAnnotationUtil;
 import org.eclipse.jdt.core.util.ExternalAnnotationUtil.MergeStrategy;
+import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
 import org.eclipse.jdt.internal.core.ClasspathAttribute;
 import org.osgi.framework.Bundle;
 
@@ -249,6 +250,22 @@
 		addClasspathEntry(this.project, entry);
 	}
 
+	protected void addProjectDependencyWithExternalAnnotations(
+			IJavaProject javaProject,
+			String referencedProjectName,
+			String externalAnnotationPath,
+			Map options) throws CoreException, IOException
+	{
+		IClasspathAttribute[] extraAttributes = new IClasspathAttribute[] { new ClasspathAttribute(IClasspathAttribute.EXTERNAL_ANNOTATION_PATH, externalAnnotationPath) };
+		IClasspathEntry entry = JavaCore.newProjectEntry(
+				new Path(referencedProjectName),
+				null/*access rules*/,
+				false/*combine access rules*/,
+				extraAttributes,
+				false/*exported*/);
+		addClasspathEntry(this.project, entry);
+	}
+
 	protected void createFileInProject(String projectRelativeFolder, String fileName, String content) throws CoreException {
 		String folderPath = this.project.getProject().getName()+'/'+projectRelativeFolder;
 		createFolder(folderPath);
@@ -292,6 +309,43 @@
 		assertEquals("Number of problems", messages.length, nMatch);
 	}
 
+	protected void assertProblems(IProblem[] problems, String[] messages, int[] lines, int[] severities) throws CoreException {
+		int nMatch = 0;
+		for (int i = 0; i < problems.length; i++) {
+			for (int j = 0; j < messages.length; j++) {
+				if (messages[j] == null) continue;
+				if (problems[i].toString().equals(messages[j])
+						&& problems[i].getSourceLineNumber() == lines[j]) {
+					switch(severities[j] & ProblemSeverities.CoreSeverityMASK ) {
+					case ProblemSeverities.Error:
+						if (!problems[i].isError()) continue;
+						break;
+					case ProblemSeverities.Warning:
+						if (!problems[i].isWarning()) continue;
+						break;
+					case ProblemSeverities.Info:
+						if (!problems[i].isInfo()) continue;
+						break;
+					default:
+						throw new IllegalArgumentException("Bad severity expected: "+severities[j]);
+					}
+					messages[j] = null;
+					problems[i] = null;
+					nMatch++;
+					break;
+				}
+			}
+		}
+		for (int i = 0; i < problems.length; i++) {
+			if (problems[i] != null)
+				fail("Unexpected problem "+problems[i]+" at "+problems[i].getSourceLineNumber());
+		}
+		for (int i = 0; i < messages.length; i++) {
+			if (messages[i] != null)
+				System.err.println("Unmatched problem "+messages[i]);
+		}
+		assertEquals("Number of problems", messages.length, nMatch);
+	}
 	protected boolean hasJRE18() {
 		return ((AbstractCompilerTest.getPossibleComplianceLevels() & AbstractCompilerTest.F_1_8) != 0);
 	}
@@ -466,10 +520,11 @@
 		CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
 		IProblem[] problems = reconciled.getProblems();
 		assertProblems(problems, new String[] {
+				"Pb(980) Unsafe interpretation of method return type as '@NonNull' based on the receiver type 'Iterator<@NonNull capture#of ?>'. Type 'Iterator<E>' doesn't seem to be designed with null type annotations in mind",
 				"Pb(953) Null type mismatch (type annotations): required '@NonNull Object' but this expression has type '@Nullable capture#of ?'",
 				"Pb(953) Null type mismatch (type annotations): required '@NonNull CharSequence' but this expression has type '@Nullable capture#of ? extends CharSequence'",
 				"Pb(953) Null type mismatch (type annotations): required '@NonNull Object' but this expression has type '@Nullable capture#of ? super CharSequence'"
-			}, new int[] { 13, 16, 19 });
+			}, new int[] { 10, 13, 16, 19 });
 	}
 	
 	public void testLibsWithArrays() throws Exception {
@@ -1419,4 +1474,215 @@
 			Platform.removeLogListener(listener);
 		}
 	}
+
+	/** Lib exists as workspace project. Perform full build. */
+	public void testProjectDependencyFullBuild() throws Exception {
+		try {
+			setupJavaProject("Lib");
+			this.project.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
+	
+			setupJavaProject("Test1");
+			addProjectDependencyWithExternalAnnotations(this.project, "/Lib", "annots", null);
+			this.project.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = this.project.getProject().findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE);
+			assertNoMarkers(markers);
+		} finally {
+			deleteProject("Lib");
+		}
+	}
+
+	/** Lib exists as workspace project. Reconcile an individual CU. */
+	public void testProjectDependencyReconcile1() throws Exception {
+		try {
+			setupJavaProject("Lib");
+			this.project.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			this.root = null; // prepare to get the root from project Test1
+	
+			setupJavaProject("Test1");
+			addProjectDependencyWithExternalAnnotations(this.project, "/Lib", "annots", null);
+			IPackageFragment fragment = this.root.getPackageFragment("test1");
+			ICompilationUnit unit = fragment.getCompilationUnit("Test1.java").getWorkingCopy(new NullProgressMonitor());
+			CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+			IProblem[] problems = reconciled.getProblems();
+			assertNoProblems(problems);
+		} finally {
+			deleteProject("Lib");
+		}
+	}
+
+	/** Lib exists as workspace project. Type-Annotations in zip file. Reconcile an individual CU. */
+	public void testProjectDependencyReconcile2() throws Exception {
+		try {
+			setupJavaProject("Lib");
+			this.project.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			this.root = null; // prepare to get the root from project Test1
+	
+			setupJavaProject("Test3b");
+			Util.createSourceZip(
+				new String[] {
+					"libs/MyFunction.eea", 
+					"class libs/MyFunction\n" + 
+					" <T:R:>\n" + 
+					"\n" + 
+					"compose\n" + 
+					" <V:Ljava/lang/Object;>(Llibs/MyFunction<-TV;+TT;>;)Llibs/MyFunction<TV;TR;>;\n" + 
+					" <V:Ljava/lang/Object;>(Llibs/MyFunction<-TV;+T0T;>;)Llibs/MyFunction<TV;TR;>;\n" + 
+					"\n",
+					"libs/Arrays.eea", 
+					"class libs/Arrays\n" + 
+					"\n" +
+					"array\n" +
+					" [Ljava/lang/String;\n" +
+					" [1L0java/lang/String;\n" +
+					"\n" + 
+					"getArray\n" +
+					" ()[[Ljava/lang/String;\n" +
+					" ()[0[1L0java/lang/String;\n"
+				},
+				this.project.getProject().getLocation().toString()+"/annots.zip");
+			this.project.getProject().refreshLocal(1, new NullProgressMonitor());
+
+			addProjectDependencyWithExternalAnnotations(this.project, "/Lib", "annots.zip", null);
+			IPackageFragment fragment = this.root.getPackageFragment("test1");
+			ICompilationUnit unit = fragment.getCompilationUnit("Reconcile2.java").getWorkingCopy(new NullProgressMonitor());
+			CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+			IProblem[] problems = reconciled.getProblems();
+			assertNoProblems(problems);
+		} finally {
+			deleteProject("Lib");
+		}
+	}
+
+	/** Lib exists as workspace project. Invocations conflict with type parameter constraints. Reconcile an individual CU. */
+	public void testProjectDependencyReconcile3() throws Exception {
+		try {
+			setupJavaProject("Lib");
+			this.project.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			this.root = null; // prepare to get the root from project Test1
+	
+			setupJavaProject("Test3b");
+			Util.createSourceZip(
+				new String[] {
+					"libs/MyFunction.eea", 
+					"class libs/MyFunction\n" + 
+					" <T:R:>\n" + 
+					" <T:1R:>\n" + 
+					"\n" + 
+					"compose\n" + 
+					" <V:Ljava/lang/Object;>(Llibs/MyFunction<-TV;+TT;>;)Llibs/MyFunction<TV;TR;>;\n" + 
+					" <1V:Ljava/lang/Object;>(Llibs/MyFunction<-TV;+TT;>;)Llibs/MyFunction<TV;TR;>;\n" + 
+					"\n",
+				},
+				this.project.getProject().getLocation().toString()+"/annots.zip");
+			this.project.getProject().refreshLocal(1, new NullProgressMonitor());
+
+			addProjectDependencyWithExternalAnnotations(this.project, "/Lib", "annots.zip", null);
+			IPackageFragment fragment = this.root.getPackageFragment("test1");
+			ICompilationUnit unit = fragment.getCompilationUnit("Reconcile3.java").getWorkingCopy(new NullProgressMonitor());
+			CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+			assertProblems(reconciled.getProblems(), new String[] {
+					"Pb(964) Null constraint mismatch: The type '@Nullable B' is not a valid substitute for the type parameter '@NonNull R'",
+					"Pb(964) Null constraint mismatch: The type '@Nullable String' is not a valid substitute for the type parameter '@NonNull V'",
+			}, new int[] { 12, 17 });
+		} finally {
+			deleteProject("Lib");
+		}
+	}
+	
+	public void testFreeTypeVariableReturn() throws Exception {
+		myCreateJavaProject("TestLibs");
+		addLibraryWithExternalAnnotations(this.project, "lib1.jar", "annots", new String[] {
+				"/UnannotatedLib/libs/Lib1.java",
+				"package libs;\n" + 
+				"\n" + 
+				"public interface Lib1<T> {\n" + 
+				"	T get();\n" + 
+				"}\n"
+			}, null);
+		IPackageFragment fragment = this.project.getPackageFragmentRoots()[0].createPackageFragment("tests", true, null);
+		ICompilationUnit unit = fragment.createCompilationUnit("Test1.java", 
+				"package tests;\n" + 
+				"import org.eclipse.jdt.annotation.*;\n" + 
+				"\n" + 
+				"import libs.Lib1;\n" + 
+				"\n" + 
+				"public class Test1 {\n" + 
+				"	@NonNull String test0(Lib1<@Nullable String> lib) {\n" + 
+				"		return lib.get();\n" + 
+				"	}\n" + 
+				"	@NonNull String test1(Lib1<@NonNull String> lib) {\n" + 
+				"		return lib.get();\n" + 
+				"	}\n" + 
+				"}\n",
+				true, new NullProgressMonitor()).getWorkingCopy(new NullProgressMonitor());
+		CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		assertProblems(reconciled.getProblems(), new String[] {
+				"Pb(953) Null type mismatch (type annotations): required '@NonNull String' but this expression has type '@Nullable String'",
+				"Pb(980) Unsafe interpretation of method return type as '@NonNull' based on the receiver type 'Lib1<@NonNull String>'. Type 'Lib1<T>' doesn't seem to be designed with null type annotations in mind",
+		}, new int[] { 8, 11 });
+		// just mark that Lib1 now has null annotations:
+		createFileInProject("annots/libs", "Lib1.eea",
+				"class libs/Lib1\n" +
+				" <T:Ljava/lang/Object;>\n" + 
+				" <T:Ljava/lang/Object;>\n" + 
+				"\n");
+		reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		assertProblems(reconciled.getProblems(), new String[] {
+				"Pb(953) Null type mismatch (type annotations): required '@NonNull String' but this expression has type '@Nullable String'",
+		}, new int[] { 8 });
+	}
+	
+	public void testFreeTypeVariableReturnSeverities() throws Exception {
+		myCreateJavaProject("TestLibs");
+		addLibraryWithExternalAnnotations(this.project, "lib1.jar", "annots", new String[] {
+				"/UnannotatedLib/libs/Lib1.java",
+				"package libs;\n" + 
+				"\n" + 
+				"public interface Lib1<T> {\n" + 
+				"	T get();\n" + 
+				"}\n"
+			}, null);
+		this.currentProject = this.project;
+		addLibrary("lib2.jar", null, new String[] {
+				"/UnanntatedLib2/libs/Lib2.java",
+				"package libs;\n" + 
+				"\n" + 
+				"public interface Lib2<T> {\n" + 
+				"	T get();\n" + 
+				"}\n"				
+		}, "1.8");
+		IPackageFragment fragment = this.project.getPackageFragmentRoots()[0].createPackageFragment("tests", true, null);
+		fragment.createCompilationUnit("Lib3.java", 
+				"package tests;\n" +
+				"public interface Lib3<T> {\n" +
+				"	T get();\n" +
+				"}\n",
+				true, new NullProgressMonitor());
+		this.project.getProject().build(IncrementalProjectBuilder.FULL_BUILD, new NullProgressMonitor());
+		ICompilationUnit unit = fragment.createCompilationUnit("Test1.java", 
+				"package tests;\n" + 
+				"import org.eclipse.jdt.annotation.*;\n" + 
+				"\n" + 
+				"import libs.Lib1;\n" + 
+				"import libs.Lib2;\n" + 
+				"import tests.Lib3;\n" + 
+				"\n" + 
+				"public class Test1 {\n" + 
+				"	@NonNull String test1(Lib1<@NonNull String> lib) {\n" + 
+				"		return lib.get();\n" + // legacy, prepared for .eea but still not annotated (=> Warning)
+				"	}\n" + 
+				"	@NonNull String test2(Lib2<@NonNull String> lib) {\n" + 
+				"		return lib.get();\n" + // legacy, not prepared for .eea (=> Info)
+				"	}\n" + 
+				"	@NonNull String test3(Lib3<@NonNull String> lib) {\n" + 
+				"		return lib.get();\n" + // not legacy, is from the same project
+				"	}\n" + 
+				"}\n",
+				true, new NullProgressMonitor()).getWorkingCopy(new NullProgressMonitor());
+		CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+		assertProblems(reconciled.getProblems(), new String[] {
+				"Pb(980) Unsafe interpretation of method return type as '@NonNull' based on the receiver type 'Lib1<@NonNull String>'. Type 'Lib1<T>' doesn't seem to be designed with null type annotations in mind",
+				"Pb(980) Unsafe interpretation of method return type as '@NonNull' based on the receiver type 'Lib2<@NonNull String>'. Type 'Lib2<T>' doesn't seem to be designed with null type annotations in mind",
+		}, new int[] { 10, 13 }, new int[] { ProblemSeverities.Warning, ProblemSeverities.Info } );
+	}
 }
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugs8Tests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugs8Tests.java
index 71ac9d7..af6ab69 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugs8Tests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugs8Tests.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -10,8 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.core.tests.model;
 
-import java.util.ArrayList;
-import java.util.List;
+import java.io.IOException;
 
 import junit.framework.Test;
 
@@ -35,6 +34,7 @@
 import org.eclipse.jdt.core.search.SearchPattern;
 import org.eclipse.jdt.core.search.TypeReferenceMatch;
 import org.eclipse.jdt.internal.core.JavaModelManager;
+import org.eclipse.jdt.internal.core.LambdaMethod;
 import org.eclipse.jdt.internal.core.search.indexing.IndexManager;
 import org.eclipse.jdt.internal.core.search.matching.AndPattern;
 import org.eclipse.jdt.internal.core.search.matching.MethodPattern;
@@ -42,7 +42,6 @@
 /**
  * Non-regression tests for bugs fixed in Java Search engine.
  */
-@SuppressWarnings({"rawtypes", "unchecked"})
 public class JavaSearchBugs8Tests extends AbstractJavaSearchTests {
 
 	static {
@@ -58,10 +57,8 @@
 	return buildModelTestSuite(JavaSearchBugs8Tests.class, BYTECODE_DECLARATION_ORDER);
 }
 class TestCollector extends JavaSearchResultCollector {
-	public List matches = new ArrayList();
 	public void acceptSearchMatch(SearchMatch searchMatch) throws CoreException {
 		super.acceptSearchMatch(searchMatch);
-		this.matches.add(searchMatch);
 	}
 }
 class ReferenceCollector extends JavaSearchResultCollector {
@@ -4707,6 +4704,38 @@
 		deleteProject("P");
 	}
 }
+// not solely a search issue but easily reproducible using search
+public void test473343_0001() throws CoreException, IOException {
+	try {
+		IJavaProject project = createJavaProject("P", new String[] {"a-b"}, new String[] {"JCL18_LIB"}, "bin", "1.8", true);
+		String source = "interface Consumer<T> {\n" +
+				"	void accept(T t);\n" +
+				"}\n" +
+				"\n" +
+				"public class X {\n" +
+				"	Consumer<? super Y> action = (i_) -> X.foo(i_);\n" +
+				"	private static void foo(Y tb) {\n" +
+				"	}\n" +
+				"}\n";
+		createFile("/P/a-b/X.java", source);
+		createFile("/P/a-b/Y.java", "public class Y{}");
+		waitForAutoBuild();
+
+		ICompilationUnit unit = getCompilationUnit("/P/a-b/X.java");
+		String foo = "foo";
+		IJavaElement[] elements = unit.codeSelect(source.indexOf(foo), foo.length());
+		SearchPattern pattern = SearchPattern.createPattern(elements[0], REFERENCES, ERASURE_RULE);
+		search(pattern, SearchEngine.createJavaSearchScope(new IJavaElement[] { project }, IJavaSearchScope.SOURCES), this.resultCollector);
+		LambdaMethod method = (LambdaMethod) this.resultCollector.match.getElement();
+  		try {
+			SearchPattern.createPattern(method, REFERENCES, ERASURE_RULE);
+		} catch (IllegalArgumentException e) {
+			assertFalse("Test Failed", true);
+		}
+	} finally {
+		deleteProject("P");
+	}
+}
 
 // Add new tests in JavaSearchBugs8Tests
 }
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests2.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests2.java
index ccc0168..4c8dfd0 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests2.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests2.java
Binary files differ
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests18.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests18.java
index 14efe24..631d1b9 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests18.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests18.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2014 IBM Corporation and others.
+ * Copyright (c) 2014, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -14,6 +14,7 @@
 import junit.framework.Test;
 
 import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.core.BindingKey;
 import org.eclipse.jdt.core.ICodeAssist;
 import org.eclipse.jdt.core.ICompilationUnit;
 import org.eclipse.jdt.core.IJavaElement;
@@ -21,6 +22,7 @@
 import org.eclipse.jdt.core.IMethod;
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.Signature;
 import org.eclipse.jdt.core.WorkingCopyOwner;
 import org.eclipse.jdt.internal.core.LambdaExpression;
 import org.eclipse.jdt.internal.core.LambdaMethod;
@@ -2187,7 +2189,7 @@
 	IJavaElement[] elements = this.wc.codeSelect(start, length);
 	assertElementsEqual(
 		"Unexpected elements",
-		"comparing(java.util.function.Function<? super T,? extends U>) {key=Ljava/util/Comparator<>;.comparing<T:Ljava/lang/Object;U::Ljava/lang/Comparable<-TU;>;>(Ljava/util/function/Function<-TT;+TU;>;)Ljava/util/Comparator<TT;>;%<Ljava/lang/Object;^{259#0};>} [in Comparator [in Comparator.class [in java.util [in "+ getExternalPath() + "jclFull1.8.jar]]]]",
+		"comparing(java.util.function.Function<? super T,? extends U>) {key=Ljava/util/Comparator<>;.comparing<T:Ljava/lang/Object;U::Ljava/lang/Comparable<-TU;>;>(Ljava/util/function/Function<-TT;+TU;>;)Ljava/util/Comparator<TT;>;%<LX~Person;Ljava/lang/String;>} [in Comparator [in Comparator.class [in java.util [in "+ getExternalPath() + "jclFull1.8.jar]]]]",
 		elements, true
 	);
 }
@@ -2813,4 +2815,88 @@
 		"fooY() [in Y [in [Working copy] X.java [in <default> [in src [in Resolve]]]]]",
 		elements);
 }
+// nested poly invocation:
+public void testBug487791() throws JavaModelException {	
+	this.wc = getWorkingCopy(
+			"Resolve/src/Example.java",
+			"import java.util.Comparator;\n" + 
+			"import java.util.stream.Collectors;\n" + 
+			"\n" + 
+			"interface Something {\n" + 
+			"      public int getSize();\n" + 
+			"      public Instant getTime();\n" + 
+			"}\n" +
+			"interface Instant extends Comparable<Instant> {\n" +
+			"}\n" + 
+			"public class Example {\n" + 
+			"   public void test2() {\n" + 
+			"      java.util.stream.Collector<Something,?,java.util.Map<Integer,Something>> c = \n" + 
+			"      Collectors.collectingAndThen(\n" + 
+			"            Collectors.<Something>toList(),\n" + 
+			"            list -> list.stream().collect(Collectors.groupingBy(Something::getSize,\n" + 
+			"                     // Returns Collector<Something,?,Object> - INCORRECT!\n" + 
+			"                     Collectors.collectingAndThen(\n" + // <-- select here
+			"                        Collectors.<Something>toList(),\n" + 
+			"                        list2 -> list2.stream().sorted(Comparator.comparing(Something::getTime)).limit(1).findAny().orElse(null)\n" + 
+			"                     )\n" + 
+			"                  )));\n" + 
+			"   }\n" + 
+			"}\n");
+	this.wc.becomeWorkingCopy(null);
+
+	String str = this.wc.getSource();
+	String selection = "collectingAndThen";
+	int start = str.lastIndexOf(selection);
+	int length = selection.length();
+
+	IJavaElement[] elements = this.wc.codeSelect(start, length);
+	assertElementsEqual(
+		"Unexpected elements",
+		"collectingAndThen(java.util.stream.Collector<T,A,R>, java.util.function.Function<R,RR>) [in Collectors [in Collectors.class [in java.util.stream [in "+ getExternalPath() + "jclFull1.8.jar]]]]",
+		elements
+	);
+	String signature = new BindingKey(((IMethod) elements[0]).getKey()).toSignature();
+	String[] typeArguments = Signature.getTypeArguments(signature);
+	assertEquals("number of type arguments", 3, typeArguments.length);
+	assertEquals("4th type argument", "LSomething;", typeArguments[2]);
+	String returnType = Signature.getReturnType(signature);
+	assertEquals("return type", "Ljava.util.stream.Collector<LSomething;!*LSomething;>;", returnType);
+}
+// ReferenceExpression:
+public void testBug487791b() throws JavaModelException {	
+	this.wc = getWorkingCopy(
+			"Resolve/src/Example.java",
+			"import java.util.function.Function;\n" + 
+			"\n" + 
+			"public class Example {\n" + 
+			"   static <T> T id(T t) { return t; }\n" + 
+			"   static <T,X> T f1 (X x) { return null; }\n" + 
+			"   \n" + 
+			"   String test() {\n" + 
+			"	   return f3(y -> y.f2(Example::f1, id(y)));\n" +  // <- select f1 here
+			"   }\n" + 
+			"   <U,V> V f2(Function<U, V> f, U u) {return f.apply(null);}\n" + 
+			"   <R> R f3(Function<Example,R> f) { return null; }\n" + 
+			"}\n");
+	this.wc.becomeWorkingCopy(null);
+
+	String str = this.wc.getSource();
+	String selection = "f1";
+	int start = str.lastIndexOf(selection);
+	int length = selection.length();
+
+	IJavaElement[] elements = this.wc.codeSelect(start, length);
+	assertElementsEqual(
+		"Unexpected elements",
+		"f1(X) [in Example [in [Working copy] Example.java [in <default> [in src [in Resolve]]]]]",
+		elements
+	);
+	BindingKey bindingKey = new BindingKey(((IMethod) elements[0]).getKey());
+	String signature = bindingKey.toSignature();
+	assertEquals("signature", "<T:Ljava.lang.Object;X:Ljava.lang.Object;>(LExample;)Ljava.lang.String;", signature);
+	String[] typeArguments = bindingKey.getTypeArguments();
+	assertEquals("number of type arguments", 2, typeArguments.length);
+	assertEquals("1st type argument", "Ljava.lang.String;", typeArguments[0]);
+	assertEquals("2nd type argument", "LExample;", typeArguments[1]);
+}
 }
diff --git a/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/.classpath b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/.classpath
new file mode 100644
index 0000000..f8a6de7
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/.classpath
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="var" path="JCL18_LIB"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/.project b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/.project
new file mode 100644
index 0000000..b68234a
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>Lib</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/src/libs/Arrays.java b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/src/libs/Arrays.java
new file mode 100644
index 0000000..29b7e15
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/src/libs/Arrays.java
@@ -0,0 +1,6 @@
+package libs;
+
+public class Arrays {
+    public String[][] getArray() { return null; }
+    public static final String[] array = new String[1] { null }
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/src/libs/MyFunction.java b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/src/libs/MyFunction.java
new file mode 100644
index 0000000..6f7bff6
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/src/libs/MyFunction.java
@@ -0,0 +1,10 @@
+package libs;
+
+public interface MyFunction<T,R> {
+
+    R apply(T t);
+
+    default <V> MyFunction<V, R> compose(MyFunction<? super V, ? extends T> before) {
+        return (V v) -> apply(before.apply(v));
+    }
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/src/libs/MyMap.java b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/src/libs/MyMap.java
new file mode 100644
index 0000000..ad51f8d
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/src/libs/MyMap.java
@@ -0,0 +1,6 @@
+package libs;
+public interface MyMap<K,V> {
+	V get(Object key);
+	V put(K key, V val);
+	V remove(Object key);
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/.classpath b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/.classpath
new file mode 100644
index 0000000..1574d24
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/.classpath
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.core.tests.model.TEST_CONTAINER"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/.project b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/.project
new file mode 100644
index 0000000..ea7fde1
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>Test3</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/src/test1/Reconcile2.java b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/src/test1/Reconcile2.java
new file mode 100644
index 0000000..385d7cb
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/src/test1/Reconcile2.java
@@ -0,0 +1,24 @@
+package test1;
+
+import org.eclipse.jdt.annotation.*;
+import libs.*;
+
+
+class A {}
+class B {}
+class C {}
+
+@NonNullByDefault
+public class Reconcile2 {
+	C test(MyFunction<A,@Nullable B> f1, MyFunction<B,C> f2, A a) {
+		return f2.compose(f1).apply(a); // actually incompatible, but we tweak compose to pretend it's compatible
+	}
+	
+	void test2(Arrays lib) {
+		@Nullable String[]@NonNull[] arr = lib.getArray();
+		if (arr == null)
+			throw new NullPointerException(); // not dead code
+		@Nullable String @NonNull[] arr2 = Arrays.array;
+		Arrays.array[1] = null;
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/src/test1/Reconcile3.java b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/src/test1/Reconcile3.java
new file mode 100644
index 0000000..7a777c0
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/src/test1/Reconcile3.java
@@ -0,0 +1,19 @@
+package test1;
+
+import org.eclipse.jdt.annotation.*;
+import libs.*;
+
+class A {}
+class B {}
+class C {}
+
+@NonNullByDefault
+public class Reconcile3 {
+	void test1(MyFunction<A,@Nullable B> f1) {
+		// nothing
+	}
+	
+	void test2(MyFunction<A,@NonNull B> f2a, MyFunction<@Nullable String,@NonNull A> f2b) {
+		f2a.<@Nullable String>compose(f2b);
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_in.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_in.java
new file mode 100644
index 0000000..a5a247f
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_in.java
@@ -0,0 +1,43 @@
+public class Example {
+	@SomeAnnotation(key1 = "value1", key2 = "value2")
+	void method1() {
+		for (int counter = 0; counter < 100; counter++) {
+			if (counter % 2 == 0 && counter % 7 == 0 && counter % 13 == 0) {
+				try (AutoCloseable resource = null) {
+					// read resource
+				} catch (Exception e) {
+					e.printStackTrace();
+				}
+			}
+		}
+	}
+	@Deprecated()
+	void method2(
+			String argument) {
+		switch (argument) {
+		case "1":
+			this.method3(this, this, this, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb", "ccccccccccccccccccc");
+			break;
+		}
+	}
+	void method3(Example argument1, Example argument2, Example argument3, String argument4, String argument5, String argument6) {
+		method1();
+		while (argument1.toString().contains(argument4)
+		) {
+			argument1.method2(argument5);
+		}
+	}
+	java.util.function.BiConsumer<Example, String> lambda = (Example example, String text) -> {
+		do {
+			example.method1();
+		} while (example.toString()//
+				.contains(""));
+	};
+	Runnable r = () -> {};
+}
+
+enum SomeEnum {
+	VALUE1(),
+	VALUE2("example")
+}
+
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out01.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out01.java
new file mode 100644
index 0000000..7f66138
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out01.java
@@ -0,0 +1,45 @@
+public class Example {
+	@SomeAnnotation(key1 = "value1", key2 = "value2")
+	void method1() {
+		for (int counter = 0; counter < 100; counter++) {
+			if (counter % 2 == 0 && counter % 7 == 0 && counter % 13 == 0) {
+				try (AutoCloseable resource = null) {
+					// read resource
+				} catch (Exception e) {
+					e.printStackTrace();
+				}
+			}
+		}
+	}
+
+	@Deprecated()
+	void method2(String argument) {
+		switch (argument) {
+		case "1":
+			this.method3(this, this, this, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
+					"ccccccccccccccccccc");
+			break;
+		}
+	}
+
+	void method3(Example argument1, Example argument2, Example argument3, String argument4, String argument5,
+			String argument6) {
+		method1();
+		while (argument1.toString().contains(argument4)) {
+			argument1.method2(argument5);
+		}
+	}
+
+	java.util.function.BiConsumer<Example, String> lambda = (Example example, String text) -> {
+		do {
+			example.method1();
+		} while (example.toString()//
+				.contains(""));
+	};
+	Runnable r = () -> {
+	};
+}
+
+enum SomeEnum {
+	VALUE1(), VALUE2("example")
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out02.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out02.java
new file mode 100644
index 0000000..2e6566c
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out02.java
@@ -0,0 +1,49 @@
+public class Example {
+	@SomeAnnotation(key1 = "value1", key2 = "value2")
+	void method1() {
+		for (int counter = 0; counter < 100; counter++) {
+			if (counter % 2 == 0 && counter % 7 == 0 && counter % 13 == 0) {
+				try (AutoCloseable resource = null) {
+					// read resource
+				} catch (Exception e) {
+					e.printStackTrace();
+				}
+			}
+		}
+	}
+
+	@Deprecated()
+	void method2(
+			String argument
+	) {
+		switch (argument) {
+		case "1":
+			this.method3(this, this, this, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
+					"ccccccccccccccccccc");
+			break;
+		}
+	}
+
+	void method3(
+			Example argument1, Example argument2, Example argument3, String argument4, String argument5,
+			String argument6
+	) {
+		method1();
+		while (argument1.toString().contains(argument4)) {
+			argument1.method2(argument5);
+		}
+	}
+
+	java.util.function.BiConsumer<Example, String> lambda = (Example example, String text) -> {
+		do {
+			example.method1();
+		} while (example.toString()//
+				.contains(""));
+	};
+	Runnable r = () -> {
+	};
+}
+
+enum SomeEnum {
+	VALUE1(), VALUE2("example")
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out03.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out03.java
new file mode 100644
index 0000000..f42580b
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out03.java
@@ -0,0 +1,47 @@
+public class Example {
+	@SomeAnnotation(key1 = "value1", key2 = "value2")
+	void method1() {
+		for (int counter = 0; counter < 100; counter++) {
+			if (counter % 2 == 0 && counter % 7 == 0 && counter % 13 == 0) {
+				try (AutoCloseable resource = null) {
+					// read resource
+				} catch (Exception e) {
+					e.printStackTrace();
+				}
+			}
+		}
+	}
+
+	@Deprecated()
+	void method2(String argument) {
+		switch (argument) {
+		case "1":
+			this.method3(this, this, this, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
+					"ccccccccccccccccccc");
+			break;
+		}
+	}
+
+	void method3(
+			Example argument1, Example argument2, Example argument3, String argument4, String argument5,
+			String argument6
+	) {
+		method1();
+		while (argument1.toString().contains(argument4)) {
+			argument1.method2(argument5);
+		}
+	}
+
+	java.util.function.BiConsumer<Example, String> lambda = (Example example, String text) -> {
+		do {
+			example.method1();
+		} while (example.toString()//
+				.contains(""));
+	};
+	Runnable r = () -> {
+	};
+}
+
+enum SomeEnum {
+	VALUE1(), VALUE2("example")
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out04.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out04.java
new file mode 100644
index 0000000..9b157b2
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out04.java
@@ -0,0 +1,50 @@
+public class Example {
+	@SomeAnnotation(key1 = "value1", key2 = "value2")
+	void method1(
+	) {
+		for (int counter = 0; counter < 100; counter++) {
+			if (counter % 2 == 0 && counter % 7 == 0 && counter % 13 == 0) {
+				try (AutoCloseable resource = null) {
+					// read resource
+				} catch (Exception e) {
+					e.printStackTrace();
+				}
+			}
+		}
+	}
+
+	@Deprecated()
+	void method2(
+			String argument
+	) {
+		switch (argument) {
+		case "1":
+			this.method3(this, this, this, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
+					"ccccccccccccccccccc");
+			break;
+		}
+	}
+
+	void method3(
+			Example argument1, Example argument2, Example argument3, String argument4, String argument5,
+			String argument6
+	) {
+		method1();
+		while (argument1.toString().contains(argument4)) {
+			argument1.method2(argument5);
+		}
+	}
+
+	java.util.function.BiConsumer<Example, String> lambda = (Example example, String text) -> {
+		do {
+			example.method1();
+		} while (example.toString()//
+				.contains(""));
+	};
+	Runnable r = () -> {
+	};
+}
+
+enum SomeEnum {
+	VALUE1(), VALUE2("example")
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out05.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out05.java
new file mode 100644
index 0000000..ac9baa7
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out05.java
@@ -0,0 +1,53 @@
+public class Example {
+	@SomeAnnotation(key1 = "value1", key2 = "value2")
+	void method1() {
+		for (int counter = 0; counter < 100; counter++) {
+			if (counter % 2 == 0 && counter % 7 == 0 && counter % 13 == 0) {
+				try (AutoCloseable resource = null) {
+					// read resource
+				} catch (Exception e) {
+					e.printStackTrace();
+				}
+			}
+		}
+	}
+
+	@Deprecated()
+	void method2(String argument) {
+		switch (argument) {
+		case "1":
+			this.method3(
+					this, this, this, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
+					"ccccccccccccccccccc"
+			);
+			break;
+		}
+	}
+
+	void method3(Example argument1, Example argument2, Example argument3, String argument4, String argument5,
+			String argument6) {
+		method1();
+		while (argument1.toString().contains(
+				argument4
+		)) {
+			argument1.method2(
+					argument5
+			);
+		}
+	}
+
+	java.util.function.BiConsumer<Example, String> lambda = (Example example, String text) -> {
+		do {
+			example.method1();
+		} while (example.toString()//
+				.contains(
+						""
+				));
+	};
+	Runnable r = () -> {
+	};
+}
+
+enum SomeEnum {
+	VALUE1(), VALUE2("example")
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out06.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out06.java
new file mode 100644
index 0000000..a517035
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out06.java
@@ -0,0 +1,50 @@
+public class Example {
+	@SomeAnnotation(key1 = "value1", key2 = "value2")
+	void method1() {
+		for (int counter = 0; counter < 100; counter++) {
+			if (counter % 2 == 0 && counter % 7 == 0 && counter % 13 == 0) {
+				try (AutoCloseable resource = null) {
+					// read resource
+				} catch (Exception e) {
+					e.printStackTrace();
+				}
+			}
+		}
+	}
+
+	@Deprecated()
+	void method2(String argument) {
+		switch (argument) {
+		case "1":
+			this.method3(
+					this, this, this, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
+					"ccccccccccccccccccc"
+			);
+			break;
+		}
+	}
+
+	void method3(Example argument1, Example argument2, Example argument3, String argument4, String argument5,
+			String argument6) {
+		method1();
+		while (argument1.toString().contains(argument4)) {
+			argument1.method2(argument5);
+		}
+	}
+
+	java.util.function.BiConsumer<Example, String> lambda = (Example example, String text) -> {
+		do {
+			example.method1();
+		} while (example.toString()//
+				.contains(""));
+	};
+	Runnable r = () -> {
+	};
+}
+
+enum SomeEnum {
+	VALUE1(
+	), VALUE2(
+			"example"
+	)
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out07.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out07.java
new file mode 100644
index 0000000..4ee529a
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out07.java
@@ -0,0 +1,53 @@
+public class Example {
+	@SomeAnnotation(key1 = "value1", key2 = "value2")
+	void method1() {
+		for (int counter = 0; counter < 100; counter++) {
+			if (
+				counter % 2 == 0 && counter % 7 == 0 && counter % 13 == 0
+			) {
+				try (AutoCloseable resource = null) {
+					// read resource
+				} catch (Exception e) {
+					e.printStackTrace();
+				}
+			}
+		}
+	}
+
+	@Deprecated()
+	void method2(String argument) {
+		switch (argument) {
+		case "1":
+			this.method3(this, this, this, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
+					"ccccccccccccccccccc");
+			break;
+		}
+	}
+
+	void method3(Example argument1, Example argument2, Example argument3, String argument4, String argument5,
+			String argument6) {
+		method1();
+		while (
+			argument1.toString().contains(argument4)
+		) {
+			argument1.method2(argument5);
+		}
+	}
+
+	java.util.function.BiConsumer<Example, String> lambda = (Example example, String text) -> {
+		do {
+			example.method1();
+		} while (
+			example.toString()//
+					.contains("")
+		);
+	};
+	Runnable r = () -> {
+	};
+}
+
+enum SomeEnum {
+	VALUE1(), VALUE2(
+			"example"
+	)
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out08.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out08.java
new file mode 100644
index 0000000..bfeb310
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out08.java
@@ -0,0 +1,49 @@
+public class Example {
+	@SomeAnnotation(key1 = "value1", key2 = "value2")
+	void method1() {
+		for (int counter = 0; counter < 100; counter++) {
+			if (counter % 2 == 0 && counter % 7 == 0 && counter % 13 == 0) {
+				try (AutoCloseable resource = null) {
+					// read resource
+				} catch (Exception e) {
+					e.printStackTrace();
+				}
+			}
+		}
+	}
+
+	@Deprecated()
+	void method2(String argument) {
+		switch (argument) {
+		case "1":
+			this.method3(this, this, this, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
+					"ccccccccccccccccccc");
+			break;
+		}
+	}
+
+	void method3(Example argument1, Example argument2, Example argument3, String argument4, String argument5,
+			String argument6) {
+		method1();
+		while (argument1.toString().contains(argument4)) {
+			argument1.method2(argument5);
+		}
+	}
+
+	java.util.function.BiConsumer<Example, String> lambda = (
+			Example example, String text
+	) -> {
+		do {
+			example.method1();
+		} while (
+			example.toString()//
+					.contains("")
+		);
+	};
+	Runnable r = () -> {
+	};
+}
+
+enum SomeEnum {
+	VALUE1(), VALUE2("example")
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out09.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out09.java
new file mode 100644
index 0000000..1a26b45
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out09.java
@@ -0,0 +1,57 @@
+public class Example {
+	@SomeAnnotation(key1 = "value1", key2 = "value2")
+	void method1() {
+		for (int counter = 0; counter < 100; counter++) {
+			if (counter % 2 == 0 && counter % 7 == 0 && counter % 13 == 0) {
+				try (AutoCloseable resource = null) {
+					// read resource
+				} catch (Exception e) {
+					e.printStackTrace();
+				}
+			}
+		}
+	}
+
+	@Deprecated()
+	void method2(String argument) {
+		switch (argument) {
+		case "1":
+			this.method3(
+					this, this, this, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
+					"ccccccccccccccccccc"
+			);
+			break;
+		}
+	}
+
+	void method3(Example argument1, Example argument2, Example argument3, String argument4, String argument5,
+			String argument6) {
+		method1();
+		while (
+			argument1.toString().contains(
+					argument4
+			)
+		) {
+			argument1.method2(
+					argument5
+			);
+		}
+	}
+
+	java.util.function.BiConsumer<Example, String> lambda = (Example example, String text) -> {
+		do {
+			example.method1();
+		} while (
+			example.toString()//
+					.contains(
+							""
+					)
+		);
+	};
+	Runnable r = () -> {
+	};
+}
+
+enum SomeEnum {
+	VALUE1(), VALUE2("example")
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out10.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out10.java
new file mode 100644
index 0000000..ddc6a5e
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out10.java
@@ -0,0 +1,48 @@
+public class Example {
+	@SomeAnnotation(key1 = "value1", key2 = "value2")
+	void method1() {
+		for (int counter = 0; counter < 100; counter++) {
+			if (counter % 2 == 0 && counter % 7 == 0 && counter % 13 == 0) {
+				try (
+						AutoCloseable resource = null
+				) {
+					// read resource
+				} catch (Exception e) {
+					e.printStackTrace();
+				}
+			}
+		}
+	}
+
+	@Deprecated()
+	void method2(
+			String argument) {
+		switch (argument) {
+		case "1":
+			this.method3(this, this, this, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
+					"ccccccccccccccccccc");
+			break;
+		}
+	}
+
+	void method3(Example argument1, Example argument2, Example argument3, String argument4, String argument5,
+			String argument6) {
+		method1();
+		while (argument1.toString().contains(argument4)) {
+			argument1.method2(argument5);
+		}
+	}
+
+	java.util.function.BiConsumer<Example, String> lambda = (Example example, String text) -> {
+		do {
+			example.method1();
+		} while (example.toString()//
+				.contains(""));
+	};
+	Runnable r = () -> {
+	};
+}
+
+enum SomeEnum {
+	VALUE1(), VALUE2("example")
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out11.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out11.java
new file mode 100644
index 0000000..09ea887
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out11.java
@@ -0,0 +1,48 @@
+public class Example {
+	@SomeAnnotation(key1 = "value1", key2 = "value2")
+	void method1() {
+		for (int counter = 0; counter < 100; counter++) {
+			if (counter % 2 == 0 && counter % 7 == 0 && counter % 13 == 0) {
+				try (AutoCloseable resource = null) {
+					// read resource
+				} catch (
+					Exception e
+				) {
+					e.printStackTrace();
+				}
+			}
+		}
+	}
+
+	@Deprecated()
+	void method2(String argument) {
+		switch (argument) {
+		case "1":
+			this.method3(this, this, this, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
+					"ccccccccccccccccccc");
+			break;
+		}
+	}
+
+	void method3(Example argument1, Example argument2, Example argument3, String argument4, String argument5,
+			String argument6) {
+		method1();
+		while (argument1.toString().contains(argument4)
+		) {
+			argument1.method2(argument5);
+		}
+	}
+
+	java.util.function.BiConsumer<Example, String> lambda = (Example example, String text) -> {
+		do {
+			example.method1();
+		} while (example.toString()//
+				.contains(""));
+	};
+	Runnable r = () -> {
+	};
+}
+
+enum SomeEnum {
+	VALUE1(), VALUE2("example")
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out12.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out12.java
new file mode 100644
index 0000000..d1c3ab2
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out12.java
@@ -0,0 +1,47 @@
+public class Example {
+	@SomeAnnotation(
+			key1 = "value1", key2 = "value2"
+	)
+	void method1() {
+		for (int counter = 0; counter < 100; counter++) {
+			if (counter % 2 == 0 && counter % 7 == 0 && counter % 13 == 0) {
+				try (AutoCloseable resource = null) {
+					// read resource
+				} catch (Exception e) {
+					e.printStackTrace();
+				}
+			}
+		}
+	}
+
+	@Deprecated()
+	void method2(String argument) {
+		switch (argument) {
+		case "1":
+			this.method3(this, this, this, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
+					"ccccccccccccccccccc");
+			break;
+		}
+	}
+
+	void method3(Example argument1, Example argument2, Example argument3, String argument4, String argument5,
+			String argument6) {
+		method1();
+		while (argument1.toString().contains(argument4)) {
+			argument1.method2(argument5);
+		}
+	}
+
+	java.util.function.BiConsumer<Example, String> lambda = (Example example, String text) -> {
+		do {
+			example.method1();
+		} while (example.toString()//
+				.contains(""));
+	};
+	Runnable r = () -> {
+	};
+}
+
+enum SomeEnum {
+	VALUE1(), VALUE2("example")
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out13.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out13.java
new file mode 100644
index 0000000..15c9d73
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out13.java
@@ -0,0 +1,49 @@
+public class Example {
+	@SomeAnnotation(key1 = "value1", key2 = "value2")
+	void method1() {
+		for (
+				int counter = 0;
+				counter < 100;
+				counter++
+		) {
+			if (counter % 2 == 0 && counter % 7 == 0 && counter % 13 == 0) {
+				try (AutoCloseable resource = null) {
+					// read resource
+				} catch (Exception e) {
+					e.printStackTrace();
+				}
+			}
+		}
+	}
+
+	@Deprecated()
+	void method2(String argument) {
+		switch (argument) {
+		case "1":
+			this.method3(this, this, this, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
+					"ccccccccccccccccccc");
+			break;
+		}
+	}
+
+	void method3(Example argument1, Example argument2, Example argument3, String argument4, String argument5,
+			String argument6) {
+		method1();
+		while (argument1.toString().contains(argument4)) {
+			argument1.method2(argument5);
+		}
+	}
+
+	java.util.function.BiConsumer<Example, String> lambda = (Example example, String text) -> {
+		do {
+			example.method1();
+		} while (example.toString()//
+				.contains(""));
+	};
+	Runnable r = () -> {
+	};
+}
+
+enum SomeEnum {
+	VALUE1(), VALUE2("example")
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out14.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out14.java
new file mode 100644
index 0000000..edb3b61
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out14.java
@@ -0,0 +1,50 @@
+public class Example {
+	@SomeAnnotation(
+			key1 = "value1", key2 = "value2"
+	)
+	void method1() {
+		for (int counter = 0; counter < 100; counter++) {
+			if (counter % 2 == 0 && counter % 7 == 0 && counter % 13 == 0) {
+				try (AutoCloseable resource = null) {
+					// read resource
+				} catch (Exception e) {
+					e.printStackTrace();
+				}
+			}
+		}
+	}
+
+	@Deprecated(
+	)
+	void method2(String argument) {
+		switch (
+			argument
+		) {
+		case "1":
+			this.method3(this, this, this, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
+					"ccccccccccccccccccc");
+			break;
+		}
+	}
+
+	void method3(Example argument1, Example argument2, Example argument3, String argument4, String argument5,
+			String argument6) {
+		method1();
+		while (argument1.toString().contains(argument4)) {
+			argument1.method2(argument5);
+		}
+	}
+
+	java.util.function.BiConsumer<Example, String> lambda = (Example example, String text) -> {
+		do {
+			example.method1();
+		} while (example.toString()//
+				.contains(""));
+	};
+	Runnable r = () -> {
+	};
+}
+
+enum SomeEnum {
+	VALUE1(), VALUE2("example")
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out15.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out15.java
new file mode 100644
index 0000000..1a69c2c
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test370540/Example_out15.java
@@ -0,0 +1,86 @@
+public class Example {
+	@SomeAnnotation(
+			key1 = "value1", key2 = "value2"
+	)
+	void method1(
+	) {
+		for (
+				int counter = 0; counter < 100; counter++
+		) {
+			if (
+				counter % 2 == 0 && counter % 7 == 0 && counter % 13 == 0
+			) {
+				try (
+						AutoCloseable resource = null
+				) {
+					// read resource
+				} catch (
+					Exception e
+				) {
+					e.printStackTrace(
+					);
+				}
+			}
+		}
+	}
+
+	@Deprecated(
+	)
+	void method2(
+			String argument
+	) {
+		switch (
+			argument
+		) {
+		case "1":
+			this.method3(
+					this, this, this, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
+					"ccccccccccccccccccc"
+			);
+			break;
+		}
+	}
+
+	void method3(
+			Example argument1, Example argument2, Example argument3, String argument4, String argument5,
+			String argument6
+	) {
+		method1(
+		);
+		while (
+			argument1.toString(
+			).contains(
+					argument4
+			)
+		) {
+			argument1.method2(
+					argument5
+			);
+		}
+	}
+
+	java.util.function.BiConsumer<Example, String> lambda = (
+			Example example, String text
+	) -> {
+		do {
+			example.method1(
+			);
+		} while (
+			example.toString(
+			)//
+					.contains(
+							""
+					)
+		);
+	};
+	Runnable r = (
+	) -> {
+	};
+}
+
+enum SomeEnum {
+	VALUE1(
+	), VALUE2(
+			"example"
+	)
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_in.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_in.java
new file mode 100644
index 0000000..1159d8d
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_in.java
@@ -0,0 +1,55 @@
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public abstract class A<T extends A<T, S>, S extends List<?>> {
+
+	T t;
+	S s;
+	A<T, S> a;
+
+	Object field = a.<T, S>getMap(t, s);
+
+	public A() {
+		<T, S>this(null, null);
+	}
+
+	public <M, N> A(M param1, N param2) {
+
+	}
+
+	public <M, N> Map<M, N> getMap(M key, N value) {
+		return null;
+	}
+
+}
+
+class B extends A<B, List<String>> {
+
+	public <M, N> B(M param1, N param2) {
+		<M, N>super(param1, param2);
+	}
+
+	public <M, N> Map<M, N> getMap(M key, N value) {
+		B b = new <M, N>B(key, value);
+		AMethod method = b::<String, String>getMap;
+		AMethod method2 = super::<String, String>getMap;
+		AMethod method3 = AMap<M>::<String, String>new;
+		AMethod method4 = AMap<M>::<String, String>createAMap;
+		return super.<M, N>getMap(key, value);
+	}
+}
+
+interface AMethod {
+	Map<String, String> getMap(String key, String value);
+}
+
+class AMap<T> extends HashMap<String, String> {
+	public <M, N> AMap(String param1, String param2) {
+
+	}
+
+	public static <M, N> AMap<M> createAMap(String param1, String param2) {
+		return new AMap<>(param1, param2);
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out1.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out1.java
new file mode 100644
index 0000000..1159d8d
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out1.java
@@ -0,0 +1,55 @@
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public abstract class A<T extends A<T, S>, S extends List<?>> {
+
+	T t;
+	S s;
+	A<T, S> a;
+
+	Object field = a.<T, S>getMap(t, s);
+
+	public A() {
+		<T, S>this(null, null);
+	}
+
+	public <M, N> A(M param1, N param2) {
+
+	}
+
+	public <M, N> Map<M, N> getMap(M key, N value) {
+		return null;
+	}
+
+}
+
+class B extends A<B, List<String>> {
+
+	public <M, N> B(M param1, N param2) {
+		<M, N>super(param1, param2);
+	}
+
+	public <M, N> Map<M, N> getMap(M key, N value) {
+		B b = new <M, N>B(key, value);
+		AMethod method = b::<String, String>getMap;
+		AMethod method2 = super::<String, String>getMap;
+		AMethod method3 = AMap<M>::<String, String>new;
+		AMethod method4 = AMap<M>::<String, String>createAMap;
+		return super.<M, N>getMap(key, value);
+	}
+}
+
+interface AMethod {
+	Map<String, String> getMap(String key, String value);
+}
+
+class AMap<T> extends HashMap<String, String> {
+	public <M, N> AMap(String param1, String param2) {
+
+	}
+
+	public static <M, N> AMap<M> createAMap(String param1, String param2) {
+		return new AMap<>(param1, param2);
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out2.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out2.java
new file mode 100644
index 0000000..3b94dfd
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out2.java
@@ -0,0 +1,74 @@
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public abstract class A<T extends A<
+		T,
+		S>, S extends List<
+				?>> {
+
+	T t;
+	S s;
+	A<
+			T,
+			S> a;
+
+	Object field = a.<T, S>getMap(t, s);
+
+	public A() {
+		<T, S>this(null, null);
+	}
+
+	public <M, N> A(M param1, N param2) {
+
+	}
+
+	public <M, N> Map<
+			M,
+			N> getMap(M key, N value) {
+		return null;
+	}
+
+}
+
+class B extends A<
+		B,
+		List<
+				String>> {
+
+	public <M, N> B(M param1, N param2) {
+		<M, N>super(param1, param2);
+	}
+
+	public <M, N> Map<
+			M,
+			N> getMap(M key, N value) {
+		B b = new <M, N>B(key, value);
+		AMethod method = b::<String, String>getMap;
+		AMethod method2 = super::<String, String>getMap;
+		AMethod method3 = AMap<
+				M>::<String, String>new;
+		AMethod method4 = AMap<
+				M>::<String, String>createAMap;
+		return super.<M, N>getMap(key, value);
+	}
+}
+
+interface AMethod {
+	Map<
+			String,
+			String> getMap(String key, String value);
+}
+
+class AMap<T> extends HashMap<
+		String,
+		String> {
+	public <M, N> AMap(String param1, String param2) {
+
+	}
+
+	public static <M, N> AMap<
+			M> createAMap(String param1, String param2) {
+		return new AMap<>(param1, param2);
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out3.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out3.java
new file mode 100644
index 0000000..f2fab44
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out3.java
@@ -0,0 +1,73 @@
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public abstract class A<T extends A<T, S>, S extends List<?>> {
+
+	T t;
+	S s;
+	A<T, S> a;
+
+	Object field = a.<
+			T,
+			S>getMap(t, s);
+
+	public A() {
+		<
+				T,
+				S>this(null, null);
+	}
+
+	public <M, N> A(M param1, N param2) {
+
+	}
+
+	public <M, N> Map<M, N> getMap(M key, N value) {
+		return null;
+	}
+
+}
+
+class B extends A<B, List<String>> {
+
+	public <M, N> B(M param1, N param2) {
+		<
+				M,
+				N>super(param1, param2);
+	}
+
+	public <M, N> Map<M, N> getMap(M key, N value) {
+		B b = new <
+				M,
+				N>B(key, value);
+		AMethod method = b::<
+				String,
+				String>getMap;
+		AMethod method2 = super::<
+				String,
+				String>getMap;
+		AMethod method3 = AMap<M>::<
+				String,
+				String>new;
+		AMethod method4 = AMap<M>::<
+				String,
+				String>createAMap;
+		return super.<
+				M,
+				N>getMap(key, value);
+	}
+}
+
+interface AMethod {
+	Map<String, String> getMap(String key, String value);
+}
+
+class AMap<T> extends HashMap<String, String> {
+	public <M, N> AMap(String param1, String param2) {
+
+	}
+
+	public static <M, N> AMap<M> createAMap(String param1, String param2) {
+		return new AMap<>(param1, param2);
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out4.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out4.java
new file mode 100644
index 0000000..8913334
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out4.java
@@ -0,0 +1,70 @@
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public abstract class A<
+		T extends A<T, S>,
+		S extends List<?>> {
+
+	T t;
+	S s;
+	A<T, S> a;
+
+	Object field = a.<T, S>getMap(t, s);
+
+	public A() {
+		<T, S>this(null, null);
+	}
+
+	public <
+			M,
+			N> A(M param1, N param2) {
+
+	}
+
+	public <
+			M,
+			N> Map<M, N> getMap(M key, N value) {
+		return null;
+	}
+
+}
+
+class B extends A<B, List<String>> {
+
+	public <
+			M,
+			N> B(M param1, N param2) {
+		<M, N>super(param1, param2);
+	}
+
+	public <
+			M,
+			N> Map<M, N> getMap(M key, N value) {
+		B b = new <M, N>B(key, value);
+		AMethod method = b::<String, String>getMap;
+		AMethod method2 = super::<String, String>getMap;
+		AMethod method3 = AMap<M>::<String, String>new;
+		AMethod method4 = AMap<M>::<String, String>createAMap;
+		return super.<M, N>getMap(key, value);
+	}
+}
+
+interface AMethod {
+	Map<String, String> getMap(String key, String value);
+}
+
+class AMap<
+		T> extends HashMap<String, String> {
+	public <
+			M,
+			N> AMap(String param1, String param2) {
+
+	}
+
+	public static <
+			M,
+			N> AMap<M> createAMap(String param1, String param2) {
+		return new AMap<>(param1, param2);
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out5.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out5.java
new file mode 100644
index 0000000..f1ac68c
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out5.java
@@ -0,0 +1,107 @@
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public abstract class A<
+		T extends A<
+				T,
+					S>,
+			S extends List<
+					?>> {
+
+	T t;
+	S s;
+	A<
+			T,
+				S> a;
+
+	Object field = a.<
+			T,
+				S>getMap(t, s);
+
+	public A() {
+		<
+				T,
+					S>this(null, null);
+	}
+
+	public <
+			M,
+				N> A(M param1, N param2) {
+
+	}
+
+	public <
+			M,
+				N> Map<
+						M,
+							N> getMap(M key, N value) {
+		return null;
+	}
+
+}
+
+class B extends A<
+		B,
+			List<
+					String>> {
+
+	public <
+			M,
+				N> B(M param1, N param2) {
+		<
+				M,
+					N>super(param1, param2);
+	}
+
+	public <
+			M,
+				N> Map<
+						M,
+							N> getMap(M key, N value) {
+		B b = new <
+				M,
+					N>B(key, value);
+		AMethod method = b::<
+				String,
+					String>getMap;
+		AMethod method2 = super::<
+				String,
+					String>getMap;
+		AMethod method3 = AMap<
+				M>::<
+						String,
+							String>new;
+		AMethod method4 = AMap<
+				M>::<
+						String,
+							String>createAMap;
+		return super.<
+				M,
+					N>getMap(key, value);
+	}
+}
+
+interface AMethod {
+	Map<
+			String,
+				String> getMap(String key, String value);
+}
+
+class AMap<
+		T> extends HashMap<
+				String,
+					String> {
+	public <
+			M,
+				N> AMap(String param1, String param2) {
+
+	}
+
+	public static <
+			M,
+				N> AMap<
+						M> createAMap(String param1, String param2) {
+		return new AMap<>(param1, param2);
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out6.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out6.java
new file mode 100644
index 0000000..49a28e1
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test384959/A_out6.java
@@ -0,0 +1,78 @@
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public abstract class A<T extends A<T,
+                                    S>,
+                        S extends List<?>> {
+
+    T t;
+    S s;
+    A<T,
+      S> a;
+
+    Object field = a.<T,
+                      S>getMap(t, s);
+
+    public A() {
+        <T,
+         S>this(null, null);
+    }
+
+    public <M,
+            N> A(M param1, N param2) {
+
+    }
+
+    public <M,
+            N> Map<M,
+                   N> getMap(M key, N value) {
+        return null;
+    }
+
+}
+
+class B extends A<B,
+                  List<String>> {
+
+    public <M,
+            N> B(M param1, N param2) {
+        <M,
+         N>super(param1, param2);
+    }
+
+    public <M,
+            N> Map<M,
+                   N> getMap(M key, N value) {
+        B b = new <M,
+                   N>B(key, value);
+        AMethod method = b::<String,
+                             String>getMap;
+        AMethod method2 = super::<String,
+                                  String>getMap;
+        AMethod method3 = AMap<M>::<String,
+                                    String>new;
+        AMethod method4 = AMap<M>::<String,
+                                    String>createAMap;
+        return super.<M,
+                      N>getMap(key, value);
+    }
+}
+
+interface AMethod {
+    Map<String,
+        String> getMap(String key, String value);
+}
+
+class AMap<T> extends HashMap<String,
+                              String> {
+    public <M,
+            N> AMap(String param1, String param2) {
+
+    }
+
+    public static <M,
+                   N> AMap<M> createAMap(String param1, String param2) {
+        return new AMap<>(param1, param2);
+    }
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java
index 5b67493..69540cf 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -177,7 +177,7 @@
 public boolean hasAnnotationFileFor(String qualifiedTypeName) {
 	int pos = qualifiedTypeName.lastIndexOf('/');
 	if (pos != -1 && (pos + 1 < qualifiedTypeName.length())) {
-		String fileName = qualifiedTypeName.substring(pos + 1) + '.' + ExternalAnnotationProvider.ANNOTION_FILE_EXTENSION;
+		String fileName = qualifiedTypeName.substring(pos + 1) + ExternalAnnotationProvider.ANNOTATION_FILE_SUFFIX;
 		return doesFileExist(fileName, qualifiedTypeName.substring(0, pos));
 	}
 	return false;
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java
index 8d56c0a..77ad903 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -127,7 +127,7 @@
 }
 @Override
 public boolean hasAnnotationFileFor(String qualifiedTypeName) {
-	return this.zipFile.getEntry(qualifiedTypeName+'.'+ExternalAnnotationProvider.ANNOTION_FILE_EXTENSION) != null; 
+	return this.zipFile.getEntry(qualifiedTypeName+ExternalAnnotationProvider.ANNOTATION_FILE_SUFFIX) != null; 
 }
 public char[][][] findTypeNames(String qualifiedPackageName) {
 	if (!isPackage(qualifiedPackageName))
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
index da461e4..eda23ea 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
@@ -11011,7 +11011,7 @@
 
 	private void findPackages(CompletionOnPackageReference packageStatement) {
 
-		this.completionToken = CharOperation.concatWith(packageStatement.tokens, '.');
+		this.completionToken = CharOperation.concatWithAll(packageStatement.tokens, '.');
 		if (this.completionToken.length == 0)
 			return;
 
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java
index 544a2ba..d3a15e0 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java
@@ -4467,9 +4467,9 @@
 	super.consumeInvocationExpression();
 	triggerRecoveryUponLambdaClosure(this.expressionStack[this.expressionPtr], false);
 }
-protected void consumeIdentifierOrNew(boolean newForm) {
+protected void consumeReferenceExpression(ReferenceExpression referenceExpression) {
 	this.inReferenceExpression = false;
-	super.consumeIdentifierOrNew(newForm);
+	super.consumeReferenceExpression(referenceExpression);
 }
 protected void consumeOnlySynchronized() {
 	super.consumeOnlySynchronized();
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Engine.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Engine.java
index b0f1690..a19d3ca 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Engine.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Engine.java
@@ -15,6 +15,8 @@
 
 import java.util.Map;
 
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.*;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
@@ -25,8 +27,11 @@
 import org.eclipse.jdt.internal.compiler.parser.*;
 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
 import org.eclipse.jdt.internal.compiler.impl.*;
+import org.eclipse.jdt.internal.core.JavaElement;
 import org.eclipse.jdt.internal.core.NameLookup;
 import org.eclipse.jdt.internal.core.SearchableEnvironment;
+import org.eclipse.jdt.internal.core.SourceType;
+import org.eclipse.jdt.internal.core.SourceTypeElementInfo;
 import org.eclipse.objectteams.otdt.internal.core.compiler.ast.AbstractMethodMappingDeclaration;
 import org.eclipse.objectteams.otdt.internal.core.compiler.ast.CallinMappingDeclaration;
 import org.eclipse.objectteams.otdt.internal.core.compiler.ast.CalloutMappingDeclaration;
@@ -90,8 +95,36 @@
 	 * secondary types defined in the same compilation unit).
 	 */
 	public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding, AccessRestriction accessRestriction) {
-		CompilationResult result =
-			new CompilationResult(sourceTypes[0].getFileName(), 1, 1, this.compilerOptions.maxProblemsPerUnit);
+		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=479656
+		// In case of the requested type not being a member type (i.e. not being a top level type)
+		// we need to find the top level ones and use them for resolution
+		CompilationResult result = null;
+		SourceTypeElementInfo sourceType;
+		if (sourceTypes[0].getEnclosingType() != null) {
+			try {
+				if (sourceTypes[0] instanceof SourceType) {
+					sourceType = (SourceTypeElementInfo) ((SourceType) sourceTypes[0]).getElementInfo();
+				} else {
+					sourceType = (SourceTypeElementInfo) sourceTypes[0];
+				}
+				IType[] types = sourceType.getHandle().getCompilationUnit().getTypes();
+				sourceTypes = new ISourceType[types.length];
+				sourceTypes[0] = sourceType;
+				int length = types.length;
+				for (int i = 0; i < length; i++) {
+					ISourceType otherType =
+						(ISourceType) ((JavaElement) types[i]).getElementInfo();
+					sourceTypes[i] = otherType;
+				}
+				ISourceType otherType =
+						(ISourceType) ((JavaElement) types[0]).getElementInfo();
+				result = new CompilationResult(otherType.getFileName(), 1, 1, this.compilerOptions.maxProblemsPerUnit);
+			} catch (JavaModelException e) {
+				// Unlikely to reach here as the elements have already been opened in NameLookup.
+			}
+		} else {
+			result = new CompilationResult(sourceTypes[0].getFileName(), 1, 1, this.compilerOptions.maxProblemsPerUnit);
+		}
 		CompilationUnitDeclaration unit =
 			SourceTypeConverter.buildCompilationUnit(
 				sourceTypes,//sourceTypes[0] is always toplevel here
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnMessageSend.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnMessageSend.java
index c585070..b467c95 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnMessageSend.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnMessageSend.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -95,7 +95,9 @@
 
 	public TypeBinding resolveType(BlockScope scope) {
 
-		super.resolveType(scope);
+		TypeBinding type = super.resolveType(scope);
+		if (type != null && type.isPolyType())
+			return type; // wait for more inference/resolution
 
 		// tolerate some error cases
 		if(this.binding == null ||
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java
index 79f6922..7c87b9f 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -64,8 +64,9 @@
 	protected static final int K_BETWEEN_CASE_AND_COLON = SELECTION_PARSER + 1; // whether we are inside a block
 	protected static final int K_INSIDE_RETURN_STATEMENT = SELECTION_PARSER + 2; // whether we are between the keyword 'return' and the end of a return statement
 	protected static final int K_CAST_STATEMENT = SELECTION_PARSER + 3; // whether we are between ')' and the end of a cast statement
-	
 
+	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=476693
+	private boolean selectionNodeFound;
 	public ASTNode assistNodeParent; // the parent node of assist node
 
 	/* public fields */
@@ -821,6 +822,21 @@
 			this.lastIgnoredToken = -1;
 		}
 	}
+	if (this.selectionNodeFound) {
+		this.restartRecovery = true;
+	}
+}
+protected void consumeAssignment() {
+	super.consumeAssignment();
+	if (this.selectionNodeFound) {
+		this.restartRecovery = true;
+	}
+}
+protected void consumeBlockStatement() {
+	super.consumeBlockStatement();
+	if (this.selectionNodeFound) {
+		this.restartRecovery = true;
+	}
 }
 protected void consumeMarkerAnnotation(boolean isTypeAnnotation) {
 	int index;
@@ -1525,7 +1541,9 @@
 	}
 	this.assistNode = messageSend;
 	if (!this.diet){
-		this.restartRecovery	= true;	// force to restart in recovery mode
+		// Don't restart recovery, not yet, until variable decl statement has been consumed.
+		// This is to ensure chained method invocations are taken into account for resolution.
+		this.selectionNodeFound = true;
 		this.lastIgnoredToken = -1;
 	}
 
@@ -1554,7 +1572,9 @@
 	}
 	this.assistNode = messageSend;
 	if (!this.diet){
-		this.restartRecovery	= true;	// force to restart in recovery mode
+		// Don't restart recovery, not yet, until variable decl statement has been consumed.
+		// This is to ensure chained method invocations are taken into account for resolution.
+		this.selectionNodeFound = true;
 		this.lastIgnoredToken = -1;
 	}
 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
index 89c602e..486320b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -1660,7 +1660,8 @@
 	int IllegalArrayTypeInIntersectionCast = TypeRelated + 893;
 	/** @since 3.10 */
 	int DuplicateBoundInIntersectionCast = TypeRelated + 894;
-	/** @since 3.10 */
+	/** @deprecated This problem is no longer reported; number Of functional interface is not an issue, number of abstract methods is.
+	 * @since 3.10 */
 	int MultipleFunctionalInterfaces = TypeRelated + 895;
 	/** @since 3.10 */
 	int StaticInterfaceMethodNotBelow18 = Internal + Syntax + 896;
@@ -1820,6 +1821,18 @@
 	int IllegalReturnNullityRedefinitionFreeTypeVariable = MethodRelated + 974;
 	/** @since 3.12 */
 	int IllegalRedefinitionOfTypeVariable = 975;
+	/** @since 3.12 */
+	int UncheckedAccessOfValueOfFreeTypeVariable = 976;
+	/** @since 3.12 */
+	int UninitializedFreeTypeVariableField = 977;
+	/** @since 3.12 */
+	int UninitializedFreeTypeVariableFieldHintMissingDefault = 978;
+	/** @since 3.12 */
+	int RequiredNonNullButProvidedFreeTypeVariable = TypeRelated + 979;
+	/** @since 3.12 */
+	int NonNullTypeVariableFromLegacyMethod = TypeRelated + 980;
+	/** @since 3.12 */
+	int NonNullMethodTypeVariableFromLegacyMethod = TypeRelated + 981;
 
 
 	// Java 8 work
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
index d184e0a..874c7bb 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -62,6 +62,7 @@
 import org.eclipse.jdt.internal.compiler.ast.NormalAnnotation;
 import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
 import org.eclipse.jdt.internal.compiler.ast.Receiver;
+import org.eclipse.jdt.internal.compiler.ast.ReferenceExpression;
 import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation;
 import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
@@ -77,10 +78,10 @@
 import org.eclipse.jdt.internal.compiler.codegen.Opcodes;
 import org.eclipse.jdt.internal.compiler.codegen.StackMapFrame;
 import org.eclipse.jdt.internal.compiler.codegen.StackMapFrameCodeStream;
-import org.eclipse.jdt.internal.compiler.codegen.TypeAnnotationCodeStream;
 import org.eclipse.jdt.internal.compiler.codegen.StackMapFrameCodeStream.ExceptionMarker;
 import org.eclipse.jdt.internal.compiler.codegen.StackMapFrameCodeStream.StackDepthMarker;
 import org.eclipse.jdt.internal.compiler.codegen.StackMapFrameCodeStream.StackMarker;
+import org.eclipse.jdt.internal.compiler.codegen.TypeAnnotationCodeStream;
 import org.eclipse.jdt.internal.compiler.codegen.VerificationTypeInfo;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.impl.Constant;
@@ -100,6 +101,8 @@
 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
 import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
 import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
+import org.eclipse.jdt.internal.compiler.problem.AbortMethod;
+import org.eclipse.jdt.internal.compiler.problem.AbortType;
 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
 import org.eclipse.jdt.internal.compiler.problem.ShouldNotImplement;
 import org.eclipse.jdt.internal.compiler.util.Messages;
@@ -1038,13 +1041,36 @@
 						case SyntheticMethodBinding.DeserializeLambda:
 							deserializeLambdaMethod = syntheticMethod; // delay processing
 							break;
+						case SyntheticMethodBinding.SerializableMethodReference:
+							// Nothing to be done
+							break;
 					}
 				}
 				emittedSyntheticsCount = currentSyntheticsCount;
 			}
 		}
 		if (deserializeLambdaMethod != null) {
-			addSyntheticDeserializeLambda(deserializeLambdaMethod,this.referenceBinding.syntheticMethods()); 
+			int problemResetPC = 0;
+			this.codeStream.wideMode = false;
+			boolean restart = false;
+			do {
+				try {
+					problemResetPC = this.contentsOffset;
+					addSyntheticDeserializeLambda(deserializeLambdaMethod,this.referenceBinding.syntheticMethods()); 
+					restart = false;
+				} catch (AbortMethod e) {
+					// Restart code generation if possible ...
+					if (e.compilationResult == CodeStream.RESTART_IN_WIDE_MODE) {
+						// a branch target required a goto_w, restart code generation in wide mode.
+						this.contentsOffset = problemResetPC;
+						this.methodCount--;
+						this.codeStream.resetInWideMode(); // request wide mode
+						restart = true;
+					} else {
+						throw new AbortType(this.referenceBinding.scope.referenceContext.compilationResult, e.problem);
+					}
+				}
+			} while (restart);
 		}
 	}
 
@@ -3038,12 +3064,9 @@
 			FunctionalExpression functional = (FunctionalExpression) functionalExpressionList.get(i);
 			MethodBinding [] bridges = functional.getRequiredBridges();
 			TypeBinding[] markerInterfaces = null;
-			if (functional instanceof LambdaExpression && 
-				   (((markerInterfaces=((LambdaExpression)functional).getMarkerInterfaces()) != null) ||
-				   	((LambdaExpression)functional).isSerializable) ||
-				   	bridges != null) {
-				
-				LambdaExpression lambdaEx = (LambdaExpression)functional;
+			if ((functional instanceof LambdaExpression
+					&& (((markerInterfaces = ((LambdaExpression) functional).getMarkerInterfaces()) != null))
+					|| bridges != null) || functional.isSerializable) {
 				// may need even more space
 				int extraSpace = 2; // at least 2 more than when the normal metafactory is used, for the bitflags entry
 				if (markerInterfaces != null) {
@@ -3085,7 +3108,7 @@
 				this.contents[localContentsOffset++] = (byte) methodTypeIndex;
 
 				int bitflags = 0;
-				if (lambdaEx.isSerializable) {
+				if (functional.isSerializable) {
 					bitflags |= ClassFileConstants.FLAG_SERIALIZABLE;
 				}
 				if (markerInterfaces!=null) {
@@ -3576,6 +3599,11 @@
 		generateCodeAttributeHeader();
 		this.codeStream.init(this);
 		this.codeStream.generateSyntheticBodyForDeserializeLambda(methodBinding, syntheticMethodBindings);
+		int code_length = this.codeStream.position;
+		if (code_length > 65535) {
+			this.referenceBinding.scope.problemReporter().bytecodeExceeds64KLimit(
+				methodBinding, this.referenceBinding.sourceStart(), this.referenceBinding.sourceEnd());
+		}
 		completeCodeAttributeForSyntheticMethod(
 			methodBinding,
 			codeAttributeOffset,
@@ -5360,10 +5388,17 @@
 		if (this.bootstrapMethods == null) {
 			this.bootstrapMethods = new ArrayList();
 		}
+		if (expression instanceof ReferenceExpression) {
+			for (int i = 0; i < this.bootstrapMethods.size(); i++) {
+				FunctionalExpression fexp = (FunctionalExpression) this.bootstrapMethods.get(i);
+				if (fexp.binding == expression.binding
+						&& TypeBinding.equalsEquals(fexp.expectedType(), expression.expectedType()))
+					return expression.bootstrapMethodNumber = i;
+			}
+		}
 		this.bootstrapMethods.add(expression);
 		// Record which bootstrap method was assigned to the expression
-		expression.bootstrapMethodNumber = this.bootstrapMethods.size() - 1;
-		return this.bootstrapMethods.size() - 1;
+		return expression.bootstrapMethodNumber = this.bootstrapMethods.size() - 1;
 	}
 
 	public void reset(SourceTypeBinding typeBinding) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
index aacac0a..80e2e1b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -358,7 +358,8 @@
   :giro */
 	public boolean checkInvocationArguments(BlockScope scope, Expression receiver, TypeBinding receiverType, MethodBinding method, Expression[] arguments, TypeBinding[] argumentTypes, boolean argsContainCast, InvocationSite invocationSite) {
 // SH}
-		boolean is1_7 = scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_7;
+		long sourceLevel = scope.compilerOptions().sourceLevel;
+		boolean is1_7 = sourceLevel >= ClassFileConstants.JDK1_7;
 		TypeBinding[] params = method.parameters;
 		int paramLength = params.length;
 		boolean isRawMemberInvocation = !method.isStatic()
@@ -451,11 +452,13 @@
 			}
 		} else if (rawOriginalGenericMethod != null 
 				|| uncheckedBoundCheck
-				|| ((invocationStatus & INVOCATION_ARGUMENT_UNCHECKED) != 0 
-						&& method instanceof ParameterizedGenericMethodBinding
-						/*&& method.returnType != scope.environment().convertToRawType(method.returnType.erasure(), true)*/)) {
-			scope.problemReporter().unsafeRawGenericMethodInvocation((ASTNode)invocationSite, method, argumentTypes);
-			return true;
+				|| ((invocationStatus & INVOCATION_ARGUMENT_UNCHECKED) != 0)) {
+			if (method instanceof ParameterizedGenericMethodBinding) {
+				scope.problemReporter().unsafeRawGenericMethodInvocation((ASTNode)invocationSite, method, argumentTypes);
+				return true;
+			}
+			if (sourceLevel >= ClassFileConstants.JDK1_8)
+				return true; // signal to erase return type and exceptions, while keeping javac compatibility at 1.7-
 		}
 		return false;
 	}
@@ -1014,7 +1017,8 @@
 				recipientTargetMask = TagBits.AnnotationForField;
 				break;
 			case Binding.METHOD:
-				recipientTargetMask = TagBits.AnnotationForMethod;
+				MethodBinding method = (MethodBinding) recipient;
+				recipientTargetMask = method.isConstructor() ? TagBits.AnnotationForConstructor : TagBits.AnnotationForMethod;
 				break;
 			default:
 				return;
@@ -1094,6 +1098,8 @@
 								method.tagBits &= ~(se8nullBits);
 							}
 						}
+					} else {
+						method.setTypeAnnotations(se8Annotations);
 					}
 					break;
 			}
@@ -1122,22 +1128,24 @@
 		TypeReference unionRef = typeRef.isUnionType() ? ((UnionTypeReference) typeRef).typeReferences[0] : null;
 		
 		// for arrays: @T X[] SE7 associates @T to the type, but in SE8 it affects the leaf component type
-		long prevNullBits = existingType.leafComponentType().tagBits & TagBits.AnnotationNullMASK;
+		TypeBinding oldLeafType = (unionRef == null) ? existingType.leafComponentType() : unionRef.resolvedType;
+		if (se8nullBits != 0 && oldLeafType.isBaseType()) {
+			scope.problemReporter().illegalAnnotationForBaseType(typeRef, new Annotation[] { se8NullAnnotation }, se8nullBits);
+			return existingType;
+		}
+
+		long prevNullBits = oldLeafType.tagBits & TagBits.AnnotationNullMASK;
 		if ((prevNullBits | se8nullBits) == TagBits.AnnotationNullMASK) { // contradiction after merge?
-			if (!(existingType instanceof TypeVariableBinding)) { // let type-use annotations override annotations on the type parameter declaration
+			if (!(oldLeafType instanceof TypeVariableBinding)) { // let type-use annotations override annotations on the type parameter declaration
 				if (prevNullBits != TagBits.AnnotationNullMASK && se8nullBits != TagBits.AnnotationNullMASK) { // conflict caused by the merge?
 					scope.problemReporter().contradictoryNullAnnotations(se8NullAnnotation);
 				}
 				se8Annotations = Binding.NO_ANNOTATIONS;
 				se8nullBits = 0;
 			}
-			existingType = existingType.withoutToplevelNullAnnotation();
+			oldLeafType = oldLeafType.withoutToplevelNullAnnotation();
 		}
-		TypeBinding oldLeafType = (unionRef == null) ? existingType.leafComponentType() : unionRef.resolvedType;
-		if (se8nullBits != 0 && oldLeafType.isBaseType()) {
-			scope.problemReporter().illegalAnnotationForBaseType(typeRef, new Annotation[] { se8NullAnnotation }, se8nullBits);
-			return existingType;
-		}
+
 		AnnotationBinding [][] goodies = new AnnotationBinding[typeRef.getAnnotatableLevels()][];
 		goodies[0] = se8Annotations;  // @T X.Y.Z local; ==> @T should annotate X
 		TypeBinding newLeafType = scope.environment().createAnnotatedType(oldLeafType, goodies);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
index 28b5382..e3ed770 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -365,6 +365,9 @@
 						flowInfo.markAsDefinitelyNonNull(methodArguments[i].binding);
 					else if (tagBits == TagBits.AnnotationNullable)
 						flowInfo.markPotentiallyNullBit(methodArguments[i].binding);
+					else if (methodBinding.parameters[i].isFreeTypeVariable()) {
+						flowInfo.markNullStatus(methodArguments[i].binding, FlowInfo.FREE_TYPEVARIABLE);
+					}
 				} else {					
 					if (methodBinding.parameterNonNullness != null) {
 						// leverage null-info from parameter annotations:
@@ -829,7 +832,7 @@
 		  if (!(this.isGenerated || this.isCopied))
 // SH}
 			resolveJavadoc();
-			resolveAnnotations(this.scope, this.annotations, this.binding);
+			resolveAnnotations(this.scope, this.annotations, this.binding, this.isConstructor());
 			
 			long sourceLevel = this.scope.compilerOptions().sourceLevel;
 			if (sourceLevel < ClassFileConstants.JDK1_8) // otherwise already checked via Argument.createBinding
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
index 315d40b..4f3b5a2 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
@@ -629,6 +629,10 @@
 			}
 		}
 	}
+	if (compilerOptions.sourceLevel >= ClassFileConstants.JDK1_8 &&
+			this.binding.getTypeAnnotations() != Binding.NO_ANNOTATIONS) {
+		this.resolvedType = scope.environment().createAnnotatedType(this.resolvedType, this.binding.getTypeAnnotations());
+	}
 //{ObjectTeams: may need to wrap the resolved type
     this.resolvedType = RoleTypeCreator.maybeWrapUnqualifiedRoleType(this.resolvedType, scope, this);
 	DependentTypeBinding dependentTypeBinding = this.resolvedType.asPlainDependentType();
@@ -966,6 +970,8 @@
 		if (value != null)
 			((InferenceContext18) value).cleanUp();
 	this.inferenceContexts = null;
+	this.outerInferenceContext = null;
+	this.solutionsPerTargetType = null;
 }
 
 //-- interface InvocationSite: --
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java
index a922eff..6aaaa5c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java
@@ -48,8 +48,6 @@
 	public Annotation [][] annotationsOnDimensions; // jsr308 style annotations.
 	public ArrayInitializer initializer;
 
-	private TypeBinding expectedType;
-
 	public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
 		for (int i = 0, max = this.dimensions.length; i < max; i++) {
 			Expression dim;
@@ -186,21 +184,6 @@
 			{
 				scope.problemReporter().contradictoryNullAnnotations(this.type.annotations[this.type.annotations.length-1]);
 			}
-			LookupEnvironment environment = scope.environment();
-			if (environment.usesNullTypeAnnotations() 
-					&& this.annotationsOnDimensions == null // don't annotate if explicit annotations are given on dimensions ...
-					&& ((referenceType.tagBits & TagBits.AnnotationNullMASK) == 0)  // ... or leaf type
-					&& this.expectedType != null) // need this to determine our action
-			{
-				Expression lastDim = this.dimensions[this.dimensions.length-1];
-				if (lastDim instanceof IntLiteral && ((IntLiteral) lastDim).value == 0) {
-					long tagBit = this.expectedType.leafComponentType().tagBits & TagBits.AnnotationNullMASK;
-					// let new X[0] be seen as "@NonNull X[]", or "@Nullable X[]" just as expected
-					AnnotationBinding[] nullAnnotations = environment.nullAnnotationsFromTagBits(tagBit);
-					if (nullAnnotations != null)
-						referenceType = environment.createAnnotatedType(referenceType, nullAnnotations);
-				}
-			}
 //{ObjectTeams:
             referenceType = RoleTypeCreator.maybeWrapUnqualifiedRoleType(referenceType, scope, this);
 // SH}
@@ -231,10 +214,6 @@
 		return this.resolvedType;
 	}
 
-	@Override
-	public void setExpectedType(TypeBinding expectedType) {
-		this.expectedType = expectedType;
-	}
 
 	public void traverse(ASTVisitor visitor, BlockScope scope) {
 		if (visitor.visit(this, scope)) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
index c520d9a..65a74bc 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
@@ -479,7 +479,7 @@
 				return this.resolvedType = null;
 		}
 		if (isPolyExpression()) {
-			if (this.expectedType == null) {
+			if (this.expectedType == null || !this.expectedType.isProperType(true)) {
 				return new PolyTypeBinding(this);
 			}
 			return this.resolvedType = computeConversions(scope, this.expectedType) ? this.expectedType : null;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java
index fa576fb..a1c18a6 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java
@@ -339,7 +339,7 @@
 								((this.bits & ASTNode.IsDefaultConstructor) != 0)
 									? (ASTNode) this.scope.referenceType().declarationOf(field.original())
 									: this);
-					} else if (field.isNonNull()) {
+					} else if (field.isNonNull() || field.type.isFreeTypeVariable()) {
 						FieldDeclaration fieldDecl = this.scope.referenceType().declarationOf(field.original());
 						if (!isValueProvidedUsingAnnotation(fieldDecl))
 							this.scope.problemReporter().uninitializedNonNullField(
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DoStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DoStatement.java
index cc61fc0..de60c7c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DoStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DoStatement.java
@@ -117,6 +117,13 @@
 		condLoopContext.complainOnDeferredNullChecks(currentScope,
 				actionInfo.addPotentialNullInfoFrom(
 				  condInfo.initsWhenTrue().unconditionalInits()));
+	} else {
+		loopingContext.complainOnDeferredNullChecks(currentScope,
+				flowInfo.unconditionalCopy().addPotentialNullInfoFrom(
+					  condInfo.initsWhenTrue().unconditionalInits()), false);
+		condLoopContext.complainOnDeferredNullChecks(currentScope,
+				actionInfo.addPotentialNullInfoFrom(
+				  condInfo.initsWhenTrue().unconditionalInits()), false);
 	}
 	if (loopingContext.hasEscapingExceptions()) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=321926
 		FlowInfo loopbackFlowInfo = flowInfo.copy();
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java
index e5b0f4d..72bca9a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -194,7 +194,7 @@
 	public int implicitConversion;
 	public TypeBinding resolvedType;
 	
-	static Expression [] NO_EXPRESSIONS = new Expression[0];
+	public static Expression [] NO_EXPRESSIONS = new Expression[0];
 	
 
 public static final boolean isConstantValueRepresentable(Constant constant, int constantTypeID, int targetTypeID) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java
index 680c44b..94110e5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java
@@ -166,7 +166,7 @@
 			// assigning a final field outside an initializer or constructor or wrong reference
 			currentScope.problemReporter().cannotAssignToFinalField(this.binding, this);
 		}
-	} else if (this.binding.isNonNull()) {
+	} else if (this.binding.isNonNull() || this.binding.type.isTypeVariable()) {
 		// in a context where it can be assigned?
 		if (   !isCompound
 			&& this.receiver.isThis()
@@ -195,7 +195,7 @@
 	}
 	if (currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_7) {
 		FieldBinding fieldBinding = this.binding;
-		if (fieldBinding.isBlankFinal() && currentScope.needBlankFinalFieldInitializationCheck(fieldBinding)) {
+		if (this.receiver.isThis() && fieldBinding.isBlankFinal() && currentScope.needBlankFinalFieldInitializationCheck(fieldBinding)) {
 			FlowInfo fieldInits = flowContext.getInitsForFinalBlankInitializationCheck(fieldBinding.declaringClass.original(), flowInfo);
 			if (!fieldInits.isDefinitelyAssigned(fieldBinding)) {
 				currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java
index 4de04c5..6c18cc8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -456,7 +456,7 @@
 			boolean isTargetJsr14 = this.scope.compilerOptions().targetJDK == ClassFileConstants.JDK1_4;
 			if (collectionType.isCapture()) {
 				TypeBinding upperBound = ((CaptureBinding)collectionType).firstBound;
-				if (upperBound.isArrayType())
+				if (upperBound != null && upperBound.isArrayType())
 					collectionType = upperBound; // partially anticipating the fix for https://bugs.openjdk.java.net/browse/JDK-8013843
 			}
 			if (collectionType.isArrayType()) { // for(E e : E[])
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FunctionalExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FunctionalExpression.java
index 9a37592..8dd97dd 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FunctionalExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FunctionalExpression.java
@@ -47,6 +47,7 @@
 import org.eclipse.jdt.internal.compiler.lookup.Scope;
 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
 import org.eclipse.jdt.internal.compiler.lookup.TypeBindingVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
 import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
 
 public abstract class FunctionalExpression extends Expression {
@@ -63,6 +64,7 @@
 	public boolean shouldCaptureInstance = false; // Whether the expression needs access to instance data of enclosing type
 	protected static IErrorHandlingPolicy silentErrorHandlingPolicy = DefaultErrorHandlingPolicies.ignoreAllProblems();
 	private boolean hasReportedSamProblem = false;
+	public boolean isSerializable;
 
 	public FunctionalExpression(CompilationResult compilationResult) {
 		this.compilationResult = compilationResult;
@@ -131,7 +133,7 @@
 		// we simulate an *invocation* of this functional expression,
 		// where the expected type of the expression is the return type of the sam:
 		MethodBinding sam = this.expectedType.getSingleAbstractMethod(this.enclosingScope, true);
-		if (sam != null) {
+		if (sam != null && sam.problemId() != ProblemReasons.NoSuchSingleAbstractMethod) {
 			if (sam.isConstructor())
 				return sam.declaringClass;
 			else
@@ -185,6 +187,17 @@
 		
 		this.descriptor = sam;
 		if (skipKosherCheck || kosherDescriptor(blockScope, sam, true)) {
+			if (this.expectedType instanceof IntersectionTypeBinding18) {
+				ReferenceBinding[] intersectingTypes =  ((IntersectionTypeBinding18)this.expectedType).intersectingTypes;
+				for (int t = 0, max = intersectingTypes.length; t < max; t++) {
+					if (intersectingTypes[t].findSuperTypeOriginatingFrom(TypeIds.T_JavaIoSerializable, false /*Serializable is not a class*/) != null) {
+						this.isSerializable = true;
+						break;
+					}
+				}
+			} else if (this.expectedType.findSuperTypeOriginatingFrom(TypeIds.T_JavaIoSerializable, false /*Serializable is not a class*/) != null) {
+				this.isSerializable = true;
+			}
 			if (blockScope.environment().globalOptions.isAnnotationBasedNullAnalysisEnabled)
 				NullAnnotationMatching.checkForContradictions(sam, this, blockScope);
 			return this.resolvedType = this.expectedType;		
@@ -205,10 +218,6 @@
 				blockScope.problemReporter().illFormedParameterizationOfFunctionalInterface(this);
 				this.hasReportedSamProblem = true;
 				break;
-			case ProblemReasons.IntersectionHasMultipleFunctionalInterfaces:
-				blockScope.problemReporter().multipleFunctionalInterfaces(this);
-				this.hasReportedSamProblem = true;
-				break;
 		}
 		return null;
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Invocation.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Invocation.java
index 2f30eea..89b10ee 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Invocation.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Invocation.java
@@ -42,6 +42,7 @@
 	 */
 	InferenceContext18 getInferenceContext(ParameterizedMethodBinding method);
 
+	/** Discard any state from type inference when compilation is done. */
 	void cleanUpInferenceContexts();
 
 	/** Record result against target type */
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java
index c1eb9be..2477ddb 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java
@@ -65,7 +65,6 @@
 import org.eclipse.jdt.internal.compiler.flow.FlowContext;
 import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
 import org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo;
-import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
 import org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding;
@@ -111,7 +110,6 @@
 	boolean voidCompatible = true;
 	boolean valueCompatible = false;
 	boolean returnsValue;
-	public boolean isSerializable;
 	private boolean requiresGenericSignature;
 	boolean returnsVoid;
 	public LambdaExpression original = this;
@@ -381,7 +379,7 @@
 				this.binding.setParameterAnnotations(parameterAnnotations);
 		}
 	
-		if (!argumentsTypeElided && this.binding.isVarargs()) {
+		if (!argumentsTypeElided && !argumentsHaveErrors && this.binding.isVarargs()) {
 			if (!this.binding.parameters[this.binding.parameters.length - 1].isReifiable()) {
 				this.scope.problemReporter().possibleHeapPollutionFromVararg(this.arguments[this.arguments.length - 1]);
 			}
@@ -435,18 +433,6 @@
 			if (!this.returnsVoid && !this.returnsValue)
 				this.valueCompatible = this.body.doesNotCompleteNormally();
 		}
-		if (this.expectedType instanceof IntersectionTypeBinding18) {
-			ReferenceBinding[] intersectingTypes =  ((IntersectionTypeBinding18)this.expectedType).intersectingTypes;
-			for (int t = 0, max = intersectingTypes.length; t < max; t++) {
-				if (intersectingTypes[t].findSuperTypeOriginatingFrom(TypeIds.T_JavaIoSerializable, false /*Serializable is not a class*/) != null) {
-					this.isSerializable = true;
-					break;
-				}
-			}
-		} else if (this.expectedType != null && 
-				   this.expectedType.findSuperTypeOriginatingFrom(TypeIds.T_JavaIoSerializable, false /*Serializable is not a class*/) != null) {
-			this.isSerializable = true;
-		}
 		if ((this.binding.tagBits & TagBits.HasMissingType) != 0) {
 			this.scope.problemReporter().missingTypeInLambda(this, this.binding);
 		}
@@ -466,9 +452,11 @@
 			if (withWildCards != null) {
 				if (!argumentTypesElided) {
 					InferenceContext18 freshInferenceContext = new InferenceContext18(blockScope);
-					ReferenceBinding inferredType = freshInferenceContext.inferFunctionalInterfaceParameterization(this, blockScope, withWildCards);
-					freshInferenceContext.cleanUp();
-					return inferredType;
+					try {
+						return freshInferenceContext.inferFunctionalInterfaceParameterization(this, blockScope, withWildCards);
+					} finally {
+						freshInferenceContext.cleanUp();
+					}
 				} else {
 					return findGroundTargetTypeForElidedLambda(blockScope, withWildCards);
 				}
@@ -825,6 +813,9 @@
 		// 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.
 		targetType = findGroundTargetType(this.enclosingScope, targetType, argumentsTypeElided());
 		MethodBinding sam = targetType.getSingleAbstractMethod(this.enclosingScope, true);
+		if (sam == null || sam.problemId() == ProblemReasons.NoSuchSingleAbstractMethod) {
+			return false;
+		}
 		if (sam.returnType.id == TypeIds.T_void) {
 			if (!copy.voidCompatible)
 				return false;
@@ -876,10 +867,7 @@
 					copy = this.copiesPerTargetType.values().iterator().next();
 			}
 		}
-		final CompilerOptions compilerOptions = this.enclosingScope.compilerOptions();
-		boolean analyzeNPE = compilerOptions.isAnnotationBasedNullAnalysisEnabled;
 		IErrorHandlingPolicy oldPolicy = this.enclosingScope.problemReporter().switchErrorHandlingPolicy(silentErrorHandlingPolicy);
-		compilerOptions.isAnnotationBasedNullAnalysisEnabled = false;
 		try {
 			if (copy == null) {
 				copy = copy();
@@ -904,7 +892,6 @@
 					copy.analyzeExceptions();
 			return copy;
 		} finally {
-			compilerOptions.isAnnotationBasedNullAnalysisEnabled = analyzeNPE;
 			this.enclosingScope.problemReporter().switchErrorHandlingPolicy(oldPolicy);
 		}
 	}
@@ -959,33 +946,34 @@
 		LambdaExpression copy = cachedResolvedCopy(s, true /* any resolved copy is good */, false, null); // we expect a cached copy - otherwise control won't reach here.
 		Expression [] returnExpressions = copy.resultExpressions;
 		int returnExpressionsLength = returnExpressions == null ? 0 : returnExpressions.length;
-		
-		int i;
-		// r1 is a primitive type, r2 is a reference type, and each result expression is a standalone expression (15.2) of a primitive type
-		if (r1.isBaseType() && !r2.isBaseType()) {
-			for (i = 0; i < returnExpressionsLength; i++) {
-				if (returnExpressions[i].isPolyExpression() || !returnExpressions[i].resolvedType.isBaseType())
-					break;
+		if (returnExpressionsLength > 0) {
+			int i;
+			// r1 is a primitive type, r2 is a reference type, and each result expression is a standalone expression (15.2) of a primitive type
+			if (r1.isBaseType() && !r2.isBaseType()) {
+				for (i = 0; i < returnExpressionsLength; i++) {
+					if (returnExpressions[i].isPolyExpression() || !returnExpressions[i].resolvedType.isBaseType())
+						break;
+				}
+				if (i == returnExpressionsLength)
+					return true;
 			}
-			if (i == returnExpressionsLength)
-				return true;
-		}
-		if (!r1.isBaseType() && r2.isBaseType()) {
-			for (i = 0; i < returnExpressionsLength; i++) {
-				if (returnExpressions[i].resolvedType.isBaseType())
-					break;
+			if (!r1.isBaseType() && r2.isBaseType()) {
+				for (i = 0; i < returnExpressionsLength; i++) {
+					if (returnExpressions[i].resolvedType.isBaseType())
+						break;
+				}
+				if (i == returnExpressionsLength)
+					return true;
 			}
-			if (i == returnExpressionsLength)
-				return true;
-		}
-		if (r1.isFunctionalInterface(this.enclosingScope) && r2.isFunctionalInterface(this.enclosingScope)) {
-			for (i = 0; i < returnExpressionsLength; i++) {
-				Expression resultExpression = returnExpressions[i];
-				if (!resultExpression.sIsMoreSpecific(r1, r2, skope))
-					break;
-			}
-			if (i == returnExpressionsLength)
-				return true;
+			if (r1.isFunctionalInterface(this.enclosingScope) && r2.isFunctionalInterface(this.enclosingScope)) {
+				for (i = 0; i < returnExpressionsLength; i++) {
+					Expression resultExpression = returnExpressions[i];
+					if (!resultExpression.sIsMoreSpecific(r1, r2, skope))
+						break;
+				}
+				if (i == returnExpressionsLength)
+					return true;
+			}	
 		}
 		return false;
 	}
@@ -1074,7 +1062,7 @@
 						parentAST.tagAsHavingErrors();
 						return;
 					}
-					break;
+					//$FALL-THROUGH$
 				default:
 					parent = parent.parent;
 					break;
@@ -1103,7 +1091,6 @@
 			case IProblem.LambdaDescriptorMentionsUnmentionable:
 			case IProblem.TargetTypeNotAFunctionalInterface:
 			case IProblem.illFormedParameterizationOfFunctionalInterface:
-			case IProblem.MultipleFunctionalInterfaces:
 			case IProblem.NoGenericLambda:
 				return;
 			default: 
@@ -1276,17 +1263,15 @@
 	public TypeBinding[] getMarkerInterfaces() {
 		if (this.expectedType instanceof IntersectionTypeBinding18) {
 			Set markerBindings = new LinkedHashSet();
-			TypeBinding[] intersectionTypes = ((IntersectionTypeBinding18)this.expectedType).intersectingTypes;
+			IntersectionTypeBinding18 intersectionType = (IntersectionTypeBinding18)this.expectedType;
+			TypeBinding[] intersectionTypes = intersectionType.intersectingTypes;
+			TypeBinding samType = intersectionType.getSAMType(this.enclosingScope);
 			for (int i = 0,max = intersectionTypes.length; i < max; i++) {
 				TypeBinding typeBinding = intersectionTypes[i];
-				MethodBinding methodBinding = typeBinding.getSingleAbstractMethod(this.scope, true);
-				// Why doesn't getSingleAbstractMethod do as the javadoc says, and return null
-				// when it is not a SAM type
-				if (!(methodBinding instanceof ProblemMethodBinding && ((ProblemMethodBinding)methodBinding).problemId()==ProblemReasons.NoSuchSingleAbstractMethod)) {
-					continue;
-				}
-				if (typeBinding.id == TypeIds.T_JavaIoSerializable) {
-					// Serializable is captured as a bitflag
+				if (!typeBinding.isInterface()							// only interfaces
+					|| TypeBinding.equalsEquals(samType, typeBinding)	// except for the samType itself
+					|| typeBinding.id == TypeIds.T_JavaIoSerializable)	// but Serializable is captured as a bitflag
+				{
 					continue;
 				}
 				markerBindings.add(typeBinding);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
index 72025ff..4d34984 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -500,8 +500,18 @@
 
 public boolean checkNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, int ttlForFieldCheck) {
 	// message send as a receiver
-	if ((nullStatus(flowInfo, flowContext) & FlowInfo.POTENTIALLY_NULL) != 0) // note that flowInfo is not used inside nullStatus(..)
-		scope.problemReporter().messageSendPotentialNullReference(this.binding, this);
+	int nullStatus = nullStatus(flowInfo, flowContext); // note that flowInfo is not used inside nullStatus(..)
+	if ((nullStatus & FlowInfo.POTENTIALLY_NULL) != 0) {
+		if(this.binding.returnType.isTypeVariable() && nullStatus == FlowInfo.FREE_TYPEVARIABLE && scope.environment().globalOptions.pessimisticNullAnalysisForFreeTypeVariablesEnabled) {
+			scope.problemReporter().methodReturnTypeFreeTypeVariableReference(this.binding, this);			
+		} else {
+			scope.problemReporter().messageSendPotentialNullReference(this.binding, this);
+		}
+	} else if ((this.resolvedType.tagBits & TagBits.AnnotationNonNull) != 0) {
+		NullAnnotationMatching nonNullStatus = NullAnnotationMatching.okNonNullStatus(this);
+		if (nonNullStatus.wantToReport())
+			nonNullStatus.report(scope);
+	}
 	return true; // done all possible checking
 }
 /**
@@ -749,7 +759,10 @@
 		// try to retrieve null status of this message send from an annotation of the called method:
 		long tagBits = this.binding.tagBits;
 		if ((tagBits & TagBits.AnnotationNullMASK) == 0L) // alternatively look for type annotation (will only be present in 1.8+):
-			tagBits = this.binding.returnType.tagBits;
+			tagBits = this.binding.returnType.tagBits & TagBits.AnnotationNullMASK;
+		if(tagBits == 0L && this.binding.returnType.isFreeTypeVariable()) {
+			return FlowInfo.FREE_TYPEVARIABLE;
+		}
 		return FlowInfo.tagBitsToNullStatus(tagBits);
 	}
 	return FlowInfo.UNKNOWN;
@@ -1685,6 +1698,8 @@
 		if (value != null)
 			((InferenceContext18) value).cleanUp();
 	this.inferenceContexts = null;
+	this.outerInferenceContext = null;
+	this.solutionsPerTargetType = null;
 }
 public Expression[] arguments() {
 	return this.arguments;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NullAnnotationMatching.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NullAnnotationMatching.java
index 748dcd3..bed1a19 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NullAnnotationMatching.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NullAnnotationMatching.java
@@ -12,11 +12,14 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
+import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.internal.compiler.flow.FlowContext;
 import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding;
 import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
+import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.ExternalAnnotationStatus;
 import org.eclipse.jdt.internal.compiler.lookup.Binding;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 import org.eclipse.jdt.internal.compiler.lookup.CaptureBinding;
@@ -37,6 +40,7 @@
 import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
 import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
 import org.eclipse.jdt.internal.compiler.lookup.WildcardBinding;
+import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
 
 /**
  * Performs matching of null type annotations.
@@ -45,10 +49,10 @@
  */
 public class NullAnnotationMatching {
 	
-	public static final NullAnnotationMatching NULL_ANNOTATIONS_OK = new NullAnnotationMatching(0, FlowInfo.UNKNOWN, null);
-	public static final NullAnnotationMatching NULL_ANNOTATIONS_OK_NONNULL = new NullAnnotationMatching(0, FlowInfo.NON_NULL, null);
-	public static final NullAnnotationMatching NULL_ANNOTATIONS_UNCHECKED = new NullAnnotationMatching(1, FlowInfo.UNKNOWN, null);
-	public static final NullAnnotationMatching NULL_ANNOTATIONS_MISMATCH = new NullAnnotationMatching(2, FlowInfo.UNKNOWN, null);
+	public static final NullAnnotationMatching NULL_ANNOTATIONS_OK = new NullAnnotationMatching(Severity.OK, FlowInfo.UNKNOWN, null);
+	public static final NullAnnotationMatching NULL_ANNOTATIONS_OK_NONNULL = new NullAnnotationMatching(Severity.OK, FlowInfo.NON_NULL, null);
+	public static final NullAnnotationMatching NULL_ANNOTATIONS_UNCHECKED = new NullAnnotationMatching(Severity.UNCHECKED, FlowInfo.UNKNOWN, null);
+	public static final NullAnnotationMatching NULL_ANNOTATIONS_MISMATCH = new NullAnnotationMatching(Severity.MISMATCH, FlowInfo.UNKNOWN, null);
 
 	public enum CheckMode {
 		/** in this mode we check normal assignment compatibility. */
@@ -87,23 +91,44 @@
 		}
 	}
 
-	/** 0 = OK, 1 = unchecked, 2 = definite mismatch */
-	public final int severity;
+	private enum Severity {
+		/** No problem detected. */
+		OK,
+		/** No real problem, but could issue an {@link IProblem#NonNullTypeVariableFromLegacyMethod} or similar. */
+		LEGACY_WARNING,
+		/** Need unchecked conversion from unannotated to annotated. */
+		UNCHECKED,
+		/** Definite nullity mismatch. */
+		MISMATCH;
+
+		public Severity max(Severity severity) {
+			if (compareTo(severity) < 0)
+				return severity;
+			return this;
+		}
+	
+		public boolean isAnyMismatch() {
+			return compareTo(LEGACY_WARNING) > 0;
+		}
+	}
+
+	private final Severity severity;
 	
 	/** If non-null this field holds the supertype of the provided type which was used for direct matching. */
 	public final TypeBinding superTypeHint;
 	public final int nullStatus;
 	
-	public NullAnnotationMatching(int severity, int nullStatus, TypeBinding superTypeHint) {
+	NullAnnotationMatching(Severity severity, int nullStatus, TypeBinding superTypeHint) {
 		this.severity = severity;
 		this.superTypeHint = superTypeHint;
 		this.nullStatus = nullStatus;
 	}
 
-	public boolean isAnyMismatch()      { return this.severity != 0; }
-	public boolean isUnchecked()        { return this.severity == 1; }
-	public boolean isDefiniteMismatch() { return this.severity == 2; }
-	
+	public boolean isAnyMismatch()      { return this.severity.isAnyMismatch(); }
+	public boolean isUnchecked()        { return this.severity == Severity.UNCHECKED; }
+	public boolean isDefiniteMismatch() { return this.severity == Severity.MISMATCH; }
+	public boolean wantToReport() 		{ return this.severity == Severity.LEGACY_WARNING; }
+
 	public boolean isPotentiallyNullMismatch() {
 		return !isDefiniteMismatch() && this.nullStatus != -1 && (this.nullStatus & FlowInfo.POTENTIALLY_NULL) != 0;
 	}
@@ -133,12 +158,16 @@
 				return nullStatus; // if both branches disagree use the precomputed & merged nullStatus
 			}
 			lhsTagBits = var.type.tagBits & TagBits.AnnotationNullMASK;
-			NullAnnotationMatching annotationStatus = analyse(var.type, providedType, nullStatus);
+			NullAnnotationMatching annotationStatus = analyse(var.type, providedType, null, null, nullStatus, expression, CheckMode.COMPATIBLE);
 			if (annotationStatus.isAnyMismatch()) {
 				flowContext.recordNullityMismatch(currentScope, expression, providedType, var.type, flowInfo, nullStatus, annotationStatus);
 				hasReported = true;
-			} else if (annotationStatus.nullStatus != FlowInfo.UNKNOWN) {
-				return annotationStatus.nullStatus;
+			} else {
+				if (annotationStatus.wantToReport())
+					annotationStatus.report(currentScope);
+				if (annotationStatus.nullStatus != FlowInfo.UNKNOWN) {
+					return annotationStatus.nullStatus;
+				}
 			}
 		}
 		if (lhsTagBits == TagBits.AnnotationNonNull && nullStatus != FlowInfo.NON_NULL) {
@@ -161,7 +190,7 @@
 	 * @return a status object representing the severity of mismatching plus optionally a supertype hint
 	 */
 	public static NullAnnotationMatching analyse(TypeBinding requiredType, TypeBinding providedType, int nullStatus) {
-		return analyse(requiredType, providedType, null, null, nullStatus, CheckMode.COMPATIBLE);
+		return analyse(requiredType, providedType, null, null, nullStatus, null, CheckMode.COMPATIBLE);
 	}
 	/**
 	 * Find any mismatches between the two given types, which are caused by null type annotations.
@@ -171,19 +200,22 @@
 	 * 		Pass null if not interested in these added checks.
 	 * @param substitution TODO
 	 * @param nullStatus we are only interested in NULL or NON_NULL, -1 indicates that we are in a recursion, where flow info is ignored
+	 * @param providedExpression optionally holds the provided expression of type 'providedType'
 	 * @param mode controls the kind of check performed (see {@link CheckMode}).
 	 * @return a status object representing the severity of mismatching plus optionally a supertype hint
 	 */
-	public static NullAnnotationMatching analyse(TypeBinding requiredType, TypeBinding providedType, TypeBinding providedSubstitute, Substitution substitution, int nullStatus, CheckMode mode) {
+	public static NullAnnotationMatching analyse(TypeBinding requiredType, TypeBinding providedType, TypeBinding providedSubstitute, Substitution substitution,
+			int nullStatus, Expression providedExpression, CheckMode mode)
+	{
 		if (!requiredType.enterRecursiveFunction())
 			return NullAnnotationMatching.NULL_ANNOTATIONS_OK;
 		try {
-			int severity = 0;
+			Severity severity = Severity.OK;
 			TypeBinding superTypeHint = null;
 			NullAnnotationMatching okStatus = NullAnnotationMatching.NULL_ANNOTATIONS_OK;
 			if (areSameTypes(requiredType, providedType, providedSubstitute)) {
 				if ((requiredType.tagBits & TagBits.AnnotationNonNull) != 0)
-					return NullAnnotationMatching.NULL_ANNOTATIONS_OK_NONNULL;
+					return okNonNullStatus(providedExpression);
 				return okStatus;
 			}
 			if (requiredType instanceof TypeVariableBinding && substitution != null && (mode == CheckMode.EXACT || mode == CheckMode.COMPATIBLE || mode == CheckMode.BOUND_SUPER_CHECK)) {
@@ -193,7 +225,7 @@
 					return NullAnnotationMatching.NULL_ANNOTATIONS_OK;
 				if (areSameTypes(requiredType, providedType, providedSubstitute)) {
 					if ((requiredType.tagBits & TagBits.AnnotationNonNull) != 0)
-						return NullAnnotationMatching.NULL_ANNOTATIONS_OK_NONNULL;
+						return okNonNullStatus(providedExpression);
 					return okStatus;
 				}
 			}
@@ -203,18 +235,18 @@
 					// during bound check against a type variable check the provided type against all upper bounds:
 					TypeBinding superClass = requiredType.superclass();
 					if (superClass != null && (superClass.hasNullTypeAnnotations() || substitution != null)) { // annotations may enter when substituting a nested type variable
-						NullAnnotationMatching status = analyse(superClass, providedType, null, substitution, nullStatus, CheckMode.BOUND_SUPER_CHECK);
-						severity = Math.max(severity, status.severity);
-						if (severity == 2)
+						NullAnnotationMatching status = analyse(superClass, providedType, null, substitution, nullStatus, providedExpression, CheckMode.BOUND_SUPER_CHECK);
+						severity = severity.max(status.severity);
+						if (severity == Severity.MISMATCH)
 							return new NullAnnotationMatching(severity, nullStatus, superTypeHint);
 					}
 					TypeBinding[] superInterfaces = requiredType.superInterfaces();
 					if (superInterfaces != null) {
 						for (int i = 0; i < superInterfaces.length; i++) {
 							if (superInterfaces[i].hasNullTypeAnnotations() || substitution != null) { // annotations may enter when substituting a nested type variable
-								NullAnnotationMatching status = analyse(superInterfaces[i], providedType, null, substitution, nullStatus, CheckMode.BOUND_SUPER_CHECK);
-								severity = Math.max(severity, status.severity);
-								if (severity == 2)
+								NullAnnotationMatching status = analyse(superInterfaces[i], providedType, null, substitution, nullStatus, providedExpression, CheckMode.BOUND_SUPER_CHECK);
+								severity = severity.max(status.severity);
+								if (severity == Severity.MISMATCH)
 									return new NullAnnotationMatching(severity, nullStatus, superTypeHint);
 							}
 						}
@@ -240,11 +272,24 @@
 							} else {
 								if (i > 0)
 									currentNullStatus = -1; // don't use beyond the outermost dimension
-								severity = Math.max(severity, computeNullProblemSeverity(requiredBits, providedBits, currentNullStatus, i == 0 ? mode : mode.toDetail(), false));
-								if (severity == 2)
+								Severity dimSeverity = computeNullProblemSeverity(requiredBits, providedBits, currentNullStatus, i == 0 ? mode : mode.toDetail(), false);
+								if (i > 0 && dimSeverity == Severity.UNCHECKED
+										&& providedExpression instanceof ArrayAllocationExpression
+										&& providedBits == 0 && requiredBits != 0)
+								{
+									Expression[] dimensions = ((ArrayAllocationExpression) providedExpression).dimensions;
+									Expression previousDim = dimensions[i-1];
+									if (previousDim instanceof IntLiteral && previousDim.constant.intValue() == 0) {
+										dimSeverity = Severity.OK; // element of empty dimension matches anything
+										nullStatus = -1;
+										break;
+									}
+								}
+								severity = severity.max(dimSeverity);
+								if (severity == Severity.MISMATCH)
 									return NullAnnotationMatching.NULL_ANNOTATIONS_MISMATCH;
 							}
-							if (severity == 0)
+							if (severity == Severity.OK)
 								nullStatus = -1;
 						}
 					} else if (providedType.id == TypeIds.T_null) {
@@ -258,16 +303,16 @@
 					// at toplevel (having a nullStatus) nullable matches all
 				} else {
 					long providedBits = providedNullTagBits(providedType);
-					int s = computeNullProblemSeverity(requiredBits, providedBits, nullStatus, mode, requiredType.isTypeVariable());
-					severity = Math.max(severity, s);
-					if (severity == 0 && (providedBits & TagBits.AnnotationNonNull) != 0)
-						okStatus = NullAnnotationMatching.NULL_ANNOTATIONS_OK_NONNULL;
+					Severity s = computeNullProblemSeverity(requiredBits, providedBits, nullStatus, mode, requiredType.isTypeVariable());
+					severity = severity.max(s);
+					if (!severity.isAnyMismatch() && (providedBits & TagBits.AnnotationNonNull) != 0)
+						okStatus = okNonNullStatus(providedExpression);
 				}
-				if (severity < 2 && nullStatus != FlowInfo.NULL) {  // null value has no details
+				if (severity != Severity.MISMATCH && nullStatus != FlowInfo.NULL) {  // null value has no details
 					TypeBinding providedSuper = providedType.findSuperTypeOriginatingFrom(requiredType);
 					TypeBinding providedSubstituteSuper = providedSubstitute != null ? providedSubstitute.findSuperTypeOriginatingFrom(requiredType) : null;
-					if(severity == 1 && requiredType.isTypeVariable() && providedType.isTypeVariable() && (providedSuper == requiredType || providedSubstituteSuper == requiredType)) { //$IDENTITY-COMPARISON$
-						severity = 0;
+					if(severity == Severity.UNCHECKED && requiredType.isTypeVariable() && providedType.isTypeVariable() && (providedSuper == requiredType || providedSubstituteSuper == requiredType)) { //$IDENTITY-COMPARISON$
+						severity = Severity.OK;
 					}
 					if (providedSuper != providedType) //$IDENTITY-COMPARISON$
 						superTypeHint = providedSuper;
@@ -278,9 +323,9 @@
 						if (requiredArguments != null && providedArguments != null && requiredArguments.length == providedArguments.length) {
 							for (int i = 0; i < requiredArguments.length; i++) {
 								TypeBinding providedArgSubstitute = providedSubstitutes != null ? providedSubstitutes[i] : null;
-								NullAnnotationMatching status = analyse(requiredArguments[i], providedArguments[i], providedArgSubstitute, substitution, -1, mode.toDetail());
-								severity = Math.max(severity, status.severity);
-								if (severity == 2)
+								NullAnnotationMatching status = analyse(requiredArguments[i], providedArguments[i], providedArgSubstitute, substitution, -1, providedExpression, mode.toDetail());
+								severity = severity.max(status.severity);
+								if (severity == Severity.MISMATCH)
 									return new NullAnnotationMatching(severity, nullStatus, superTypeHint);
 							}
 						}
@@ -289,18 +334,45 @@
 					TypeBinding providedEnclosing = providedType.enclosingType();
 					if (requiredEnclosing != null && providedEnclosing != null) {
 						TypeBinding providedEnclSubstitute = providedSubstitute != null ? providedSubstitute.enclosingType() : null;
-						NullAnnotationMatching status = analyse(requiredEnclosing, providedEnclosing, providedEnclSubstitute, substitution, -1, mode);
-						severity = Math.max(severity, status.severity);
+						NullAnnotationMatching status = analyse(requiredEnclosing, providedEnclosing, providedEnclSubstitute, substitution, -1, providedExpression, mode);
+						severity = severity.max(status.severity);
 					}
 				}
 			}
-			if (severity == 0)
+			if (!severity.isAnyMismatch())
 				return okStatus;
 			return new NullAnnotationMatching(severity, nullStatus, superTypeHint);
 		} finally {
 			requiredType.exitRecursiveFunction();
 		}
 	}
+	public void report(Scope scope) {
+		// nop
+	}
+	public static NullAnnotationMatching okNonNullStatus(final Expression providedExpression) {
+		if (providedExpression instanceof MessageSend) {
+			final MethodBinding method = ((MessageSend) providedExpression).binding;
+			if (method != null && method.isValidBinding()) {
+				MethodBinding originalMethod = method.original();
+				TypeBinding originalDeclaringClass = originalMethod.declaringClass;
+				if (originalDeclaringClass instanceof BinaryTypeBinding 
+						&& ((BinaryTypeBinding) originalDeclaringClass).externalAnnotationStatus.isPotentiallyUnannotatedLib()
+						&& originalMethod.returnType.isTypeVariable()
+						&& (originalMethod.returnType.tagBits & TagBits.AnnotationNullMASK) == 0)
+				{
+					final int severity = ((BinaryTypeBinding) originalDeclaringClass).externalAnnotationStatus == ExternalAnnotationStatus.NO_EEA_FILE
+												? ProblemSeverities.Warning : ProblemSeverities.Info; // reduce severity if not configured to for external annotations
+					return new NullAnnotationMatching(Severity.LEGACY_WARNING, FlowInfo.UNKNOWN, null) {
+						@Override
+						public void report(Scope scope) {
+							scope.problemReporter().nonNullTypeVariableInUnannotatedBinary(scope.environment(), method, providedExpression, severity);
+						}
+					};
+				}
+			}
+		}
+		return NullAnnotationMatching.NULL_ANNOTATIONS_OK_NONNULL;
+	}
 
 	/** Are both types identical wrt the unannotated type and any null type annotations? Only unstructured types and captures are considered. */
 	protected static boolean areSameTypes(TypeBinding requiredType, TypeBinding providedType, TypeBinding providedSubstitute) {
@@ -313,14 +385,14 @@
 				// when providing exactly the lower bound of the required type we're definitely fine:
 				TypeBinding lowerBound = ((CaptureBinding)requiredType).lowerBound;
 				if (lowerBound != null && areSameTypes(lowerBound, providedType, providedSubstitute))
-					return true;
+					return (requiredType.tagBits & TagBits.AnnotationNullMASK) == (providedType.tagBits & TagBits.AnnotationNullMASK);
 			} else if (requiredType.kind() == Binding.TYPE_PARAMETER && requiredType == providedSubstitute) { //$IDENTITY-COMPARISON$
 				return true;
 			} else if (providedType instanceof CaptureBinding) {
 				// when requiring exactly the upper bound of the provided type we're fine, too:
 				TypeBinding upperBound = ((CaptureBinding)providedType).upperBound();
 				if (upperBound != null && areSameTypes(requiredType, upperBound, providedSubstitute))
-					return true;
+					return (requiredType.tagBits & TagBits.AnnotationNullMASK) == (providedType.tagBits & TagBits.AnnotationNullMASK);
 			}
 			return false;
 		}
@@ -369,7 +441,8 @@
 			switch (mode) {
 				case BOUND_CHECK: // no pessimistic checks during boundcheck (we *have* the instantiation)
 				case BOUND_SUPER_CHECK:
-				case OVERRIDE_RETURN: // allow covariance
+				case OVERRIDE: 	  // no pessimistic checks during override check (comparing two *declarations*)
+				case OVERRIDE_RETURN:
 					break;
 				default:
 					return TagBits.AnnotationNonNull; // instantiation could require @NonNull
@@ -467,41 +540,41 @@
 	 * @param requiredIsTypeVariable is the required type a type variable (possibly: "free type variable")?
 	 * @return see {@link #severity} for interpretation of values
 	 */
-	private static int computeNullProblemSeverity(long requiredBits, long providedBits, int nullStatus, CheckMode mode, boolean requiredIsTypeVariable) {
+	private static Severity computeNullProblemSeverity(long requiredBits, long providedBits, int nullStatus, CheckMode mode, boolean requiredIsTypeVariable) {
 		if (requiredBits == providedBits)
-			return 0;
+			return Severity.OK;
 		if (requiredBits == 0) { 
 			switch (mode) {
 				case COMPATIBLE:
 				case BOUND_CHECK:
 				case BOUND_SUPER_CHECK:
 				case EXACT:
-					return 0;
+					return Severity.OK;
 				case OVERRIDE_RETURN:
 					if (providedBits == TagBits.AnnotationNonNull)
-						return 0; // covariant redefinition to nonnull is good
+						return Severity.OK; // covariant redefinition to nonnull is good
 					if (!requiredIsTypeVariable)
-						return 0; // refining an unconstrained non-TVB return to nullable is also legal
-					return 1;
+						return Severity.OK; // refining an unconstrained non-TVB return to nullable is also legal
+					return Severity.UNCHECKED;
 				case OVERRIDE:
-					return 1; // warn about dropped annotation
+					return Severity.UNCHECKED; // warn about dropped annotation
 			}
 		} else if (requiredBits == TagBits.AnnotationNullMASK) {
-			return 0; // OK since LHS accepts either
+			return Severity.OK; // OK since LHS accepts either
 		} else if (requiredBits == TagBits.AnnotationNonNull) {
 			switch (mode) {
 				case COMPATIBLE:
 				case BOUND_SUPER_CHECK:
 					if (nullStatus == FlowInfo.NON_NULL)
-						return 0; // OK by flow analysis
+						return Severity.OK; // OK by flow analysis
 					//$FALL-THROUGH$
 				case BOUND_CHECK:
 				case EXACT:
 				case OVERRIDE_RETURN:
 				case OVERRIDE:
 					if (providedBits == 0)
-						return 1;
-					return 2;
+						return Severity.UNCHECKED;
+					return Severity.MISMATCH;
 			}
 			
 		} else if (requiredBits == TagBits.AnnotationNullable) {
@@ -509,17 +582,17 @@
 				case COMPATIBLE:
 				case OVERRIDE_RETURN:
 				case BOUND_SUPER_CHECK:
-					return 0; // in these modes everything is compatible to nullable
+					return Severity.OK; // in these modes everything is compatible to nullable
 				case BOUND_CHECK:
 				case EXACT:
 					if (providedBits == 0)
-						return 1;
-					return 2;
+						return Severity.UNCHECKED;
+					return Severity.MISMATCH;
 				case OVERRIDE:
-					return 2;
+					return Severity.MISMATCH;
 			}
 		}
-		return 0; // shouldn't get here, requiredBits should be one of the listed cases
+		return Severity.OK; // shouldn't get here, requiredBits should be one of the listed cases
 	}
 
 	static class SearchContradictions extends TypeBindingVisitor {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
index 47c4410..d62204a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
@@ -377,6 +377,10 @@
 					}
 				}
 			}
+			if (compilerOptions.sourceLevel >= ClassFileConstants.JDK1_8 &&
+					this.binding.getTypeAnnotations() != Binding.NO_ANNOTATIONS) {
+				this.resolvedType = scope.environment().createAnnotatedType(this.resolvedType, this.binding.getTypeAnnotations());
+			}
 		}
 		return result;
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Reference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Reference.java
index a8cff6c..a80776c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Reference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Reference.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -83,6 +83,10 @@
 		if ((field.type.tagBits & TagBits.AnnotationNullable) != 0) {
 			scope.problemReporter().dereferencingNullableExpression(sourcePosition, scope.environment());
 			return true;
+		} 
+		if (field.type.isFreeTypeVariable()) {
+			scope.problemReporter().fieldFreeTypeVariableReference(field, sourcePosition);
+			return true;
 		}
 		if ((field.tagBits & TagBits.AnnotationNullable) != 0) {
 			scope.problemReporter().nullableFieldDereference(field, sourcePosition);
@@ -170,6 +174,8 @@
 			return FlowInfo.NON_NULL;
 		} else if (fieldBinding.isNullable()) {
 			return FlowInfo.POTENTIALLY_NULL;
+		} else if (fieldBinding.type.isFreeTypeVariable()) {
+			return FlowInfo.FREE_TYPEVARIABLE;
 		}
 	}
 	if (this.resolvedType != null) {
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 a7d145d..2fe6be3 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
@@ -103,7 +103,7 @@
 	public int nameSourceStart;
 
 	public TypeBinding receiverType;
-	private boolean haveReceiver;
+	public boolean haveReceiver;
 	public TypeBinding[] resolvedTypeArguments;
 	private boolean typeArgumentsHaveErrors;
 	
@@ -264,8 +264,7 @@
 		// these cases are either too complicated, impossible to handle or result in significant code duplication 
 		return (this.binding.isVarargs() || 
 				(isConstructorReference() && this.receiverType.syntheticOuterLocalVariables() != null && this.shouldCaptureInstance) ||
-				this.expectedType instanceof IntersectionTypeBinding18 || // marker interfaces require alternate meta factory.
-				this.expectedType.findSuperTypeOriginatingFrom(currentScope.getJavaIoSerializable()) != null || // serialization support.
+				this.expectedType instanceof IntersectionTypeBinding18 || // marker interfaces require alternate meta factory. 
 				this.requiresBridges()); // bridges.
 		// To fix: We should opt for direct code generation wherever possible.
 	}
@@ -296,7 +295,9 @@
 				}
 			}
 		}
-		
+		if (this.isSerializable) {
+			sourceType.addSyntheticMethod(this);
+		}
 		int pc = codeStream.position;
 		StringBuffer buffer = new StringBuffer();
 		int argumentsSize = 0;
@@ -342,6 +343,7 @@
 				}
 				if (this.syntheticAccessor != null) {
 					this.binding = sourceType.addSyntheticFactoryMethod(this.binding, this.syntheticAccessor, enclosingInstances);
+					this.syntheticAccessor = null; // add only once
 				}
 			}
 		}
@@ -849,7 +851,7 @@
 	public ReferenceExpression resolveExpressionExpecting(TypeBinding targetType, Scope scope, InferenceContext18 inferenceContext) {
 		if (this.exactMethodBinding != null) { // We may see inference variables in target type.
 			MethodBinding functionType = targetType.getSingleAbstractMethod(scope, true);
-			if (functionType == null)
+			if (functionType == null || functionType.problemId() == ProblemReasons.NoSuchSingleAbstractMethod)
 				return null;
 			int n = functionType.parameters.length;
 			int k = this.exactMethodBinding.parameters.length;
@@ -990,7 +992,7 @@
 		final MethodBinding sam = targetType.getSingleAbstractMethod(this.enclosingScope, true);
 		if (sam == null || !sam.isValidBinding())
 			return false;
-		if (this.typeArgumentsHaveErrors || this.lhs.resolvedType == null || !this.lhs.resolvedType.isValidBinding())
+		if (this.typeArgumentsHaveErrors || this.receiverType == null || !this.receiverType.isValidBinding())
 			return false;
 		
 		int parametersLength = sam.parameters.length;
@@ -1104,7 +1106,14 @@
 		if (tSam == null || !tSam.isValidBinding())
 			return false;
 		TypeBinding r2 = tSam.returnType;
-		
+
+		TypeBinding[] sParams = sSam.parameters;
+		TypeBinding[] tParams = tSam.parameters;
+		// Both must have the same number of parameters if we got this far
+		for (int i = 0; i < sParams.length; i++) {
+			if (TypeBinding.notEquals(sParams[i], tParams[i]))
+				return false;
+		}
 		if (r2.id == TypeIds.T_void)
 			return true;
 		
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java
index 9f7216e..c019c03 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -147,7 +147,7 @@
 				} else {
 					currentScope.problemReporter().cannotAssignToFinalField(fieldBinding, this);
 				}
-			} else if (!isCompound && fieldBinding.isNonNull()
+			} else if (!isCompound && (fieldBinding.isNonNull() || fieldBinding.type.isTypeVariable())
 						&& TypeBinding.equalsEquals(fieldBinding.declaringClass, currentScope.enclosingReceiverType())) { // inherited fields are not tracked here
 				// record assignment for detecting uninitialized non-null fields:
 				flowInfo.markAsDefinitelyAssigned(fieldBinding);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java
index 12d85d5..e22b0fd 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -42,6 +42,7 @@
 
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.ast.NullAnnotationMatching.CheckMode;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
@@ -222,11 +223,15 @@
 }
 private void internalCheckAgainstNullTypeAnnotation(BlockScope scope, TypeBinding requiredType, Expression expression,
 		int nullStatus, FlowContext flowContext, FlowInfo flowInfo) {
-	NullAnnotationMatching annotationStatus = NullAnnotationMatching.analyse(requiredType, expression.resolvedType, nullStatus);
+	NullAnnotationMatching annotationStatus = NullAnnotationMatching.analyse(requiredType, expression.resolvedType, null, null, nullStatus, expression, CheckMode.COMPATIBLE);
 	if (annotationStatus.isDefiniteMismatch()) {
 		scope.problemReporter().nullityMismatchingTypeAnnotation(expression, expression.resolvedType, requiredType, annotationStatus);
-	} else if (annotationStatus.isUnchecked()) {
-		flowContext.recordNullityMismatch(scope, expression, expression.resolvedType, requiredType, flowInfo, nullStatus, annotationStatus);
+	} else {
+		if (annotationStatus.wantToReport())
+			annotationStatus.report(scope);
+		if (annotationStatus.isUnchecked()) {
+			flowContext.recordNullityMismatch(scope, expression, expression.resolvedType, requiredType, flowInfo, nullStatus, annotationStatus);
+		}
 	}
 }
 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java
index 0101b0d..77064d2 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java
@@ -857,7 +857,7 @@
 	if (variables != null && variables.length > rank) {
 		TypeBinding variable = variables[rank];
 		if (variable.hasNullTypeAnnotations()) {
-			if (NullAnnotationMatching.analyse(variable, this.resolvedType, null, substitution, -1, CheckMode.BOUND_CHECK).isAnyMismatch())
+			if (NullAnnotationMatching.analyse(variable, this.resolvedType, null, substitution, -1, null, CheckMode.BOUND_CHECK).isAnyMismatch())
 				scope.problemReporter().nullityMismatchTypeArgument(variable, this.resolvedType, this);
     	}
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java
index f8fc493..a215dda 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java
@@ -129,6 +129,11 @@
 				if ((combinedTagBits & FlowInfo.UNREACHABLE_OR_DEAD) != 0)
 					this.continueLabel = null;
 				exitBranch.addInitializationsFrom(condInfo.initsWhenFalse());
+				actionInfo = actionInfo.mergedWith(loopingContext.initsOnContinue.unconditionalInits());
+				condLoopContext.complainOnDeferredNullChecks(currentScope,
+						actionInfo, false);
+				loopingContext.complainOnDeferredNullChecks(currentScope,
+						actionInfo, false);
 			} else {
 				condLoopContext.complainOnDeferredFinalChecks(currentScope,
 						condInfo);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java
index 4828a69..5b5d2a1 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java
@@ -41,6 +41,7 @@
 import org.eclipse.jdt.internal.compiler.lookup.TagBits;
 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
 import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
+import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.ExternalAnnotationStatus;
 import org.eclipse.jdt.internal.compiler.util.Util;
 import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
 import org.eclipse.objectteams.otdt.internal.core.compiler.bytecode.*;
@@ -94,6 +95,7 @@
 	private int enclosingNameAndTypeIndex;
 	private char[] enclosingMethod;
 	private ExternalAnnotationProvider annotationProvider;
+	private ExternalAnnotationStatus externalAnnotationStatus = ExternalAnnotationStatus.NOT_EEA_CONFIGURED;
 
 private static String printTypeModifiers(int modifiers) {
 	java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream();
@@ -546,6 +548,7 @@
  *		this is unexpected.
  */
 public ZipFile setExternalAnnotationProvider(String basePath, String qualifiedBinaryTypeName, ZipFile zipFile, ZipFileProducer producer) throws IOException {
+	this.externalAnnotationStatus = ExternalAnnotationStatus.NO_EEA_FILE;
 	String qualifiedBinaryFileName = qualifiedBinaryTypeName + ExternalAnnotationProvider.ANNOTATION_FILE_SUFFIX;
 	if (zipFile == null) {
 		File annotationBase = new File(basePath);
@@ -553,6 +556,7 @@
 			try {
 				String filePath = annotationBase.getAbsolutePath()+'/'+qualifiedBinaryFileName;
 				this.annotationProvider = new ExternalAnnotationProvider(new FileInputStream(filePath), String.valueOf(getName()));
+				this.externalAnnotationStatus = ExternalAnnotationStatus.TYPE_IS_ANNOTATED;
 			} catch (FileNotFoundException e) {
 				// expected, no need to report an error here
 			}
@@ -563,14 +567,22 @@
 		zipFile = (producer != null ? producer.produce() : new ZipFile(annotationBase));
 	}
 	ZipEntry entry = zipFile.getEntry(qualifiedBinaryFileName);
-	if (entry != null)
+	if (entry != null) {
 		this.annotationProvider = new ExternalAnnotationProvider(zipFile.getInputStream(entry), String.valueOf(getName()));
+		this.externalAnnotationStatus = ExternalAnnotationStatus.TYPE_IS_ANNOTATED;
+	}
 	return zipFile;
 }
 public boolean hasAnnotationProvider() {
 	return this.annotationProvider != null;
 }
-
+public void markAsFromSource() {
+	this.externalAnnotationStatus = ExternalAnnotationStatus.FROM_SOURCE;
+}
+@Override
+public ExternalAnnotationStatus getExternalAnnotationStatus() {
+	return this.externalAnnotationStatus;
+}
 /**
  * Conditionally add external annotations to the mix.
  * If 'member' is given it must be either of IBinaryField or IBinaryMethod, in which case we're seeking annotations for that member.
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ExternalAnnotationProvider.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ExternalAnnotationProvider.java
index cbb2bc1..f58c49c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ExternalAnnotationProvider.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ExternalAnnotationProvider.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2014, 2015 GK Software AG.
+ * Copyright (c) 2014, 2016 GK Software AG.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -30,7 +30,7 @@
 
 public class ExternalAnnotationProvider {
 
-	public static final String ANNOTION_FILE_EXTENSION= "eea"; //$NON-NLS-1$
+	public static final String ANNOTATION_FILE_EXTENSION= "eea"; //$NON-NLS-1$
 	public static final String CLASS_PREFIX = "class "; //$NON-NLS-1$
 	public static final String SUPER_PREFIX = "super "; //$NON-NLS-1$
 
@@ -46,7 +46,7 @@
 	 */
 	public static final char NO_ANNOTATION = '@';
 
-	static final String ANNOTATION_FILE_SUFFIX = ".eea"; //$NON-NLS-1$
+	public static final String ANNOTATION_FILE_SUFFIX = ".eea"; //$NON-NLS-1$
 
 	private static final String TYPE_PARAMETER_PREFIX = " <"; //$NON-NLS-1$
 
@@ -69,8 +69,7 @@
 	}
 
 	private void initialize(InputStream input) throws IOException {
-		LineNumberReader reader = new LineNumberReader(new InputStreamReader(input));
-		try {
+		try (LineNumberReader reader = new LineNumberReader(new InputStreamReader(input))) {
 			assertClassHeader(reader.readLine(), this.typeName);
 
 			String line;
@@ -137,8 +136,6 @@
 					this.fieldAnnotationSources.put(selector+':'+rawSig, annotSig);
 				}
 			} while (((line = pendingLine) != null) || (line = reader.readLine()) != null);
-		} finally {
-			reader.close();
 		}
 	}
 
@@ -402,7 +399,7 @@
 						}
 				}				
 			}
-			return null;
+			return NO_ANNOTATIONS;
 		}
 	}
 
@@ -441,6 +438,19 @@
 								if ((depth == 0) && (i +1 < length) && (this.source[i+1] != Util.C_COLON))
 									pendingVariable = true;
 								break;
+							case Util.C_COLON :
+								if (depth == 0)
+									pendingVariable = true; // end of variable name
+								// skip optional bound ReferenceTypeSignature
+								i++; // peek next
+								while (i < length && this.source[i] == Util.C_ARRAY)
+									i++;
+								if (i < length && this.source[i] == Util.C_RESOLVED) {
+									while (i < length && this.source[i] != Util.C_NAME_END)
+										i++;
+								}
+								i--; // unget
+								break;
 							default:
 								if (pendingVariable) {
 									pendingVariable = false;
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 9fa7cbf..f6092ac 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
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2014 GK Software AG.
+ * Copyright (c) 2014, 2016 GK Software AG.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -176,7 +176,7 @@
 
 	@Override
 	public IBinaryAnnotation[] getAnnotationsAtCursor(int currentTypeId) {
-		IBinaryAnnotation[] normalAnnotations = this.isEmpty ? null : super.getAnnotationsAtCursor(currentTypeId);
+		IBinaryAnnotation[] normalAnnotations = this.isEmpty ? NO_ANNOTATIONS : super.getAnnotationsAtCursor(currentTypeId);
 		if (this.atDefaultLocation &&
 				!(currentTypeId == -1) && // never apply default on type variable use or wildcard
 				!(this.atTypeBound && currentTypeId == TypeIds.T_JavaLangObject)) // for CLIMB-to-top consider a j.l.Object type bound as no explicit type bound
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java
index eb58e53..50e87a8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -45,8 +45,10 @@
 import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
 import org.eclipse.jdt.internal.compiler.ast.Expression;
 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.FunctionalExpression;
 import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
 import org.eclipse.jdt.internal.compiler.ast.OperatorIds;
+import org.eclipse.jdt.internal.compiler.ast.ReferenceExpression;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.TypeReference;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
@@ -2590,28 +2592,24 @@
 public void generateSyntheticBodyForDeserializeLambda(SyntheticMethodBinding methodBinding,SyntheticMethodBinding[] syntheticMethodBindings) {
 	initializeMaxLocals(methodBinding);
 
-	// Compute the list of the serializable lambdas from the full set of synthetic method bindings
-	// Also compute a map of hashcodes to a list of serializable lambdas whose names share a hashcode 
-	List syntheticsForSerializableLambdas = new ArrayList();	
-	Map hashcodesToLambdas = new LinkedHashMap();
+	// Compute a map of hashcodes to a list of synthetic methods whose names share a hashcode 
+	Map hashcodesTosynthetics = new LinkedHashMap();
 	for (int i=0,max=syntheticMethodBindings.length;i<max;i++) {
 		SyntheticMethodBinding syntheticMethodBinding = syntheticMethodBindings[i];
-		if (syntheticMethodBinding.lambda!=null && syntheticMethodBinding.lambda.isSerializable) {
-			syntheticsForSerializableLambdas.add(syntheticMethodBinding);
+		if (syntheticMethodBinding.lambda!=null && syntheticMethodBinding.lambda.isSerializable ||
+				syntheticMethodBinding.serializableMethodRef != null) {
 			// TODO can I use > Java 1.4 features here?
 			Integer hashcode = new Integer(new String(syntheticMethodBinding.selector).hashCode());
-			List lambdasForThisHashcode = (List)hashcodesToLambdas.get(hashcode);
-			if (hashcodesToLambdas.get(hashcode)==null) {
-				lambdasForThisHashcode = new ArrayList();
-				hashcodesToLambdas.put(hashcode,lambdasForThisHashcode);
+			List syntheticssForThisHashcode = (List)hashcodesTosynthetics.get(hashcode);
+			if (syntheticssForThisHashcode==null) {
+				syntheticssForThisHashcode = new ArrayList();
+				hashcodesTosynthetics.put(hashcode,syntheticssForThisHashcode);
 			}
-			lambdasForThisHashcode.add(syntheticMethodBinding);
+			syntheticssForThisHashcode.add(syntheticMethodBinding);
 		}
 	}
-	int lambdaCount = syntheticsForSerializableLambdas.size();
 	ClassScope scope = ((SourceTypeBinding)methodBinding.declaringClass).scope;
 	
-	
 	// Generate the first switch, on method name hashcode
 	aload_0();
 	invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName, ConstantPool.GetImplMethodName, ConstantPool.GetImplMethodNameSignature);
@@ -2629,11 +2627,11 @@
 	
 	BranchLabel label = new BranchLabel(this);
 	CaseLabel defaultLabel = new CaseLabel(this);
-	int numberOfHashcodes = hashcodesToLambdas.size();
+	int numberOfHashcodes = hashcodesTosynthetics.size();
 	CaseLabel[] switchLabels = new CaseLabel[numberOfHashcodes];
 	int[] keys = new int[numberOfHashcodes];
 	int[] sortedIndexes = new int[numberOfHashcodes];
-	Set hashcodes = hashcodesToLambdas.keySet();
+	Set hashcodes = hashcodesTosynthetics.keySet();
 	Iterator hashcodeIterator = hashcodes.iterator();
 	int index=0;
 	while (hashcodeIterator.hasNext()) {
@@ -2653,152 +2651,185 @@
 	index = 0;
 	while (hashcodeIterator.hasNext()) {
 		Integer hashcode = (Integer)hashcodeIterator.next();
-		List lambdas = (List)hashcodesToLambdas.get(hashcode);
+		List synthetics = (List)hashcodesTosynthetics.get(hashcode);
 		switchLabels[index].place();
 		BranchLabel nextOne = new BranchLabel(this);
 		// Loop through all lambdas that share the same hashcode
-		for (int j=0,max=lambdas.size();j<max;j++) {
-			SyntheticMethodBinding syntheticMethodBinding = (SyntheticMethodBinding)lambdas.get(j);
+		// TODO: isn't doing this for just one of these enough because they all share
+		// the same name?
+		for (int j=0,max=synthetics.size();j<max;j++) {
+			SyntheticMethodBinding syntheticMethodBinding = (SyntheticMethodBinding)synthetics.get(j);
 			aload_1();
 			ldc(new String(syntheticMethodBinding.selector));
 			invokeStringEquals();
 			ifeq(nextOne);
-			loadInt(index++);
+			loadInt(index);
 			istore_2();
 			goto_(label);
 			nextOne.place();
 			nextOne = new BranchLabel(this);
 		}
+		index++;
 		goto_(label);
 	}
 	defaultLabel.place();
 	label.place();
-	
+	int syntheticsCount = hashcodes.size();
 	// Second block is switching on the lambda id, -1 is the error (unrecognized) case
-	switchLabels = new CaseLabel[lambdaCount];
-	keys = new int[lambdaCount];
-	sortedIndexes = new int[lambdaCount];
+	switchLabels = new CaseLabel[syntheticsCount];
+	keys = new int[syntheticsCount];
+	sortedIndexes = new int[syntheticsCount];
 	BranchLabel errorLabel = new BranchLabel(this);
 	defaultLabel = new CaseLabel(this);
 	iload_2();
-	for (int j=0;j<lambdaCount;j++) {
+	for (int j=0;j<syntheticsCount;j++) {
 		switchLabels[j] = new CaseLabel(this);
 		keys[j] = j;
 		sortedIndexes[j] = j;
 	}
-	System.arraycopy(keys,0,(localKeysCopy = new int[lambdaCount]),0,lambdaCount);
+	System.arraycopy(keys,0,(localKeysCopy = new int[syntheticsCount]),0,syntheticsCount);
 	// TODO no need to sort here? They should all be in order
-	sort(localKeysCopy, 0, lambdaCount-1, sortedIndexes);
+	sort(localKeysCopy, 0, syntheticsCount-1, sortedIndexes);
 	// TODO need to use a tableswitch at some size threshold?
 	lookupswitch(defaultLabel, keys, sortedIndexes, switchLabels);
-	for (int i=0;i<lambdaCount;i++) {
-		SyntheticMethodBinding syntheticMethodBinding = (SyntheticMethodBinding)syntheticsForSerializableLambdas.get(i);
-		switchLabels[i].place();
-		
-		// Compare ImplMethodKind
-		aload_0();
-		LambdaExpression lambdaEx = syntheticMethodBinding.lambda;
-		MethodBinding mb = lambdaEx.binding;
-		invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName, 
-				ConstantPool.GetImplMethodKind, ConstantPool.GetImplMethodKindSignature);
-		byte methodKind = 0;
-		if (mb.isStatic()) {
-			methodKind = ClassFileConstants.MethodHandleRefKindInvokeStatic;
-		} else if (mb.isPrivate()) {
-			methodKind = ClassFileConstants.MethodHandleRefKindInvokeSpecial;
-		} else {
-			methodKind = ClassFileConstants.MethodHandleRefKindInvokeVirtual;
-		}
-		bipush(methodKind);// TODO see table below
-		if_icmpne(errorLabel);
-
-		// Compare FunctionalInterfaceClass
-		aload_0();
-		invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName, 
-				ConstantPool.GetFunctionalInterfaceClass, ConstantPool.GetFunctionalInterfaceClassSignature);
-		String functionalInterface = null;
-		final TypeBinding expectedType = lambdaEx.expectedType();
-		if (expectedType instanceof IntersectionTypeBinding18) {
-			functionalInterface = new String(((IntersectionTypeBinding18)expectedType).getSAMType(scope).constantPoolName());
-		} else {
-			functionalInterface = new String(expectedType.constantPoolName());
-		}
-		ldc(functionalInterface);// e.g. "com/foo/X$Foo"
-		invokeObjectEquals();
-		ifeq(errorLabel);
-		
-		// Compare FunctionalInterfaceMethodName
-		aload_0();
-		invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName, 
-				ConstantPool.GetFunctionalInterfaceMethodName, ConstantPool.GetFunctionalInterfaceMethodNameSignature);
-		ldc(new String(lambdaEx.descriptor.selector)); // e.g. "m"
-		invokeObjectEquals();
-		ifeq(errorLabel);
-
-		// Compare FunctionalInterfaceMethodSignature
-		aload_0();
-		invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName, 
-				ConstantPool.GetFunctionalInterfaceMethodSignature, ConstantPool.GetFunctionalInterfaceMethodSignatureSignature);
-		ldc(new String(lambdaEx.descriptor.original().signature())); // e.g "()I"
-		invokeObjectEquals();
-		ifeq(errorLabel);
-
-		// Compare ImplClass
-		aload_0();
-		invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName, 
-				ConstantPool.GetImplClass, ConstantPool.GetImplClassSignature);
-		ldc(new String(mb.declaringClass.constantPoolName())); // e.g. "com/foo/X"
-		invokeObjectEquals();
-		ifeq(errorLabel);
-
-		// Compare ImplMethodSignature
-		aload_0();
-		invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName, 
-				ConstantPool.GetImplMethodSignature, ConstantPool.GetImplMethodSignatureSignature);
-		ldc(new String(mb.signature())); // e.g. "(I)I"
-		invokeObjectEquals();
-		ifeq(errorLabel);
-
-		// Captured arguments
-		StringBuffer sig = new StringBuffer("("); //$NON-NLS-1$
-		index = 0;
-		if (lambdaEx.shouldCaptureInstance) {
+	hashcodeIterator = hashcodes.iterator();
+	int hashcodeIndex = 0;
+	while (hashcodeIterator.hasNext()) {
+		Integer hashcode = (Integer)hashcodeIterator.next();
+		List synthetics = (List)hashcodesTosynthetics.get(hashcode);
+		switchLabels[hashcodeIndex++].place();
+		BranchLabel nextOne = synthetics.size() > 1 ? new BranchLabel(this) : errorLabel;
+		// Loop through all lambdas that share the same hashcode
+		for (int j = 0, count = synthetics.size(); j < count; j++) {
+			SyntheticMethodBinding syntheticMethodBinding = (SyntheticMethodBinding) synthetics.get(j);
+			// Compare ImplMethodKind
 			aload_0();
-			loadInt(index++);
-			invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName, 
-					ConstantPool.GetCapturedArg, ConstantPool.GetCapturedArgSignature);
-			checkcast(mb.declaringClass);
-			sig.append(mb.declaringClass.signature());
-		}
-		
-		SyntheticArgumentBinding[] outerLocalVariables = lambdaEx.outerLocalVariables;
-		for (int p=0,max=outerLocalVariables.length;p<max;p++) {
-			aload_0();
-			loadInt(index);
-			invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName, 
-					ConstantPool.GetCapturedArg, ConstantPool.GetCapturedArgSignature);
-			TypeBinding varType = outerLocalVariables[p].type;
-			if (varType.isBaseType()) {
-				checkcast(scope.boxing(varType));
-				generateUnboxingConversion(varType.id);
-				if (varType.id == TypeIds.T_JavaLangLong || varType.id == TypeIds.T_JavaLangDouble) {
-					index++;
-				}
+			FunctionalExpression funcEx = syntheticMethodBinding.lambda != null ? syntheticMethodBinding.lambda
+					: syntheticMethodBinding.serializableMethodRef;
+			MethodBinding mb = funcEx.binding;
+			invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName,
+					ConstantPool.GetImplMethodKind, ConstantPool.GetImplMethodKindSignature);
+			byte methodKind = 0;
+			if (mb.isStatic()) {
+				methodKind = ClassFileConstants.MethodHandleRefKindInvokeStatic;
+			} else if (mb.isPrivate()) {
+				methodKind = ClassFileConstants.MethodHandleRefKindInvokeSpecial;
 			} else {
-				checkcast(varType);
+				methodKind = ClassFileConstants.MethodHandleRefKindInvokeVirtual;
 			}
-			index++;
-			sig.append(varType.signature());
+			bipush(methodKind);// TODO see table below
+			if_icmpne(nextOne);
+
+			// Compare FunctionalInterfaceClass
+			aload_0();
+			invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName,
+					ConstantPool.GetFunctionalInterfaceClass, ConstantPool.GetFunctionalInterfaceClassSignature);
+			String functionalInterface = null;
+			final TypeBinding expectedType = funcEx.expectedType();
+			if (expectedType instanceof IntersectionTypeBinding18) {
+				functionalInterface = new String(
+						((IntersectionTypeBinding18) expectedType).getSAMType(scope).constantPoolName());
+			} else {
+				functionalInterface = new String(expectedType.constantPoolName());
+			}
+			ldc(functionalInterface);// e.g. "com/foo/X$Foo"
+			invokeObjectEquals();
+			ifeq(nextOne);
+
+			// Compare FunctionalInterfaceMethodName
+			aload_0();
+			invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName,
+					ConstantPool.GetFunctionalInterfaceMethodName,
+					ConstantPool.GetFunctionalInterfaceMethodNameSignature);
+			ldc(new String(funcEx.descriptor.selector)); // e.g. "m"
+			invokeObjectEquals();
+			ifeq(nextOne);
+
+			// Compare FunctionalInterfaceMethodSignature
+			aload_0();
+			invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName,
+					ConstantPool.GetFunctionalInterfaceMethodSignature,
+					ConstantPool.GetFunctionalInterfaceMethodSignatureSignature);
+			ldc(new String(funcEx.descriptor.original().signature())); // e.g "()I"
+			invokeObjectEquals();
+			ifeq(nextOne);
+
+			// Compare ImplClass
+			aload_0();
+			invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName,
+					ConstantPool.GetImplClass, ConstantPool.GetImplClassSignature);
+			ldc(new String(mb.declaringClass.constantPoolName())); // e.g. "com/foo/X"
+			invokeObjectEquals();
+			ifeq(nextOne);
+
+			// Compare ImplMethodSignature
+			aload_0();
+			invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName,
+					ConstantPool.GetImplMethodSignature, ConstantPool.GetImplMethodSignatureSignature);
+			ldc(new String(mb.signature())); // e.g. "(I)I"
+			invokeObjectEquals();
+			ifeq(nextOne);
+
+			// Captured arguments
+			StringBuffer sig = new StringBuffer("("); //$NON-NLS-1$
+			index = 0;
+			boolean isLambda = funcEx instanceof LambdaExpression;
+			TypeBinding receiverType = null;
+			SyntheticArgumentBinding[] outerLocalVariables = null;
+			if (isLambda) {
+				LambdaExpression lambdaEx = (LambdaExpression) funcEx;
+				if (lambdaEx.shouldCaptureInstance)
+					receiverType = mb.declaringClass;
+				outerLocalVariables = lambdaEx.outerLocalVariables;
+			} else {
+				ReferenceExpression refEx = (ReferenceExpression)funcEx;
+				if (refEx.haveReceiver)
+					receiverType = ((ReferenceExpression)funcEx).receiverType;
+				// Should never have outer locals
+			}
+			if (receiverType != null) {
+				aload_0();
+				loadInt(index++);
+				invoke(Opcodes.OPC_invokevirtual, 1, 1,
+						ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName,
+						ConstantPool.GetCapturedArg, ConstantPool.GetCapturedArgSignature);
+				checkcast(isLambda ? mb.declaringClass : ((ReferenceExpression)funcEx).receiverType);
+				sig.append(mb.declaringClass.signature());
+			}
+			for (int p = 0, max = outerLocalVariables == null ? 0 : outerLocalVariables.length; p < max; p++) {
+				TypeBinding varType = outerLocalVariables[p].type;
+				aload_0();
+				loadInt(index);
+				invoke(Opcodes.OPC_invokevirtual, 1, 1,
+						ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName,
+						ConstantPool.GetCapturedArg, ConstantPool.GetCapturedArgSignature);
+				if (varType.isBaseType()) {
+					checkcast(scope.boxing(varType));
+					generateUnboxingConversion(varType.id);
+					if (varType.id == TypeIds.T_JavaLangLong || varType.id == TypeIds.T_JavaLangDouble) {
+						index++;
+					}
+				} else {
+					checkcast(varType);
+				}
+				index++;
+				sig.append(varType.signature());
+			}
+			sig.append(")"); //$NON-NLS-1$
+			if (funcEx.resolvedType instanceof IntersectionTypeBinding18) {
+				sig.append(((IntersectionTypeBinding18) funcEx.resolvedType).getSAMType(scope).signature());
+			} else {
+				sig.append(funcEx.resolvedType.signature());
+			}
+			// Example: invokeDynamic(0, 0, 1, "m".toCharArray(), "()Lcom/foo/X$Foo;".toCharArray());
+			invokeDynamic(funcEx.bootstrapMethodNumber, index, 1, funcEx.descriptor.selector,
+					sig.toString().toCharArray());
+			areturn();
+			if (j < count - 1) {
+				nextOne.place();
+				nextOne = j < count - 2 ? new BranchLabel(this) : errorLabel;
+			}
 		}
-		sig.append(")"); //$NON-NLS-1$
-		if (lambdaEx.resolvedType instanceof IntersectionTypeBinding18) {
-			sig.append(((IntersectionTypeBinding18)lambdaEx.resolvedType).getSAMType(scope).signature());
-		} else {
-			sig.append(lambdaEx.resolvedType.signature());
-		}
-		// Example: invokeDynamic(0, 0, 1, "m".toCharArray(), "()Lcom/foo/X$Foo;".toCharArray());
-		invokeDynamic(lambdaEx.bootstrapMethodNumber, index, 1, lambdaEx.descriptor.selector, sig.toString().toCharArray());
-		areturn();
 	}
 	
 	removeVariable(lvb1);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryType.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryType.java
index 4d58e4f..092fe6c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryType.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryType.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -15,6 +15,7 @@
 package org.eclipse.jdt.internal.compiler.env;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.ExternalAnnotationStatus;
 import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
 
 public interface IBinaryType extends IGenericType {
@@ -160,4 +161,9 @@
  */
 ITypeAnnotationWalker enrichWithExternalAnnotationsFor(ITypeAnnotationWalker walker, Object member, LookupEnvironment environment);
 
+/**
+ * Answer whether a provider for external annotations is associated with this binary type.
+ */
+ExternalAnnotationStatus getExternalAnnotationStatus();
+
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java
index f43f037..bc79c2f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -17,6 +17,7 @@
 	ICompilationUnit compilationUnit;
 	ISourceType[] sourceTypes;
 	AccessRestriction accessRestriction;
+	String externalAnnotationPath; // should be an absolute file system path
 
 	public NameEnvironmentAnswer(IBinaryType binaryType, AccessRestriction accessRestriction) {
 		this.binaryType = binaryType;
@@ -28,9 +29,10 @@
 		this.accessRestriction = accessRestriction;
 	}
 
-	public NameEnvironmentAnswer(ISourceType[] sourceTypes, AccessRestriction accessRestriction) {
+	public NameEnvironmentAnswer(ISourceType[] sourceTypes, AccessRestriction accessRestriction, String externalAnnotationPath) {
 		this.sourceTypes = sourceTypes;
 		this.accessRestriction = accessRestriction;
+		this.externalAnnotationPath = externalAnnotationPath;
 	}
 	/**
 	 * Returns the associated access restriction, or null if none.
@@ -54,6 +56,10 @@
 		return this.compilationUnit;
 	}
 
+	public String getExternalAnnotationPath() {
+		return this.externalAnnotationPath;
+	}
+
 	/**
 	 * Answer the unresolved source forms for the type or null if the
 	 * receiver represents a compilation unit or binary type.
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java
index 6b1a868..e75997d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -947,6 +947,10 @@
 				return;
 			}
 			if (flowInfo.isPotentiallyNull(local)) {
+				if(local.type.isFreeTypeVariable()) {
+					scope.problemReporter().localVariableFreeTypeVariableReference(local, location);
+					return;
+				}
 				scope.problemReporter().localVariablePotentialNullReference(local, location);
 				return;
 			}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java
index f1e5d43..382cb83 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -63,6 +63,8 @@
 	public final static int POTENTIALLY_NON_NULL = 32;
 
 	public final static int UNROOTED = 64; // marks a flowInfo that may be appended to another flowInfo (accepting incoming nulls/nonnulls, see UFI.iNBit/iNNBit).
+	
+	public static final int FREE_TYPEVARIABLE = FlowInfo.POTENTIALLY_NULL | FlowInfo.POTENTIALLY_NON_NULL;
 
 	public static final UnconditionalFlowInfo DEAD_END; // Represents a dead branch status of initialization
 	static {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java
index 3b49f17..ec758b4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java
@@ -161,6 +161,9 @@
  * @param callerFlowInfo the flow info against which checks must be performed
  */
 public void complainOnDeferredNullChecks(BlockScope scope, FlowInfo callerFlowInfo) {
+	complainOnDeferredNullChecks(scope, callerFlowInfo, true);
+}
+public void complainOnDeferredNullChecks(BlockScope scope, FlowInfo callerFlowInfo, boolean updateInitsOnBreak) {
 	for (int i = 0 ; i < this.innerFlowContextsCount ; i++) {
 		this.upstreamNullFlowInfo.
 			addPotentialNullInfoFrom(
@@ -433,9 +436,11 @@
 		}
 	}
 	// propagate breaks
-	this.initsOnBreak.addPotentialNullInfoFrom(incomingInfo);
-	for (int i = 0; i < this.breakTargetsCount; i++) {
-		this.breakTargetContexts[i].initsOnBreak.addPotentialNullInfoFrom(incomingInfo);
+	if(updateInitsOnBreak) {
+		this.initsOnBreak.addPotentialNullInfoFrom(incomingInfo);
+		for (int i = 0; i < this.breakTargetsCount; i++) {
+			this.breakTargetContexts[i].initsOnBreak.addPotentialNullInfoFrom(incomingInfo);
+		}
 	}
 }
 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
index 549f674..2f0b36c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -274,6 +274,9 @@
 	public static final String OPTION_SyntacticNullAnalysisForFields = "org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields"; //$NON-NLS-1$
 	public static final String OPTION_InheritNullAnnotations = "org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations";  //$NON-NLS-1$
 	public static final String OPTION_ReportNonnullParameterAnnotationDropped = "org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped";  //$NON-NLS-1$
+	public static final String OPTION_PessimisticNullAnalysisForFreeTypeVariables = "org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables";  //$NON-NLS-1$
+	public static final String OPTION_ReportNonNullTypeVariableFromLegacyInvocation = "org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation"; //$NON-NLS-1$
+	
 	/**
 	 * Possible values for configurable options
 	 */
@@ -394,6 +397,8 @@
 	public static final int UnusedTypeParameter = IrritantSet.GROUP2 | ASTNode.Bit17;
 	public static final int NonnullParameterAnnotationDropped = IrritantSet.GROUP2 | ASTNode.Bit18;
 	public static final int UnusedExceptionParameter = IrritantSet.GROUP2 | ASTNode.Bit19;
+	public static final int PessimisticNullAnalysisForFreeTypeVariables = IrritantSet.GROUP2 | ASTNode.Bit20;
+	public static final int NonNullTypeVariableFromLegacyInvocation = IrritantSet.GROUP2 | ASTNode.Bit21;
 
 //{ObjectTeams: OT/J specific problems/irritants:
 	public static final int OTJFlag = IrritantSet.GROUP3;
@@ -604,11 +609,15 @@
 	/** Should immediate null-check for fields be considered during null analysis (syntactical match)? */
 	public boolean enableSyntacticNullAnalysisForFields;
 
+	/** Is the error level for pessimistic null analysis for free type variables different from "ignore"? */
+	public boolean pessimisticNullAnalysisForFreeTypeVariablesEnabled;
+
 	public boolean complainOnUninternedIdentityComparison;
 	public boolean emulateJavacBug8031744 = true;
 
 	/** Not directly configurable, derived from other options by LookupEnvironment.usesNullTypeAnnotations() */
 	public Boolean useNullTypeAnnotations = null;
+	
 
 	// keep in sync with warningTokenToIrritant and warningTokenFromIrritant
 	public final static String[] warningTokens = {
@@ -893,6 +902,10 @@
 				return OPTION_ReportRedundantNullAnnotation;
 			case NonnullParameterAnnotationDropped:
 				return OPTION_ReportNonnullParameterAnnotationDropped;
+			case PessimisticNullAnalysisForFreeTypeVariables:
+				return OPTION_PessimisticNullAnalysisForFreeTypeVariables;
+			case NonNullTypeVariableFromLegacyInvocation:
+				return OPTION_ReportNonNullTypeVariableFromLegacyInvocation;
 		}
 		return null;
 	}
@@ -1180,6 +1193,8 @@
 			case RedundantNullAnnotation :
 			case MissingNonNullByDefaultAnnotation:
 			case NonnullParameterAnnotationDropped:
+			case PessimisticNullAnalysisForFreeTypeVariables:
+			case NonNullTypeVariableFromLegacyInvocation:
 				return "null"; //$NON-NLS-1$
 			case FallthroughCase :
 				return "fallthrough"; //$NON-NLS-1$
@@ -1554,6 +1569,8 @@
 		optionsMap.put(OPTION_InheritNullAnnotations, this.inheritNullAnnotations ? ENABLED : DISABLED);
 		optionsMap.put(OPTION_ReportNonnullParameterAnnotationDropped, getSeverityString(NonnullParameterAnnotationDropped));
 		optionsMap.put(OPTION_ReportUninternedIdentityComparison, this.complainOnUninternedIdentityComparison ? ENABLED : DISABLED);
+		optionsMap.put(OPTION_PessimisticNullAnalysisForFreeTypeVariables, getSeverityString(PessimisticNullAnalysisForFreeTypeVariables));
+		optionsMap.put(OPTION_ReportNonNullTypeVariableFromLegacyInvocation, getSeverityString(NonNullTypeVariableFromLegacyInvocation));
 		return optionsMap;
 	}
 
@@ -2143,6 +2160,13 @@
 				this.inheritNullAnnotations = ENABLED.equals(optionValue);
 			}
 			if ((optionValue = optionsMap.get(OPTION_ReportNonnullParameterAnnotationDropped)) != null) updateSeverity(NonnullParameterAnnotationDropped, optionValue);
+			if ((optionValue = optionsMap.get(OPTION_PessimisticNullAnalysisForFreeTypeVariables)) != null) updateSeverity(PessimisticNullAnalysisForFreeTypeVariables, optionValue);
+			if (getSeverity(PessimisticNullAnalysisForFreeTypeVariables) == ProblemSeverities.Ignore) {
+				this.pessimisticNullAnalysisForFreeTypeVariablesEnabled = false;
+			} else {
+				this.pessimisticNullAnalysisForFreeTypeVariablesEnabled = true;
+			}
+			if ((optionValue = optionsMap.get(OPTION_ReportNonNullTypeVariableFromLegacyInvocation)) != null) updateSeverity(NonNullTypeVariableFromLegacyInvocation, optionValue);
 		}
 
 		// Javadoc options
@@ -2410,6 +2434,8 @@
 		buf.append("\n\t- resource may not be closed: ").append(getSeverityString(PotentiallyUnclosedCloseable)); //$NON-NLS-1$
 		buf.append("\n\t- resource should be handled by try-with-resources: ").append(getSeverityString(ExplicitlyClosedAutoCloseable)); //$NON-NLS-1$
 		buf.append("\n\t- Unused Type Parameter: ").append(getSeverityString(UnusedTypeParameter)); //$NON-NLS-1$
+		buf.append("\n\t- pessimistic null analysis for free type variables: ").append(getSeverityString(PessimisticNullAnalysisForFreeTypeVariables)); //$NON-NLS-1$
+		buf.append("\n\t- report unsafe nonnull return from legacy method: ").append(getSeverityString(NonNullTypeVariableFromLegacyInvocation)); //$NON-NLS-1$
 //{ObjectTeams
 		buf.append("\n\t- decapsulation : ").append(this.decapsulation); //$NON-NLS-1$
 		buf.append("\n\t- report if not exactly one basecall in callin method : ").append(getSeverityString(NotExactlyOneBasecall)); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java
index 547352e..80db44d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IrritantSet.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -191,7 +191,9 @@
 				|CompilerOptions.UnclosedCloseable
 				|CompilerOptions.NullUncheckedConversion
 				|CompilerOptions.RedundantNullAnnotation
-				|CompilerOptions.NonnullParameterAnnotationDropped);
+				|CompilerOptions.NonnullParameterAnnotationDropped
+				|CompilerOptions.PessimisticNullAnalysisForFreeTypeVariables
+				|CompilerOptions.NonNullTypeVariableFromLegacyInvocation);
 		// default errors IF AnnotationBasedNullAnalysis is enabled:
 		COMPILER_DEFAULT_ERRORS.set(
 				CompilerOptions.NullSpecViolation
@@ -210,7 +212,9 @@
 			.set(CompilerOptions.NullUncheckedConversion)
 			.set(CompilerOptions.RedundantNullAnnotation)
 			.set(CompilerOptions.NonnullParameterAnnotationDropped)
-			.set(CompilerOptions.MissingNonNullByDefaultAnnotation);
+			.set(CompilerOptions.MissingNonNullByDefaultAnnotation)
+			.set(CompilerOptions.PessimisticNullAnalysisForFreeTypeVariables)
+			.set(CompilerOptions.NonNullTypeVariableFromLegacyInvocation);
 
 		RESTRICTION.set(CompilerOptions.DiscouragedReference);
 		STATIC_ACCESS.set(CompilerOptions.NonStaticAccessToStatic);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
index 4ba51ba..a632887 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -155,8 +155,23 @@
 
 	private ReferenceBinding containerAnnotationType;
 	int defaultNullness = 0;
-
-
+	public enum ExternalAnnotationStatus {
+		FROM_SOURCE,
+		NOT_EEA_CONFIGURED,
+		NO_EEA_FILE,
+		TYPE_IS_ANNOTATED;
+		public boolean isPotentiallyUnannotatedLib() {
+			switch (this) {
+				case FROM_SOURCE:
+				case TYPE_IS_ANNOTATED:
+					return false;
+				default:
+					return true;
+			}
+		}
+	}
+	public ExternalAnnotationStatus externalAnnotationStatus = ExternalAnnotationStatus.NOT_EEA_CONFIGURED; // unless proven differently
+	
 //{ObjectTeams: support callout-to-field
 
 	/** Callout to field adds faked access method (set or get): */
@@ -292,7 +307,14 @@
 			return ((WildcardBinding) type).resolve();
 
 		case Binding.ARRAY_TYPE :
-			resolveType(((ArrayBinding) type).leafComponentType, environment, convertGenericToRawType);
+			ArrayBinding arrayBinding = (ArrayBinding) type;
+			TypeBinding leafComponentType = arrayBinding.leafComponentType;
+			resolveType(leafComponentType, environment, convertGenericToRawType);
+			if (leafComponentType.hasNullTypeAnnotations() && environment.usesNullTypeAnnotations()) {
+				if (arrayBinding.nullTagBitsPerDimension == null)
+					arrayBinding.nullTagBitsPerDimension = new long[arrayBinding.dimensions+1];
+				arrayBinding.nullTagBitsPerDimension[arrayBinding.dimensions] = leafComponentType.tagBits & TagBits.AnnotationNullMASK;
+			}
 			break;
 
 		case Binding.TYPE_PARAMETER :
@@ -574,6 +596,10 @@
 		}
 		ITypeAnnotationWalker walker = getTypeAnnotationWalker(binaryType.getTypeAnnotations(), Binding.NO_NULL_DEFAULT);
 		ITypeAnnotationWalker toplevelWalker = binaryType.enrichWithExternalAnnotationsFor(walker, null, this.environment);
+		this.externalAnnotationStatus = binaryType.getExternalAnnotationStatus();
+		if (this.externalAnnotationStatus.isPotentiallyUnannotatedLib() && this.defaultNullness != 0) {
+			this.externalAnnotationStatus = ExternalAnnotationStatus.TYPE_IS_ANNOTATED;
+		}
 		char[] typeSignature = binaryType.getGenericSignature(); // use generic signature even in 1.4
 		this.tagBits |= binaryType.getTagBits();
 		
@@ -663,6 +689,19 @@
 				this.tagBits |= TagBits.HasUnresolvedSuperinterfaces;
 			}
 		}
+		boolean canUseNullTypeAnnotations = this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled && this.environment.globalOptions.sourceLevel >= ClassFileConstants.JDK1_8;
+		if (canUseNullTypeAnnotations && this.externalAnnotationStatus.isPotentiallyUnannotatedLib()) {
+			if (this.superclass != null && this.superclass.hasNullTypeAnnotations()) {
+				this.externalAnnotationStatus = ExternalAnnotationStatus.TYPE_IS_ANNOTATED;
+			} else {
+				for (TypeBinding ifc : this.superInterfaces) {
+					if (ifc.hasNullTypeAnnotations()) {
+						this.externalAnnotationStatus = ExternalAnnotationStatus.TYPE_IS_ANNOTATED;
+						break;
+					}
+				}
+			}
+		}
 
 		if (needFieldsAndMethods) {
 			IBinaryField[] iFields = binaryType.getFields();
@@ -699,7 +738,7 @@
 						ITypeAnnotationWalker methodWalker = ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER;
 						if (sourceLevel < ClassFileConstants.JDK1_8)
 							methodWalker = binaryType.enrichWithExternalAnnotationsFor(methodWalker, iMethods[i], this.environment);
-						scanMethodForNullAnnotation(iMethods[i], this.methods[i], methodWalker);
+						scanMethodForNullAnnotation(iMethods[i], this.methods[i], methodWalker, canUseNullTypeAnnotations);
 					}
 				}
 			}
@@ -766,7 +805,7 @@
 	if (iFields != null) {
 		int size = iFields.length;
 		if (size > 0) {
-			this.fields = new FieldBinding[size];
+			FieldBinding[] fields1 = new FieldBinding[size];
 			boolean use15specifics = sourceLevel >= ClassFileConstants.JDK1_5;
 			boolean hasRestrictedAccess = hasRestrictedAccess();
 			int firstAnnotatedFieldIndex = -1;
@@ -806,7 +845,7 @@
 					field.modifiers |= ExtraCompilerModifiers.AccRestrictedAccess;
 				if (fieldSignature != null)
 					field.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
-				this.fields[i] = field;
+				fields1[i] = field;
 //{ObjectTeams:
 				// field attributes:
 				if (binaryField instanceof FieldInfo)
@@ -816,6 +855,7 @@
 					addValueParameter(field);
 // SH}
 			}
+			this.fields = fields1;
 			// second pass for reifying annotations, since may refer to fields being constructed (147875)
 			if (firstAnnotatedFieldIndex >= 0) {
 				for (int i = firstAnnotatedFieldIndex; i <size; i++) {
@@ -1163,15 +1203,16 @@
 		return NO_BINARY_METHODS;
 	}
 
-	boolean hasRestrictedAccess = hasRestrictedAccess();
-	this.methods = new MethodBinding[total];
+boolean hasRestrictedAccess = hasRestrictedAccess();
+	MethodBinding[] methods1 = new MethodBinding[total];
 	if (total == initialTotal) {
 		for (int i = 0; i < initialTotal; i++) {
 			MethodBinding method = createMethod(iMethods[i], binaryType, sourceLevel, missingTypeNames);
 			if (hasRestrictedAccess)
 				method.modifiers |= ExtraCompilerModifiers.AccRestrictedAccess;
-			this.methods[i] = method;
+			methods1[i] = method;
 		}
+		this.methods = methods1;
 		return iMethods;
 	} else {
 		IBinaryMethod[] mappedBinaryMethods = new IBinaryMethod[total];
@@ -1181,9 +1222,10 @@
 				if (hasRestrictedAccess)
 					method.modifiers |= ExtraCompilerModifiers.AccRestrictedAccess;
 				mappedBinaryMethods[index] = iMethods[i];
-				this.methods[index++] = method;
+				methods1[index++] = method;
 			}
 		}
+		this.methods = methods1;
 		return mappedBinaryMethods;
 	}
 }
@@ -1254,6 +1296,8 @@
 		this.typeVariables = result;
 	for (int i = 0; i < rank; i++) {
 		initializeTypeVariable(result[i], result, wrapper, missingTypeNames, walker.toTypeParameterBounds(isClassTypeParameter, i));
+		if (this.externalAnnotationStatus.isPotentiallyUnannotatedLib() && result[i].hasNullTypeAnnotations())
+			this.externalAnnotationStatus = ExternalAnnotationStatus.TYPE_IS_ANNOTATED;
 	}
 	return result;
 }
@@ -1945,11 +1989,13 @@
 		return; // we know it's nonnull, no need to look for null *annotations* on enum constants.
 	}
 
-	if (this.environment.globalOptions.sourceLevel >= ClassFileConstants.JDK1_8) {
+	if (!CharOperation.equals(this.fPackage.compoundName, TypeConstants.JAVA_LANG_ANNOTATION) // avoid dangerous re-entry via usesNullTypeAnnotations()
+			&& this.environment.usesNullTypeAnnotations()) {
 		TypeBinding fieldType = fieldBinding.type;
 		if (fieldType != null
 				&& !fieldType.isBaseType()
 				&& (fieldType.tagBits & TagBits.AnnotationNullMASK) == 0
+				&& fieldType.acceptsNonNullDefault()
 				&& hasNonNullDefaultFor(DefaultLocationField, true)) {
 			fieldBinding.type = this.environment.createAnnotatedType(fieldType, new AnnotationBinding[]{this.environment.getNonNullAnnotation()});
 		}
@@ -1983,12 +2029,14 @@
 			}
 		}
 	}
+	if (explicitNullness && this.externalAnnotationStatus.isPotentiallyUnannotatedLib())
+		this.externalAnnotationStatus = ExternalAnnotationStatus.TYPE_IS_ANNOTATED;
 	if (!explicitNullness && (this.tagBits & TagBits.AnnotationNonNullByDefault) != 0) {
 		fieldBinding.tagBits |= TagBits.AnnotationNonNull;
 	}
 }
 
-private void scanMethodForNullAnnotation(IBinaryMethod method, MethodBinding methodBinding, ITypeAnnotationWalker externalAnnotationWalker) {
+private void scanMethodForNullAnnotation(IBinaryMethod method, MethodBinding methodBinding, ITypeAnnotationWalker externalAnnotationWalker, boolean useNullTypeAnnotations) {
 	if (!isPrototype()) throw new IllegalStateException();
 	if (isEnum()) {
 		int purpose = 0;
@@ -2077,6 +2125,18 @@
 			}
 		}
 	}
+	if (useNullTypeAnnotations && this.externalAnnotationStatus.isPotentiallyUnannotatedLib()) {
+		if (methodBinding.returnType.hasNullTypeAnnotations()) {
+			this.externalAnnotationStatus = ExternalAnnotationStatus.TYPE_IS_ANNOTATED;
+		} else {
+			for (TypeBinding parameter : parameters) {
+				if (parameter.hasNullTypeAnnotations()) {
+					this.externalAnnotationStatus = ExternalAnnotationStatus.TYPE_IS_ANNOTATED;
+					break;
+				}
+			}
+		}
+	}
 }
 // pre: null annotation analysis is enabled
 private void scanTypeForNullDefaultAnnotation(IBinaryType binaryType, PackageBinding packageBinding) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintExpressionFormula.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintExpressionFormula.java
index c51a617..09ffa02 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintExpressionFormula.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintExpressionFormula.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2013, 2015 GK Software AG.
+ * Copyright (c) 2013, 2016 GK Software AG.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -318,19 +318,7 @@
 	static void inferInvocationApplicability(InferenceContext18 inferenceContext, MethodBinding method, TypeBinding[] arguments, boolean isDiamond, int checkType)
 	{
 		// 18.5.1
-		TypeVariableBinding[] typeVariables = method.typeVariables;
-		if (isDiamond) {
-			TypeVariableBinding[] classTypeVariables = method.declaringClass.typeVariables();
-			int l1 = typeVariables.length;
-			int l2 = classTypeVariables.length;
-			if (l1 == 0) {
-				typeVariables = classTypeVariables;
-			} else if (l2 != 0) {
-				System.arraycopy(typeVariables, 0, typeVariables=new TypeVariableBinding[l1+l2], 0, l1);
-				System.arraycopy(classTypeVariables, 0, typeVariables, l1, l2);
-			}				
-		}
-		TypeBinding[] parameters = method.parameters;
+		TypeVariableBinding[] typeVariables = method.getAllTypeVariables(isDiamond);
 		InferenceVariable[] inferenceVariables = inferenceContext.createInitialBoundSet(typeVariables); // creates initial bound set B
 
 		// check if varargs need special treatment:
@@ -340,7 +328,7 @@
 			int varArgPos = paramLength-1;
 			varArgsType = method.parameters[varArgPos];
 		}
-		inferenceContext.createInitialConstraintsForParameters(parameters, checkType==InferenceContext18.CHECK_VARARG, varArgsType, method);
+		inferenceContext.createInitialConstraintsForParameters(method.parameters, checkType==InferenceContext18.CHECK_VARARG, varArgsType, method);
 		inferenceContext.addThrowsContraints(typeVariables, inferenceVariables, method.thrownExceptions);
 	}
 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintTypeFormula.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintTypeFormula.java
index 9daff30..7ce5578 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintTypeFormula.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintTypeFormula.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2013, 2015 GK Software AG.
+ * Copyright (c) 2013, 2016 GK Software AG.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -184,10 +184,13 @@
 						return TRUE;
 					return FALSE;
 				}
-				if (this.left instanceof InferenceVariable) {
+				if (this.left.id == TypeIds.T_null || this.right.id== TypeIds.T_null) {
+					return FALSE;
+				}
+				if (this.left instanceof InferenceVariable && !this.right.isPrimitiveType()) {
 					return new TypeBound((InferenceVariable) this.left, this.right, SAME, this.isSoft);
 				}
-				if (this.right instanceof InferenceVariable) {
+				if (this.right instanceof InferenceVariable && !this.left.isPrimitiveType()) {
 					return new TypeBound((InferenceVariable) this.right, this.left, SAME, this.isSoft);
 				}
 				if ((this.left.isClass() || this.left.isInterface()) 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExternalAnnotationSuperimposer.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExternalAnnotationSuperimposer.java
new file mode 100644
index 0000000..781a451
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExternalAnnotationSuperimposer.java
@@ -0,0 +1,269 @@
+/*******************************************************************************
+ * Copyright (c) 2016 GK Software AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Stephan Herrmann - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.lookup;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationProvider;
+import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation;
+import org.eclipse.jdt.internal.compiler.env.ITypeAnnotationWalker;
+import org.eclipse.jdt.internal.compiler.util.Messages;
+
+/**
+ * Used for superimposing external annotations (served by an {@link ITypeAnnotationWalker})
+ * over signatures of a {@link SourceTypeBinding}.
+ */
+class ExternalAnnotationSuperimposer extends TypeBindingVisitor {
+
+	public static void apply(SourceTypeBinding typeBinding, String externalAnnotationPath) {
+		ZipFile zipFile = null;
+		try {
+			File annotationBase = new File(externalAnnotationPath);
+			if (annotationBase.exists()) {
+				String binaryTypeName = String.valueOf(typeBinding.constantPoolName());
+				String relativeFileName = binaryTypeName.replace('.', '/')+ExternalAnnotationProvider.ANNOTATION_FILE_SUFFIX;
+
+				InputStream input;
+				if (annotationBase.isDirectory()) {
+					input = new FileInputStream(externalAnnotationPath+'/'+relativeFileName);
+				} else {
+					zipFile = new ZipFile(externalAnnotationPath);
+					ZipEntry zipEntry = zipFile.getEntry(relativeFileName);
+					if (zipEntry == null)
+						return;
+					input = zipFile.getInputStream(zipEntry);
+				}
+				annotateType(typeBinding, new ExternalAnnotationProvider(input, binaryTypeName), typeBinding.environment);
+			}
+		} catch (FileNotFoundException e) {
+			// file not found is expected
+		} catch (IOException e) {
+			typeBinding.scope.problemReporter().abortDueToInternalError(Messages.bind(Messages.abort_externaAnnotationFile, 
+						new String[] {String.valueOf(typeBinding.readableName()), externalAnnotationPath, e.getMessage()}));
+		} finally {
+			if (zipFile != null)
+				try {
+					zipFile.close();
+				} catch (IOException e) {
+					// nothing
+				}
+		}
+	}
+
+	static void annotateType(SourceTypeBinding binding, ExternalAnnotationProvider provider, LookupEnvironment environment) {
+		ITypeAnnotationWalker typeWalker = provider.forTypeHeader(environment);
+		if (typeWalker != null && typeWalker != ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER) {
+			ExternalAnnotationSuperimposer visitor = new ExternalAnnotationSuperimposer(environment);
+			TypeVariableBinding[] typeParameters = binding.typeVariables();
+			for (int i = 0; i < typeParameters.length; i++) {
+				if (visitor.go(typeWalker.toTypeParameter(true, i)))
+					typeParameters[i] = visitor.superimpose(typeParameters[i], TypeVariableBinding.class);
+			}
+		}
+		binding.externalAnnotationProvider = provider; // for superimposing method signatures
+	}
+
+	public static void annotateFieldBinding(FieldBinding field, ExternalAnnotationProvider provider, LookupEnvironment environment) {
+		char[] fieldSignature = field.genericSignature();
+		if (fieldSignature == null && field.type != null)
+			fieldSignature = field.type.signature();
+		ITypeAnnotationWalker walker = provider.forField(field.name, fieldSignature, environment);
+		ExternalAnnotationSuperimposer visitor = new ExternalAnnotationSuperimposer(environment);
+		if (visitor.go(walker))
+			field.type = visitor.superimpose(field.type, TypeBinding.class);
+	}
+
+	public static void annotateMethodBinding(MethodBinding method, ExternalAnnotationProvider provider, LookupEnvironment environment) {
+		char[] methodSignature = method.genericSignature();
+		if (methodSignature == null)
+			methodSignature = method.signature();
+		ITypeAnnotationWalker walker = provider.forMethod(method.selector, methodSignature, environment);
+		if (walker != null && walker != ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER) {
+			ExternalAnnotationSuperimposer visitor = new ExternalAnnotationSuperimposer(environment);
+			TypeVariableBinding[] typeParams = method.typeVariables;
+			for (short i = 0; i < typeParams.length; i++) {
+				if (visitor.go(walker.toTypeParameter(false, i)))
+					typeParams[i] = visitor.superimpose(typeParams[i], TypeVariableBinding.class);
+			}
+			if (!method.isConstructor()) {
+				if (visitor.go(walker.toMethodReturn()))
+					method.returnType = visitor.superimpose(method.returnType, TypeBinding.class);
+			}
+			TypeBinding[] parameters = method.parameters;
+			for (short i = 0; i < parameters.length; i++) {
+				if (visitor.go(walker.toMethodParameter(i)))
+					parameters[i] = visitor.superimpose(parameters[i], TypeBinding.class);
+			}
+		}
+	}
+
+	private ITypeAnnotationWalker currentWalker;
+	private TypeBinding typeReplacement;
+	private LookupEnvironment environment;
+	private boolean isReplacing;
+	
+	ExternalAnnotationSuperimposer(LookupEnvironment environment) {
+		this.environment = environment;
+	}
+
+	/** for constructing a memento of the superimposer's current state. */
+	private ExternalAnnotationSuperimposer(TypeBinding typeReplacement, boolean isReplacing, ITypeAnnotationWalker walker) {
+		this.typeReplacement = typeReplacement;
+		this.isReplacing = isReplacing;
+		this.currentWalker = walker;
+	}
+	private ExternalAnnotationSuperimposer snapshot() {
+		ExternalAnnotationSuperimposer memento = new ExternalAnnotationSuperimposer(this.typeReplacement, this.isReplacing, this.currentWalker);
+		// soft reset:
+		this.typeReplacement = null;
+		this.isReplacing = false;
+		return memento;
+	}
+	private void restore(ExternalAnnotationSuperimposer memento) {
+		this.isReplacing = memento.isReplacing;
+		this.currentWalker = memento.currentWalker;
+	}
+
+	boolean go(ITypeAnnotationWalker walker) {
+		// hard reset:
+		reset();
+		this.typeReplacement = null;
+		this.isReplacing = false;
+		// and start anew:
+		this.currentWalker = walker;
+		return walker != ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER;
+	}
+
+	<T extends TypeBinding> T superimpose(T type, Class<? extends T> cl) {
+		TypeBindingVisitor.visit(this, type);
+		if (cl.isInstance(this.typeReplacement))
+			return cl.cast(this.typeReplacement);
+		return type;
+	}
+	
+	private TypeBinding goAndSuperimpose(ITypeAnnotationWalker walker, TypeBinding type) {
+		// no reset here
+		if (walker == ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER)
+			return type;
+		this.currentWalker = walker;
+		
+		TypeBindingVisitor.visit(this, type);
+
+		if (this.typeReplacement == null)
+			return type;
+		this.isReplacing = true;
+		TypeBinding answer = this.typeReplacement;
+		this.typeReplacement = null;
+		return answer;
+	}
+	
+	@Override
+	public boolean visit(ArrayBinding arrayBinding) {
+		ExternalAnnotationSuperimposer memento = snapshot();
+		try {
+			int dims = arrayBinding.dimensions;
+			AnnotationBinding[][] annotsOnDims = new AnnotationBinding[dims][];
+			ITypeAnnotationWalker walker = this.currentWalker;
+			for (int i = 0; i < dims; i++) {
+				IBinaryAnnotation[] binaryAnnotations = walker.getAnnotationsAtCursor(arrayBinding.id);
+				if (binaryAnnotations != ITypeAnnotationWalker.NO_ANNOTATIONS) {
+					annotsOnDims[i] = BinaryTypeBinding.createAnnotations(binaryAnnotations, this.environment, null);
+					this.isReplacing = true;
+				} else {
+					annotsOnDims[i] = Binding.NO_ANNOTATIONS;
+				}
+				walker = walker.toNextArrayDimension();
+			}
+			TypeBinding leafComponentType = goAndSuperimpose(walker, arrayBinding.leafComponentType());
+			if (this.isReplacing) {
+				this.typeReplacement = this.environment.createArrayType(leafComponentType, dims, AnnotatableTypeSystem.flattenedAnnotations(annotsOnDims));
+			}
+		} finally {
+			restore(memento);
+		}
+		return false;
+	}
+	@Override
+	public boolean visit(BaseTypeBinding baseTypeBinding) {
+		return false; // no null annotations
+	}
+	@Override
+	public boolean visit(IntersectionTypeBinding18 intersectionTypeBinding18) {
+		return false; // shouldn't occur in declarations
+	}
+	@Override
+	public boolean visit(ParameterizedTypeBinding parameterizedTypeBinding) {
+		ExternalAnnotationSuperimposer memento = snapshot();
+		try {
+			IBinaryAnnotation[] binaryAnnotations = this.currentWalker.getAnnotationsAtCursor(parameterizedTypeBinding.id);
+			AnnotationBinding[] annotations = Binding.NO_ANNOTATIONS;
+			if (binaryAnnotations != ITypeAnnotationWalker.NO_ANNOTATIONS) {
+				annotations = BinaryTypeBinding.createAnnotations(binaryAnnotations, this.environment, null);
+				this.isReplacing = true;
+			}
+
+			TypeBinding[] typeArguments = parameterizedTypeBinding.typeArguments();
+			TypeBinding[] newArguments = new TypeBinding[typeArguments.length];
+			for (int i = 0; i < typeArguments.length; i++) {
+				newArguments[i] = goAndSuperimpose(memento.currentWalker.toTypeArgument(i), typeArguments[i]);
+			}
+			if (this.isReplacing)
+				this.typeReplacement = this.environment.createParameterizedType(parameterizedTypeBinding.genericType(), newArguments, parameterizedTypeBinding.enclosingType(), annotations);
+			return false;
+		} finally {
+			restore(memento);
+		}		
+	}
+	@Override
+	public boolean visit(RawTypeBinding rawTypeBinding) {
+		return visit((ReferenceBinding)rawTypeBinding);
+	}
+	@Override
+	public boolean visit(ReferenceBinding referenceBinding) {
+		IBinaryAnnotation[] binaryAnnotations = this.currentWalker.getAnnotationsAtCursor(referenceBinding.id);
+		if (binaryAnnotations != ITypeAnnotationWalker.NO_ANNOTATIONS)
+			this.typeReplacement = this.environment.createAnnotatedType(referenceBinding, BinaryTypeBinding.createAnnotations(binaryAnnotations, this.environment, null));
+		return false;
+	}
+	@Override
+	public boolean visit(TypeVariableBinding typeVariable) {
+		return visit((ReferenceBinding) typeVariable);
+	}
+	@Override
+	public boolean visit(WildcardBinding wildcardBinding) {
+		TypeBinding bound = wildcardBinding.bound;
+		ExternalAnnotationSuperimposer memento = snapshot();
+		try {
+			if (bound != null) {
+				bound = goAndSuperimpose(memento.currentWalker.toWildcardBound(), bound);
+			}
+			IBinaryAnnotation[] binaryAnnotations = memento.currentWalker.getAnnotationsAtCursor(-1); 
+			if (this.isReplacing || binaryAnnotations != ITypeAnnotationWalker.NO_ANNOTATIONS) {
+				TypeBinding[] otherBounds = wildcardBinding.otherBounds;
+				if (binaryAnnotations != ITypeAnnotationWalker.NO_ANNOTATIONS) {
+					AnnotationBinding[] annotations = BinaryTypeBinding.createAnnotations(binaryAnnotations, this.environment, null);
+					this.typeReplacement = this.environment.createWildcard(wildcardBinding.genericType, wildcardBinding.rank, bound, otherBounds, wildcardBinding.boundKind, annotations);
+				} else {
+					this.typeReplacement = this.environment.createWildcard(wildcardBinding.genericType, wildcardBinding.rank, bound, otherBounds, wildcardBinding.boundKind);
+				}
+			}
+		} finally {
+			restore(memento);
+		}
+		return false;
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ImplicitNullAnnotationVerifier.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ImplicitNullAnnotationVerifier.java
index 7247fc3..ad48663 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ImplicitNullAnnotationVerifier.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ImplicitNullAnnotationVerifier.java
@@ -306,7 +306,7 @@
 						ParameterizedGenericMethodBinding substitute = this.environment.createParameterizedGenericMethod(currentMethod, typeVariables);
 						substituteReturnType = substitute.returnType;
 					}
-					if (NullAnnotationMatching.analyse(inheritedMethod.returnType, currentMethod.returnType, substituteReturnType, null, 0, CheckMode.OVERRIDE_RETURN).isAnyMismatch()) {
+					if (NullAnnotationMatching.analyse(inheritedMethod.returnType, currentMethod.returnType, substituteReturnType, null, 0, null, CheckMode.OVERRIDE_RETURN).isAnyMismatch()) {
 						if (srcMethod != null)
 							scope.problemReporter().illegalReturnRedefinition(srcMethod, inheritedMethod,
 																	this.environment.getNonNullAnnotationName());
@@ -437,7 +437,7 @@
 				if (useTypeAnnotations) {
 					TypeBinding inheritedParameter = inheritedMethod.parameters[i];
 					TypeBinding substituteParameter = substituteParameters != null ? substituteParameters[i] : null;
-					if (NullAnnotationMatching.analyse(currentMethod.parameters[i], inheritedParameter, substituteParameter, null, 0, CheckMode.OVERRIDE).isAnyMismatch()) {
+					if (NullAnnotationMatching.analyse(currentMethod.parameters[i], inheritedParameter, substituteParameter, null, 0, null, CheckMode.OVERRIDE).isAnyMismatch()) {
 						if (currentArgument != null)
 							scope.problemReporter().illegalParameterRedefinition(currentArgument, inheritedMethod.declaringClass, inheritedParameter);
 						else
@@ -453,7 +453,7 @@
 			if (currentTypeVariables != Binding.NO_TYPE_VARIABLES && currentTypeVariables.length == inheritedTypeVariables.length) {
 				for (int i = 0; i < currentTypeVariables.length; i++) {
 					TypeVariableBinding inheritedVariable = inheritedTypeVariables[i];
-					if (NullAnnotationMatching.analyse(inheritedVariable, currentTypeVariables[i], null, null, -1, CheckMode.BOUND_CHECK).isAnyMismatch())
+					if (NullAnnotationMatching.analyse(inheritedVariable, currentTypeVariables[i], null, null, -1, null, CheckMode.BOUND_CHECK).isAnyMismatch())
 						scope.problemReporter().cannotRedefineTypeArgumentNullity(inheritedVariable, inheritedMethod, srcMethod.typeParameters()[i]);
 				}
 			}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java
index 5fecda1..f197cfa 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2013, 2015 GK Software AG, and others.
+ * Copyright (c) 2013, 2016 GK Software AG, and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -497,10 +497,6 @@
 					if (withWildCards != null) {
 						t = ConstraintExpressionFormula.findGroundTargetType(this, skope, lambda, withWildCards);
 					}
-					if (!t.isProperType(true) && t.isParameterizedType()) {
-						// prevent already resolved inference variables from leaking into the lambda
-						t = (ReferenceBinding) Scope.substitute(getResultSubstitution(this.currentBounds, false), t);
-					}
 					MethodBinding functionType;
 					if (t != null && (functionType = t.getSingleAbstractMethod(skope, true)) != null && (lambda = lambda.resolveExpressionExpecting(t, this.scope, this)) != null) {
 						TypeBinding r = functionType.returnType;
@@ -540,9 +536,7 @@
 					this.inferenceKind = applicabilityKind;
 					if (innerContext != null)
 						innerContext.outerContext = this;
-					inferInvocationApplicability(shallowMethod, argumentTypes, shallowMethod.isConstructor());
-					if (!ConstraintExpressionFormula.inferPolyInvocationType(this, invocation, substF, shallowMethod))
-						return false;
+					createInitialBoundSet(shallowMethod.getAllTypeVariables(shallowMethod.isConstructor())); // minimal preparation to work with inner inference variables
 				} finally {
 					resumeSuspendedInference(prevInvocation);
 				}
@@ -729,37 +723,43 @@
 	private boolean checkExpression(Expression expri, TypeBinding[] u, TypeBinding r1, TypeBinding[] v, TypeBinding r2) 
 			throws InferenceFailureException {
 		if (expri instanceof LambdaExpression && !((LambdaExpression)expri).argumentsTypeElided()) {
+			for (int i = 0; i < u.length; i++) {
+				if (!reduceAndIncorporate(ConstraintTypeFormula.create(u[i], v[i], ReductionResult.SAME)))
+					return false;
+			}
 			if (r2.id == TypeIds.T_void)
 				return true;
 			LambdaExpression lambda = (LambdaExpression) expri;
 			Expression[] results = lambda.resultExpressions();
-			if (r1.isFunctionalInterface(this.scope) && r2.isFunctionalInterface(this.scope)
-					&& !(r1.isCompatibleWith(r2) || r2.isCompatibleWith(r1))) {
-				// "these rules are applied recursively to R1 and R2, for each result expression in expi."
-				// (what does "applied .. to R1 and R2" mean? Why mention R1/R2 and not U/V?)
-				for (int i = 0; i < results.length; i++) {
-					if (!checkExpression(results[i], u, r1, v, r2))
-						return false;
+			if (results != Expression.NO_EXPRESSIONS) {
+				if (r1.isFunctionalInterface(this.scope) && r2.isFunctionalInterface(this.scope)
+						&& !(r1.isCompatibleWith(r2) || r2.isCompatibleWith(r1))) {
+					// "these rules are applied recursively to R1 and R2, for each result expression in expi."
+					// (what does "applied .. to R1 and R2" mean? Why mention R1/R2 and not U/V?)
+					for (int i = 0; i < results.length; i++) {
+						if (!checkExpression(results[i], u, r1, v, r2))
+							return false;
+					}
+					return true;
 				}
-				return true;
-			}
-			checkPrimitive1: if (r1.isPrimitiveType() && !r2.isPrimitiveType()) {
-				// check: each result expression is a standalone expression of a primitive type
-				for (int i = 0; i < results.length; i++) {
-					if (results[i].isPolyExpression() || (results[i].resolvedType != null && !results[i].resolvedType.isPrimitiveType()))
-						break checkPrimitive1;
+				checkPrimitive1: if (r1.isPrimitiveType() && !r2.isPrimitiveType()) {
+					// check: each result expression is a standalone expression of a primitive type
+					for (int i = 0; i < results.length; i++) {
+						if (results[i].isPolyExpression() || (results[i].resolvedType != null && !results[i].resolvedType.isPrimitiveType()))
+							break checkPrimitive1;
+					}
+					return true;
 				}
-				return true;
-			}
-			checkPrimitive2: if (r2.isPrimitiveType() && !r1.isPrimitiveType()) {
-				for (int i = 0; i < results.length; i++) {
-					// for all expressions (not for any expression not)
-					if (!(
-							(!results[i].isPolyExpression() && (results[i].resolvedType != null && !results[i].resolvedType.isPrimitiveType())) // standalone of a referencetype
-							|| results[i].isPolyExpression()))	// or a poly
-						break checkPrimitive2;
-				}
-				return true;
+				checkPrimitive2: if (r2.isPrimitiveType() && !r1.isPrimitiveType()) {
+					for (int i = 0; i < results.length; i++) {
+						// for all expressions (not for any expression not)
+						if (!(
+								(!results[i].isPolyExpression() && (results[i].resolvedType != null && !results[i].resolvedType.isPrimitiveType())) // standalone of a referencetype
+								|| results[i].isPolyExpression()))	// or a poly
+							break checkPrimitive2;
+					}
+					return true;
+				}	
 			}
 			return reduceAndIncorporate(ConstraintTypeFormula.create(r1, r2, ReductionResult.SUBTYPE));
 		} else if (expri instanceof ReferenceExpression && ((ReferenceExpression)expri).isExactMethodReference()) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/IntersectionTypeBinding18.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/IntersectionTypeBinding18.java
index a93c1b5..929dbe6 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/IntersectionTypeBinding18.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/IntersectionTypeBinding18.java
@@ -20,6 +20,7 @@
 
 import java.util.Set;
 
+import org.eclipse.jdt.core.compiler.InvalidInputException;
 import org.eclipse.jdt.internal.compiler.ast.Wildcard;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 
@@ -51,28 +52,24 @@
 	public TypeBinding clone(TypeBinding enclosingType) {
 		return new IntersectionTypeBinding18(this);
 	}
-	
-	public MethodBinding getSingleAbstractMethod(Scope scope, boolean replaceWildcards) {
-		int index = replaceWildcards ? 0 : 1;
-		if (this.singleAbstractMethod != null) {
-			if (this.singleAbstractMethod[index] != null)
-			return this.singleAbstractMethod[index];
-		} else {
-			this.singleAbstractMethod = new MethodBinding[2];
+
+	@Override
+	protected MethodBinding[] getInterfaceAbstractContracts(Scope scope) throws InvalidInputException {
+		int typesLength = this.intersectingTypes.length;
+		MethodBinding[][] methods = new MethodBinding[typesLength][];
+		int contractsLength = 0;
+		for (int i = 0; i < typesLength; i++) {
+			methods[i] = this.intersectingTypes[i].getInterfaceAbstractContracts(scope);
+			contractsLength += methods[i].length;
 		}
-		MethodBinding sam = samProblemBinding;  // guilty unless proven innocent !
-		for (int i = 0; i < this.length; i++) {
-			MethodBinding method = this.intersectingTypes[i].getSingleAbstractMethod(scope, replaceWildcards);
-			if (method != null) {
-				if (method.isValidBinding()) {
-					if (sam.isValidBinding())
-						return this.singleAbstractMethod[index] = new ProblemMethodBinding(TypeConstants.ANONYMOUS_METHOD, null, ProblemReasons.IntersectionHasMultipleFunctionalInterfaces);
-					else
-						sam = method;
-				}
-			}
+		MethodBinding[] contracts = new MethodBinding[contractsLength];
+		int idx = 0;
+		for (int i = 0; i < typesLength; i++) {
+			int len = methods[i].length;
+			System.arraycopy(methods[i], 0, contracts, idx, len);
+			idx += len;
 		}
-		return this.singleAbstractMethod[index] = sam; // I don't see a value in building the notional interface described in 9.8 - it appears just pedantic/normative - perhaps it plays a role in wildcard parameterized types ?
+		return contracts;
 	}
 
 	public boolean hasTypeBit(int bit) { // Stephan ??
@@ -256,21 +253,16 @@
 	}
 
 	public TypeBinding getSAMType(Scope scope) {
-		TypeBinding samType = null;
 		for (int i = 0, max = this.intersectingTypes.length; i < max; i++) {
 			TypeBinding typeBinding = this.intersectingTypes[i];
 			MethodBinding methodBinding = typeBinding.getSingleAbstractMethod(scope, true);
 			// Why doesn't getSingleAbstractMethod do as the javadoc says, and return null
 			// when it is not a SAM type
-			if (methodBinding instanceof ProblemMethodBinding && ((ProblemMethodBinding) methodBinding).problemId()==ProblemReasons.NoSuchSingleAbstractMethod) {
-				continue;
+			if (methodBinding != null && methodBinding.problemId() != ProblemReasons.NoSuchSingleAbstractMethod) {
+				return typeBinding; // answer the first SAM we find
 			}
-			if (samType != null) {
-				return null; // There is more than one (!), so we don't know which
-			}
-			samType = typeBinding;
 		}
-		return samType;
+		return null;
 	}
 
 //{ObjectTeams: enable crossing package boundaries:
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
index 7304f35..7b9c016 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -278,6 +278,12 @@
 	} else if (answer.isSourceType()) {
 		// the type was found as a source model
 		this.typeRequestor.accept(answer.getSourceTypes(), packageBinding, answer.getAccessRestriction());
+		ReferenceBinding binding = packageBinding.getType0(name);
+		String externalAnnotationPath = answer.getExternalAnnotationPath();
+		if (externalAnnotationPath != null && this.globalOptions.isAnnotationBasedNullAnalysisEnabled && binding instanceof SourceTypeBinding) {
+			ExternalAnnotationSuperimposer.apply((SourceTypeBinding) binding, externalAnnotationPath);
+		}
+		return binding;
 	}
 	return packageBinding.getType0(name);
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
index dd98267..8618213 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -119,6 +119,8 @@
 	public TypeVariableBinding[] typeVariables = Binding.NO_TYPE_VARIABLES;
 	char[] signature;
 	public long tagBits;
+	// Used only for constructors
+	protected AnnotationBinding [] typeAnnotations = Binding.NO_ANNOTATIONS;
 
 //{ObjectTeams:
 	public MethodModel model = null;
@@ -1177,6 +1179,22 @@
 	return null;
 }
 
+public TypeVariableBinding[] getAllTypeVariables(boolean isDiamond) {
+	TypeVariableBinding[] allTypeVariables = this.typeVariables;
+	if (isDiamond) {
+		TypeVariableBinding[] classTypeVariables = this.declaringClass.typeVariables();
+		int l1 = allTypeVariables.length;
+		int l2 = classTypeVariables.length;
+		if (l1 == 0) {
+			allTypeVariables = classTypeVariables;
+		} else if (l2 != 0) {
+			System.arraycopy(allTypeVariables, 0, allTypeVariables=new TypeVariableBinding[l1+l2], 0, l1);
+			System.arraycopy(classTypeVariables, 0, allTypeVariables, l1, l2);
+		}
+	}
+	return allTypeVariables;
+}
+
 /**
  * Returns true if method got substituted parameter types
  * (see ParameterizedMethodBinding)
@@ -1404,6 +1422,13 @@
 	buffer.append(')');
 	return buffer.toString().toCharArray();
 }
+final public AnnotationBinding[] getTypeAnnotations() {
+	return this.typeAnnotations;
+}
+
+public void setTypeAnnotations(AnnotationBinding[] annotations) {
+	this.typeAnnotations = annotations;
+}
 public void setAnnotations(AnnotationBinding[] annotations) {
 	this.declaringClass.storeAnnotations(this, annotations);
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java
index 67e6e83..8d08f05 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -663,7 +663,7 @@
 		// the erasure of the return type and thrown types of m's type."
 		if (substitute)
 			type = Scope.substitute(this, type);
-		return env.convertToRawType(type, true);
+		return env.convertToRawType(type.erasure(), true);
 	}
 
 	/*
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReasons.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReasons.java
index 3c3464c..04438a8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReasons.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReasons.java
@@ -38,7 +38,7 @@
 	final int VarargsElementTypeNotVisible = 16;
 	final int NoSuchSingleAbstractMethod = 17;
 	final int NotAWellFormedParameterizedType = 18;
-	final int IntersectionHasMultipleFunctionalInterfaces = 19;
+	// no longer in use: final int IntersectionHasMultipleFunctionalInterfaces = 19;
 	final int NonStaticOrAlienTypeReceiver = 20;
 	final int AttemptToBypassDirectSuper = 21; // super access within default method
 	final int DefectiveContainerAnnotationType = 22;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
index 0c878c4..9206ec8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -2389,7 +2389,7 @@
 	return null;
 }
 // SH}
-private MethodBinding [] getInterfaceAbstractContracts(Scope scope) throws InvalidInputException {
+protected MethodBinding [] getInterfaceAbstractContracts(Scope scope) throws InvalidInputException {
 	
 	if (!isInterface() || !isValidBinding()) {
 		throw new InvalidInputException("Not a functional interface"); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
index 98f4f35..2d969cd 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -2928,15 +2928,15 @@
 								if (compatibleMethod != null) {
 									if (compatibleMethod.isValidBinding()) {
 										if (compatibleMethod.canBeSeenBy(unitScope.fPackage)) {
+											if (!skipOnDemand && !importBinding.onDemand) {
+												visible = null; // forget previous matches from on demand imports
+												skipOnDemand = true;
+											}
 											if (visible == null || !visible.contains(compatibleMethod)) {
 												ImportReference importReference = importBinding.reference;
 												if (importReference != null) {
 													importReference.bits |= ASTNode.Used;
 												}
-												if (!skipOnDemand && !importBinding.onDemand) {
-													visible = null; // forget previous matches from on demand imports
-													skipOnDemand = true;
-												}
 												if (visible == null)
 													visible = new ObjectVector(3);
 												visible.add(compatibleMethod);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
index 9004d2b..35e52b1 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -66,12 +66,14 @@
 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
 import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ReferenceExpression;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
 import org.eclipse.jdt.internal.compiler.ast.TypeReference;
 import org.eclipse.jdt.internal.compiler.ast.TypeReference.AnnotationPosition;
 import org.eclipse.jdt.internal.compiler.ast.Expression.DecapsulationState;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationProvider;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions.WeavingScheme;
@@ -181,6 +183,8 @@
 	private int lambdaOrdinal = 0;
 	private ReferenceBinding containerAnnotationType = null;
 	
+	public ExternalAnnotationProvider externalAnnotationProvider;

+	

 public SourceTypeBinding(char[][] compoundName, PackageBinding fPackage, ClassScope scope) {
 //{ObjectTeams:	// share model from TypeDeclaration:
 	super(scope.referenceContext.getModel());
@@ -843,17 +847,47 @@
 	
 	// Create a $deserializeLambda$ method if necessary, one is shared amongst all lambdas
 	if (lambda.isSerializable) {
-		SyntheticMethodBinding[] deserializeLambdaMethods = (SyntheticMethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL].get(TypeConstants.DESERIALIZE_LAMBDA);
-		if (deserializeLambdaMethods == null) {
-			SyntheticMethodBinding deserializeLambdaMethod = new SyntheticMethodBinding(this);
-			this.synthetics[SourceTypeBinding.METHOD_EMUL].put(TypeConstants.DESERIALIZE_LAMBDA,deserializeLambdaMethods = new SyntheticMethodBinding[1]);
-			deserializeLambdaMethods[0] = deserializeLambdaMethod;
-		}
+		addDeserializeLambdaMethod();
 	}
 	
 	return lambdaMethod;
 }
+/*
+ * Add a synthetic method for the reference expression as a place holder for code generation
+ * only if the reference expression's target is serializable 
+ * 
+ */
+public SyntheticMethodBinding addSyntheticMethod(ReferenceExpression ref) {
+	if (!isPrototype()) throw new IllegalStateException();
+	if (!ref.isSerializable)
+		return null;
+	if (this.synthetics == null)
+		this.synthetics = new HashMap[MAX_SYNTHETICS];
+	if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null)
+		this.synthetics[SourceTypeBinding.METHOD_EMUL] = new HashMap(5);
+	
+	SyntheticMethodBinding lambdaMethod = null;
+	SyntheticMethodBinding[] lambdaMethods = (SyntheticMethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL].get(ref);
+	if (lambdaMethods == null) {
+		lambdaMethod = new SyntheticMethodBinding(ref, this);
+		this.synthetics[SourceTypeBinding.METHOD_EMUL].put(ref, lambdaMethods = new SyntheticMethodBinding[1]);
+		lambdaMethods[0] = lambdaMethod;
+	} else {
+		lambdaMethod = lambdaMethods[0];
+	}
 
+	// Create a $deserializeLambda$ method, one is shared amongst all lambdas
+	addDeserializeLambdaMethod();	
+	return lambdaMethod;
+}
+private void addDeserializeLambdaMethod() {
+	SyntheticMethodBinding[] deserializeLambdaMethods = (SyntheticMethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL].get(TypeConstants.DESERIALIZE_LAMBDA);
+	if (deserializeLambdaMethods == null) {
+		SyntheticMethodBinding deserializeLambdaMethod = new SyntheticMethodBinding(this);
+		this.synthetics[SourceTypeBinding.METHOD_EMUL].put(TypeConstants.DESERIALIZE_LAMBDA,deserializeLambdaMethods = new SyntheticMethodBinding[1]);
+		deserializeLambdaMethods[0] = deserializeLambdaMethod;
+	}
+}
 /* Add a new synthetic access method for access to <targetMethod>.
  * Must distinguish access method used for super access from others (need to use invokespecial bytecode)
 	Answer the new method or the existing method if one already existed.
@@ -2335,7 +2369,7 @@
 					// enum constants neither have a type declaration nor can they be null
 					field.tagBits |= TagBits.AnnotationNonNull;
 				} else {
-					if (hasNonNullDefaultFor(DefaultLocationField, sourceLevel >= ClassFileConstants.JDK1_8)) {
+					if (hasNonNullDefaultFor(DefaultLocationField, this.environment.usesNullTypeAnnotations())) {
 						field.fillInDefaultNonNullness(fieldDecl, initializationScope);
 					}
 					// validate null annotation:
@@ -2346,6 +2380,9 @@
 		} finally {
 		    initializationScope.initializedField = previousField;
 		}
+		if (this.externalAnnotationProvider != null) {
+			ExternalAnnotationSuperimposer.annotateFieldBinding(field, this.externalAnnotationProvider, this.environment);
+		}
 //{ObjectTeams: copy-inherited fields and anchored types:
 		if (fieldDecls[f].getKind() != AbstractVariableDeclaration.ENUM_CONSTANT) {
 			if (fieldDecls[f].type == null)  // should not happen for non-enum types
@@ -2685,6 +2722,13 @@
 					rejectTypeAnnotatedVoidMethod(methodDecl);
 			}
 		}
+	} else {
+		if (sourceLevel >= ClassFileConstants.JDK1_8) {
+			Annotation [] annotations = methodDecl.annotations;
+			if (annotations != null && annotations.length != 0) {
+				ASTNode.copySE8AnnotationsToType(methodDecl.scope, method, methodDecl.annotations, false);
+			}
+		}
 	}
 	if (foundArgProblem) {
 		methodDecl.binding = null;
@@ -2727,6 +2771,9 @@
 		return method; // but its still unresolved with a null return type & is still connected to its method declaration
 
 	method.modifiers &= ~ExtraCompilerModifiers.AccUnresolved;
+	if (this.externalAnnotationProvider != null) {
+		ExternalAnnotationSuperimposer.annotateMethodBinding(method, this.externalAnnotationProvider, this.environment);
+	}
 //{ObjectTeams: need role method bridges?
 	int abstractStatic = ClassFileConstants.AccAbstract | ClassFileConstants.AccStatic;
 	if (   isRole() 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java
index 6cd03d7..1b76da9 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -23,6 +23,7 @@
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
+import org.eclipse.jdt.internal.compiler.ast.ReferenceExpression;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
 import org.eclipse.jdt.internal.compiler.util.Util;
@@ -43,7 +44,11 @@
 	public MethodBinding targetMethod;			// method or constructor
 	public TypeBinding targetEnumType; 			// enum type
 	public LambdaExpression lambda;
-	
+	/**
+	 * Method reference expression whose target FI is Serializable. Should be set when
+	 * purpose is {@link #SerializableMethodReference}
+	 */
+	public ReferenceExpression serializableMethodRef;
 	public int purpose;
 
 	// fields used to generate enum constants when too many
@@ -67,11 +72,16 @@
 	public static final int ArrayClone = 15; // X[]::clone
     public static final int FactoryMethod = 16; // for indy call to private constructor.
     public static final int DeserializeLambda = 17; // For supporting lambda deserialization.
+    /**
+     * Serves as a placeholder for a method reference whose target FI is Serializable.
+     * Is never directly materialized in bytecode
+     */
+    public static final int SerializableMethodReference = 18;
 //{ObjectTeams: other purposes:
-	public final static int InferredCalloutToField = 18; // calling an inferred callout-to-field
-	public final static int RoleMethodBridgeOuter = 19; // a team-level bridge method towards a private role method (for callout)
-	public final static int RoleMethodBridgeInner = 20; // a role-level bridge method towards a private role method (for callout)
-	public final static int MethodDecapsulation = 21;
+	public final static int InferredCalloutToField = 19; // calling an inferred callout-to-field
+	public final static int RoleMethodBridgeOuter = 20; // a team-level bridge method towards a private role method (for callout)
+	public final static int RoleMethodBridgeInner = 21; // a role-level bridge method towards a private role method (for callout)
+	public final static int MethodDecapsulation = 22;
 // SH}
 
 	public int sourceStart = 0; // start position of the matching declaration
@@ -491,6 +501,21 @@
 		this.index = methodId;
 	}
 
+	public SyntheticMethodBinding(ReferenceExpression ref, SourceTypeBinding declaringClass) {
+		this.serializableMethodRef = ref;
+	    this.declaringClass = declaringClass;
+	    this.selector = ref.binding.selector;
+	    this.modifiers = ref.binding.modifiers;
+		this.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved) | (ref.binding.tagBits & TagBits.HasParameterAnnotations);
+	    this.returnType = ref.binding.returnType;
+	    this.parameters = ref.binding.parameters;
+	    this.thrownExceptions = ref.binding.thrownExceptions;
+	    this.purpose = SyntheticMethodBinding.SerializableMethodReference;
+		SyntheticMethodBinding[] knownAccessMethods = declaringClass.syntheticMethods();
+		int methodId = knownAccessMethods == null ? 0 : knownAccessMethods.length;
+		this.index = methodId;
+	}
+
 	public SyntheticMethodBinding(MethodBinding privateConstructor, MethodBinding publicConstructor, char[] selector, TypeBinding[] enclosingInstances, SourceTypeBinding declaringClass) {
 	    this.declaringClass = declaringClass;
 	    this.selector = selector;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java
index 23fbd34..4546476 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -1663,11 +1663,12 @@
 // SH}
 
 /**
- * Return the single abstract method of a functional interface, or null, if the receiver is not a functional interface as defined in JLS 9.8.
+ * Return the single abstract method of a functional interface, or one of {@code null} or {@link ReferenceBinding#samProblemBinding}, if the receiver is not a functional interface as defined in JLS 9.8.
+ * In particular {@code null} is answered if the receiver is not a reference type, or is a problem type.
  * @param scope scope
  * @param replaceWildcards Should wildcards be replaced following JLS 9.8? Say false for lambdas with explicit argument types which should apply 18.5.3
  *  
- * @return The single abstract method of a functional interface, or null, if the receiver is not a functional interface. 
+ * @return The single abstract method of a functional interface, or one of {@code null} or {@link ReferenceBinding#samProblemBinding}, if the receiver is not a functional interface. 
  */
 public MethodBinding getSingleAbstractMethod(Scope scope, boolean replaceWildcards) {
 	return null;
@@ -1780,4 +1781,8 @@
 public long updateTagBits() {
 	return this.tagBits & TagBits.HasNullTypeAnnotation; // subclasses to override
 }
+
+public boolean isFreeTypeVariable() {
+	return false;
+}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBindingVisitor.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBindingVisitor.java
index 99f1bae..faca34a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBindingVisitor.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBindingVisitor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2013 IBM Corporation and others.
+ * Copyright (c) 2013, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -18,6 +18,10 @@
 
 	private SimpleLookupTable visitedCache;
 
+	public void reset() {
+		this.visitedCache = null;
+	}
+
 	public boolean visit(BaseTypeBinding baseTypeBinding)  {
 		return true;  // continue traversal.
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java
index baa1c68..b3d6f59 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -126,6 +126,7 @@
 	// Constant compound names
 	char[][] JAVA_LANG = {JAVA, LANG};
 	char[][] JAVA_IO = {JAVA, IO};
+	char[][] JAVA_LANG_ANNOTATION = {JAVA, LANG, ANNOTATION};
 	char[][] JAVA_LANG_ANNOTATION_ANNOTATION = {JAVA, LANG, ANNOTATION, "Annotation".toCharArray()}; //$NON-NLS-1$
 	char[][] JAVA_LANG_ASSERTIONERROR = {JAVA, LANG, "AssertionError".toCharArray()}; //$NON-NLS-1$
 	char[][] JAVA_LANG_CLASS = {JAVA, LANG, "Class".toCharArray()}; //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeSystem.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeSystem.java
index cbf69ab..769e8f5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeSystem.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeSystem.java
@@ -234,22 +234,25 @@
 				}
 			}
 		}
-		if (type.id == TypeIds.NoId) {
-			if (type.hasTypeAnnotations())
-				throw new IllegalStateException();
-			int typesLength = this.types.length;
-			if (this.typeid == typesLength)
-				System.arraycopy(this.types, 0, this.types = new TypeBinding[typesLength * 2][], 0, typesLength);
-			this.types[type.id = this.typeid++] = new TypeBinding[4];
-			if (urb != null)
+		try {
+			if (type.id == TypeIds.NoId) {
+				if (type.hasTypeAnnotations())
+					throw new IllegalStateException();
+				int typesLength = this.types.length;
+				if (this.typeid == typesLength)
+					System.arraycopy(this.types, 0, this.types = new TypeBinding[typesLength * 2][], 0, typesLength);
+				this.types[type.id = this.typeid++] = new TypeBinding[4];
+			} else {
+				TypeBinding nakedType = this.types[type.id] == null ? null : this.types[type.id][0];
+				if (type.hasTypeAnnotations() && nakedType == null)
+					throw new IllegalStateException();
+				if (nakedType != null)
+					return nakedType;
+				this.types[type.id] = new TypeBinding[4];  // well known type, assigned id elsewhere.
+			}
+		} finally {
+			if (urb != null && urb.id == TypeIds.NoId)
 				urb.id = type.id;
-		} else {
-			TypeBinding nakedType = this.types[type.id] == null ? null : this.types[type.id][0];
-			if (type.hasTypeAnnotations() && nakedType == null)
-				throw new IllegalStateException();
-			if (nakedType != null)
-				return nakedType;
-			this.types[type.id] = new TypeBinding[4];  // well known type, assigned id elsewhere.
 		}
 	
 		return this.types[type.id][0] = type;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java
index 8147618..5e723f8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java
@@ -44,10 +44,10 @@
 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.ast.Annotation;
 import org.eclipse.jdt.internal.compiler.ast.NullAnnotationMatching;
+import org.eclipse.jdt.internal.compiler.ast.NullAnnotationMatching.CheckMode;
 import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
 import org.eclipse.jdt.internal.compiler.ast.TypeReference;
 import org.eclipse.jdt.internal.compiler.ast.Wildcard;
-import org.eclipse.jdt.internal.compiler.ast.NullAnnotationMatching.CheckMode;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants.BoundCheckStatus;
@@ -248,7 +248,7 @@
 				}
 	    	}
 			if (location != null && checkNullAnnotations) {
-				if (NullAnnotationMatching.analyse(this, argumentType, substitutedSuperType, substitution, -1, CheckMode.BOUND_CHECK).isAnyMismatch()) {
+				if (NullAnnotationMatching.analyse(this, argumentType, substitutedSuperType, substitution, -1, null, CheckMode.BOUND_CHECK).isAnyMismatch()) {
 					scope.problemReporter().nullityMismatchTypeArgument(this, argumentType, location);
 					haveReportedNullProblem = true;
 				}
@@ -309,7 +309,7 @@
 				}
 	    	}
 			if (location != null && checkNullAnnotations) {
-				if (NullAnnotationMatching.analyse(this, argumentType, substitutedSuperType, substitution, -1, CheckMode.BOUND_CHECK).isAnyMismatch()) {
+				if (NullAnnotationMatching.analyse(this, argumentType, substitutedSuperType, substitution, -1, null, CheckMode.BOUND_CHECK).isAnyMismatch()) {
 					scope.problemReporter().nullityMismatchTypeArgument(this, argumentType, location);
 					haveReportedNullProblem = true;
 				}
@@ -1190,4 +1190,11 @@
 		}
 		return super.updateTagBits();
 	}
+
+	@Override
+	public boolean isFreeTypeVariable() {
+		return this.environment.usesNullTypeAnnotations() 
+				&& this.environment.globalOptions.pessimisticNullAnalysisForFreeTypeVariablesEnabled 
+				&& (this.tagBits & TagBits.AnnotationNullMASK) == 0;	
+	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/messages.properties b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/messages.properties
index 614d5ac..1d1a5bb 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/messages.properties
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/messages.properties
@@ -1,5 +1,5 @@
 ###############################################################################
-# Copyright (c) 2000, 2009 IBM Corporation and others.
+# Copyright (c) 2000, 2016 IBM Corporation and others.
 # All rights reserved. This program and the accompanying materials
 # are made available under the terms of the Eclipse Public License v1.0
 # which accompanies this distribution, and is available at
@@ -39,6 +39,7 @@
 abort_missingCode = Missing code implementation in the compiler
 abort_againstSourceModel = Cannot compile against source model {0} issued from {1}
 abort_invalidOpcode = SANITY CHECK: Invalid opcode {0} at pc {1} for stackmap table attribute for method {2}
+abort_externaAnnotationFile = Failed to read external annotations for {0} from {1} due to an exception: {2}
 
 ### accept
 accept_cannot = Cannot accept the compilation unit:
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemHandler.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemHandler.java
index a43819c..3927198 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemHandler.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemHandler.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -50,6 +50,8 @@
 	/* When temporarily switching policies, store here the original root policy (for temporary resume). */
 	private IErrorHandlingPolicy rootPolicy;
 
+	protected boolean suppressTagging = false;
+
 //{ObjectTeams: support for passing a rechecker:
 	public IProblemRechecker rechecker;
 // SH}
@@ -323,7 +325,9 @@
 //{ObjectTeams: problems with a rechecker are considered "optional", don't tag the reference context
 			  if (!requireRecheck)
 // SH}
-				referenceContext.tagAsHavingErrors();
+				if (!this.suppressTagging || this.options.treatOptionalErrorAsFatal) {
+					referenceContext.tagAsHavingErrors();
+				}
 				// should abort ?
 				int abortLevel;
 				if ((abortLevel = this.policy.stopOnFirstError() ? ProblemSeverities.AbortCompilation : severity & ProblemSeverities.Abort) != 0) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
index 59c3bcd..4353449 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -468,8 +468,6 @@
 		case IProblem.CannotImplementIncompatibleNullness:
 		case IProblem.ConflictingNullAnnotations:
 		case IProblem.ConflictingInheritedNullAnnotations:
-		case IProblem.NullNotCompatibleToFreeTypeVariable:
-		case IProblem.NullityMismatchAgainstFreeTypeVariable:
 		case IProblem.NullityMismatchingTypeAnnotation:
 		case IProblem.NullityMismatchingTypeAnnotationSuperHint:
 		case IProblem.NullityMismatchTypeArgument:
@@ -483,6 +481,18 @@
 		case IProblem.ContradictoryNullAnnotationsInferredFunctionType:
 			return CompilerOptions.NullSpecViolation;
 
+		case IProblem.NullNotCompatibleToFreeTypeVariable:
+		case IProblem.NullityMismatchAgainstFreeTypeVariable:
+		case IProblem.UncheckedAccessOfValueOfFreeTypeVariable:
+		case IProblem.RequiredNonNullButProvidedFreeTypeVariable:
+		case IProblem.UninitializedFreeTypeVariableField:
+		case IProblem.UninitializedFreeTypeVariableFieldHintMissingDefault:
+			return CompilerOptions.PessimisticNullAnalysisForFreeTypeVariables;
+
+		case IProblem.NonNullTypeVariableFromLegacyMethod:
+		case IProblem.NonNullMethodTypeVariableFromLegacyMethod:
+			return CompilerOptions.NonNullTypeVariableFromLegacyInvocation;
+
 		case IProblem.ParameterLackingNonNullAnnotation:
 			return CompilerOptions.NonnullParameterAnnotationDropped;
 
@@ -815,6 +825,8 @@
 			case CompilerOptions.UnusedObjectAllocation :
 			case CompilerOptions.UnclosedCloseable :
 			case CompilerOptions.PotentiallyUnclosedCloseable :
+			case CompilerOptions.PessimisticNullAnalysisForFreeTypeVariables :
+			case CompilerOptions.NonNullTypeVariableFromLegacyInvocation :
 				return CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM;
 			
 			case CompilerOptions.OverriddenPackageDefaultMethod :
@@ -1344,6 +1356,15 @@
 		location.sourceStart,
 		location.sourceEnd);
 }
+public void bytecodeExceeds64KLimit(MethodBinding method, int start, int end) {
+	this.handle(
+		IProblem.BytecodeExceeds64KLimit,
+		new String[] {new String(method.selector), typesAsString(method, false)},
+		new String[] {new String(method.selector), typesAsString(method, true)},
+		ProblemSeverities.Error | ProblemSeverities.Abort | ProblemSeverities.Fatal,
+		start,
+		end);
+}
 public void bytecodeExceeds64KLimit(AbstractMethodDeclaration location) {
 	MethodBinding method = location.binding;
 	if (location.isConstructor()) {
@@ -1355,24 +1376,11 @@
 			location.sourceStart,
 			location.sourceEnd);
 	} else {
-		this.handle(
-			IProblem.BytecodeExceeds64KLimit,
-			new String[] {new String(location.selector), typesAsString(method, false)},
-			new String[] {new String(location.selector), typesAsString(method, true)},
-			ProblemSeverities.Error | ProblemSeverities.Abort | ProblemSeverities.Fatal,
-			location.sourceStart,
-			location.sourceEnd);
+		bytecodeExceeds64KLimit(method,	location.sourceStart, location.sourceEnd);
 	}
 }
 public void bytecodeExceeds64KLimit(LambdaExpression location) {
-	MethodBinding method = location.binding;
-		this.handle(
-			IProblem.BytecodeExceeds64KLimit,
-			new String[] {new String(method.selector), typesAsString(method, false)},
-			new String[] {new String(method.selector), typesAsString(method, true)},
-			ProblemSeverities.Error | ProblemSeverities.Abort | ProblemSeverities.Fatal,
-			location.sourceStart,
-			location.diagnosticsSourceEnd());
+	bytecodeExceeds64KLimit(location.binding, location.sourceStart, location.diagnosticsSourceEnd());
 }
 public void bytecodeExceeds64KLimit(TypeDeclaration location) {
 	this.handle(
@@ -1459,7 +1467,7 @@
 }
 public void cannotImportPackage(ImportReference importRef) {
 	String[] arguments = new String[] {CharOperation.toString(importRef.tokens)};
-	this.handle(
+	this.handleUntagged(
 		IProblem.CannotImportPackage,
 		arguments,
 		arguments,
@@ -1816,7 +1824,7 @@
 }
 public void conflictingImport(ImportReference importRef) {
 	String[] arguments = new String[] {CharOperation.toString(importRef.tokens)};
-	this.handle(
+	this.handleUntagged(
 		IProblem.ConflictingImport,
 		arguments,
 		arguments,
@@ -2036,7 +2044,7 @@
 }
 public void duplicateImport(ImportReference importRef) {
 	String[] arguments = new String[] {CharOperation.toString(importRef.tokens)};
-	this.handle(
+	this.handleUntagged(
 		IProblem.DuplicateImport,
 		arguments,
 		arguments,
@@ -2700,6 +2708,20 @@
 			problemEndPosition);
 }
 
+protected void handleUntagged(
+			int problemId,
+			String[] problemArguments,
+			String[] messageArguments,
+			int problemStartPosition,
+			int problemEndPosition) {
+	boolean oldSuppressing = this.suppressTagging;
+	this.suppressTagging = true;
+	try {
+		this.handle(problemId, problemArguments, messageArguments, problemStartPosition, problemEndPosition);
+	} finally {
+		this.suppressTagging = oldSuppressing;
+	}
+}
 public void hiddenCatchBlock(ReferenceBinding exceptionType, ASTNode location) {
 	this.handle(
 		IProblem.MaskedCatch,
@@ -3363,7 +3385,7 @@
 				shortArguments = new String[] {new String(field.declaringClass.leafComponentType().shortReadableName())};
 				break;
 		}
-		this.handle(
+		this.handleUntagged(
 			id,
 			readableArguments,
 			shortArguments,
@@ -3377,7 +3399,7 @@
 			? ((ProblemReferenceBinding) expectedImport).compoundName
 			: importRef.tokens;
 		String[] arguments = new String[]{CharOperation.toString(tokens)};
-		this.handle(
+		this.handleUntagged(
 		        IProblem.ImportNotFound,
 		        arguments,
 		        arguments,
@@ -3388,7 +3410,7 @@
 	if (expectedImport.problemId() == ProblemReasons.InvalidTypeForStaticImport) {
 		char[][] tokens = importRef.tokens;
 		String[] arguments = new String[]{CharOperation.toString(tokens)};
-		this.handle(
+		this.handleUntagged(
 		        IProblem.InvalidTypeForStaticImport,
 		        arguments,
 		        arguments,
@@ -6439,7 +6461,54 @@
 		nodeSourceEnd(local, location));
 }
 
+public void fieldFreeTypeVariableReference(FieldBinding variable, long position) {
+	char[][] nullableName = this.options.nullableAnnotationName;
+	String[] arguments = new String[] {new String(variable.type.readableName()), 
+			new String(nullableName[nullableName.length-1])};
+	this.handle(
+		IProblem.UncheckedAccessOfValueOfFreeTypeVariable,
+		arguments,
+		arguments,
+		(int)(position >>> 32),
+		(int)position);
+}
+
+
+public void localVariableFreeTypeVariableReference(LocalVariableBinding local, ASTNode location) {
+	int severity = computeSeverity(IProblem.UncheckedAccessOfValueOfFreeTypeVariable);
+	if (severity == ProblemSeverities.Ignore) return;
+	char[][] nullableName = this.options.nullableAnnotationName;
+	String[] arguments = new String[] {new String(local.type.readableName()), 
+			new String(nullableName[nullableName.length-1])};
+	this.handle(
+		IProblem.UncheckedAccessOfValueOfFreeTypeVariable,
+		arguments,
+		arguments,
+		severity,
+		nodeSourceStart(local, location),
+		nodeSourceEnd(local, location));
+}
+
+public void methodReturnTypeFreeTypeVariableReference(MethodBinding method, ASTNode location) {
+	int severity = computeSeverity(IProblem.UncheckedAccessOfValueOfFreeTypeVariable);
+	if (severity == ProblemSeverities.Ignore) return;
+	char[][] nullableName = this.options.nullableAnnotationName;
+	String[] arguments = new String[] {new String(method.returnType.readableName()), 
+			new String(nullableName[nullableName.length-1])};
+	this.handle(
+		IProblem.UncheckedAccessOfValueOfFreeTypeVariable,
+		arguments,
+		arguments,
+		location.sourceStart,
+		location.sourceEnd);
+}
+
+
 public void localVariablePotentialNullReference(LocalVariableBinding local, ASTNode location) {
+	if(local.type.isFreeTypeVariable()) {
+		localVariableFreeTypeVariableReference(local, location);
+		return;
+	}
 	if (location instanceof Expression && (((Expression)location).implicitConversion & TypeIds.UNBOXING) != 0) {
 		potentialNullUnboxing(location, local.type);
 		return;
@@ -8834,6 +8903,20 @@
 }
 public void uninitializedNonNullField(FieldBinding field, ASTNode location) {
 	char[][] nonNullAnnotationName = this.options.nonNullAnnotationName;
+	if(!field.isNonNull()) {
+		String[] arguments = new String[] {
+				new String(field.readableName()), 
+				new String(field.type.readableName()), 
+				new String(nonNullAnnotationName[nonNullAnnotationName.length-1])
+		};
+		this.handle(
+				methodHasMissingSwitchDefault() ? IProblem.UninitializedFreeTypeVariableFieldHintMissingDefault : IProblem.UninitializedFreeTypeVariableField,
+				arguments,
+				arguments,
+				nodeSourceStart(field, location),
+				nodeSourceEnd(field, location));	
+		return;
+	}
 	String[] arguments = new String[] {
 			new String(nonNullAnnotationName[nonNullAnnotationName.length-1]),
 			new String(field.readableName())
@@ -9964,6 +10047,10 @@
 		if (var == null && expression instanceof Reference) {
 			var = ((Reference)expression).lastFieldBinding();
 		}
+		if(var != null && var.type.isFreeTypeVariable()) {			
+			nullityMismatchVariableIsFreeTypeVariable(var, expression);
+			return;
+		}
 		if (var != null && var.isNullable()) {
 					nullityMismatchSpecdNullable(expression, requiredType, annotationName);
 					return;
@@ -13663,6 +13750,21 @@
 
 // SH}
 
+private void nullityMismatchIsFreeTypeVariable(TypeBinding providedType, int sourceStart, int sourceEnd) {
+	char[][] nullableName = this.options.nullableAnnotationName;
+	char[][] nonNullName = this.options.nonNullAnnotationName;
+	String[] arguments = new String[] { 
+			new String(nonNullName[nonNullName.length-1]), 
+			new String(providedType.readableName()), 
+			new String(nullableName[nullableName.length-1])};
+	this.handle(IProblem.RequiredNonNullButProvidedFreeTypeVariable, arguments, arguments, sourceStart, sourceEnd);
+}
+public void nullityMismatchVariableIsFreeTypeVariable(VariableBinding variable, ASTNode location) {
+	int severity = computeSeverity(IProblem.RequiredNonNullButProvidedFreeTypeVariable);
+	if (severity == ProblemSeverities.Ignore) return;
+	nullityMismatchIsFreeTypeVariable(variable.type, nodeSourceStart(variable, location),
+			nodeSourceEnd(variable, location));
+}
 public void illegalRedefinitionToNonNullParameter(Argument argument, ReferenceBinding declaringClass, char[][] inheritedAnnotationName) {
 	int sourceStart = argument.type.sourceStart;
 	if (argument.annotations != null) {
@@ -14189,6 +14291,11 @@
 			&& (requiredType.tagBits & TagBits.AnnotationNonNull) != 0 
 			&& (providedType.tagBits & TagBits.AnnotationNullable) == 0)
 	{
+		if(this.options.pessimisticNullAnalysisForFreeTypeVariablesEnabled && providedType.isTypeVariable() && !providedType.hasNullTypeAnnotations()) {
+			nullityMismatchIsFreeTypeVariable(providedType, expression.sourceStart, expression.sourceEnd);
+			return;
+		}
+
 		nullityMismatchPotentiallyNull(expression, requiredType, this.options.nonNullAnnotationName);
 		return;
 	}
@@ -14284,7 +14391,54 @@
 			ProblemSeverities.Warning,
 			reference.sourceStart, reference.sourceEnd);
 }
+public void nonNullTypeVariableInUnannotatedBinary(LookupEnvironment environment, MethodBinding method, Expression expression, int providedSeverity) {
+	TypeBinding declaredReturnType = method.original().returnType;
+	int severity = computeSeverity(IProblem.NonNullTypeVariableFromLegacyMethod);
+	if ((severity & ProblemSeverities.CoreSeverityMASK) == ProblemSeverities.Warning)
+		severity = providedSeverity; // leverage the greater precision from our caller
+	if (declaredReturnType instanceof TypeVariableBinding) { // paranoia check
+		TypeVariableBinding typeVariable = (TypeVariableBinding) declaredReturnType;
+		TypeBinding declaringClass = method.declaringClass;
 
+		char[][] nonNullName = this.options.nonNullAnnotationName;
+		String shortNonNullName = String.valueOf(nonNullName[nonNullName.length-1]);
+		
+		if (typeVariable.declaringElement instanceof ReferenceBinding) {
+			String[] arguments = new String[] {
+					shortNonNullName,
+					String.valueOf(declaringClass.nullAnnotatedReadableName(this.options, false)),
+					String.valueOf(declaringClass.original().readableName())};
+			String[] shortArguments = {
+					shortNonNullName,
+					String.valueOf(declaringClass.nullAnnotatedReadableName(this.options, true)),
+					String.valueOf(declaringClass.original().shortReadableName()) };
+			this.handle(IProblem.NonNullTypeVariableFromLegacyMethod,
+					arguments, 
+					shortArguments,
+					severity,
+					expression.sourceStart,
+					expression.sourceEnd);
+		} else if (typeVariable.declaringElement instanceof MethodBinding && method instanceof ParameterizedGenericMethodBinding) {
+			TypeBinding substitution = ((ParameterizedGenericMethodBinding) method).typeArguments[typeVariable.rank];
+			String[] arguments = new String[] {
+					shortNonNullName,
+					String.valueOf(typeVariable.readableName()),
+					String.valueOf(substitution.nullAnnotatedReadableName(this.options, false)),
+					String.valueOf(declaringClass.original().readableName())};
+			String[] shortArguments = {
+					shortNonNullName,
+					String.valueOf(typeVariable.shortReadableName()),
+					String.valueOf(substitution.nullAnnotatedReadableName(this.options, true)),
+					String.valueOf(declaringClass.original().shortReadableName()) };
+			this.handle(IProblem.NonNullMethodTypeVariableFromLegacyMethod,
+					arguments, 
+					shortArguments, 
+					severity,
+					expression.sourceStart,
+					expression.sourceEnd);			
+		}
+	}
+}
 public void dereferencingNullableExpression(Expression expression) {
 	if (expression instanceof MessageSend) {
 		MessageSend send = (MessageSend) expression;
@@ -14340,14 +14494,6 @@
 			typeReference.sourceEnd);
 }
 
-public void multipleFunctionalInterfaces(FunctionalExpression functionalExpression) {
-	this.handle(
-			IProblem.MultipleFunctionalInterfaces,
-			NoArgument,
-			NoArgument,
-			functionalExpression.sourceStart,
-			functionalExpression.diagnosticsSourceEnd());
-}
 public void lambdaRedeclaresArgument(Argument argument) {
 	String[] arguments = new String[] {new String(argument.name)};
 	this.handle(
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemSeverities.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemSeverities.java
index c6e2e21..dca13cc 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemSeverities.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemSeverities.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -31,4 +31,6 @@
 //{ObjectTeams: signal problem that should be ignored, but yet recorded to match potential @SuppressWarnings
 	final int IgnoredGenerated = 2048;
 // SH}
+
+	final int CoreSeverityMASK = Warning | Error | Info | Ignore;
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
index 353784d..03f3c63 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
@@ -1,5 +1,5 @@
 ###############################################################################
-# Copyright (c) 2000, 2015 IBM Corporation and others.
+# Copyright (c) 2000, 2016 IBM Corporation and others.
 # All rights reserved. This program and the accompanying materials
 # are made available under the terms of the Eclipse Public License v1.0
 # which accompanies this distribution, and is available at
@@ -759,7 +759,7 @@
 892 = Base types are not allowed in intersection cast operator
 893 = Arrays are not allowed in intersection cast operator
 894 = Duplicate type in intersection cast operator
-895 = The target type of this expression is not a functional interface: more than one of the intersecting interfaces are functional
+#[obsolete] 895 = The target type of this expression is not a functional interface: more than one of the intersecting interfaces are functional
 896 = Static methods are allowed in interfaces only at source level 1.8 or above
 
 897 = Duplicate annotation of non-repeatable type @{0}. Only annotation types marked @Repeatable can be used multiple times at one target.
@@ -834,6 +834,13 @@
 973 = Contradictory null annotations: function type was inferred as ''{2} ({4})'', but only one of ''@{0}'' and ''@{1}'' can be effective at any location
 974 = The return type is incompatible with the free type variable ''{1}'' returned from {0} (mismatching null constraints)
 975 = Cannot redefine null constraints of type variable ''{0}'' declared in ''{1}''
+976 = Potential null pointer access: this expression has type ''{0}'', a free type variable that may represent a ''@{1}'' type
+977 = The field {0} may not have been initialized, whereas its type ''{1}'' is a free type variable that may represent a ''@{2}'' type
+978 = The field {0} may not have been initialized, whereas its type ''{1}'' is a free type variable that may represent a ''@{2}'' type. Note that a problem regarding missing ''default:'' on ''switch'' has been suppressed, which is perhaps related to this problem
+979 = Null type safety: required ''@{0}'' but this expression has type ''{1}'', a free type variable that may represent a ''@{2}'' type
+980 = Unsafe interpretation of method return type as ''@{0}'' based on the receiver type ''{1}''. Type ''{2}'' doesn't seem to be designed with null type annotations in mind
+981 = Unsafe interpretation of method return type as ''@{0}'' based on substitution ''{1}={2}''. Declaring type ''{3}'' doesn't seem to be designed with null type annotations in mind
+
 
 # Java 8
 1001 = Syntax error, modifiers and annotations are not allowed for the lambda parameter {0} as its type is elided
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Messages.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Messages.java
index 5eded19..317d830 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Messages.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Messages.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -100,6 +100,7 @@
 	public static String abort_invalidOpcode;
 	public static String abort_missingCode;
 	public static String abort_againstSourceModel;
+	public static String abort_externaAnnotationFile;
 	public static String accept_cannot;
 	public static String parser_incorrectPath;
 	public static String parser_moveFiles;
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationBinding.java
index 5475581..0e8f6db 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationBinding.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AnnotationBinding.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2005, 2015 BEA Systems, Inc.
+ * Copyright (c) 2005, 2011 BEA Systems, Inc.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -28,7 +28,6 @@
  */
 class AnnotationBinding implements IAnnotationBinding {
 	static final AnnotationBinding[] NoAnnotations = new AnnotationBinding[0];
-	static final AnnotationBinding[][] NoAnnotationsOnDimensions = new AnnotationBinding[0][];
 	private org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding binding;
 	private BindingResolver bindingResolver;
 	private String key;
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ITypeBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ITypeBinding.java
index f1caf75..ea9f555 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ITypeBinding.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ITypeBinding.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -299,6 +299,9 @@
 	 * Returns the binding representing the element type of this array type,
 	 * or <code>null</code> if this is not an array type binding. The element
 	 * type of an array type is never itself an array type.
+	 * 
+	 * To get the type annotations on dimensions, clients should repeatedly
+	 *  call getComponentType() and get the type annotations from there. 
 	 *
 	 * @return the element type binding, or <code>null</code> if this is
 	 *   not an array type
@@ -563,6 +566,9 @@
 	 * <li>java.lang.String</li>
 	 * </ul>
 	 * </p>
+	 * To get the type annotations on dimensions, clients should repeatedly call 
+	 * {@link #getComponentType()} and get the type annotations from there. 
+
 	 * @return type annotations specified on this type reference, or an empty array if
 	 * no type use annotations are found.
 	 * @see #getTypeDeclaration()
@@ -572,23 +578,6 @@
 	public IAnnotationBinding[] getTypeAnnotations();
 
 	/**
-	 * Returns the type use annotations on dimensions, or the empty array if there
-	 * are no annotations on dimensions.
-	 * 
-	 * <p>
-	 *  Since JLS8, (Section 9.7.4) type annotations can appear at array dimensions. These annotations
-	 *  are returned in a 2-d array with each row containing annotations for that dimension. If only some
-	 *  of the dimensions have type annotations, the rows corresponding to the dimensions without
-	 *  annotations will have an empty single dimensional array.
-	 * </p>
-	 * 
-	 * @return type annotations specified on the dimensions of this type reference, or an empty array if
-	 * either there is no dimension or no type use annotation is found on the dimensions.
-	 * @since 3.12
-	 */
-	public IAnnotationBinding[][] getTypeAnnotationsOnDimensions();
-
-	/**
 	 * Returns the type arguments of this generic type instance, or the
 	 * empty list for other type bindings.
 	 * <p>
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RecoveredTypeBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RecoveredTypeBinding.java
index ec5abf0..b4a9fdf 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RecoveredTypeBinding.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RecoveredTypeBinding.java
@@ -785,10 +785,6 @@
 		return AnnotationBinding.NoAnnotations;
 	}
 
-	@Override
-	public IAnnotationBinding[][] getTypeAnnotationsOnDimensions() {
-		return AnnotationBinding.NoAnnotationsOnDimensions;
-	}
 //{ObjectTeams: new lookup-functions
 	public org.eclipse.jdt.internal.compiler.lookup.TypeBinding getResolvedBinding() {
 		return this.binding;
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java
index 7a26dbd..5d02bab 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java
@@ -83,7 +83,6 @@
 	private IVariableBinding[] fields;
 	private IAnnotationBinding[] annotations;
 	private IAnnotationBinding[] typeAnnotations;
-	private IAnnotationBinding[][] typeAnnotationsOnDimensions;
 	private IMethodBinding[] methods;
 	private ITypeBinding[] members;
 	private ITypeBinding[] interfaces;
@@ -176,34 +175,6 @@
 		return AnnotationBinding.NoAnnotations;
 	}
 
-	private IAnnotationBinding[][] resolveAnnotationBindingsOnDimensions(org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding[] internalAnnotations) {
-		int length = internalAnnotations == null ? 0 : internalAnnotations.length;
-		if (length != 0) {
-			IAnnotationBinding[][] dimAnnotations = new IAnnotationBinding[length][];
-			int row = 0;
-			List <IAnnotationBinding> tmpList = new ArrayList<>();
-			for (int i = 0; i < length; i++) {
-				org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding internalAnnotation = internalAnnotations[i];
-				if (internalAnnotation == null) {
-					if (tmpList.size() > 0) {
-						dimAnnotations[row] = tmpList.toArray(new AnnotationBinding[0]);
-						tmpList.clear();
-					} else {
-						dimAnnotations[row] = AnnotationBinding.NoAnnotations;
-					}
-					++row;
-				}
-				IAnnotationBinding annotationInstance = this.resolver.getAnnotationInstance(internalAnnotation);
-				if (annotationInstance == null) {
-					continue;
-				}
-				tmpList.add(annotationInstance);
-			}
-			System.arraycopy(dimAnnotations, 0, (dimAnnotations = new IAnnotationBinding[row][]), 0, row);
-			return dimAnnotations;
-		}
-		return AnnotationBinding.NoAnnotationsOnDimensions;
-	}
 	/*
 	 * @see ITypeBinding#getBinaryName()
 	 * @since 3.0
@@ -1713,17 +1684,6 @@
 		return this.typeAnnotations;
 	}
 
-	/*
-	 * (non-Javadoc)
-	 * @see org.eclipse.jdt.core.dom.ITypeBinding#getTypeAnnotationsOnDimensions()
-	 */
-	public IAnnotationBinding[][] getTypeAnnotationsOnDimensions() {
-		if (this.typeAnnotationsOnDimensions == null) {
-			this.typeAnnotationsOnDimensions = resolveAnnotationBindingsOnDimensions(this.binding.getTypeAnnotations());
-		}
-		return this.typeAnnotationsOnDimensions;
-	}
-
 	static class LocalTypeBinding extends TypeBinding {
 
 		private IBinding declaringMember;
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSkeleton.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSkeleton.java
index 4687630..950f481 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSkeleton.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSkeleton.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -27,6 +27,7 @@
 import org.eclipse.jdt.internal.compiler.env.IBinaryTypeAnnotation;
 import org.eclipse.jdt.internal.compiler.env.ITypeAnnotationWalker;
 import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
+import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.ExternalAnnotationStatus;
 import org.eclipse.jdt.internal.core.util.Util;
 
 /**
@@ -197,4 +198,8 @@
 public ITypeAnnotationWalker enrichWithExternalAnnotationsFor(ITypeAnnotationWalker walker, Object member, LookupEnvironment environment) {
 	return walker;
 }
+@Override
+public ExternalAnnotationStatus getExternalAnnotationStatus() {
+	return ExternalAnnotationStatus.NOT_EEA_CONFIGURED;
+}
 }
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java
index 6a2d05a..2e24b5a 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java
@@ -73,7 +73,7 @@
 	 * FORMATTER / Option to align groups of members independently if they are separated by a certain number of blank lines
 	 *     - option id:         "org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines"
 	 *     - possible values:   "&lt;n&gt;", where n is a positive integer
-	 *     - default:           "99"
+	 *     - default:           {@code Integer.MAX_VALUE}
 	 * </pre>
 	 * @since 3.12
 	 */
@@ -213,6 +213,18 @@
 	public static final String FORMATTER_ALIGNMENT_FOR_EXPRESSIONS_IN_ARRAY_INITIALIZER = JavaCore.PLUGIN_ID + ".formatter.alignment_for_expressions_in_array_initializer";	 //$NON-NLS-1$
 	/**
 	 * <pre>
+	 * FORMATTER / Option for alignment of initialization, termination, and increment expressions in 'for'
+	 *             loop header
+	 *     - option id:         "org.eclipse.jdt.core.formatter.alignment_for_for_loop_header"
+	 *     - possible values:   values returned by <code>createAlignmentValue(boolean, int, int)</code> call
+	 *     - default:           createAlignmentValue(false, WRAP_NO_SPLIT, INDENT_DEFAULT)
+	 * </pre>
+	 * @see #createAlignmentValue(boolean, int, int)
+	 * @since 3.12
+	 */
+	public static final String FORMATTER_ALIGNMENT_FOR_EXPRESSIONS_IN_FOR_LOOP_HEADER = JavaCore.PLUGIN_ID + ".formatter.alignment_for_expressions_in_for_loop_header";	 //$NON-NLS-1$
+	/**
+	 * <pre>
 	 * FORMATTER / Option for alignment of method declaration
 	 *     - option id:         "org.eclipse.jdt.core.formatter.alignment_for_method_declaration"
 	 *     - possible values:   values returned by <code>createAlignmentValue(boolean, int, int)</code> call
@@ -235,6 +247,17 @@
 	public static final String FORMATTER_ALIGNMENT_FOR_MULTIPLE_FIELDS = JavaCore.PLUGIN_ID + ".formatter.alignment_for_multiple_fields";//$NON-NLS-1$	
 	/**
 	 * <pre>
+	 * FORMATTER / Option for alignment of type arguments in parameterized type references
+	 *     - option id:         "org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references"
+	 *     - possible values:   values returned by <code>createAlignmentValue(boolean, int, int)</code> call
+	 *     - default:           createAlignmentValue(false, WRAP_NO_SPLIT, INDENT_DEFAULT)
+	 * </pre>
+	 * @see #createAlignmentValue(boolean, int, int)
+	 * @since 3.12
+	 */
+	public static final String FORMATTER_ALIGNMENT_FOR_PARAMETERIZED_TYPE_REFERENCES = JavaCore.PLUGIN_ID + ".formatter.alignment_for_parameterized_type_references";	 //$NON-NLS-1$
+	/**
+	 * <pre>
 	 * FORMATTER / Option for alignment of parameters in constructor declaration
 	 *     - option id:         "org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration"
 	 *     - possible values:   values returned by <code>createAlignmentValue(boolean, int, int)</code> call
@@ -334,6 +357,28 @@
 	public static final String FORMATTER_ALIGNMENT_FOR_THROWS_CLAUSE_IN_METHOD_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.alignment_for_throws_clause_in_method_declaration";	 //$NON-NLS-1$
 	/**
 	 * <pre>
+	 * FORMATTER / Option for alignment of type arguments in method invocations and references
+	 *     - option id:         "org.eclipse.jdt.core.formatter.alignment_for_type_arguments"
+	 *     - possible values:   values returned by <code>createAlignmentValue(boolean, int, int)</code> call
+	 *     - default:           createAlignmentValue(false, WRAP_NO_SPLIT, INDENT_DEFAULT)
+	 * </pre>
+	 * @see #createAlignmentValue(boolean, int, int)
+	 * @since 3.12
+	 */
+	public static final String FORMATTER_ALIGNMENT_FOR_TYPE_ARGUMENTS = JavaCore.PLUGIN_ID + ".formatter.alignment_for_type_arguments";	 //$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option for alignment of type parameters in method and type declarations
+	 *     - option id:         "org.eclipse.jdt.core.formatter.alignment_for_type_parameters"
+	 *     - possible values:   values returned by <code>createAlignmentValue(boolean, int, int)</code> call
+	 *     - default:           createAlignmentValue(false, WRAP_NO_SPLIT, INDENT_DEFAULT)
+	 * </pre>
+	 * @see #createAlignmentValue(boolean, int, int)
+	 * @since 3.12
+	 */
+	public static final String FORMATTER_ALIGNMENT_FOR_TYPE_PARAMETERS = JavaCore.PLUGIN_ID + ".formatter.alignment_for_type_parameters";	 //$NON-NLS-1$
+	/**
+	 * <pre>
 	 * FORMATTER / Option for alignment of exceptions declared in a Union Type in the argument of a multicatch statement
 	 *     - option id:         "org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch"
 	 *     - possible values:   values returned by <code>createAlignmentValue(boolean, int, int)</code> call
@@ -639,6 +684,161 @@
 
 	/**
 	 * <pre>
+	 * FORMATTER / Option to position parentheses in method declarations
+	 *     - option id:         "org.eclipse.jdt.core.formatter.parentheses_positions_in_method_declaration"
+	 *     - possible values:   { COMMON_LINES, SEPARATE_LINES_IF_NOT_EMPY, SEPARATE_LINES_IF_WRAPPED, SEPARATE_LINES, PRESERVE_POSITIONS }
+	 *     - default:           END_OF_LINE
+	 * </pre>
+	 * @see #COMMON_LINES
+	 * @see #SEPARATE_LINES_IF_NOT_EMPY
+	 * @see #SEPARATE_LINES_IF_WRAPPED
+	 * @see #SEPARATE_LINES
+	 * @see #PRESERVE_POSITIONS
+	 * @since 3.12
+	 */
+	public static final String FORMATTER_PARENTHESES_POSITIONS_IN_METHOD_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.parentheses_positions_in_method_delcaration";	//$NON-NLS-1$
+
+	/**
+	 * <pre>
+	 * FORMATTER / Option to position parentheses in method invocations
+	 *     - option id:         "org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation"
+	 *     - possible values:   { COMMON_LINES, SEPARATE_LINES_IF_NOT_EMPY, SEPARATE_LINES_IF_WRAPPED, SEPARATE_LINES, PRESERVE_POSITIONS }
+	 *     - default:           END_OF_LINE
+	 * </pre>
+	 * @see #COMMON_LINES
+	 * @see #SEPARATE_LINES_IF_NOT_EMPY
+	 * @see #SEPARATE_LINES_IF_WRAPPED
+	 * @see #SEPARATE_LINES
+	 * @see #PRESERVE_POSITIONS
+	 * @since 3.12
+	 */
+	public static final String FORMATTER_PARENTHESES_POSITIONS_IN_METHOD_INVOCATION = JavaCore.PLUGIN_ID + ".formatter.parentheses_positions_in_method_invocation";	//$NON-NLS-1$
+
+	/**
+	 * <pre>
+	 * FORMATTER / Option to position parentheses in enum constant declarations
+	 *     - option id:         "org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration"
+	 *     - possible values:   { COMMON_LINES, SEPARATE_LINES_IF_NOT_EMPY, SEPARATE_LINES_IF_WRAPPED, SEPARATE_LINES, PRESERVE_POSITIONS }
+	 *     - default:           END_OF_LINE
+	 * </pre>
+	 * @see #COMMON_LINES
+	 * @see #SEPARATE_LINES_IF_NOT_EMPY
+	 * @see #SEPARATE_LINES_IF_WRAPPED
+	 * @see #SEPARATE_LINES
+	 * @see #PRESERVE_POSITIONS
+	 * @since 3.12
+	 */
+	public static final String FORMATTER_PARENTHESES_POSITIONS_IN_ENUM_CONSTANT_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.parentheses_positions_in_enum_constant_declaration";	//$NON-NLS-1$
+
+	/**
+	 * <pre>
+	 * FORMATTER / Option to position parentheses in 'if' and 'while' statements
+	 *     - option id:         "org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement"
+	 *     - possible values:   { COMMON_LINES, SEPARATE_LINES_IF_WRAPPED, SEPARATE_LINES, PRESERVE_POSITIONS }
+	 *     - default:           END_OF_LINE
+	 * </pre>
+	 * @see #COMMON_LINES
+	 * @see #SEPARATE_LINES_IF_WRAPPED
+	 * @see #SEPARATE_LINES
+	 * @see #PRESERVE_POSITIONS
+	 * @since 3.12
+	 */
+	public static final String FORMATTER_PARENTHESES_POSITIONS_IN_IF_WHILE_STATEMENT = JavaCore.PLUGIN_ID + ".formatter.parentheses_positions_in_if_while_statement";	//$NON-NLS-1$
+
+	/**
+	 * <pre>
+	 * FORMATTER / Option to position parentheses in 'for' statements
+	 *     - option id:         "org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statement"
+	 *     - possible values:   { COMMON_LINES,  SEPARATE_LINES_IF_WRAPPED, SEPARATE_LINES, PRESERVE_POSITIONS }
+	 *     - default:           END_OF_LINE
+	 * </pre>
+	 * @see #COMMON_LINES
+	 * @see #SEPARATE_LINES_IF_WRAPPED
+	 * @see #SEPARATE_LINES
+	 * @see #PRESERVE_POSITIONS
+	 * @since 3.12
+	 */
+	public static final String FORMATTER_PARENTHESES_POSITIONS_IN_FOR_STATEMENT = JavaCore.PLUGIN_ID + ".formatter.parentheses_positions_in_for_statment";	//$NON-NLS-1$
+
+	/**
+	 * <pre>
+	 * FORMATTER / Option to position parentheses in 'switch' statements
+	 *     - option id:         "org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement"
+	 *     - possible values:   { COMMON_LINES, SEPARATE_LINES_IF_WRAPPED, SEPARATE_LINES, PRESERVE_POSITIONS }
+	 *     - default:           END_OF_LINE
+	 * </pre>
+	 * @see #COMMON_LINES
+	 * @see #SEPARATE_LINES_IF_WRAPPED
+	 * @see #SEPARATE_LINES
+	 * @see #PRESERVE_POSITIONS
+	 * @since 3.12
+	 */
+	public static final String FORMATTER_PARENTHESES_POSITIONS_IN_SWITCH_STATEMENT = JavaCore.PLUGIN_ID + ".formatter.parentheses_positions_in_switch_statement";	//$NON-NLS-1$
+
+	/**
+	 * <pre>
+	 * FORMATTER / Option to position parentheses in try clauses
+	 *     - option id:         "org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause"
+	 *     - possible values:   { COMMON_LINES, SEPARATE_LINES_IF_WRAPPED, SEPARATE_LINES, PRESERVE_POSITIONS }
+	 *     - default:           END_OF_LINE
+	 * </pre>
+	 * @see #COMMON_LINES
+	 * @see #SEPARATE_LINES_IF_WRAPPED
+	 * @see #SEPARATE_LINES
+	 * @see #PRESERVE_POSITIONS
+	 * @since 3.12
+	 */
+	public static final String FORMATTER_PARENTHESES_POSITIONS_IN_TRY_CLAUSE = JavaCore.PLUGIN_ID + ".formatter.parentheses_positions_in_try_clause";	//$NON-NLS-1$
+
+	/**
+	 * <pre>
+	 * FORMATTER / Option to position parentheses in catch clauses
+	 *     - option id:         "org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause"
+	 *     - possible values:   { COMMON_LINES, SEPARATE_LINES_IF_WRAPPED, SEPARATE_LINES, PRESERVE_POSITIONS }
+	 *     - default:           END_OF_LINE
+	 * </pre>
+	 * @see #COMMON_LINES
+	 * @see #SEPARATE_LINES_IF_WRAPPED
+	 * @see #SEPARATE_LINES
+	 * @see #PRESERVE_POSITIONS
+	 * @since 3.12
+	 */
+	public static final String FORMATTER_PARENTHESES_POSITIONS_IN_CATCH_CLAUSE = JavaCore.PLUGIN_ID + ".formatter.parentheses_positions_in_catch_clause";	//$NON-NLS-1$
+
+	/**
+	 * <pre>
+	 * FORMATTER / Option to position parentheses in annotations
+	 *     - option id:         "org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation"
+	 *     - possible values:   { COMMON_LINES, SEPARATE_LINES_IF_NOT_EMPY, SEPARATE_LINES_IF_WRAPPED, SEPARATE_LINES, PRESERVE_POSITIONS }
+	 *     - default:           END_OF_LINE
+	 * </pre>
+	 * @see #COMMON_LINES
+	 * @see #SEPARATE_LINES_IF_NOT_EMPY
+	 * @see #SEPARATE_LINES_IF_WRAPPED
+	 * @see #SEPARATE_LINES
+	 * @see #PRESERVE_POSITIONS
+	 * @since 3.12
+	 */
+	public static final String FORMATTER_PARENTHESES_POSITIONS_IN_ANNOTATION = JavaCore.PLUGIN_ID + ".formatter.parentheses_positions_in_annotation";	//$NON-NLS-1$
+
+	/**
+	 * <pre>
+	 * FORMATTER / Option to position parentheses in lambda declarations
+	 *     - option id:         "org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration"
+	 *     - possible values:   { COMMON_LINES, SEPARATE_LINES_IF_NOT_EMPY, SEPARATE_LINES_IF_WRAPPED, SEPARATE_LINES, PRESERVE_POSITIONS }
+	 *     - default:           END_OF_LINE
+	 * </pre>
+	 * @see #COMMON_LINES
+	 * @see #SEPARATE_LINES_IF_NOT_EMPY
+	 * @see #SEPARATE_LINES_IF_WRAPPED
+	 * @see #SEPARATE_LINES
+	 * @see #PRESERVE_POSITIONS
+	 * @since 3.12
+	 */
+	public static final String FORMATTER_PARENTHESES_POSITIONS_IN_LAMBDA_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.parentheses_positions_in_lambda_declaration";	//$NON-NLS-1$
+
+	/**
+	 * <pre>
 	 * FORMATTER / Option to control whether blank lines are cleared inside comments
 	 *     - option id:         "org.eclipse.jdt.core.formatter.comment.clear_blank_lines"
 	 *     - possible values:   { TRUE, FALSE }
@@ -1364,6 +1564,19 @@
 
 	/**
 	 * <pre>
+	 * FORMATTER / Option to insert a new line after an annotation on an enum constant declaration
+	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant"
+	 *     - possible values:   { INSERT, DO_NOT_INSERT }
+	 *     - default:           INSERT
+	 * </pre>
+	 * @see JavaCore#INSERT
+	 * @see JavaCore#DO_NOT_INSERT
+	 * @since 3.12
+	 */
+	public static final String FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_ENUM_CONSTANT = JavaCore.PLUGIN_ID + ".formatter.insert_new_line_after_annotation_on_enum_constant";//$NON-NLS-1$
+
+	/**
+	 * <pre>
 	 * FORMATTER / Option to insert a new line after an annotation on a field declaration
 	 *     - option id:         "org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field"
 	 *     - possible values:   { INSERT, DO_NOT_INSERT }
@@ -3816,6 +4029,32 @@
 	public static final String FORMATTER_WRAP_BEFORE_OR_OPERATOR_MULTICATCH = JavaCore.PLUGIN_ID + ".formatter.wrap_before_or_operator_multicatch"; //$NON-NLS-1$
 	/**
 	 * <pre>
+	 * FORMATTER / Option to wrap before the '?' and ':' operators in conditional expressions
+	 *     - option id:         "org.eclipse.jdt.core.formatter.wrap_before_conditional_operator"
+	 *     - possible values:   { TRUE, FALSE }
+	 *     - default:           TRUE
+	 * </pre>
+	 * This option is used only if the option {@link #FORMATTER_ALIGNMENT_FOR_CONDITIONAL_EXPRESSION} is set.
+	 * @see #TRUE
+	 * @see #FALSE
+	 * @since 3.12
+	 */
+	public static final String FORMATTER_WRAP_BEFORE_CONDITIONAL_OPERATOR = JavaCore.PLUGIN_ID + ".formatter.wrap_before_conditional_operator"; //$NON-NLS-1$
+	/**
+	 * <pre>
+	 * FORMATTER / Option to wrap before the assignment operator
+	 *     - option id:         "org.eclipse.jdt.core.formatter.wrap_before_assignment_operator"
+	 *     - possible values:   { TRUE, FALSE }
+	 *     - default:           TRUE
+	 * </pre>
+	 * This option is used only if the option {@link #FORMATTER_ALIGNMENT_FOR_ASSIGNMENT} is set.
+	 * @see #TRUE
+	 * @see #FALSE
+	 * @since 3.12
+	 */
+	public static final String FORMATTER_WRAP_BEFORE_ASSIGNMENT_OPERATOR = JavaCore.PLUGIN_ID + ".formatter.wrap_before_assignment_operator"; //$NON-NLS-1$
+	/**
+	 * <pre>
 	 * FORMATTER / Option to wrap outer expressions in nested expressions
 	 *     - option id:         "org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested"
 	 *     - possible values:   { TRUE, FALSE }
@@ -3940,6 +4179,98 @@
 	 * @since 3.0
 	 */
 	public static final String NEXT_LINE_SHIFTED = "next_line_shifted";	//$NON-NLS-1$
+
+	/**
+	 * <pre>
+	 * FORMATTER / Value to keep always parentheses on common lines with their contents..
+	 * </pre>
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_METHOD_DECLARATION
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_METHOD_INVOCATION
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_ENUM_CONSTANT_DECLARATION
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_IF_WHILE_STATEMENT
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_FOR_STATEMENT
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_SWITCH_STATEMENT
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_TRY_CLAUSE
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_CATCH_CLAUSE
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_ANNOTATION
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_LAMBDA_DECLARATION
+	 * @since 3.12
+	 */
+	public static final String COMMON_LINES = "common_lines";	//$NON-NLS-1$
+
+	/**
+	 * <pre>
+	 * FORMATTER / Value to keep always parentheses on common lines with their contents..
+	 * </pre>
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_METHOD_DECLARATION
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_METHOD_INVOCATION
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_ENUM_CONSTANT_DECLARATION
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_IF_WHILE_STATEMENT
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_FOR_STATEMENT
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_SWITCH_STATEMENT
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_TRY_CLAUSE
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_CATCH_CLAUSE
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_ANNOTATION
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_LAMBDA_DECLARATION
+	 * @since 3.12
+	 */
+	public static final String SEPARATE_LINES_IF_NOT_EMPY = "separate_lines_if_not_empty";	//$NON-NLS-1$
+
+	/**
+	 * <pre>
+	 * FORMATTER / Value to keep always parentheses on common lines with their contents..
+	 * </pre>
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_METHOD_DECLARATION
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_METHOD_INVOCATION
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_ENUM_CONSTANT_DECLARATION
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_IF_WHILE_STATEMENT
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_FOR_STATEMENT
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_SWITCH_STATEMENT
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_TRY_CLAUSE
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_CATCH_CLAUSE
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_ANNOTATION
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_LAMBDA_DECLARATION
+	 * @since 3.12
+	 */
+	public static final String SEPARATE_LINES_IF_WRAPPED = "separate_lines_if_wrapped";	//$NON-NLS-1$
+	
+	/**
+	 * <pre>
+	 * FORMATTER / Value to keep always parentheses on common lines with their contents..
+	 * </pre>
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_METHOD_DECLARATION
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_METHOD_INVOCATION
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_ENUM_CONSTANT_DECLARATION
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_IF_WHILE_STATEMENT
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_FOR_STATEMENT
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_SWITCH_STATEMENT
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_TRY_CLAUSE
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_CATCH_CLAUSE
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_ANNOTATION
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_LAMBDA_DECLARATION
+	 * @since 3.12
+	 */
+	public static final String SEPARATE_LINES = "separate_lines";	//$NON-NLS-1$
+
+	/**
+	 * <pre>
+	 * FORMATTER / Value to set a closing parenthesis position to same line or next
+	 *             line depending on what was in the original source.
+	 * </pre>
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_METHOD_DECLARATION
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_METHOD_INVOCATION
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_ENUM_CONSTANT_DECLARATION
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_IF_WHILE_STATEMENT
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_FOR_STATEMENT
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_SWITCH_STATEMENT
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_TRY_CLAUSE
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_CATCH_CLAUSE
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_ANNOTATION
+	 * @see #FORMATTER_PARENTHESES_POSITIONS_IN_LAMBDA_DECLARATION
+	 * @since 3.12
+	 */
+	public static final String PRESERVE_POSITIONS = "preserve_positions";	//$NON-NLS-1$
+
 	/**
 	 * <pre>
 	 * FORMATTER / Value to set an option to true.
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CommentsPreparator.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CommentsPreparator.java
index 24ba74e..e6cf535 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CommentsPreparator.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CommentsPreparator.java
@@ -196,14 +196,15 @@
 			this.tm.remove(commentIndex);
 			List<Token> lastStructure = this.lastLineComment.getInternalStructure();
 			lastStructure.addAll(structure);
-			structure = lastStructure;
-			commentToken = merged;
+			merged.setInternalStructure(lastStructure);
+			this.lastLineComment = merged;
 		} else {
+			commentToken.setInternalStructure(structure);
+			handleCompilerTags(commentToken, commentIndex);
+			preserveWhitespace(commentToken, commentIndex);
+			this.lastLineComment = commentToken;
 			this.lastLineCommentPosition = positionInLine;
 		}
-		commentToken.setInternalStructure(structure);
-		preserveWhitespace(commentToken, commentIndex);
-		this.lastLineComment = commentToken;
 	}
 
 	private void preserveWhitespace(Token commentToken, int commentIndex) {
@@ -286,6 +287,28 @@
 		}
 	}
 
+	private void handleCompilerTags(Token commentToken, int commentIndex) {
+		final String commentText = this.tm.toString(commentToken);
+		final List<Token> structure = commentToken.getInternalStructure();
+		if (commentText.startsWith("//$FALL-THROUGH$") //$NON-NLS-1$
+				|| commentText.startsWith("//$IDENTITY-COMPARISON$")) { //$NON-NLS-1$
+			structure.get(1).clearSpaceBefore();
+		}
+		if (commentText.contains("//$IDENTITY-COMPARISON$")) { //$NON-NLS-1$
+			// make sure the whole line is not broken
+			Token token = commentToken;
+			for (int i = commentIndex; i > 0; i--) {
+				Token left = this.tm.get(i - 1);
+				if (this.tm.countLineBreaksBetween(left, token) > 0)
+					break;
+				token.clearLineBreaksBefore();
+				left.clearLineBreaksAfter();
+				token.setWrapPolicy(WrapPolicy.DISABLE_WRAP);
+				token = left;
+			}
+		}
+	}
+
 	private List<Token> findStringLiteralsInLine(int lastTokenIndex) {
 		List<Token> stringLiterals = new ArrayList<>();
 		Token previous = this.tm.get(lastTokenIndex);
@@ -336,11 +359,6 @@
 				sourcePosition++;
 			}
 		}
-
-		if (this.tm.getSource().startsWith("$FALL-THROUGH$", result.get(0).originalEnd + 1)) { //$NON-NLS-1$
-			result.get(1).clearSpaceBefore();
-		}
-
 		return result;
 	}
 
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java
index 6b19e91..a789695 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java
@@ -130,9 +130,11 @@
 	public int alignment_for_conditional_expression;
 	public int alignment_for_enum_constants;
 	public int alignment_for_expressions_in_array_initializer;
+	public int alignment_for_expressions_in_for_loop_header;
 	public int alignment_for_method_declaration;
 	// TODO following option cannot be set in preferences dialog (but it's used by old.CodeFormatter)
 	public int alignment_for_multiple_fields;
+	public int alignment_for_parameterized_type_references;
 	public int alignment_for_parameters_in_constructor_declaration;
 	public int alignment_for_parameters_in_method_declaration;
 	public int alignment_for_selector_in_method_invocation;
@@ -141,6 +143,8 @@
 	public int alignment_for_superinterfaces_in_type_declaration;
 	public int alignment_for_throws_clause_in_constructor_declaration;
 	public int alignment_for_throws_clause_in_method_declaration;
+	public int alignment_for_type_arguments;
+	public int alignment_for_type_parameters;
 	public int alignment_for_resources_in_try;
 	public int alignment_for_union_type_in_multicatch;
 
@@ -160,6 +164,17 @@
 	public String brace_position_for_type_declaration;
 	public String brace_position_for_switch;
 
+	public String parenthesis_positions_in_method_declaration;
+	public String parenthesis_positions_in_method_invocation;
+	public String parenthesis_positions_in_enum_constant_declaration;
+	public String parenthesis_positions_in_if_while_statement;
+	public String parenthesis_positions_in_for_statement;
+	public String parenthesis_positions_in_switch_statement;
+	public String parenthesis_positions_in_try_clause;
+	public String parenthesis_positions_in_catch_clause;
+	public String parenthesis_positions_in_annotation;
+	public String parenthesis_positions_in_lambda_declaration;
+
 	public int continuation_indentation;
 	public int continuation_indentation_for_array_initializer;
 
@@ -214,6 +229,7 @@
 
 	public boolean insert_new_line_after_annotation_on_type;
 	public boolean insert_new_line_after_type_annotation;
+	public boolean insert_new_line_after_annotation_on_enum_constant;
 	public boolean insert_new_line_after_annotation_on_field;
 	public boolean insert_new_line_after_annotation_on_method;
 	public boolean insert_new_line_after_annotation_on_package;
@@ -414,6 +430,8 @@
 	public boolean use_tabs_only_for_leading_indentations;
 	public boolean wrap_before_binary_operator;
 	public boolean wrap_before_or_operator_multicatch;
+	public boolean wrap_before_conditional_operator;
+	public boolean wrap_before_assignment_operator;
 	public boolean wrap_outer_expressions_when_nested;
 
 	public int initial_indentation_level;
@@ -447,8 +465,10 @@
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_CONDITIONAL_EXPRESSION, getAlignment(this.alignment_for_conditional_expression));
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_ENUM_CONSTANTS, getAlignment(this.alignment_for_enum_constants));
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_EXPRESSIONS_IN_ARRAY_INITIALIZER, getAlignment(this.alignment_for_expressions_in_array_initializer));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_EXPRESSIONS_IN_FOR_LOOP_HEADER, getAlignment(this.alignment_for_expressions_in_for_loop_header));
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_METHOD_DECLARATION, getAlignment(this.alignment_for_method_declaration));
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_MULTIPLE_FIELDS, getAlignment(this.alignment_for_multiple_fields));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_PARAMETERIZED_TYPE_REFERENCES, getAlignment(this.alignment_for_parameterized_type_references));
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_PARAMETERS_IN_CONSTRUCTOR_DECLARATION, getAlignment(this.alignment_for_parameters_in_constructor_declaration));
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_PARAMETERS_IN_METHOD_DECLARATION, getAlignment(this.alignment_for_parameters_in_method_declaration));
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_RESOURCES_IN_TRY, getAlignment(this.alignment_for_resources_in_try));
@@ -458,6 +478,8 @@
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_SUPERINTERFACES_IN_TYPE_DECLARATION, getAlignment(this.alignment_for_superinterfaces_in_type_declaration));
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_THROWS_CLAUSE_IN_CONSTRUCTOR_DECLARATION, getAlignment(this.alignment_for_throws_clause_in_constructor_declaration));
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_THROWS_CLAUSE_IN_METHOD_DECLARATION, getAlignment(this.alignment_for_throws_clause_in_method_declaration));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_TYPE_ARGUMENTS, getAlignment(this.alignment_for_type_arguments));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_TYPE_PARAMETERS, getAlignment(this.alignment_for_type_parameters));
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_UNION_TYPE_IN_MULTICATCH, getAlignment(this.alignment_for_union_type_in_multicatch));
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGN_TYPE_MEMBERS_ON_COLUMNS, this.align_type_members_on_columns ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGN_FIELDS_GROUPING_BLANK_LINES, Integer.toString(this.align_fields_grouping_blank_lines));
@@ -473,6 +495,16 @@
 		options.put(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_TYPE_DECLARATION, this.brace_position_for_type_declaration);