Fix failures from missing classes update

Change-Id: I727ce93f4965fc63bb00e986b2332353b99fe2c2
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/nest/D8NestBasedAccessDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/nest/D8NestBasedAccessDesugaring.java
index de211e8..9fcf485 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/nest/D8NestBasedAccessDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/nest/D8NestBasedAccessDesugaring.java
@@ -37,6 +37,9 @@
   public void reportDesugarDependencies() {
     forEachNest(
         nest -> {
+          if (nest.hasMissingMembers()) {
+            throw appView.options().errorMissingNestMember(nest);
+          }
           DexClass hostClass = nest.getHostClass();
           for (DexClass memberClass : nest.getMembers()) {
             if (hostClass.isProgramClass() || memberClass.isProgramClass()) {
@@ -44,6 +47,9 @@
               reportDependencyEdge(memberClass, hostClass, appView.options());
             }
           }
+        },
+        classWithoutHost -> {
+          throw appView.options().errorMissingNestHost(classWithoutHost);
         });
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/nest/Nest.java b/src/main/java/com/android/tools/r8/ir/desugar/nest/Nest.java
index 1e66edc..979eb9c 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/nest/Nest.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/nest/Nest.java
@@ -11,6 +11,7 @@
 import com.google.common.collect.Iterables;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.function.Consumer;
 
 public class Nest {
 
@@ -25,13 +26,19 @@
   }
 
   public static Nest create(AppView<?> appView, DexClass clazz) {
+    return create(appView, clazz, null);
+  }
+
+  public static Nest create(
+      AppView<?> appView, DexClass clazz, Consumer<DexClass> missingHostConsumer) {
     assert clazz.isInANest();
 
     DexClass hostClass = clazz.isNestHost() ? clazz : appView.definitionFor(clazz.getNestHost());
     if (hostClass == null) {
       // Missing nest host means the class is considered as not being part of a nest.
-      clazz.clearNestHost();
-      appView.options().nestDesugaringWarningMissingNestHost(clazz);
+      if (missingHostConsumer != null) {
+        missingHostConsumer.accept(clazz);
+      }
       return null;
     }
 
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaring.java
index bab308e..cbaa05a 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaring.java
@@ -4,6 +4,8 @@
 
 package com.android.tools.r8.ir.desugar.nest;
 
+import static com.android.tools.r8.utils.ConsumerUtils.emptyConsumer;
+
 import com.android.tools.r8.cf.code.CfConstNull;
 import com.android.tools.r8.cf.code.CfFieldInstruction;
 import com.android.tools.r8.cf.code.CfInstruction;
@@ -76,13 +78,17 @@
   }
 
   void forEachNest(Consumer<Nest> consumer) {
+    forEachNest(consumer, emptyConsumer());
+  }
+
+  void forEachNest(Consumer<Nest> consumer, Consumer<DexClass> missingHostConsumer) {
     Set<DexType> seenNestHosts = Sets.newIdentityHashSet();
     for (DexProgramClass clazz : appView.appInfo().classes()) {
       if (!clazz.isInANest() || !seenNestHosts.add(clazz.getNestHost())) {
         continue;
       }
 
-      Nest nest = Nest.create(appView, clazz);
+      Nest nest = Nest.create(appView, clazz, missingHostConsumer);
       if (nest != null) {
         consumer.accept(nest);
       }
@@ -225,7 +231,7 @@
   private RuntimeException reportIncompleteNest(LibraryMember<?, ?> member) {
     Nest nest = Nest.create(appView, member.getHolder());
     assert nest != null : "Should be a compilation error if missing nest host on library class.";
-    throw appView.options().errorMissingClassIncompleteNest(nest);
+    throw appView.options().errorMissingNestMember(nest);
   }
 
   private DexProgramClass createNestAccessConstructor() {
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 9230427..a8bec4a 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -21,6 +21,7 @@
 import com.android.tools.r8.dex.Marker.Tool;
 import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.errors.ExperimentalClassFileVersionDiagnostic;
+import com.android.tools.r8.errors.IncompleteNestNestDesugarDiagnosic;
 import com.android.tools.r8.errors.InterfaceDesugarMissingTypeDiagnostic;
 import com.android.tools.r8.errors.InvalidDebugInfoException;
 import com.android.tools.r8.errors.InvalidLibrarySuperclassDiagnostic;
@@ -602,6 +603,7 @@
   public boolean printCfg = false;
   public String printCfgFile;
   public boolean ignoreMissingClasses = false;
+
   // EXPERIMENTAL flag to get behaviour as close to Proguard as possible.
   public boolean forceProguardCompatibility = false;
   public AssertionConfigurationWithDefault assertionsConfiguration = null;
@@ -789,42 +791,28 @@
 
   private final Set<DexItem> invalidLibraryClasses = Sets.newConcurrentHashSet();
 
-  public RuntimeException errorMissingClassMissingNestHost(DexClass compiledClass) {
-    throw reporter.fatalError(messageErrorMissingNestHost(compiledClass));
-  }
-
-  public void nestDesugaringWarningMissingNestHost(DexClass compiledClass) {
-    if (compiledClass.isLibraryClass()) {
-      throw errorMissingClassMissingNestHost(compiledClass);
-    }
-    reporter.warning(
+  public RuntimeException errorMissingNestHost(DexClass clazz) {
+    throw reporter.fatalError(
         new MissingNestHostNestDesugarDiagnostic(
-            compiledClass.getOrigin(),
-            Position.UNKNOWN,
-            messageWarningMissingNestHost(compiledClass)));
+            clazz.getOrigin(), Position.UNKNOWN, messageErrorMissingNestHost(clazz)));
   }
 
-  public RuntimeException errorMissingClassIncompleteNest(Nest nest) {
-    throw reporter.fatalError(messageErrorIncompleteNest(nest));
-  }
-
-  private String messageErrorMissingNestHost(DexClass compiledClass) {
+  private static String messageErrorMissingNestHost(DexClass compiledClass) {
     String nestHostName = compiledClass.getNestHost().getName();
     return "Class "
         + compiledClass.type.getName()
         + " requires its nest host "
         + nestHostName
-        + " to be on program or class path. ";
+        + " to be on program or class path.";
   }
 
-  private String messageWarningMissingNestHost(DexClass compiledClass) {
-    return messageErrorMissingNestHost(compiledClass)
-        + "Class "
-        + compiledClass.type.getName()
-        + " is considered as not being part of any nest.";
+  public RuntimeException errorMissingNestMember(Nest nest) {
+    throw reporter.fatalError(
+        new IncompleteNestNestDesugarDiagnosic(
+            nest.getHostClass().getOrigin(), Position.UNKNOWN, messageErrorIncompleteNest(nest)));
   }
 
-  private String messageErrorIncompleteNest(Nest nest) {
+  private static String messageErrorIncompleteNest(Nest nest) {
     List<DexProgramClass> programClassesFromNest = new ArrayList<>();
     List<DexClasspathClass> classpathClassesFromNest = new ArrayList<>();
     List<DexLibraryClass> libraryClassesFromNest = new ArrayList<>();
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ProgramRewritingTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ProgramRewritingTest.java
index 7dde5dc..07f4415 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ProgramRewritingTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ProgramRewritingTest.java
@@ -14,6 +14,7 @@
 import com.android.tools.r8.D8TestRunResult;
 import com.android.tools.r8.R8TestRunResult;
 import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestShrinkerBuilder;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.ToolHelper.DexVm;
 import com.android.tools.r8.utils.AndroidApiLevel;
@@ -120,7 +121,9 @@
           testForR8(parameters.getBackend())
               .minification(minifying)
               .addKeepMainRule(TEST_CLASS)
-              .addDontWarnEmulatedLibraryClasses()
+              .applyIf(
+                  parameters.getApiLevel().isLessThan(AndroidApiLevel.N),
+                  TestShrinkerBuilder::addDontWarnEmulatedLibraryClasses)
               .addProgramFiles(Paths.get(ToolHelper.EXAMPLES_JAVA9_BUILD_DIR + "stream.jar"))
               .setMinApi(parameters.getApiLevel())
               .addOptionsModification(
diff --git a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestCompilationExceptionTest.java b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestCompilationExceptionTest.java
index 62aa4a3..66e2ec7 100644
--- a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestCompilationExceptionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestCompilationExceptionTest.java
@@ -58,12 +58,14 @@
   }
 
   @Test
-  public void testWarningD8() throws Exception {
+  public void testD8() throws Exception {
     Assume.assumeTrue(parameters.isDexRuntime());
-    testIncompleteNestWarning(true, true);
-    testMissingNestHostWarning(true, true);
+    testMissingNestHostError(true);
+    testIncompleteNestError(true);
   }
-
+  // TODO R8:
+  // appView.options().reportMissingNestHost(clazz);
+  // clazz.clearNestHost();
   @Test
   public void testWarningR8() throws Exception {
     testIncompleteNestWarning(false, parameters.isDexRuntime());
@@ -72,8 +74,8 @@
 
   @Test
   public void testErrorR8() {
-    testMissingNestHostError();
-    testIncompleteNestError();
+    testMissingNestHostError(false);
+    testIncompleteNestError(false);
   }
 
   private TestCompilerBuilder<?, ?, ?, ?, ?> compileOnlyClassesMatching(
@@ -106,23 +108,38 @@
     }
   }
 
-  private void testMissingNestHostError() {
+  private void testMissingNestHostError(boolean d8) {
     try {
       Matcher<String> innerClassMatcher =
           containsString("BasicNestHostWithInnerClassMethods$BasicNestedClass");
-      compileOnlyClassesMatching(innerClassMatcher, false, false, false)
+      compileOnlyClassesMatching(innerClassMatcher, d8, false, false)
           .compileWithExpectedDiagnostics(
               diagnostics -> {
-                diagnostics
-                    .assertOnlyErrors()
-                    .assertErrorsMatch(diagnosticType(MissingClassesDiagnostic.class));
+                if (d8) {
+                  diagnostics
+                      .assertOnlyErrors()
+                      .assertErrorsMatch(
+                          diagnosticType(MissingNestHostNestDesugarDiagnostic.class));
 
-                MissingClassesDiagnostic diagnostic =
-                    (MissingClassesDiagnostic) diagnostics.getErrors().get(0);
-                assertEquals(1, diagnostic.getMissingClasses().size());
-                assertEquals(
-                    "nesthostexample.BasicNestHostWithInnerClassMethods",
-                    diagnostic.getMissingClasses().iterator().next().getTypeName());
+                  MissingNestHostNestDesugarDiagnostic diagnostic =
+                      (MissingNestHostNestDesugarDiagnostic) diagnostics.getErrors().get(0);
+                  assertEquals(
+                      "Class BasicNestHostWithInnerClassMethods$BasicNestedClass requires its nest "
+                          + "host BasicNestHostWithInnerClassMethods to be on program or class "
+                          + "path.",
+                      diagnostic.getDiagnosticMessage());
+                } else {
+                  diagnostics
+                      .assertOnlyErrors()
+                      .assertErrorsMatch(diagnosticType(MissingClassesDiagnostic.class));
+
+                  MissingClassesDiagnostic diagnostic =
+                      (MissingClassesDiagnostic) diagnostics.getErrors().get(0);
+                  assertEquals(1, diagnostic.getMissingClasses().size());
+                  assertEquals(
+                      "nesthostexample.BasicNestHostWithInnerClassMethods",
+                      diagnostic.getMissingClasses().iterator().next().getTypeName());
+                }
               });
     } catch (CompilationFailedException e) {
       // Expected failure.
@@ -131,22 +148,37 @@
     fail("Should have raised an exception for missing nest host");
   }
 
-  private void testIncompleteNestError() {
+  private void testIncompleteNestError(boolean d8) {
     try {
       Matcher<String> innerClassMatcher = endsWith("BasicNestHostWithInnerClassMethods");
-      compileOnlyClassesMatching(innerClassMatcher, false, false, false)
+      compileOnlyClassesMatching(innerClassMatcher, d8, false, false)
           .compileWithExpectedDiagnostics(
               diagnostics -> {
-                diagnostics
-                    .assertOnlyErrors()
-                    .assertErrorsMatch(diagnosticType(MissingClassesDiagnostic.class));
+                if (d8) {
+                  diagnostics
+                      .assertOnlyErrors()
+                      .assertErrorsMatch(diagnosticType(IncompleteNestNestDesugarDiagnosic.class));
 
-                MissingClassesDiagnostic diagnostic =
-                    (MissingClassesDiagnostic) diagnostics.getErrors().get(0);
-                assertEquals(1, diagnostic.getMissingClasses().size());
-                assertEquals(
-                    "nesthostexample.BasicNestHostWithInnerClassMethods$BasicNestedClass",
-                    diagnostic.getMissingClasses().iterator().next().getTypeName());
+                  IncompleteNestNestDesugarDiagnosic diagnostic =
+                      (IncompleteNestNestDesugarDiagnosic) diagnostics.getErrors().get(0);
+                  assertEquals(
+                      "Compilation of classes nesthostexample.BasicNestHostWithInnerClassMethods "
+                          + "requires its nest mates "
+                          + "nesthostexample.BasicNestHostWithInnerClassMethods$BasicNestedClass "
+                          + "(unavailable) to be on program or class path.",
+                      diagnostic.getDiagnosticMessage());
+                } else {
+                  diagnostics
+                      .assertOnlyErrors()
+                      .assertErrorsMatch(diagnosticType(MissingClassesDiagnostic.class));
+
+                  MissingClassesDiagnostic diagnostic =
+                      (MissingClassesDiagnostic) diagnostics.getErrors().get(0);
+                  assertEquals(1, diagnostic.getMissingClasses().size());
+                  assertEquals(
+                      "nesthostexample.BasicNestHostWithInnerClassMethods$BasicNestedClass",
+                      diagnostic.getMissingClasses().iterator().next().getTypeName());
+                }
               });
     } catch (Exception e) {
       // Expected failure.