Releng: update jdt.core to 4.7.2 RC2
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 71a7266..9f5def5 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
@@ -6463,6 +6463,184 @@
 		}
 	);
 }
+public void testBug517951() {
+	runConformTest(
+		new String[] {
+			"Minimal.java",
+			"public class Minimal {\n" + 
+			"    public void iCrash() {\n" + 
+			"        try {\n" + 
+			"            System.out.println(\"Body can't be empty\");\n" + 
+			"        } finally {\n" + 
+			"            consumes(sneaky()::withVarargs);\n" + 
+			"        }\n" + 
+			"    }\n" + 
+			"    public static void main(String[] args) {\n" + 
+			"		new Minimal().iCrash();\n" + 
+			"	}\n" + 
+			"    private Minimal sneaky() { return this; }\n" + 
+			"    private void withVarargs(String... test) {}\n" + 
+			"    private void consumes(Runnable r) {}\n" + 
+			"}"
+		},
+		"Body can't be empty"
+	);
+}
+public void testBug517951a() {
+	runConformTest(
+		new String[] {
+			"Snippet.java",
+			"import java.nio.file.Files;\n" + 
+			"import java.nio.file.Paths;\n" + 
+			"import java.util.function.Consumer;\n" + 
+			"public class Snippet {\n" + 
+			"	void postError( String fmt, Object ... args ) {\n" + 
+			"	}\n" + 
+			"	public boolean test(Consumer<String> postError ) {\n" + 
+			"		return false;\n" + 
+			"	}\n" + 
+			"	void func() {\n" + 
+			"		try( java.io.InputStream istr = Files.newInputStream( Paths.get( \"\" ) )){\n" + 
+			"		} catch( Exception e ) {\n" + 
+			"		} finally {\n" + 
+			"			test( this::postError);\n" + 
+			"		}\n" + 
+			"	}\n" + 
+			"}"
+		}
+	);
+}
+public void testBug517951b() {
+	runConformTest(
+		new String[] {
+			"Element.java",
+			"public class Element\n" + 
+			"{\n" + 
+			"    Operation operation = new Operation(Element::new);\n" + 
+			"    public Element(Integer matrix)\n" + 
+			"    {\n" + 
+			"    		//...\n" + 
+			"    }\n" + 
+			"    public Element(Operation... operation)\n" + 
+			"    {\n" + 
+			"    		//...\n" + 
+			"    }\n" + 
+			"}\n" + 
+			"class Operation\n" + 
+			"{\n" + 
+			"    public Operation(Factory factory)\n" + 
+			"    {\n" + 
+			"        //...\n" + 
+			"    }\n" + 
+			"}\n" + 
+			"interface Factory\n" + 
+			"{\n" + 
+			"    Element create(Operation... operations);\n" + 
+			"}"
+		}
+	);
+}
+public void testBug517951c() {
+	runConformTest(
+		new String[] {
+			"npetest/NpeTest.java",
+			"package npetest;\n" + 
+			"public class NpeTest {\n" + 
+			"    public NpeTestScheduler scheduler;\n" + 
+			"    private void doIt(Object... params) {\n" + 
+			"        try {\n" + 
+			"            System.out.println(\"Done\");\n" + 
+			"        }\n" + 
+			"        finally {\n" + 
+			"            scheduler.schedule(this::doIt);\n" + 
+			"        }\n" + 
+			"    }\n" + 
+			"}",
+			"npetest/NpeTestIf.java",
+			"package npetest;\n" + 
+			"@FunctionalInterface\n" + 
+			"public interface NpeTestIf {\n" + 
+			"    void doSomething(Object... params);\n" + 
+			"}",
+			"npetest/NpeTestScheduler.java",
+			"package npetest;\n" + 
+			"public class NpeTestScheduler {\n" + 
+			"    public void schedule(NpeTestIf what) {\n" + 
+			"        what.doSomething();\n" + 
+			"    }\n" + 
+			"}"
+		}
+	);
+}
+public void testBug521808() {
+	runConformTest(
+		new String[] {
+			"Z.java",
+			"interface FI1 {\n" + 
+			"	Object m(Integer... s);\n" + 
+			"}\n" + 
+			"interface FI2<T> {\n" + 
+			"	Object m(T... arg);\n" + 
+			"}\n" + 
+			"public class Z {\n" + 
+			"	static Object m(FI1 fi, Integer v1, Integer v2) {\n" + 
+			"		return fi.m(v1, v2);\n" + 
+			"	}\n" + 
+			"	static <V extends Integer> Object m(FI2<V> fi, V v1, V v2) {\n" + 
+			"		return null;\n" + 
+			"	}\n" + 
+			"	public static void main(String argv[]) {\n" + 
+			"		Object obj = m((FI1) (Integer... is) -> is[0] + is[1], 3, 4);\n" + 
+			"		obj = m((Integer... is) -> is[0] + is[1], 3, 4); // Javac compiles, ECJ won't\n" + 
+			"	}\n" + 
+			"}",
+		}
+	);
+}
+public void testBug521818() {
+	runConformTest(
+		new String[] {
+			"test/Main.java",
+			"package test;\n" + 
+			"class C {}\n" + 
+			"class D {\n" + 
+			"	<T extends C & Runnable> D(int i, T t) {" +
+			"		System.out.println(\"D\");\n" +
+			"}\n" + 
+			"}\n" + 
+			"interface Goo {\n" + 
+			"    <T extends C & Runnable> String m(T p);\n" + 
+			"}\n" + 
+			"class A {\n" + 
+			"    public static <K extends Runnable> String bar(K a) {\n" +
+			"		System.out.println(\"Bar\");\n" +
+			"       return null;\n" + 
+			"    }\n" + 
+			"    public static <K extends Runnable> D baz(int i, K a) {\n" +
+			"		System.out.println(\"Baz\");\n" +
+			"       return null;\n" + 
+			"    }\n"+ 
+			"}\n" +  
+			"interface Foo<Z extends C & Runnable> {\n" + 
+			"	D get(int i, Z z);\n" + 
+			"}\n" + 
+			"public class Main  {\n" +  
+			"    public static void main(String[] args) {\n" + 
+			"    	Foo<? extends C> h = A::baz;\n" + 
+			"    	h.get(0,  null);\n" + 
+			"    	Foo<? extends C> h2 = D::new;\n" + 
+			"    	h2.get(0,  null);\n" + 
+			"    	Goo g = A::bar;\n" + 
+			"    	g.m(null);\n" + 
+			"    } \n" + 
+			"}"
+		},
+		"Baz\n" +
+		"D\n" +
+		"Bar"
+		
+	);
+}
 public static Class testClass() {
 	return LambdaExpressionsTest.class;
 }
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 3e1675c..494bda5 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
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2011, 2016 IBM Corporation and others.
+ * Copyright (c) 2011, 2017 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
@@ -10024,6 +10024,47 @@
 		"The code of method $deserializeLambda$(SerializedLambda) is exceeding the 65535 bytes limit\n" + 
 		"----------\n");
 }
