Rename unsafe definitionForProgramType and implement safe variant.

Change-Id: Icdadba6335d8a7ef105dceed28b785733bf811f6
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java b/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java
index a7949db..510249b 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java
@@ -280,7 +280,7 @@
   private Type invokeTypeForInvokeSpecialToNonInitMethodOnHolder(
       AppView<?> appView, CfSourceCode code) {
     boolean desugaringEnabled = appView.options().isInterfaceMethodDesugaringEnabled();
-    DexEncodedMethod encodedMethod = lookupMethod(appView, method);
+    DexEncodedMethod encodedMethod = lookupMethodOnHolder(appView, method);
     if (encodedMethod == null) {
       // The method is not defined on the class, we can use super to target. When desugaring
       // default interface methods, it is expected they are targeted with invoke-direct.
@@ -303,11 +303,13 @@
         "Failed to compile unsupported use of invokespecial", code.getOrigin());
   }
 
-  private DexEncodedMethod lookupMethod(AppView<?> appView, DexMethod method) {
+  private DexEncodedMethod lookupMethodOnHolder(AppView<?> appView, DexMethod method) {
     GraphLensLookupResult lookupResult =
         appView.graphLens().lookupMethod(method, method, Type.DIRECT);
     DexMethod rewrittenMethod = lookupResult.getMethod();
-    DexProgramClass clazz = appView.definitionForProgramType(rewrittenMethod.holder);
+    // Directly lookup the program type for holder. This bypasses lookup order as well as looks
+    // directly on the application data, which bypasses and indirection or validation.
+    DexProgramClass clazz = appView.appInfo().unsafeDirectProgramTypeLookup(rewrittenMethod.holder);
     assert clazz != null;
     return clazz.lookupMethod(rewrittenMethod);
   }
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfo.java b/src/main/java/com/android/tools/r8/graph/AppInfo.java
index 60b8220..ee67876 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfo.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfo.java
@@ -150,8 +150,7 @@
     return definition;
   }
 
-  @Override
-  public DexProgramClass definitionForProgramType(DexType type) {
+  public DexProgramClass unsafeDirectProgramTypeLookup(DexType type) {
     return app.programDefinitionFor(type);
   }
 
diff --git a/src/main/java/com/android/tools/r8/graph/AppView.java b/src/main/java/com/android/tools/r8/graph/AppView.java
index 7b0c80f..aa5b5cd 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -230,11 +230,6 @@
     return appInfo().definitionFor(type);
   }
 