+public void testBug521808() {
+	runNegativeTest(
+		new String[] {
+			"Z.java",
+			"interface FI1 {\n" + 
+			"	Object m(Integer... s);\n" + 
+			"}\n" + 
+			"interface FI2<T> {\n" + 
+			"	Object m(T... arg);\n" + 
+			"}\n" + 
+			"public class Z {\n" + 
+			"	static Object m(FI1 fi, Number v1, Number v2) {\n" + 
+			"		return fi.m(v1.intValue(), v2.intValue());\n" + 
+			"	}\n" + 
+			"	static <V extends Integer> Object m(FI2<V> fi, V v1, V v2) {\n" + 
+			"		return null;// fi.m(v1, v2);\n" + 
+			"	}\n" + 
+			"	public static void main(String argv[]) {\n" + 
+			"		Object obj = m((FI1) (Integer... is) -> is[0] + is[1], 3, 4);\n" + 
+			"		obj = m((FI2<Integer>) (Integer... is) -> is[0] + is[1], 3, 4);\n" + 
+			"		obj = m((Integer... is) -> is[0] + is[1], 3, 4); // ECJ compiles, Javac won't\n" + 
+			"	}\n" + 
+			"}",
+		},
+		"----------\n" + 
+		"1. WARNING in Z.java (at line 5)\n" + 
+		"	Object m(T... arg);\n" + 
+		"	              ^^^\n" + 
+		"Type safety: Potential heap pollution via varargs parameter arg\n" + 
+		"----------\n" + 
+		"2. WARNING in Z.java (at line 11)\n" + 
+		"	static <V extends Integer> Object m(FI2<V> fi, V v1, V v2) {\n" + 
+		"	                  ^^^^^^^\n" + 
+		"The type parameter V should not be bounded by the final type Integer. Final types cannot be further extended\n" + 
+		"----------\n" + 
+		"3. ERROR in Z.java (at line 17)\n" + 
+		"	obj = m((Integer... is) -> is[0] + is[1], 3, 4); // ECJ compiles, Javac won\'t\n" + 
+		"	      ^\n" + 
+		"The method m(FI1, Number, Number) is ambiguous for the type Z\n" +  
+		"----------\n");
+}
 public static Class testClass() {
 	return NegativeLambdaExpressionsTest.class;
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/dom/StandAloneASTParserTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/dom/StandAloneASTParserTest.java
index 9df7f76..9254c0b 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/dom/StandAloneASTParserTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/dom/StandAloneASTParserTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2010, 2016 IBM Corporation and others.
+ * Copyright (c) 2010, 2017 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
@@ -677,4 +677,99 @@
 	    parser.setCompilerOptions(options1);
 	    assertNotNull(parser.createAST(null));
 	}
-}
+	public void testBug526996_001() {
+		File rootDir = new File(System.getProperty("java.io.tmpdir"));
+		String contents = 
+				"public class X {\n" +
+				"    public X() {\n" +
+				"        this.f16132b =\n" +
+				"/*\n" +
+				"        at jadx.api.JavaClass.decompile(JavaClass.java:62)\n" +
+				"*/\n" +
+				"\n" +
+				"            /* JADX WARNING: inconsistent code. */\n" +
+				"            /* Code decompiled incorrectly, please refer to instructions dump. */\n" +
+				"            public final C1984r m22030a() {\n" +
+				"            }\n" +
+				"        }\n" +
+				"\n";
+		
+		File file = new File(rootDir, "X.java");
+		Writer writer = null;
+		try {
+			try {
+				writer = new BufferedWriter(new FileWriter(file));
+				writer.write(contents);
+			} catch (IOException e1) {
+				// ignore
+			}
+		} finally {
+			if (writer != null) {
+				try {
+					writer.close();
+				} catch(IOException e) {
+					// ignore
+				}
+			}
+		}
+		String contents2 =
+				"public class Y {\n" +
+				"\n" +
+				"    /* JADX WARNING: inconsistent code. */\n" +
+				"    protected void finalize() {\n" +
+				"        for (i =\n" +
+				"/*\n" +
+				"        at jadx.core.codegen.InsnGen.makeInsn(InsnGen.java:220)\n" +
+				"*/\n" +
+				"        public void close() { }\n" +
+				"    }\n" ;
+
+		File fileY = new File(rootDir, "Y.java");
+		Writer writer2 = null;
+		try {
+			try {
+				writer2 = new BufferedWriter(new FileWriter(fileY));
+				writer2.write(contents2);
+			} catch (IOException e) {
+				// ignore
+			}
+		} finally {
+			try {
+				if (writer2 != null) writer2.close();
+			} catch(IOException e) {
+				// ignore
+			}
+		}
+		try {
+			final FileASTRequestor astRequestor = new FileASTRequestor() {
+				@Override
+				public void acceptAST(String sourceFilePath, CompilationUnit ast) {
+					super.acceptAST(sourceFilePath, ast);
+					System.out.println(sourceFilePath);
+				}
+			};
+			ASTParser parser = ASTParser.newParser(AST.JLS9);
+			parser.setResolveBindings(true);
+			parser.setStatementsRecovery(true);
+			parser.setBindingsRecovery(true);
+			parser.setKind(ASTParser.K_COMPILATION_UNIT);
+			parser.setEnvironment(new String[0], new String[] { rootDir.getAbsolutePath() }, null, true);
+		    String[] files = null;
+			try {
+				files = new String[] {file.getCanonicalPath(), fileY.getCanonicalPath()};
+				System.out.println("Building...");
+				parser.createASTs(files,
+						null,
+						new String[0],
+						astRequestor,
+						null);
+			} catch (IOException e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+			}
+		} finally {
+			file.delete();
+			fileY.delete();
+		}
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter9Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter9Test.java
index 74d87a3..f501ee8 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter9Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter9Test.java
@@ -799,6 +799,45 @@
 				deleteProject(project2);
 		}
 	}
+	public void testBug519884_001() throws Exception {
+		try {
+
+			IJavaProject project1 = createJavaProject("ConverterTests9", new String[] {"src"}, new String[] {jcl9lib}, "bin", "9");
+			project1.open(null);
+			String fileContent =
+				"module first {\n" +
+				"}";
+			createFile("/ConverterTests9/src/module-info.java",	fileContent);
+			createFolder("/ConverterTests9/src/pack");
+			createFile("/ConverterTests9/src/pack/X.java",
+					"package pack;\n" +
+					"import java.MyObject;\n" +
+					"public class X{}");
+
+			project1.close(); // sync
+			project1.open(null);
+
+			ICompilationUnit sourceUnit1 = getCompilationUnit("ConverterTests9" , "src", "pack", "X.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+			ASTNode unit1 = runConversion(AST_INTERNAL_JLS9, sourceUnit1, true);
+			assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, unit1.getNodeType());
+			CompilationUnit cu = (CompilationUnit) unit1;
+			ImportDeclaration importDeclaration = (ImportDeclaration) cu.imports().get(0);
+			QualifiedName qName = (QualifiedName) importDeclaration.getName();
+			Name name = qName.getQualifier();
+			IBinding binding = name.resolveBinding();
+			if (binding != null) {
+				assertTrue("Not PackageBinding", binding instanceof IPackageBinding);
+				IPackageBinding packageBinding = (IPackageBinding) binding;
+				IJavaElement element = packageBinding.getJavaElement();
+				assertTrue("element null", element != null);
+			}
+		} catch (NullPointerException e) {
+			e.printStackTrace();
+			assertFalse("Failed", true);
+		} finally {
+			deleteProject("ConverterTests9");
+		}
+	}
 
 // Add new tests here
 }
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests9.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests9.java
index fa5c7df..49b8078 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests9.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests9.java
@@ -821,4 +821,56 @@
 		deleteProject(project1);
 	}
 }