-  @Override
-  public final DexProgramClass definitionForProgramType(DexType type) {
-    return appInfo.app().programDefinitionFor(type);
-  }
-
   public OptionalBool isInterface(DexType type) {
     assert type.isClassType();
     // Without whole program information we should not assume anything about any other class than
@@ -430,7 +425,7 @@
 
   public boolean validateUnboxedEnumsHaveBeenPruned() {
     for (DexType unboxedEnum : unboxedEnums.enumSet()) {
-      assert definitionForProgramType(unboxedEnum) == null
+      assert appInfo.definitionForWithoutExistenceAssert(unboxedEnum) == null
           : "Enum " + unboxedEnum + " has been unboxed but is still in the program.";
       assert appInfo().withLiveness().wasPruned(unboxedEnum)
           : "Enum " + unboxedEnum + " has been unboxed but was not pruned.";
diff --git a/src/main/java/com/android/tools/r8/graph/DexDefinitionSupplier.java b/src/main/java/com/android/tools/r8/graph/DexDefinitionSupplier.java
index 2ec6dbf..47223c0 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDefinitionSupplier.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDefinitionSupplier.java
@@ -8,7 +8,9 @@
 
   DexClass definitionFor(DexType type);
 
-  DexProgramClass definitionForProgramType(DexType type);
+  default DexProgramClass definitionForProgramType(DexType type) {
+    return DexProgramClass.asProgramClassOrNull(definitionFor(type));
+  }
 
   default <D extends DexEncodedMember<D, R>, R extends DexMember<D, R>>
       DexClass definitionForHolder(DexEncodedMember<D, R> member) {
diff --git a/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java b/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java
index 3a78118..f0f7d32 100644
--- a/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java
+++ b/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java
@@ -80,19 +80,14 @@
   }
 
   @Override
-  public DexProgramClass definitionForProgramType(DexType type) {
-    return programDefinitionFor(type);
-  }
-
-  @Override
   public DexItemFactory dexItemFactory() {
     return dexItemFactory;
   }
 
   @Override
   public DexProgramClass programDefinitionFor(DexType type) {
-    DexClass clazz = definitionFor(type);
-    return clazz instanceof DexProgramClass ? clazz.asProgramClass() : null;
+    // The direct mapped application has no duplicates so this coincides with definitionFor.
+    return DexProgramClass.asProgramClassOrNull(definitionFor(type));
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/graph/LazyLoadedDexApplication.java b/src/main/java/com/android/tools/r8/graph/LazyLoadedDexApplication.java
index 7127794..1721860 100644
--- a/src/main/java/com/android/tools/r8/graph/LazyLoadedDexApplication.java
+++ b/src/main/java/com/android/tools/r8/graph/LazyLoadedDexApplication.java
@@ -88,7 +88,7 @@
     return programClasses.get(type);
   }
 
-  public DexLibraryClass libraryDefintionFor(DexType type) {
+  public DexLibraryClass libraryDefinitionFor(DexType type) {
     assert type.isClassType() : "Cannot lookup library definition for type: " + type;
     return libraryClasses.get(type);
   }
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataEnqueuerExtension.java b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataEnqueuerExtension.java
index 680bd5c..5327873 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataEnqueuerExtension.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataEnqueuerExtension.java
@@ -8,7 +8,6 @@
 import static com.android.tools.r8.kotlin.KotlinMetadataUtils.NO_KOTLIN_INFO;
 import static com.android.tools.r8.utils.FunctionUtils.forEachApply;
 
-import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexDefinitionSupplier;
@@ -132,11 +131,6 @@
     }
 
     @Override
-    public DexProgramClass definitionForProgramType(DexType type) {
-      throw new Unreachable("Should not be called");
-    }
-
-    @Override
     public DexItemFactory dexItemFactory() {
       return baseSupplier.dexItemFactory();
     }
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index 6fdcb48..b31228b 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -4226,11 +4226,6 @@
     }
 
     @Override
-    public DexProgramClass definitionForProgramType(DexType type) {
-      return enqueuer.getProgramClassOrNull(type);
-    }
-
-    @Override
     public DexItemFactory dexItemFactory() {
       return appView.dexItemFactory();
     }
diff --git a/src/test/java/com/android/tools/r8/resolution/virtualtargets/KeptTargetsIncompleteLookupTest.java b/src/test/java/com/android/tools/r8/resolution/virtualtargets/KeptTargetsIncompleteLookupTest.java
index 4332d86..3566d3a 100644
--- a/src/test/java/com/android/tools/r8/resolution/virtualtargets/KeptTargetsIncompleteLookupTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/virtualtargets/KeptTargetsIncompleteLookupTest.java
@@ -88,7 +88,11 @@
     DexMethod method = buildNullaryVoidMethod(initial, "foo", appInfo.dexItemFactory());
     ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(method);
     DexProgramClass context =
-        appView.definitionForProgramType(buildType(Unrelated.class, appInfo.dexItemFactory()));
+        DexProgramClass.asProgramClassOrNull(
+            appView
+                .appInfo()
+                .definitionForWithoutExistenceAssert(
+                    buildType(Unrelated.class, appInfo.dexItemFactory())));
     LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(context, appInfo);
     assertTrue(lookupResult.isLookupResultSuccess());
     LookupResultSuccess lookupResultSuccess = lookupResult.asLookupResultSuccess();