+public void test527099_001() throws Exception {
+	IJavaProject project1 = createJavaProject("Completion9_1", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9");
+	IJavaProject project2 = createJavaProject("Completion9_2", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9");
+	try {
+		project1.open(null);
+		createType("/Completion9_1/src/", "pack11", "X11");
+		createType("/Completion9_1/src/", "pack11.packinternal", "Z11");
+		createTypePlus("/Completion9_1/src/", "pack11.packinternal", "Z12", "implements pack22.I22", true /* isClass */, false /* createFolder */);
+		createType("/Completion9_1/src/", "pack12", "X12");
+		createTypePlus("/Completion9_1/src/", "pack12", "Y12", "implements pack22.I22", true /* isClass */, false /* createFolder */);
+		String filePath1 = "/Completion9_1/src/module-info.java";
+		String completeBehind = "exports ";
+		String fileContent1 =  "module first {\n"
+				+ "requires second;\n"
+				+ completeBehind
+				+ "}\n";
+		createFile(filePath1, fileContent1);
+		addClasspathEntry(project1, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH")));
+
+		project2.open(null);
+		createType("/Completion9_2/src/", "pack21", "X21");
+		createType("/Completion9_2/src/", "pack22", "X22");
+		createTypePlus("/Completion9_2/src/", "pack22", "I22", null, false /* isClass */, false /* createFolder */);
+
+		String fileContent2 =  "module second { "
+				+ "exports pack21 to first;\n"
+				+ "exports pack22 to first;\n" 
+				+ "}\n";
+		String filePath2 = "/Completion9_2/src/module-info.java";
+		createFile(filePath2, fileContent2);
+		addClasspathEntry(project2, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH")));
+
+		project1.close(); // sync
+		project2.close();
+		project2.open(null);
+		project1.open(null);
+
+		int cursorLocation = fileContent1.lastIndexOf(completeBehind) + completeBehind.length();
+		CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2();
+
+		ICompilationUnit unit = getCompilationUnit(filePath1);
+		unit.codeComplete(cursorLocation, requestor);
+
+		String expected = "pack11[PACKAGE_REF]{pack11, pack11, null, null, 39}\n"
+				+ "pack11.packinternal[PACKAGE_REF]{pack11.packinternal, pack11.packinternal, null, null, 39}\n"
+				+ "pack12[PACKAGE_REF]{pack12, pack12, null, null, 39}";
+		assertResults(expected,	requestor.getResults());
+	} finally {
+		deleteProject(project1);
+		deleteProject(project2);
+	}
+}
 }
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/Java9ElementTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/Java9ElementTests.java
index bc15c6e..e0dfe5a 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/Java9ElementTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/Java9ElementTests.java
@@ -1278,4 +1278,200 @@
 			deleteProject("Java9Elements2");
 		}	
 	}
+	public void test526761a() throws Exception {
+		try {
+			IJavaProject project1 = createJava9Project("Java9Elements", new String[] {"work/src/java"});
+			project1.open(null);
+			createFolder("/Java9Elements/work/src/java/test");
+			String fileContent =
+					"package test;\n" +
+					"public class Test {}";
+			createFile("/Java9Elements/work/src/java/test/Test.java", fileContent);
+
+			ICompilationUnit unit = getCompilationUnit("/Java9Elements/work/src/java/test/Test.java");
+			IJavaElement parent = unit.getParent();
+			IPackageFragment pkg = (IPackageFragment) parent;
+			IPackageFragmentRoot root = (IPackageFragmentRoot) pkg.getParent();
+			String id = root.getHandleIdentifier();
+			System.out.println(id);
+			assertTrue("incorrect id", id.matches("=Java9Elements/work\\\\/src\\\\/java"));
+			IJavaElement element = JavaCore.create(id);
+			assertEquals("incorrect element type", IJavaElement.PACKAGE_FRAGMENT_ROOT, element.getElementType());
+			id = "=Java9Elements/work/src/java";
+			IJavaElement element2 = JavaCore.create(id);
+			assertEquals("incorrect element type", IJavaElement.PACKAGE_FRAGMENT_ROOT, element2.getElementType());
+			assertEquals("roots should be same", element, element2);
+		} finally {
+			deleteProject("Java9Elements");
+		}	
+	}
+	private IJavaProject createJavaProjectWithBaseSql() throws CoreException {
+		IJavaProject project1 = createJava9Project("Java9Elements", new String[] {"src"});
+		project1.open(null);
+		IClasspathEntry[] rawClasspath = project1.getRawClasspath();
+		IClasspathEntry[] newClasspath = new IClasspathEntry[rawClasspath.length + 1];
+		for (int i = 0; i < rawClasspath.length; i++) {
+			IPath path = rawClasspath[i].getPath();
+			if (path.lastSegment().equals("jrt-fs.jar")) {
+				path = path.removeLastSegments(2).append("jmods").append("java.base.jmod");
+				IClasspathEntry newEntry = JavaCore.newLibraryEntry(path, rawClasspath[i].getSourceAttachmentPath(), new Path("java.base"));
+				newClasspath[i] = newEntry;
+				path = path.removeLastSegments(2).append("jmods").append("java.sql.jmod");
+				newEntry = JavaCore.newLibraryEntry(path, rawClasspath[i].getSourceAttachmentPath(), new Path("java.sql"));
+				newClasspath[rawClasspath.length] = newEntry;
+			} else {
+				newClasspath[i] = rawClasspath[i];
+			}
+		}
+		project1.setRawClasspath(rawClasspath, null);
+		return project1;
+	}
+	public void test526326a() throws Exception {
+		try {
+			IJavaProject project = createJavaProjectWithBaseSql();
+			project.open(null);
+				String fileContent = 
+						"import java.sql.Driver;\n" +
+						"import p.q.Main;\n" +
+						"module my.mod{\n"  +
+						 "	exports p.q;" +
+						 "	requires java.sql;\n" +
+						 "	provides Driver with Main;\n" +
+						 "}";
+				createFile(	"/Java9Elements/src/module-info.java",	fileContent);
+				createFolder("/Java9Elements/src/p/q");
+				createFile("/Java9Elements/src/p/q/Main.java",
+						"package p.q;\n" +
+						"import java.sql.Connection;\n" +
+						"import java.sql.Driver;\n" +
+						"import java.sql.DriverPropertyInfo;\n" +
+						"import java.sql.SQLException;\n" +
+						"import java.sql.SQLFeatureNotSupportedException;\n" +
+						"import java.util.Properties;\n" +
+						"import java.util.logging.Logger;\n" +
+						"public class Main implements Driver {\n" +
+						"	public boolean acceptsURL(String arg0) throws SQLException { return false; }\n" +
+						"	public Connection connect(String arg0, Properties arg1) throws SQLException { return null; }\n" +
+						"	public int getMajorVersion() { return 0; }\n" +
+						"	public int getMinorVersion() { return 0;}\n" +
+						"	public Logger getParentLogger() throws SQLFeatureNotSupportedException { return null; }\n" +
+						"	public DriverPropertyInfo[] getPropertyInfo(String arg0, Properties arg1) throws SQLException { return null; }\n" +
+						"	public boolean jdbcCompliant() { return false; }\n" +
+						"}");
+				ICompilationUnit unit = getCompilationUnit("/Java9Elements/src/module-info.java");
+				int start = fileContent.lastIndexOf("Driver");
+				IJavaElement[] elements = unit.codeSelect(start, "Driver".length());
+				assertEquals("Incorrect no of elements", 1, elements.length);
+				assertEquals("Incorrect element type", IJavaElement.TYPE, elements[0].getElementType());
+				assertElementEquals("Incorrect Java element", 
+						"Driver [in Driver.class [in java.sql [in <module:java.sql>]]]", elements[0]);
+				start = fileContent.lastIndexOf("Main");
+				elements = unit.codeSelect(start, "Main".length());
+				assertEquals("Incorrect no of elements", 1, elements.length);
+				assertEquals("Incorrect element type", IJavaElement.TYPE, elements[0].getElementType());
+				assertElementEquals("Incorrect Java element", 
+						"Main [in Main.java [in p.q [in src [in Java9Elements]]]]", elements[0]);
+		}
+		finally {
+			deleteProject("Java9Elements");
+		}
+	}
+	public void test526326b() throws Exception {
+		try {
+			IJavaProject project = createJavaProjectWithBaseSql();
+			project.open(null);
+				String fileContent = 
+						"import java.sql.Driver;\n" +
+						"import p.q.Main;\n" +
+						"module my.mod{\n"  +
+						 "	exports p.q;" +
+						 "	requires java.sql;\n" +
+						 "	provides java.sql.Driver with p.q.Main;\n" +
+						 "}";
+				createFile(	"/Java9Elements/src/module-info.java",	fileContent);
+				createFolder("/Java9Elements/src/p/q");
+				createFile("/Java9Elements/src/p/q/Main.java",
+						"package p.q;\n" +
+						"import java.sql.Connection;\n" +
+						"import java.sql.Driver;\n" +
+						"import java.sql.DriverPropertyInfo;\n" +
+						"import java.sql.SQLException;\n" +
+						"import java.sql.SQLFeatureNotSupportedException;\n" +
+						"import java.util.Properties;\n" +
+						"import java.util.logging.Logger;\n" +
+						"public class Main implements Driver {\n" +
+						"	public boolean acceptsURL(String arg0) throws SQLException { return false; }\n" +
+						"	public Connection connect(String arg0, Properties arg1) throws SQLException { return null; }\n" +
+						"	public int getMajorVersion() { return 0; }\n" +
+						"	public int getMinorVersion() { return 0;}\n" +
+						"	public Logger getParentLogger() throws SQLFeatureNotSupportedException { return null; }\n" +
+						"	public DriverPropertyInfo[] getPropertyInfo(String arg0, Properties arg1) throws SQLException { return null; }\n" +
+						"	public boolean jdbcCompliant() { return false; }\n" +
+						"}");
+				ICompilationUnit unit = getCompilationUnit("/Java9Elements/src/module-info.java");
+				int start = fileContent.lastIndexOf("Driver");
+				IJavaElement[] elements = unit.codeSelect(start, "Driver".length());
+				assertEquals("Incorrect no of elements", 1, elements.length);
+				assertEquals("Incorrect element type", IJavaElement.TYPE, elements[0].getElementType());
+				assertElementEquals("Incorrect Java element", 
+						"Driver [in Driver.class [in java.sql [in <module:java.sql>]]]", elements[0]);
+				start = fileContent.lastIndexOf("Main");
+				elements = unit.codeSelect(start, "Main".length());
+				assertEquals("Incorrect no of elements", 1, elements.length);
+				assertEquals("Incorrect element type", IJavaElement.TYPE, elements[0].getElementType());
+				assertElementEquals("Incorrect Java element", 
+						"Main [in Main.java [in p.q [in src [in Java9Elements]]]]", elements[0]);
+		}
+		finally {
+			deleteProject("Java9Elements");
+		}
+	}
+	public void test526326c() throws Exception {
+		try {
+			IJavaProject project = createJavaProjectWithBaseSql();
+			project.open(null);
+				String fileContent = 
+						"module my.mod{\n"  +
+						 "	exports p.q;" +
+						 "	requires java.sql;\n" +
+						 "	provides java.sql.Driver with p.q.Main;\n" +
+						 "}";
+				createFile(	"/Java9Elements/src/module-info.java",	fileContent);
+				createFolder("/Java9Elements/src/p/q");
+				createFile("/Java9Elements/src/p/q/Main.java",
+						"package p.q;\n" +
+						"import java.sql.Connection;\n" +
+						"import java.sql.Driver;\n" +
+						"import java.sql.DriverPropertyInfo;\n" +
+						"import java.sql.SQLException;\n" +
+						"import java.sql.SQLFeatureNotSupportedException;\n" +
+						"import java.util.Properties;\n" +
+						"import java.util.logging.Logger;\n" +
+						"public class Main implements Driver {\n" +
+						"	public boolean acceptsURL(String arg0) throws SQLException { return false; }\n" +
+						"	public Connection connect(String arg0, Properties arg1) throws SQLException { return null; }\n" +
+						"	public int getMajorVersion() { return 0; }\n" +
+						"	public int getMinorVersion() { return 0;}\n" +
+						"	public Logger getParentLogger() throws SQLFeatureNotSupportedException { return null; }\n" +
+						"	public DriverPropertyInfo[] getPropertyInfo(String arg0, Properties arg1) throws SQLException { return null; }\n" +
+						"	public boolean jdbcCompliant() { return false; }\n" +
+						"}");
+				ICompilationUnit unit = getCompilationUnit("/Java9Elements/src/module-info.java");
+				int start = fileContent.lastIndexOf("Driver");
+				IJavaElement[] elements = unit.codeSelect(start, "Driver".length());
+				assertEquals("Incorrect no of elements", 1, elements.length);
+				assertEquals("Incorrect element type", IJavaElement.TYPE, elements[0].getElementType());
+				assertElementEquals("Incorrect Java element", 
+						"Driver [in Driver.class [in java.sql [in <module:java.sql>]]]", elements[0]);
+				start = fileContent.lastIndexOf("Main");
+				elements = unit.codeSelect(start, "Main".length());
+				assertEquals("Incorrect no of elements", 1, elements.length);
+				assertEquals("Incorrect element type", IJavaElement.TYPE, elements[0].getElementType());
+				assertElementEquals("Incorrect Java element", 
+						"Main [in Main.java [in p.q [in src [in Java9Elements]]]]", elements[0]);
+		}
+		finally {
+			deleteProject("Java9Elements");
+		}
+	}
 }
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java
index f1af2d6..65ffee3 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java
@@ -5103,7 +5103,7 @@
 				deleteProject(javaProject);
 		}
 	}
-	public void _testAutoModule3() throws Exception {
+	public void testAutoModule3() throws Exception {
 		if (!isJRE9) return;
 		IJavaProject javaProject = null, auto = null;
 		try {
@@ -5134,6 +5134,7 @@
 				"	p.a.X f;\n" +
 				"}";
 			createFile("/mod.one/src/q/X.java", srcX);
+			auto.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
 
 			this.problemRequestor.initialize(srcMod.toCharArray());
 			getWorkingCopy("/mod.one/module-info.java", srcMod, true);
@@ -5253,6 +5254,59 @@
 				deleteProject(javaProject2);
 		}
 	}
+	// like testAutoModule3 without name derived from project, not manifest
+	public void testAutoModule5() throws Exception {
+		if (!isJRE9) return;
+		IJavaProject javaProject = null, auto = null;
+		try {
+			auto = createJava9Project("auto", new String[] {"src"});
+			createFolder("auto/src/p/a");
+			createFile("auto/src/p/a/X.java",
+				"package p.a;\n" +
+				"public class X {}\n;");
+
+			javaProject = createJava9Project("mod.one", new String[] {"src"});
+			IClasspathAttribute[] attributes = { JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true") };
+			addClasspathEntry(javaProject, JavaCore.newProjectEntry(auto.getPath(), null, false, attributes, false));
+
+			String srcMod =
+				"module mod.one { \n" +
+				"	requires auto;\n" +
+				"}";
+			createFile("/mod.one/src/module-info.java", 
+				srcMod);
+			createFolder("mod.one/src/q");
+			String srcX =
+				"package q;\n" +
+				"public class X {\n" +
+				"	p.a.X f;\n" +
+				"}";
+			createFile("/mod.one/src/q/X.java", srcX);
+			auto.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
+
+			this.problemRequestor.initialize(srcMod.toCharArray());
+			getWorkingCopy("/mod.one/module-info.java", srcMod, true);
+			assertProblems("module-info should have no problems",
+					"----------\n" + 
+					"----------\n",
+					this.problemRequestor);
+
+			this.problemRequestor.initialize(srcX.toCharArray());
+			getWorkingCopy("/mod.one/src/q/X.java", srcX, true);
+			assertProblems("X should have no problems",
+					"----------\n" + 
+					"----------\n",
+					this.problemRequestor);
+
+			javaProject.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			assertNoErrors();
+		} finally {
+			if (javaProject != null)
+				deleteProject(javaProject);
+			if (auto != null)
+				deleteProject(auto);
+		}
+	}
 
 	// patch can see unexported type from host (and package accessible method), but not vice versa
 	public void testPatch1() throws CoreException, IOException {
diff --git a/org.eclipse.jdt.core/META-INF/MANIFEST.MF b/org.eclipse.jdt.core/META-INF/MANIFEST.MF
index 1ebaad0..386a0c2 100644
--- a/org.eclipse.jdt.core/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.core/META-INF/MANIFEST.MF
@@ -38,7 +38,7 @@
    org.eclipse.jdt.compiler.tool,
    org.eclipse.pde.api.tools,
    org.eclipse.jdt.apt.core",
- org.eclipse.jdt.internal.core;x-friends:="org.eclipse.jdt.apt.pluggable.core,org.eclipse.pde.api.tools",
+ org.eclipse.jdt.internal.core;x-friends:="org.eclipse.jdt.apt.pluggable.core,org.eclipse.pde.api.tools,org.eclipse.jdt.launching",
  org.eclipse.jdt.internal.core.builder;x-friends:="org.eclipse.jdt.apt.pluggable.core,org.eclipse.pde.api.tools",
  org.eclipse.jdt.internal.core.dom;x-internal:=true,
  org.eclipse.jdt.internal.core.dom.rewrite;x-internal:=true,
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 e50c370..168efdf 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
@@ -747,6 +747,7 @@
 	private INameEnvironment noCacheNameEnvironment;
 	char[] source;
 	ModuleDeclaration moduleDeclaration;
+	boolean isPackageVisibilityCompletion = false;
 	char[] completionToken;
 
 	char[] qualifiedCompletionToken;
@@ -1365,6 +1366,10 @@
 		if (this.knownPkgs.containsKey(packageName)) return;
 
 		if (!isValidPackageName(packageName)) return;
+		
+		if (this.isPackageVisibilityCompletion &&
+			CharOperation.equals(packageName, CharOperation.NO_CHAR))
+			return;
 
 		this.knownPkgs.put(packageName, this);
 
@@ -2427,44 +2432,49 @@
 
 	private boolean completeOnPackageVisibilityStatements(boolean contextAccepted,
 			CompilationUnitDeclaration parsedUnit, PackageVisibilityStatement[] pvsStmts) {
-		for (int i = 0, l = pvsStmts.length; i < l; ++i) {
-			PackageVisibilityStatement pvs = pvsStmts[i];
-			if (pvs instanceof CompletionOnKeywordModuleInfo) { // dummy pvs statement
-				contextAccepted = true;
-				processModuleKeywordCompletion(parsedUnit, pvs, (CompletionOnKeyword) pvs);
-				return contextAccepted;
-			}
-			if (pvs.pkgRef instanceof CompletionOnPackageVisibilityReference) {
-				contextAccepted = true;
-				buildContext(pvs, null, parsedUnit, null, null);
-				if(!this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) {
-					findPackages((CompletionOnPackageVisibilityReference) pvs.pkgRef);
-				}
-				debugPrintf();
-				return contextAccepted;
-			}
-			ModuleReference[] targets = pvs.targets;
-			if (targets == null) continue;
-			HashSet<String> skipSet = new HashSet<>();
-			for (int j = 0, lj = targets.length; j < lj; j++) {
-				ModuleReference target = targets[j];
-				if (target == null) break;
-				if (target instanceof CompletionOnModuleReference) {
-					buildContext(target, null, parsedUnit, null, null);
+		try {
+			this.isPackageVisibilityCompletion = true;
+			for (int i = 0, l = pvsStmts.length; i < l; ++i) {
+				PackageVisibilityStatement pvs = pvsStmts[i];
+				if (pvs instanceof CompletionOnKeywordModuleInfo) { // dummy pvs statement
 					contextAccepted = true;
-					if(!this.requestor.isIgnored(CompletionProposal.MODULE_REF)) {
-						findTargettedModules((CompletionOnModuleReference) target, skipSet);
+					processModuleKeywordCompletion(parsedUnit, pvs, (CompletionOnKeyword) pvs);
+					return contextAccepted;
+				}
+				if (pvs.pkgRef instanceof CompletionOnPackageVisibilityReference) {
+					contextAccepted = true;
+					buildContext(pvs, null, parsedUnit, null, null);
+					if(!this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) {
+						findPackages((CompletionOnPackageVisibilityReference) pvs.pkgRef);
 					}
 					debugPrintf();
 					return contextAccepted;
-				} else if (target instanceof CompletionOnKeyword) {
-					contextAccepted = true;
-					processModuleKeywordCompletion(parsedUnit, target, (CompletionOnKeyword) target);
-				} else {
-					if (target.moduleName != null || target.moduleName.equals(CharOperation.NO_CHAR))
-						skipSet.add(new String(target.moduleName));
+				}
+				ModuleReference[] targets = pvs.targets;
+				if (targets == null) continue;
+				HashSet<String> skipSet = new HashSet<>();
+				for (int j = 0, lj = targets.length; j < lj; j++) {
+					ModuleReference target = targets[j];
+					if (target == null) break;
+					if (target instanceof CompletionOnModuleReference) {
+						buildContext(target, null, parsedUnit, null, null);
+						contextAccepted = true;
+						if(!this.requestor.isIgnored(CompletionProposal.MODULE_REF)) {
+							findTargettedModules((CompletionOnModuleReference) target, skipSet);
+						}
+						debugPrintf();
+						return contextAccepted;
+					} else if (target instanceof CompletionOnKeyword) {
+						contextAccepted = true;
+						processModuleKeywordCompletion(parsedUnit, target, (CompletionOnKeyword) target);
+					} else {
+						if (target.moduleName != null || target.moduleName.equals(CharOperation.NO_CHAR))
+							skipSet.add(new String(target.moduleName));
+					}
 				}
 			}
+		} finally {
+			this.isPackageVisibilityCompletion = false;
 		}
 		return contextAccepted;
 	}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java
index f90d826..13b0179 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java
@@ -1095,6 +1095,9 @@
 					if (parsedUnit.isModuleInfo() && parsedUnit.moduleDeclaration != null) {
 						ModuleDeclaration module = parsedUnit.moduleDeclaration;
 						this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
+						if ((this.unitScope = parsedUnit.scope)  != null) {
+							this.lookupEnvironment.completeTypeBindings(parsedUnit, true);
+						}
 						module.resolveModuleDirectives(parsedUnit.scope);
 						module.resolvePackageDirectives(parsedUnit.scope);
 						module.resolveTypeDirectives(parsedUnit.scope);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java
index bd23d9e..73b6a0b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java
@@ -190,6 +190,11 @@
 			localType.enclosingCase = null;
 		}
 	}
+	if (this.functionalExpressionsCount > 0) {
+		for (int i = 0, max = this.functionalExpressionsCount; i < max; i++) {
+			this.functionalExpressions[i].cleanUp();
+		}
+	}
 
 	this.compilationResult.recoveryScannerData = null; // recovery is already done
 
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 eb968b7..32cbece 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
@@ -370,4 +370,7 @@
 	boolean requiresBridges() {
 		return getRequiredBridges() != null; 
 	}
+	public void cleanUp() {
+		// to be overridden by sub-classes
+	}
 }
\ No newline at end of file
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 e9c66d3..87f3e47 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
@@ -942,15 +942,28 @@
 		
 		if (argumentsTypeElided() || t.findSuperTypeOriginatingFrom(s) != null)
 			return false;
-		
+		TypeBinding sPrime = s; // uncaptured
 		s = s.capture(this.enclosingScope, this.sourceStart, this.sourceEnd);
 		MethodBinding sSam = s.getSingleAbstractMethod(this.enclosingScope, true);
 		if (sSam == null || !sSam.isValidBinding())
 			return false;
-		TypeBinding r1 = sSam.returnType;
 		MethodBinding tSam = t.getSingleAbstractMethod(this.enclosingScope, true);
 		if (tSam == null || !tSam.isValidBinding())
 			return true; // See ORT8.test450415a for a case that slips through isCompatibleWith.
+		MethodBinding adapted = tSam.computeSubstitutedMethod(sSam, skope.environment());
+		if (adapted == null) // not same type params
+			return false;
+		MethodBinding sSamPrime = sPrime.getSingleAbstractMethod(this.enclosingScope, true);
+		TypeBinding[] ps = adapted.parameters; // parameters of S adapted to type parameters of T
+		// parameters of S (without capture), adapted to type params of T
+		MethodBinding prime = tSam.computeSubstitutedMethod(sSamPrime, skope.environment());
+		TypeBinding[] pPrimes = prime.parameters;
+		TypeBinding[] qs = tSam.parameters;
+		for (int i = 0; i < ps.length; i++) {
+			if (!qs[i].isCompatibleWith(ps[i]) || TypeBinding.notEquals(qs[i], pPrimes[i]))
+				return false;
+		}
+		TypeBinding r1 = adapted.returnType; // return type of S adapted to type parameters of T
 		TypeBinding r2 = tSam.returnType;
 		
 		if (r2.id == TypeIds.T_void)
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 2d516bd..dec5751 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
@@ -88,6 +88,7 @@
 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
 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.parser.Parser;
 import org.eclipse.jdt.internal.compiler.parser.Scanner;
 
@@ -264,7 +265,6 @@
 		implicitLambda.generateCode(lambdaScope, codeStream, valueRequired);
 		if (generateSecretReceiverVariable) {
 			codeStream.removeVariable(this.receiverVariable);
-			this.receiverVariable = null;
 		}
 	}	
 	
@@ -272,19 +272,45 @@
 		// 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.requiresBridges()); // bridges.
+				this.requiresBridges() || // bridges.
+				!isDirectCodeGenPossible());
 		// To fix: We should opt for direct code generation wherever possible.
 	}
-	
+	private boolean isDirectCodeGenPossible() {
+		if (this.binding != null) {
+			if (isMethodReference() && this.syntheticAccessor == null) {
+				if (TypeBinding.notEquals(this.binding.declaringClass, this.lhs.resolvedType.erasure())) {
+					// reference to a method declared by an inaccessible type accessed via a
+					// subtype - normally a bridge method would be present to facilitate
+					// this access, unless the method is final, in which case, direct access to
+					// the method is not possible, an implicit lambda is needed
+					if (!this.binding.declaringClass.canBeSeenBy(this.enclosingScope)) {
+						return !this.binding.isFinal();
+					}
+				}
+			}
+			TypeBinding[] descriptorParams = this.descriptor.parameters;
+			TypeBinding[] origParams = this.binding.original().parameters;
+			TypeBinding[] origDescParams = this.descriptor.original().parameters;
+			int offset = this.receiverPrecedesParameters ? 1 : 0;
+			for (int i = 0; i < descriptorParams.length - offset; i++) {
+				TypeBinding descType = descriptorParams[i + offset];
+				TypeBinding origDescType = origDescParams[i + offset];
+				if (descType.isIntersectionType18() || 
+						(descType.isTypeVariable() && ((TypeVariableBinding) descType).otherUpperBounds() != null)) {
+					return CharOperation.equals(origDescType.signature(), origParams[i].signature());
+				}
+			}
+		}
+		return true;
+	}
 	public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
 		this.actualMethodBinding = this.binding; // grab before synthetics come into play.
 		// Handle some special cases up front and transform them into implicit lambdas.
 		if (shouldGenerateImplicitLambda(currentScope)) {
 			generateImplicitLambda(currentScope, codeStream, valueRequired);
-			cleanUp();
 			return;
 		}
-		cleanUp();
 		SourceTypeBinding sourceType = currentScope.enclosingSourceType();
 		if (this.receiverType.isArrayType()) {
 			char [] lambdaName = CharOperation.concat(TypeConstants.ANONYMOUS_METHOD, Integer.toString(this.ordinal).toCharArray());
@@ -370,7 +396,7 @@
 		codeStream.recordPositionsFrom(pc, this.sourceStart);
 	}
 	
-	private void cleanUp() {
+	public void cleanUp() {
 		// no more rescanning needed beyond this point, so free the memory:
 		if (this.copiesPerTargetType != null) {
 			for (ReferenceExpression copy : this.copiesPerTargetType.values())
@@ -380,6 +406,7 @@
 			this.original.cleanUp();
 		}
 		this.scanner = null;
+		this.receiverVariable = null;
 	}
 
 	public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
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 4d4f088..99bcde9 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
@@ -715,7 +715,7 @@
 	return missingTypes;
 }
 
-MethodBinding computeSubstitutedMethod(MethodBinding method, LookupEnvironment env) {
+public MethodBinding computeSubstitutedMethod(MethodBinding method, LookupEnvironment env) {
 	int length = this.typeVariables.length;
 	TypeVariableBinding[] vars = method.typeVariables;
 	if (length != vars.length)
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemMethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemMethodBinding.java
index 5098c14..92027d0 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemMethodBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemMethodBinding.java
@@ -90,7 +90,7 @@
 // SH}
 
 @Override
-MethodBinding computeSubstitutedMethod(MethodBinding method, LookupEnvironment env) {
+public MethodBinding computeSubstitutedMethod(MethodBinding method, LookupEnvironment env) {
 	return this.closestMatch == null ? this : this.closestMatch.computeSubstitutedMethod(method, env);
 }
 @Override
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java
index 338fcd7..0099b2f 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java
@@ -1913,7 +1913,7 @@
 					// https://bugs.eclipse.org/bugs/show_bug.cgi?id=331821
 					if (token == MementoTokenizer.PACKAGEFRAGMENT || token == MementoTokenizer.COUNT) {
 						break;
-					} else if (token == MementoTokenizer.PACKAGEFRAGMENTROOT) {
+					} else if (token == MementoTokenizer.MODULE) {
 						if (memento.hasMoreTokens()) {
 							token = memento.nextToken();
 							if (token != null) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java
index ce24470..bf5ce46 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java
@@ -891,6 +891,10 @@
 	String elementName = getElementName();
 	Manifest manifest = null;
 	switch (classpathEntry.getEntryKind()) {
+		case IClasspathEntry.CPE_SOURCE:
+			manifest = ((JavaProject) getJavaProject()).getManifest();
+			elementName = getJavaProject().getElementName();
+			break;
 		case IClasspathEntry.CPE_LIBRARY:
 			manifest = getManifest();
 			break;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java
index 0f03104..2b30b8e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java
@@ -16,7 +16,6 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.function.Function;
 
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResource;
@@ -888,15 +887,8 @@
 		if (this.rootToModule == null) {
 			this.rootToModule = new HashMap<>();
 		}
-		Function<IPackageFragmentRoot, IClasspathEntry> rootToEntry = r -> {
-			try {
-				return ((JavaProject) r.getJavaProject()).getClasspathEntryFor(r.getPath());
-			} catch (JavaModelException e) {
-				return null;
-			}
-		};
 		for (IPackageFragmentRoot root : roots) {
-			IModuleDescription moduleDescription = NameLookup.getModuleDescription(root, this.rootToModule, rootToEntry);
+			IModuleDescription moduleDescription = NameLookup.getModuleDescription(root, this.rootToModule, this.nameLookup.rootToResolvedEntries::get);
 			if (moduleDescription != null)
 				return moduleDescription;
 		}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CommentRecorderParser.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CommentRecorderParser.java
index bf2a426..7678c40 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CommentRecorderParser.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CommentRecorderParser.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 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
@@ -266,6 +266,7 @@
 	private void pushOnCommentsStack(int start, int end) {
 
 		for (int i=start; i<=end; i++) {
+			if (this.scanner.commentPtr < i) break;
 			// First see if comment hasn't been already stored
 			int scannerStart = this.scanner.commentStarts[i]<0 ? -this.scanner.commentStarts[i] : this.scanner.commentStarts[i];
 			int commentStart = this.commentPtr == -1 ? -1 : (this.commentStarts[this.commentPtr]<0 ? -this.commentStarts[this.commentPtr] : this.commentStarts[this.commentPtr]);
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java
index c4e23a8..292bd6d 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java
@@ -1325,6 +1325,14 @@
 
 	this.lookupEnvironment.addResolutionListener(this.patternLocator);
 }
+private boolean skipMatch(JavaProject javaProject, PossibleMatch possibleMatch) {
+	if (this.options.sourceLevel >= ClassFileConstants.JDK9) {
+		char[] pModuleName = possibleMatch.getModuleName();
+		if (pModuleName != null && this.lookupEnvironment.getModule(pModuleName) == null)
+			return true;
+	}
+	return false;
+}
 protected void locateMatches(JavaProject javaProject, PossibleMatch[] possibleMatches, int start, int length) throws CoreException {
 	initialize(javaProject, length);
 
@@ -1364,6 +1372,7 @@
 // SH}
 		for (int i = start, maxUnits = start + length; i < maxUnits; i++) {
 			PossibleMatch possibleMatch = possibleMatches[i];
+			if (skipMatch(javaProject, possibleMatch)) continue;
 			try {
 				if (!parseAndBuildBindings(possibleMatch, mustResolvePattern)) continue;
 				// Currently we only need to resolve over pattern flag if there's potential parameterized types