Merge "Add a test about optimizing unused Kotlin singleton."
diff --git a/src/main/java/com/android/tools/r8/GenerateMainDexList.java b/src/main/java/com/android/tools/r8/GenerateMainDexList.java
index 5737aa0..4b1d11f 100644
--- a/src/main/java/com/android/tools/r8/GenerateMainDexList.java
+++ b/src/main/java/com/android/tools/r8/GenerateMainDexList.java
@@ -9,7 +9,6 @@
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexApplication;
 import com.android.tools.r8.graph.DexReference;
-import com.android.tools.r8.graph.GraphLense;
 import com.android.tools.r8.shaking.DiscardedChecker;
 import com.android.tools.r8.shaking.Enqueuer;
 import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
@@ -45,8 +44,7 @@
       DexApplication application =
           new ApplicationReader(app, options, timing).read(executor).toDirect();
       AppView<? extends AppInfoWithSubtyping> appView =
-          new AppView<>(
-              new AppInfoWithSubtyping(application), GraphLense.getIdentityLense(), options);
+          AppView.createForR8(new AppInfoWithSubtyping(application), options);
       RootSet mainDexRootSet =
           new RootSetBuilder(appView, application, options.mainDexKeepRules, options).run(executor);
 
diff --git a/src/main/java/com/android/tools/r8/PrintSeeds.java b/src/main/java/com/android/tools/r8/PrintSeeds.java
index 475ca70..865b60d 100644
--- a/src/main/java/com/android/tools/r8/PrintSeeds.java
+++ b/src/main/java/com/android/tools/r8/PrintSeeds.java
@@ -7,7 +7,6 @@
 import com.android.tools.r8.graph.AppInfoWithSubtyping;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexApplication;
-import com.android.tools.r8.graph.GraphLense;
 import com.android.tools.r8.shaking.Enqueuer;
 import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 import com.android.tools.r8.shaking.RootSetBuilder;
@@ -84,8 +83,7 @@
       DexApplication application =
           new ApplicationReader(command.getInputApp(), options, timing).read(executor).toDirect();
       AppView<? extends AppInfoWithSubtyping> appView =
-          new AppView<>(
-              new AppInfoWithSubtyping(application), GraphLense.getIdentityLense(), options);
+          AppView.createForR8(new AppInfoWithSubtyping(application), options);
       RootSet rootSet =
           new RootSetBuilder(
                   appView, application, options.getProguardConfiguration().getRules(), options)
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 6bade2f..a47351c 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -268,8 +268,7 @@
       inputApp.closeInternalArchiveProviders();
 
       AppView<AppInfoWithSubtyping> appView =
-          new AppView<>(
-              new AppInfoWithSubtyping(application), GraphLense.getIdentityLense(), options);
+          AppView.createForR8(new AppInfoWithSubtyping(application), options);
       appView.setAppServices(AppServices.builder(appView).build());
 
       List<ProguardConfigurationRule> synthesizedProguardRules = new ArrayList<>();
@@ -420,7 +419,7 @@
 
       if (appView.appInfo().hasLiveness()) {
         AppView<AppInfoWithLiveness> appViewWithLiveness = appView.withLiveness();
-        appView.setGraphLense(new MemberRebindingAnalysis(appViewWithLiveness, options).run());
+        appView.setGraphLense(new MemberRebindingAnalysis(appViewWithLiveness).run());
         if (options.enableHorizontalClassMerging) {
           StaticClassMerger staticClassMerger =
               new StaticClassMerger(appViewWithLiveness, options, mainDexClasses);
@@ -477,9 +476,8 @@
         }
 
         // Collect switch maps and ordinals maps.
-        appViewWithLiveness.setAppInfo(new SwitchMapCollector(appViewWithLiveness, options).run());
-        appViewWithLiveness.setAppInfo(
-            new EnumOrdinalMapCollector(appViewWithLiveness, options).run());
+        appViewWithLiveness.setAppInfo(new SwitchMapCollector(appViewWithLiveness).run());
+        appViewWithLiveness.setAppInfo(new EnumOrdinalMapCollector(appViewWithLiveness).run());
       }
 
       appView.setAppServices(appView.appServices().rewrittenWithLens(appView.graphLense()));
@@ -488,9 +486,7 @@
       Set<DexCallSite> desugaredCallSites;
       CfgPrinter printer = options.printCfg ? new CfgPrinter() : null;
       try {
-        IRConverter converter =
-            new IRConverter(
-                appView.withLiveness(), options, timing, printer, mainDexClasses, rootSet);
+        IRConverter converter = new IRConverter(appView, timing, printer, mainDexClasses, rootSet);
         application = converter.optimize(application, executorService);
         desugaredCallSites = converter.getDesugaredCallSites();
       } finally {
@@ -632,7 +628,8 @@
       NamingLens namingLens;
       if (options.getProguardConfiguration().hasApplyMappingFile()) {
         SeedMapper seedMapper =
-            SeedMapper.seedMapperFromFile(options.getProguardConfiguration().getApplyMappingFile());
+            SeedMapper.seedMapperFromFile(
+                options.reporter, options.getProguardConfiguration().getApplyMappingFile());
         timing.begin("apply-mapping");
         namingLens =
             new ProguardMapMinifier(appView.withLiveness(), rootSet, seedMapper, desugaredCallSites)
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 93db17b..a01f840 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfo.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfo.java
@@ -17,7 +17,7 @@
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.function.Consumer;
 
-public class AppInfo {
+public class AppInfo implements DexDefinitionSupplier {
 
   public final DexApplication app;
   public final DexItemFactory dexItemFactory;
@@ -48,6 +48,11 @@
     this(application);
   }
 
+  @Override
+  public DexItemFactory dexItemFactory() {
+    return dexItemFactory;
+  }
+
   public void addSynthesizedClass(DexProgramClass clazz) {
     assert clazz.type.isD8R8SynthesizedClassType();
     DexProgramClass previous = synthesizedClasses.put(clazz.type, clazz);
@@ -76,6 +81,7 @@
     return app.classesWithDeterministicOrder();
   }
 
+  @Override
   public DexDefinition definitionFor(DexReference reference) {
     if (reference.isDexType()) {
       return definitionFor(reference.asDexType());
@@ -87,6 +93,7 @@
     return definitionFor(reference.asDexField());
   }
 
+  @Override
   public DexClass definitionFor(DexType type) {
     DexProgramClass cached = synthesizedClasses.get(type);
     if (cached != null) {
@@ -101,6 +108,7 @@
     return definition == null ? Origin.unknown() : definition.origin;
   }
 
+  @Override
   public DexEncodedMethod definitionFor(DexMethod method) {
     DexType holderType = method.getHolder();
     DexEncodedMethod cached = (DexEncodedMethod) getDefinitions(holderType).get(method);
@@ -111,6 +119,7 @@
     return cached;
   }
 
+  @Override
   public DexEncodedField definitionFor(DexField field) {
     return (DexEncodedField) getDefinitions(field.getHolder()).get(field);
   }
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 084ad80..8690894 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -8,22 +8,40 @@
 import com.android.tools.r8.shaking.VerticalClassMerger.VerticallyMergedClasses;
 import com.android.tools.r8.utils.InternalOptions;
 
-public class AppView<T extends AppInfo> {
+public class AppView<T extends AppInfo> implements DexDefinitionSupplier {
 
   private T appInfo;
   private AppServices appServices;
   private final DexItemFactory dexItemFactory;
+  private final boolean enableWholeProgramOptimizations;
   private GraphLense graphLense;
   private final InternalOptions options;
   private VerticallyMergedClasses verticallyMergedClasses;
 
-  public AppView(T appInfo, GraphLense graphLense, InternalOptions options) {
+  private AppView(
+      T appInfo,
+      boolean enableWholeProgramOptimizations,
+      GraphLense graphLense,
+      InternalOptions options) {
     this.appInfo = appInfo;
     this.dexItemFactory = appInfo != null ? appInfo.dexItemFactory : null;
+    this.enableWholeProgramOptimizations = enableWholeProgramOptimizations;
     this.graphLense = graphLense;
     this.options = options;
   }
 
+  public static <T extends AppInfo> AppView<T> createForD8(T appInfo, InternalOptions options) {
+    boolean enableWholeProgramOptimizations = false;
+    return new AppView<>(
+        appInfo, enableWholeProgramOptimizations, GraphLense.getIdentityLense(), options);
+  }
+
+  public static <T extends AppInfo> AppView<T> createForR8(T appInfo, InternalOptions options) {
+    boolean enableWholeProgramOptimizations = true;
+    return new AppView<>(
+        appInfo, enableWholeProgramOptimizations, GraphLense.getIdentityLense(), options);
+  }
+
   public T appInfo() {
     return appInfo;
   }
@@ -40,14 +58,33 @@
     this.appServices = appServices;
   }
 
+  @Override
+  public final DexDefinition definitionFor(DexReference reference) {
+    return appInfo().definitionFor(reference);
+  }
+
+  @Override
+  public final DexEncodedField definitionFor(DexField field) {
+    return appInfo().definitionFor(field);
+  }
+
+  @Override
+  public final DexEncodedMethod definitionFor(DexMethod method) {
+    return appInfo().definitionFor(method);
+  }
+
+  @Override
+  public final DexClass definitionFor(DexType type) {
+    return appInfo().definitionFor(type);
+  }
+
+  @Override
   public DexItemFactory dexItemFactory() {
     return dexItemFactory;
   }
 
-  // TODO(b/114469298): If we at some point replace all occurences of AppInfo with AppView,
-  // then this method should return false when we are running with D8.
   public boolean enableWholeProgramOptimizations() {
-    return true;
+    return enableWholeProgramOptimizations;
   }
 
   public GraphLense graphLense() {
@@ -79,7 +116,7 @@
   private class AppViewWithLiveness extends AppView<AppInfoWithLiveness> {
 
     private AppViewWithLiveness() {
-      super(null, null, null);
+      super(null, false, null, null);
     }
 
     @Override
@@ -110,6 +147,11 @@
     }
 
     @Override
+    public boolean enableWholeProgramOptimizations() {
+      return AppView.this.enableWholeProgramOptimizations();
+    }
+
+    @Override
     public GraphLense graphLense() {
       return AppView.this.graphLense();
     }
diff --git a/src/main/java/com/android/tools/r8/graph/DexDefinitionSupplier.java b/src/main/java/com/android/tools/r8/graph/DexDefinitionSupplier.java
new file mode 100644
index 0000000..7d9888e
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/DexDefinitionSupplier.java
@@ -0,0 +1,18 @@
+// Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.graph;
+
+public interface DexDefinitionSupplier {
+
+  DexDefinition definitionFor(DexReference reference);
+
+  DexEncodedField definitionFor(DexField field);
+
+  DexEncodedMethod definitionFor(DexMethod method);
+
+  DexClass definitionFor(DexType type);
+
+  DexItemFactory dexItemFactory();
+}
diff --git a/src/main/java/com/android/tools/r8/graph/DexType.java b/src/main/java/com/android/tools/r8/graph/DexType.java
index 249a2b5..4f90719 100644
--- a/src/main/java/com/android/tools/r8/graph/DexType.java
+++ b/src/main/java/com/android/tools/r8/graph/DexType.java
@@ -160,68 +160,70 @@
     type.directSubtypes = NO_DIRECT_SUBTYPE;
   }
 
-  public boolean isSubtypeOf(DexType other, AppInfo appInfo) {
-    return this == other || isStrictSubtypeOf(other, appInfo);
+  public boolean isSubtypeOf(DexType other, DexDefinitionSupplier definitions) {
+    return this == other || isStrictSubtypeOf(other, definitions);
   }
 
   public boolean hasSubtypes() {
     return !directSubtypes.isEmpty();
   }
 
-  public boolean isStrictSubtypeOf(DexType other, AppInfo appInfo) {
+  public boolean isStrictSubtypeOf(DexType other, DexDefinitionSupplier definitions) {
     // For all erroneous cases, saying `no`---not a strict subtype---is conservative.
-    return isStrictSubtypeOf(other, appInfo, false);
+    return isStrictSubtypeOf(other, definitions, false);
   }
 
   // Depending on optimizations, conservative answer of subtype relation may vary.
   // Pass different `orElse` in that case.
-  public boolean isStrictSubtypeOf(DexType other, AppInfo appInfo, boolean orElse) {
+  public boolean isStrictSubtypeOf(
+      DexType other, DexDefinitionSupplier definitions, boolean orElse) {
     if (this == other) {
       return false;
     }
     // Treat the object class special as it is always the supertype, even in the case of broken
     // subtype chains.
-    if (this == appInfo.dexItemFactory.objectType) {
+    if (this == definitions.dexItemFactory().objectType) {
       return false;
     }
-    if (other == appInfo.dexItemFactory.objectType) {
+    if (other == definitions.dexItemFactory().objectType) {
       return true;
     }
     if (this.hierarchyLevel == INTERFACE_LEVEL) {
-      return isInterfaceSubtypeOf(this, other, appInfo);
+      return isInterfaceSubtypeOf(this, other, definitions);
     }
     if (other.hierarchyLevel == INTERFACE_LEVEL) {
-      return other.directSubtypes.stream().anyMatch(subtype -> this.isSubtypeOf(subtype,
-          appInfo));
+      return other.directSubtypes.stream().anyMatch(subtype -> isSubtypeOf(subtype, definitions));
     }
-    return isSubtypeOfClass(other, appInfo, orElse);
+    return isSubtypeOfClass(other, definitions, orElse);
   }
 
-  private boolean isInterfaceSubtypeOf(DexType candidate, DexType other, AppInfo appInfo) {
-    if (candidate == other || other == appInfo.dexItemFactory.objectType) {
+  private boolean isInterfaceSubtypeOf(
+      DexType candidate, DexType other, DexDefinitionSupplier definitions) {
+    if (candidate == other || other == definitions.dexItemFactory().objectType) {
       return true;
     }
-    DexClass candidateHolder = appInfo.definitionFor(candidate);
+    DexClass candidateHolder = definitions.definitionFor(candidate);
     if (candidateHolder == null) {
       return false;
     }
     for (DexType iface : candidateHolder.interfaces.values) {
       assert iface.hierarchyLevel == INTERFACE_LEVEL;
-      if (isInterfaceSubtypeOf(iface, other, appInfo)) {
+      if (isInterfaceSubtypeOf(iface, other, definitions)) {
         return true;
       }
     }
     return false;
   }
 
-  private boolean isSubtypeOfClass(DexType other, AppInfo appInfo, boolean orElse) {
+  private boolean isSubtypeOfClass(
+      DexType other, DexDefinitionSupplier definitions, boolean orElse) {
     DexType self = this;
     if (other.hierarchyLevel == UNKNOWN_LEVEL) {
       // We have no definition for this class, hence it is not part of the hierarchy.
       return orElse;
     }
     while (other.hierarchyLevel < self.hierarchyLevel) {
-      DexClass holder = appInfo.definitionFor(self);
+      DexClass holder = definitions.definitionFor(self);
       assert holder != null && !holder.isInterface();
       self = holder.superType;
     }
diff --git a/src/main/java/com/android/tools/r8/graph/LazyCfCode.java b/src/main/java/com/android/tools/r8/graph/LazyCfCode.java
index a09ba4f..42a427c 100644
--- a/src/main/java/com/android/tools/r8/graph/LazyCfCode.java
+++ b/src/main/java/com/android/tools/r8/graph/LazyCfCode.java
@@ -669,11 +669,6 @@
     }
 
     @Override
-    public void visitMethodInsn(int opcode, String owner, String name, String desc) {
-      visitMethodInsn(opcode, owner, name, desc, false);
-    }
-
-    @Override
     public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
       DexMethod method = application.getMethod(owner, name, desc);
       instructions.add(new CfInvoke(opcode, method, itf));
diff --git a/src/main/java/com/android/tools/r8/graph/TopDownClassHierarchyTraversal.java b/src/main/java/com/android/tools/r8/graph/TopDownClassHierarchyTraversal.java
index e8d6a4f..7562e84 100644
--- a/src/main/java/com/android/tools/r8/graph/TopDownClassHierarchyTraversal.java
+++ b/src/main/java/com/android/tools/r8/graph/TopDownClassHierarchyTraversal.java
@@ -53,7 +53,7 @@
 
     // Add super classes to worklist.
     if (clazz.superType != null) {
-      DexClass definition = appView.appInfo().definitionFor(clazz.superType);
+      DexClass definition = appView.definitionFor(clazz.superType);
       if (definition != null && definition.isProgramClass()) {
         addAncestorsToWorklist(definition.asProgramClass(), worklist, visited, appView);
       }
@@ -61,7 +61,7 @@
 
     // Add super interfaces to worklist.
     for (DexType interfaceType : clazz.interfaces.values) {
-      DexClass definition = appView.appInfo().definitionFor(interfaceType);
+      DexClass definition = appView.definitionFor(interfaceType);
       if (definition != null && definition.isProgramClass()) {
         addAncestorsToWorklist(definition.asProgramClass(), worklist, visited, appView);
       }
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/ClassInitializationAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/ClassInitializationAnalysis.java
index 9532404..4e08835 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/ClassInitializationAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/ClassInitializationAnalysis.java
@@ -4,8 +4,8 @@
 
 package com.android.tools.r8.ir.analysis;
 
+import com.android.tools.r8.graph.AppInfo;
 import com.android.tools.r8.graph.AppInfo.ResolutionResult;
-import com.android.tools.r8.graph.AppInfoWithSubtyping;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexItemFactory;
@@ -196,7 +196,7 @@
           || exceptionalExit.isInvokeMethodWithReceiver()) {
         // If an instance-get, instance-put, or instance-invoke instruction does not fail with a
         // NullPointerException, then the receiver class must have been initialized.
-        if (!dexItemFactory.npeType.isSubtypeOf(guard, appView.appInfo())) {
+        if (!dexItemFactory.npeType.isSubtypeOf(guard, appView)) {
           continue;
         }
       }
@@ -205,7 +205,7 @@
           || exceptionalExit.isInvokeStatic()) {
         // If a static-get, static-put, or invoke-static does not fail with an ExceptionIn-
         // InitializerError, then the holder class must have been initialized.
-        if (!dexItemFactory.exceptionInInitializerErrorType.isSubtypeOf(guard, appView.appInfo())) {
+        if (!dexItemFactory.exceptionInInitializerErrorType.isSubtypeOf(guard, appView)) {
           continue;
         }
       }
@@ -246,7 +246,7 @@
     public static boolean forInstanceGet(
         InstanceGet instruction,
         DexType type,
-        AppView<? extends AppInfoWithSubtyping> appView,
+        AppView<? extends AppInfo> appView,
         Query mode,
         AnalysisAssumption assumption) {
       return forInstanceGetOrPut(instruction, type, appView, mode, assumption);
@@ -255,7 +255,7 @@
     public static boolean forInstancePut(
         InstancePut instruction,
         DexType type,
-        AppView<? extends AppInfoWithSubtyping> appView,
+        AppView<? extends AppInfo> appView,
         Query mode,
         AnalysisAssumption assumption) {
       return forInstanceGetOrPut(instruction, type, appView, mode, assumption);
@@ -264,7 +264,7 @@
     private static boolean forInstanceGetOrPut(
         FieldInstruction instruction,
         DexType type,
-        AppView<? extends AppInfoWithSubtyping> appView,
+        AppView<? extends AppInfo> appView,
         Query mode,
         AnalysisAssumption assumption) {
       assert instruction.isInstanceGet() || instruction.isInstancePut();
@@ -284,7 +284,7 @@
     public static boolean forInvokeDirect(
         InvokeDirect instruction,
         DexType type,
-        AppView<? extends AppInfoWithSubtyping> appView,
+        AppView<? extends AppInfo> appView,
         Query mode,
         AnalysisAssumption assumption) {
       if (assumption == AnalysisAssumption.NONE) {
@@ -299,7 +299,7 @@
     public static boolean forInvokeStatic(
         InvokeStatic instruction,
         DexType type,
-        AppView<? extends AppInfoWithSubtyping> appView,
+        AppView<? extends AppInfo> appView,
         Query mode,
         AnalysisAssumption assumption) {
       if (assumption == AnalysisAssumption.NONE) {
@@ -312,7 +312,7 @@
     public static boolean forInvokeSuper(
         InvokeSuper instruction,
         DexType type,
-        AppView<? extends AppInfoWithSubtyping> appView,
+        AppView<? extends AppInfo> appView,
         Query mode,
         AnalysisAssumption assumption) {
       if (assumption == AnalysisAssumption.NONE) {
@@ -328,7 +328,7 @@
         return false;
       }
       DexMethod method = instruction.getInvokedMethod();
-      DexClass enclosingClass = appView.appInfo().definitionFor(method.holder);
+      DexClass enclosingClass = appView.definitionFor(method.holder);
       if (enclosingClass == null) {
         return false;
       }
@@ -341,13 +341,13 @@
         return false;
       }
       DexType holder = resolutionResult.asSingleTarget().method.holder;
-      return holder.isSubtypeOf(type, appView.appInfo());
+      return holder.isSubtypeOf(type, appView);
     }
 
     public static boolean forInvokeVirtual(
         InvokeVirtual instruction,
         DexType type,
-        AppView<? extends AppInfoWithSubtyping> appView,
+        AppView<? extends AppInfo> appView,
         Query mode,
         AnalysisAssumption assumption) {
       if (assumption == AnalysisAssumption.NONE) {
@@ -368,13 +368,13 @@
         return false;
       }
       DexType holder = resolutionResult.asSingleTarget().method.holder;
-      return holder.isSubtypeOf(type, appView.appInfo());
+      return holder.isSubtypeOf(type, appView);
     }
 
     public static boolean forNewInstance(
         NewInstance instruction,
         DexType type,
-        AppView<? extends AppInfoWithSubtyping> appView,
+        AppView<? extends AppInfo> appView,
         Query mode,
         AnalysisAssumption assumption) {
       return isTypeInitializedBy(type, instruction.clazz, appView, mode);
@@ -383,7 +383,7 @@
     public static boolean forStaticGet(
         StaticGet instruction,
         DexType type,
-        AppView<? extends AppInfoWithSubtyping> appView,
+        AppView<? extends AppInfo> appView,
         Query mode,
         AnalysisAssumption assumption) {
       return forStaticGetOrPut(instruction, type, appView, mode, assumption);
@@ -392,7 +392,7 @@
     public static boolean forStaticPut(
         StaticPut instruction,
         DexType type,
-        AppView<? extends AppInfoWithSubtyping> appView,
+        AppView<? extends AppInfo> appView,
         Query mode,
         AnalysisAssumption assumption) {
       return forStaticGetOrPut(instruction, type, appView, mode, assumption);
@@ -401,7 +401,7 @@
     private static boolean forStaticGetOrPut(
         FieldInstruction instruction,
         DexType type,
-        AppView<? extends AppInfoWithSubtyping> appView,
+        AppView<? extends AppInfo> appView,
         Query mode,
         AnalysisAssumption assumption) {
       assert instruction.isStaticGet() || instruction.isStaticPut();
@@ -415,12 +415,12 @@
     private static boolean isTypeInitializedBy(
         DexType typeToBeInitialized,
         DexType typeKnownToBeInitialized,
-        AppView<? extends AppInfoWithSubtyping> appView,
+        AppView<? extends AppInfo> appView,
         Query mode) {
       if (mode == Query.DIRECTLY) {
         return typeKnownToBeInitialized == typeToBeInitialized;
       } else {
-        return typeKnownToBeInitialized.isSubtypeOf(typeToBeInitialized, appView.appInfo());
+        return typeKnownToBeInitialized.isSubtypeOf(typeToBeInitialized, appView);
       }
     }
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingDefinition.java b/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingDefinition.java
index 1d42746..d419cbb 100644
--- a/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingDefinition.java
+++ b/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingDefinition.java
@@ -12,7 +12,6 @@
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.ir.conversion.CfBuilder;
 import com.android.tools.r8.ir.conversion.DexBuilder;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 
 public class AlwaysMaterializingDefinition extends ConstInstruction {
 
@@ -21,8 +20,7 @@
   }
 
   @Override
-  public boolean canBeDeadCode(
-      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
     // This instruction may never be considered dead as it must remain.
     return false;
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingNop.java b/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingNop.java
index 37bbd07..7f8c6eb 100644
--- a/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingNop.java
+++ b/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingNop.java
@@ -13,7 +13,6 @@
 import com.android.tools.r8.ir.conversion.DexBuilder;
 import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 
 public class AlwaysMaterializingNop extends Instruction {
 
@@ -22,8 +21,7 @@
   }
 
   @Override
-  public boolean canBeDeadCode(
-      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
     return false;
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingUser.java b/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingUser.java
index ecb7a81..c36ee42 100644
--- a/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingUser.java
+++ b/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingUser.java
@@ -12,7 +12,6 @@
 import com.android.tools.r8.ir.conversion.DexBuilder;
 import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 
 public class AlwaysMaterializingUser extends Instruction {
 
@@ -21,8 +20,7 @@
   }
 
   @Override
-  public boolean canBeDeadCode(
-      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
     // This instruction may never be considered dead as it must remain.
     return false;
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/Argument.java b/src/main/java/com/android/tools/r8/ir/code/Argument.java
index 4ae0c3e..997f1c5 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Argument.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Argument.java
@@ -15,7 +15,6 @@
 import com.android.tools.r8.ir.conversion.DexBuilder;
 import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 
 /**
  * Argument pseudo instruction used to introduce values for all arguments for SSA conversion.
@@ -28,8 +27,7 @@
   }
 
   @Override
-  public boolean canBeDeadCode(
-      AppView<? extends AppInfoWithLiveness> appview, AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(AppView<? extends AppInfo> appview, IRCode code) {
     // Never remove argument instructions. That would change the signature of the method.
     // TODO(b/65810338): If we can tell that a method never uses an argument we might be able to
     // rewrite the signature and call-sites.
diff --git a/src/main/java/com/android/tools/r8/ir/code/ArrayPut.java b/src/main/java/com/android/tools/r8/ir/code/ArrayPut.java
index 34a0041..f0be051 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ArrayPut.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ArrayPut.java
@@ -24,7 +24,6 @@
 import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 import com.android.tools.r8.ir.regalloc.RegisterAllocator;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 import java.util.Arrays;
 
 public class ArrayPut extends Instruction implements ImpreciseMemberTypeInstruction {
@@ -130,8 +129,7 @@
   }
 
   @Override
-  public boolean canBeDeadCode(
-      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
     // ArrayPut has side-effects on input values.
     return false;
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstClass.java b/src/main/java/com/android/tools/r8/ir/code/ConstClass.java
index ea1d912..b3ab484 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstClass.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstClass.java
@@ -18,7 +18,6 @@
 import com.android.tools.r8.ir.conversion.DexBuilder;
 import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 
 public class ConstClass extends ConstInstruction {
 
@@ -85,16 +84,14 @@
 
   @Override
   public boolean instructionMayHaveSideEffects(
-      AppInfo appInfo, AppView<? extends AppInfo> appView, DexType context) {
-    assert appView == null || appView.appInfo() == appInfo;
-
-    DexType baseType = getValue().toBaseType(appInfo.dexItemFactory);
+      AppView<? extends AppInfo> appView, DexType context) {
+    DexType baseType = getValue().toBaseType(appView.dexItemFactory());
     if (baseType.isPrimitiveType()) {
       return false;
     }
 
-    if (appView != null && appView.enableWholeProgramOptimizations()) {
-      DexClass clazz = appView.appInfo().definitionFor(baseType);
+    if (appView.enableWholeProgramOptimizations()) {
+      DexClass clazz = appView.definitionFor(baseType);
       if (clazz != null && clazz.isProgramClass()) {
         return false;
       }
@@ -108,9 +105,8 @@
   }
 
   @Override
-  public boolean canBeDeadCode(
-      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
-    return !instructionMayHaveSideEffects(appInfo, appView, code.method.method.holder);
+  public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
+    return !instructionMayHaveSideEffects(appView, code.method.method.holder);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstString.java b/src/main/java/com/android/tools/r8/ir/code/ConstString.java
index 356b73d..f6f1ccf 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstString.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstString.java
@@ -16,7 +16,6 @@
 import com.android.tools.r8.ir.code.BasicBlock.ThrowingInfo;
 import com.android.tools.r8.ir.conversion.CfBuilder;
 import com.android.tools.r8.ir.conversion.DexBuilder;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 import java.io.UTFDataFormatException;
 
 public class ConstString extends ConstInstruction {
@@ -116,8 +115,7 @@
   }
 
   @Override
-  public boolean canBeDeadCode(
-      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
     // No side-effect, such as throwing an exception, in CF.
     return code.options.isGeneratingClassFiles() || !instructionInstanceCanThrow();
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/DebugLocalRead.java b/src/main/java/com/android/tools/r8/ir/code/DebugLocalRead.java
index 1c372ed..8697b79 100644
--- a/src/main/java/com/android/tools/r8/ir/code/DebugLocalRead.java
+++ b/src/main/java/com/android/tools/r8/ir/code/DebugLocalRead.java
@@ -12,7 +12,6 @@
 import com.android.tools.r8.ir.conversion.DexBuilder;
 import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 
 public class DebugLocalRead extends Instruction {
   private static final String ERROR_MESSAGE = "Unexpected attempt to emit debug-local read.";
@@ -63,8 +62,7 @@
   }
 
   @Override
-  public boolean canBeDeadCode(
-      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
     // Reads are never dead code.
     // They should also have a non-empty set of debug values (see RegAlloc::computeDebugInfo)
     return false;
diff --git a/src/main/java/com/android/tools/r8/ir/code/DebugLocalsChange.java b/src/main/java/com/android/tools/r8/ir/code/DebugLocalsChange.java
index a2aa761..4f097ff 100644
--- a/src/main/java/com/android/tools/r8/ir/code/DebugLocalsChange.java
+++ b/src/main/java/com/android/tools/r8/ir/code/DebugLocalsChange.java
@@ -13,7 +13,6 @@
 import com.android.tools.r8.ir.conversion.DexBuilder;
 import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 import com.android.tools.r8.utils.StringUtils;
 import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
 import it.unimi.dsi.fastutil.ints.Int2ReferenceMap.Entry;
@@ -75,8 +74,7 @@
   }
 
   @Override
-  public boolean canBeDeadCode(
-      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
     return false;
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/code/DebugPosition.java b/src/main/java/com/android/tools/r8/ir/code/DebugPosition.java
index 6990e18..02957b6 100644
--- a/src/main/java/com/android/tools/r8/ir/code/DebugPosition.java
+++ b/src/main/java/com/android/tools/r8/ir/code/DebugPosition.java
@@ -13,7 +13,6 @@
 import com.android.tools.r8.ir.conversion.DexBuilder;
 import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 
 public class DebugPosition extends Instruction {
 
@@ -59,8 +58,7 @@
   }
 
   @Override
-  public boolean canBeDeadCode(
-      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
     return false;
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/code/DexItemBasedConstString.java b/src/main/java/com/android/tools/r8/ir/code/DexItemBasedConstString.java
index e4e0e10..7d0d44f 100644
--- a/src/main/java/com/android/tools/r8/ir/code/DexItemBasedConstString.java
+++ b/src/main/java/com/android/tools/r8/ir/code/DexItemBasedConstString.java
@@ -17,7 +17,6 @@
 import com.android.tools.r8.ir.conversion.CfBuilder;
 import com.android.tools.r8.ir.conversion.DexBuilder;
 import com.android.tools.r8.ir.optimize.ReflectionOptimizer.ClassNameComputationInfo;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 
 public class DexItemBasedConstString extends ConstInstruction {
 
@@ -111,8 +110,7 @@
   }
 
   @Override
-  public boolean canBeDeadCode(
-      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
     // No side-effect, such as throwing an exception, in CF.
     return true;
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/InstanceGet.java b/src/main/java/com/android/tools/r8/ir/code/InstanceGet.java
index fba69c0..44cc6a1 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InstanceGet.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InstanceGet.java
@@ -19,7 +19,6 @@
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppInfo;
-import com.android.tools.r8.graph.AppInfoWithSubtyping;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexEncodedField;
 import com.android.tools.r8.graph.DexField;
@@ -34,7 +33,6 @@
 import com.android.tools.r8.ir.conversion.DexBuilder;
 import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 import org.objectweb.asm.Opcodes;
 
 public class InstanceGet extends FieldInstruction {
@@ -102,17 +100,18 @@
   }
 
   @Override
-  public boolean canBeDeadCode(
-      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
     // Not applicable for D8.
-    if (appView == null || !appView.enableWholeProgramOptimizations()) {
+    if (!appView.enableWholeProgramOptimizations()) {
       return false;
     }
+
     // instance-get can be dead code as long as it cannot have any of the following:
     // * NoSuchFieldError (resolution failure)
     // * IllegalAccessError (not visible from the access context)
     // * NullPointerException (null receiver).
     // TODO(b/123857022): Should be possible to use definitionFor().
+    AppInfo appInfo = appView.appInfo();
     DexEncodedField resolvedField = appInfo.resolveFieldOn(getField().getHolder(), getField());
     if (resolvedField == null) {
       return false;
@@ -197,7 +196,7 @@
   @Override
   public boolean definitelyTriggersClassInitialization(
       DexType clazz,
-      AppView<? extends AppInfoWithSubtyping> appView,
+      AppView<? extends AppInfo> appView,
       Query mode,
       AnalysisAssumption assumption) {
     return ClassInitializationAnalysis.InstructionUtils.forInstanceGet(
diff --git a/src/main/java/com/android/tools/r8/ir/code/InstancePut.java b/src/main/java/com/android/tools/r8/ir/code/InstancePut.java
index 57fe121..327138b 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InstancePut.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InstancePut.java
@@ -15,7 +15,7 @@
 import com.android.tools.r8.code.IputWide;
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graph.AppInfoWithSubtyping;
+import com.android.tools.r8.graph.AppInfo;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexField;
 import com.android.tools.r8.graph.DexItemFactory;
@@ -150,7 +150,7 @@
   @Override
   public boolean definitelyTriggersClassInitialization(
       DexType clazz,
-      AppView<? extends AppInfoWithSubtyping> appView,
+      AppView<? extends AppInfo> appView,
       Query mode,
       AnalysisAssumption assumption) {
     return ClassInitializationAnalysis.InstructionUtils.forInstancePut(
diff --git a/src/main/java/com/android/tools/r8/ir/code/Instruction.java b/src/main/java/com/android/tools/r8/ir/code/Instruction.java
index 38e5d32..b05cd55 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Instruction.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Instruction.java
@@ -8,7 +8,6 @@
 import com.android.tools.r8.errors.Unimplemented;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppInfo;
-import com.android.tools.r8.graph.AppInfoWithSubtyping;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DebugLocalInfo;
 import com.android.tools.r8.graph.DexItemFactory;
@@ -25,7 +24,6 @@
 import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 import com.android.tools.r8.ir.regalloc.RegisterAllocator;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 import com.android.tools.r8.utils.CfgPrinter;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.StringUtils.BraceType;
@@ -505,13 +503,12 @@
   }
 
   public boolean instructionMayHaveSideEffects(
-      AppInfo appInfo, AppView<? extends AppInfo> appView, DexType context) {
+      AppView<? extends AppInfo> appView, DexType context) {
     return instructionInstanceCanThrow();
   }
 
   /** Returns true is this instruction can be treated as dead code if its outputs are not used. */
-  public boolean canBeDeadCode(
-      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
     return !instructionInstanceCanThrow();
   }
 
@@ -1260,7 +1257,7 @@
    */
   public boolean definitelyTriggersClassInitialization(
       DexType clazz,
-      AppView<? extends AppInfoWithSubtyping> appView,
+      AppView<? extends AppInfo> appView,
       Query mode,
       AnalysisAssumption assumption) {
     return false;
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java b/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java
index 301f710..462da0d 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java
@@ -6,6 +6,7 @@
 import com.android.tools.r8.cf.code.CfInvoke;
 import com.android.tools.r8.code.InvokeDirectRange;
 import com.android.tools.r8.dex.Constants;
+import com.android.tools.r8.graph.AppInfo;
 import com.android.tools.r8.graph.AppInfoWithSubtyping;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexEncodedMethod;
@@ -128,7 +129,7 @@
   @Override
   public boolean definitelyTriggersClassInitialization(
       DexType clazz,
-      AppView<? extends AppInfoWithSubtyping> appView,
+      AppView<? extends AppInfo> appView,
       Query mode,
       AnalysisAssumption assumption) {
     return ClassInitializationAnalysis.InstructionUtils.forInvokeDirect(
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java b/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java
index 77c21fe..dbff861 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java
@@ -127,7 +127,7 @@
   @Override
   public boolean definitelyTriggersClassInitialization(
       DexType clazz,
-      AppView<? extends AppInfoWithSubtyping> appView,
+      AppView<? extends AppInfo> appView,
       Query mode,
       AnalysisAssumption assumption) {
     return ClassInitializationAnalysis.InstructionUtils.forInvokeStatic(
@@ -136,8 +136,8 @@
 
   @Override
   public boolean instructionMayHaveSideEffects(
-      AppInfo appInfo, AppView<? extends AppInfo> appView, DexType context) {
-    if (appView == null || !appView.enableWholeProgramOptimizations()) {
+      AppView<? extends AppInfo> appView, DexType context) {
+    if (!appView.enableWholeProgramOptimizations()) {
       return true;
     }
 
@@ -178,8 +178,7 @@
   }
 
   @Override
-  public boolean canBeDeadCode(
-      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
-    return !instructionMayHaveSideEffects(appInfo, appView, code.method.method.holder);
+  public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
+    return !instructionMayHaveSideEffects(appView, code.method.method.holder);
   }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeSuper.java b/src/main/java/com/android/tools/r8/ir/code/InvokeSuper.java
index bc3d982..0fe6c63 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeSuper.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeSuper.java
@@ -5,6 +5,7 @@
 
 import com.android.tools.r8.cf.code.CfInvoke;
 import com.android.tools.r8.code.InvokeSuperRange;
+import com.android.tools.r8.graph.AppInfo;
 import com.android.tools.r8.graph.AppInfoWithSubtyping;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexEncodedMethod;
@@ -115,7 +116,7 @@
   @Override
   public boolean definitelyTriggersClassInitialization(
       DexType clazz,
-      AppView<? extends AppInfoWithSubtyping> appView,
+      AppView<? extends AppInfo> appView,
       Query mode,
       AnalysisAssumption assumption) {
     return ClassInitializationAnalysis.InstructionUtils.forInvokeSuper(
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java b/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java
index 26efb4f..d404a6c 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java
@@ -107,7 +107,7 @@
   @Override
   public boolean definitelyTriggersClassInitialization(
       DexType clazz,
-      AppView<? extends AppInfoWithSubtyping> appView,
+      AppView<? extends AppInfo> appView,
       Query mode,
       AnalysisAssumption assumption) {
     return ClassInitializationAnalysis.InstructionUtils.forInvokeVirtual(
@@ -116,8 +116,8 @@
 
   @Override
   public boolean instructionMayHaveSideEffects(
-      AppInfo appInfo, AppView<? extends AppInfo> appView, DexType context) {
-    if (appView == null || !appView.enableWholeProgramOptimizations()) {
+      AppView<? extends AppInfo> appView, DexType context) {
+    if (!appView.enableWholeProgramOptimizations()) {
       return true;
     }
 
@@ -140,8 +140,7 @@
   }
 
   @Override
-  public boolean canBeDeadCode(
-      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
-    return !instructionMayHaveSideEffects(appInfo, appView, code.method.method.holder);
+  public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
+    return !instructionMayHaveSideEffects(appView, code.method.method.holder);
   }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/code/JumpInstruction.java b/src/main/java/com/android/tools/r8/ir/code/JumpInstruction.java
index 8e7c646..44bdd23 100644
--- a/src/main/java/com/android/tools/r8/ir/code/JumpInstruction.java
+++ b/src/main/java/com/android/tools/r8/ir/code/JumpInstruction.java
@@ -8,7 +8,6 @@
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 import java.util.List;
 
 public abstract class JumpInstruction extends Instruction {
@@ -34,8 +33,7 @@
   }
 
   @Override
-  public boolean canBeDeadCode(
-      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
     return false;
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/code/MoveException.java b/src/main/java/com/android/tools/r8/ir/code/MoveException.java
index a82bfa1..96d5186 100644
--- a/src/main/java/com/android/tools/r8/ir/code/MoveException.java
+++ b/src/main/java/com/android/tools/r8/ir/code/MoveException.java
@@ -15,7 +15,6 @@
 import com.android.tools.r8.ir.conversion.DexBuilder;
 import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 import com.android.tools.r8.utils.InternalOptions;
 
 public class MoveException extends Instruction {
@@ -71,8 +70,7 @@
   }
 
   @Override
-  public boolean canBeDeadCode(
-      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
     return !(code.options.debug || code.method.getOptimizationInfo().isReachabilitySensitive())
         && code.options.isGeneratingDex();
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/NewArrayEmpty.java b/src/main/java/com/android/tools/r8/ir/code/NewArrayEmpty.java
index fb4d23b..a8bcea2 100644
--- a/src/main/java/com/android/tools/r8/ir/code/NewArrayEmpty.java
+++ b/src/main/java/com/android/tools/r8/ir/code/NewArrayEmpty.java
@@ -17,7 +17,6 @@
 import com.android.tools.r8.ir.conversion.DexBuilder;
 import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 
 public class NewArrayEmpty extends Instruction {
 
@@ -73,14 +72,13 @@
   }
 
   @Override
-  public boolean canBeDeadCode(
-      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
     if (instructionInstanceCanThrow()) {
       return false;
     }
     // This would belong better in instructionInstanceCanThrow, but that is not passed an appInfo.
-    DexType baseType = type.toBaseType(appInfo.dexItemFactory);
-    return baseType.isPrimitiveType() || appInfo.definitionFor(baseType) != null;
+    DexType baseType = type.toBaseType(appView.dexItemFactory());
+    return baseType.isPrimitiveType() || appView.definitionFor(baseType) != null;
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/NewArrayFilledData.java b/src/main/java/com/android/tools/r8/ir/code/NewArrayFilledData.java
index f107c90..3151a94 100644
--- a/src/main/java/com/android/tools/r8/ir/code/NewArrayFilledData.java
+++ b/src/main/java/com/android/tools/r8/ir/code/NewArrayFilledData.java
@@ -15,7 +15,6 @@
 import com.android.tools.r8.ir.conversion.DexBuilder;
 import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 import java.util.Arrays;
 
 public class NewArrayFilledData extends Instruction {
@@ -76,8 +75,7 @@
   }
 
   @Override
-  public boolean canBeDeadCode(
-      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
     if (!src().getTypeLattice().isNullable() && src().numberOfAllUsers() == 1) {
       // The NewArrayFilledData instruction is only inserted by an R8 optimization following
       // a NewArrayEmpty when there are more than one entry.
diff --git a/src/main/java/com/android/tools/r8/ir/code/NewInstance.java b/src/main/java/com/android/tools/r8/ir/code/NewInstance.java
index 3d7c81b..b5401b0 100644
--- a/src/main/java/com/android/tools/r8/ir/code/NewInstance.java
+++ b/src/main/java/com/android/tools/r8/ir/code/NewInstance.java
@@ -8,7 +8,6 @@
 import com.android.tools.r8.cf.code.CfNew;
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.graph.AppInfo;
-import com.android.tools.r8.graph.AppInfoWithSubtyping;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis;
@@ -113,7 +112,7 @@
   @Override
   public boolean definitelyTriggersClassInitialization(
       DexType clazz,
-      AppView<? extends AppInfoWithSubtyping> appView,
+      AppView<? extends AppInfo> appView,
       Query mode,
       AnalysisAssumption assumption) {
     return ClassInitializationAnalysis.InstructionUtils.forNewInstance(
diff --git a/src/main/java/com/android/tools/r8/ir/code/Pop.java b/src/main/java/com/android/tools/r8/ir/code/Pop.java
index 41d17b0..32bd532 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Pop.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Pop.java
@@ -13,7 +13,6 @@
 import com.android.tools.r8.ir.conversion.DexBuilder;
 import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 
 public class Pop extends Instruction {
 
@@ -83,8 +82,7 @@
   }
 
   @Override
-  public boolean canBeDeadCode(
-      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
     // Pop cannot be dead code as it modifies the stack height.
     return false;
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/StaticGet.java b/src/main/java/com/android/tools/r8/ir/code/StaticGet.java
index d446f4c..f4b0beb 100644
--- a/src/main/java/com/android/tools/r8/ir/code/StaticGet.java
+++ b/src/main/java/com/android/tools/r8/ir/code/StaticGet.java
@@ -18,7 +18,6 @@
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppInfo;
-import com.android.tools.r8.graph.AppInfoWithSubtyping;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexEncodedField;
 import com.android.tools.r8.graph.DexField;
@@ -32,7 +31,6 @@
 import com.android.tools.r8.ir.conversion.DexBuilder;
 import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 import org.objectweb.asm.Opcodes;
 
 public class StaticGet extends FieldInstruction {
@@ -95,18 +93,19 @@
   }
 
   @Override
-  public boolean canBeDeadCode(
-      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
     // Not applicable for D8.
-    if (appView == null || !appView.enableWholeProgramOptimizations()) {
+    if (!appView.enableWholeProgramOptimizations()) {
       return false;
     }
+
     // static-get can be dead as long as it cannot have any of the following:
     // * NoSuchFieldError (resolution failure)
     // * IllegalAccessError (not visible from the access context)
     // * side-effects in <clinit>
     // TODO(b/123857022): Should be possible to use definitionFor().
-    DexEncodedField resolvedField = appInfo.resolveFieldOn(getField().getHolder(), getField());
+    AppInfo appInfo = appView.appInfo();
+    DexEncodedField resolvedField = appInfo.resolveField(getField());
     if (resolvedField == null) {
       return false;
     }
@@ -188,7 +187,7 @@
   @Override
   public boolean definitelyTriggersClassInitialization(
       DexType clazz,
-      AppView<? extends AppInfoWithSubtyping> appView,
+      AppView<? extends AppInfo> appView,
       Query mode,
       AnalysisAssumption assumption) {
     return ClassInitializationAnalysis.InstructionUtils.forStaticGet(
diff --git a/src/main/java/com/android/tools/r8/ir/code/StaticPut.java b/src/main/java/com/android/tools/r8/ir/code/StaticPut.java
index 29ce40c..4609bb1 100644
--- a/src/main/java/com/android/tools/r8/ir/code/StaticPut.java
+++ b/src/main/java/com/android/tools/r8/ir/code/StaticPut.java
@@ -14,7 +14,7 @@
 import com.android.tools.r8.code.SputWide;
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graph.AppInfoWithSubtyping;
+import com.android.tools.r8.graph.AppInfo;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexField;
 import com.android.tools.r8.graph.DexType;
@@ -137,7 +137,7 @@
   @Override
   public boolean definitelyTriggersClassInitialization(
       DexType clazz,
-      AppView<? extends AppInfoWithSubtyping> appView,
+      AppView<? extends AppInfo> appView,
       Query mode,
       AnalysisAssumption assumption) {
     return ClassInitializationAnalysis.InstructionUtils.forStaticPut(
diff --git a/src/main/java/com/android/tools/r8/ir/code/Store.java b/src/main/java/com/android/tools/r8/ir/code/Store.java
index 07cb184..f09107f 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Store.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Store.java
@@ -17,7 +17,6 @@
 import com.android.tools.r8.ir.conversion.DexBuilder;
 import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 
 public class Store extends Instruction {
 
@@ -91,8 +90,7 @@
   }
 
   @Override
-  public boolean canBeDeadCode(
-      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(AppView<? extends AppInfo> appView, IRCode code) {
     return !(outValue instanceof FixedLocalValue);
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/code/Value.java b/src/main/java/com/android/tools/r8/ir/code/Value.java
index 88fd645..3b783d9 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Value.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Value.java
@@ -13,7 +13,6 @@
 import com.android.tools.r8.ir.regalloc.LiveIntervals;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.position.MethodPosition;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 import com.android.tools.r8.utils.LongInterval;
 import com.android.tools.r8.utils.Reporter;
 import com.android.tools.r8.utils.StringDiagnostic;
@@ -848,17 +847,12 @@
     }
   }
 
-  public boolean isDead(
-      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
+  public boolean isDead(AppView<? extends AppInfo> appView, IRCode code) {
     // Totally unused values are trivially dead.
-    return !isUsed() || isDead(appView, appInfo, code, new HashSet<>());
+    return !isUsed() || isDead(appView, code, new HashSet<>());
   }
 
-  protected boolean isDead(
-      AppView<? extends AppInfoWithLiveness> appView,
-      AppInfo appInfo,
-      IRCode code,
-      Set<Value> active) {
+  protected boolean isDead(AppView<? extends AppInfo> appView, IRCode code, Set<Value> active) {
     // Give up when the dependent set of values reach a given threshold (otherwise this fails with
     // a StackOverflowError on Art003_omnibus_opcodesTest).
     if (active.size() > 100) {
@@ -874,18 +868,18 @@
     // currently active values.
     active.add(this);
     for (Instruction instruction : uniqueUsers()) {
-      if (!instruction.canBeDeadCode(appView, appInfo, code)) {
+      if (!instruction.canBeDeadCode(appView, code)) {
         return false;
       }
       Value outValue = instruction.outValue();
       if (outValue != null
           && !active.contains(outValue)
-          && !outValue.isDead(appView, appInfo, code, active)) {
+          && !outValue.isDead(appView, code, active)) {
         return false;
       }
     }
     for (Phi phi : uniquePhiUsers()) {
-      if (!active.contains(phi) && !phi.isDead(appView, appInfo, code, active)) {
+      if (!active.contains(phi) && !phi.isDead(appView, code, active)) {
         return false;
       }
     }
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CallGraph.java b/src/main/java/com/android/tools/r8/ir/conversion/CallGraph.java
index f8702db..e9c825d 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/CallGraph.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/CallGraph.java
@@ -150,7 +150,7 @@
 
   public static CallGraph build(
       DexApplication application,
-      AppView<AppInfoWithLiveness> appView,
+      AppView<? extends AppInfoWithLiveness> appView,
       InternalOptions options,
       Timing timing) {
     CallGraph graph = new CallGraph(options);
@@ -488,7 +488,7 @@
     private final Node caller;
     private final CallGraph graph;
 
-    InvokeExtractor(AppView<AppInfoWithLiveness> appView, Node caller, CallGraph graph) {
+    InvokeExtractor(AppView<? extends AppInfoWithLiveness> appView, Node caller, CallGraph graph) {
       super(appView.dexItemFactory());
       this.appInfo = appView.appInfo();
       this.graphLense = appView.graphLense();
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index e025553..f23b8ab 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -9,7 +9,6 @@
 
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppInfo;
-import com.android.tools.r8.graph.AppInfoWithSubtyping;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.CfCode;
 import com.android.tools.r8.graph.Code;
@@ -109,8 +108,7 @@
 
   private static final int PEEPHOLE_OPTIMIZATION_PASSES = 2;
 
-  private final AppInfo appInfoD8; // Used only from D8, null in R8.
-  public final AppView<? extends AppInfoWithSubtyping> appView;
+  public final AppView<? extends AppInfo> appView;
   public final Set<DexType> mainDexClasses;
   public final RootSet rootSet;
 
@@ -142,8 +140,6 @@
 
   final DeadCodeRemover deadCodeRemover;
 
-  public final boolean enableWholeProgramOptimizations;
-
   private final OptimizationFeedbackDelayed delayedOptimizationFeedback =
       new OptimizationFeedbackDelayed();
   private final OptimizationFeedback ignoreOptimizationFeedback = new OptimizationFeedbackIgnore();
@@ -154,66 +150,58 @@
 
   // The argument `appView` is only available when full program optimizations are allowed
   // (i.e., when running R8).
-  private IRConverter(
-      AppView<? extends AppInfoWithLiveness> appView,
-      InternalOptions options,
+  public IRConverter(
+      AppView<? extends AppInfo> appView,
       Timing timing,
       CfgPrinter printer,
       MainDexClasses mainDexClasses,
-      RootSet rootSet,
-      AppInfo appInfoD8) {
-    assert (appInfoD8 == null) != (appView == null);
-    assert options != null;
-    assert options.programConsumer != null;
-    assert appView == null
-        || appView.appInfo().hasLiveness()
-        || appView.graphLense().isIdentityLense();
+      RootSet rootSet) {
+    assert appView.appInfo().hasLiveness() || appView.graphLense().isIdentityLense();
+    assert appView.options() != null;
+    assert appView.options().programConsumer != null;
     this.timing = timing != null ? timing : new Timing("internal");
-    this.appInfoD8 = appInfoD8;
     this.appView = appView;
+    this.options = appView.options();
     this.rootSet = rootSet;
-    this.options = options;
     this.printer = printer;
     this.mainDexClasses = mainDexClasses.getClasses();
-    this.codeRewriter = new CodeRewriter(this, libraryMethodsReturningReceiver(), options);
+    this.codeRewriter = new CodeRewriter(appView, this, libraryMethodsReturningReceiver());
     this.classInitializerDefaultsOptimization =
-        options.debug
-            ? null
-            : new ClassInitializerDefaultsOptimization(appInfo(), appView, this, options);
-    this.stringConcatRewriter = new StringConcatRewriter(appInfo());
-    this.lambdaRewriter = options.enableDesugaring ? new LambdaRewriter(this) : null;
+        options.debug ? null : new ClassInitializerDefaultsOptimization(appView, this);
+    this.stringConcatRewriter = new StringConcatRewriter(appView);
+    this.lambdaRewriter = options.enableDesugaring ? new LambdaRewriter(appView, this) : null;
     this.interfaceMethodRewriter =
         options.isInterfaceMethodDesugaringEnabled()
-            ? new InterfaceMethodRewriter(appView, this, options)
+            ? new InterfaceMethodRewriter(appView, this)
             : null;
     this.twrCloseResourceRewriter =
         (options.enableDesugaring && enableTwrCloseResourceDesugaring())
-            ? new TwrCloseResourceRewriter(this) : null;
+            ? new TwrCloseResourceRewriter(appView, this)
+            : null;
     this.java8MethodRewriter =
         (options.enableDesugaring && !options.canUseJava8Methods())
-            ? new Java8MethodRewriter(this) : null;
-    this.lambdaMerger =
-        options.enableLambdaMerging ? new LambdaMerger(appInfo(), options.reporter) : null;
+            ? new Java8MethodRewriter(appView, this)
+            : null;
+    this.lambdaMerger = options.enableLambdaMerging ? new LambdaMerger(appView) : null;
     this.covariantReturnTypeAnnotationTransformer =
         options.processCovariantReturnTypeAnnotations
-            ? new CovariantReturnTypeAnnotationTransformer(this, appInfo().dexItemFactory)
+            ? new CovariantReturnTypeAnnotationTransformer(this, appView.dexItemFactory())
             : null;
-    this.stringOptimizer = new StringOptimizer(appInfo(), options.getInternalOutputMode());
-    this.enableWholeProgramOptimizations =
-        appView != null && appView.enableWholeProgramOptimizations();
-    if (enableWholeProgramOptimizations) {
-      assert appInfo().hasLiveness();
-      AppInfoWithLiveness appInfoWithLiveness = appInfo().withLiveness();
+    this.stringOptimizer = new StringOptimizer(appView);
+    if (appView.enableWholeProgramOptimizations()) {
+      assert appView.appInfo().hasLiveness();
       AppView<? extends AppInfoWithLiveness> appViewWithLiveness = appView.withLiveness();
+      AppInfoWithLiveness appInfoWithLiveness = appViewWithLiveness.appInfo();
       assert rootSet != null;
+      this.classStaticizer = new ClassStaticizer(appViewWithLiveness, this);
       this.nonNullTracker =
           new NonNullTracker(
-              appInfoWithLiveness, libraryMethodsReturningNonNull(appInfo().dexItemFactory));
+              appInfoWithLiveness, libraryMethodsReturningNonNull(appView.dexItemFactory()));
       this.inliner = new Inliner(appViewWithLiveness, this, options, mainDexClasses);
       this.outliner = new Outliner(appInfoWithLiveness, options, this);
       this.memberValuePropagation =
-          options.enableValuePropagation ? new MemberValuePropagation(appView) : null;
-      this.lensCodeRewriter = new LensCodeRewriter(appView, options);
+          options.enableValuePropagation ? new MemberValuePropagation(appViewWithLiveness) : null;
+      this.lensCodeRewriter = new LensCodeRewriter(appViewWithLiveness);
       if (!appInfoWithLiveness.identifierNameStrings.isEmpty() && options.enableMinification) {
         this.identifierNameStringMarker =
             new IdentifierNameStringMarker(appInfoWithLiveness, options);
@@ -228,6 +216,7 @@
               : null;
       this.typeChecker = new TypeChecker(appView);
     } else {
+      this.classStaticizer = null;
       this.nonNullTracker = null;
       this.inliner = null;
       this.outliner = null;
@@ -241,15 +230,11 @@
     this.classInliner =
         (options.enableClassInlining && options.enableInlining && inliner != null)
             ? new ClassInliner(
-                appInfo().dexItemFactory, lambdaRewriter, options.classInliningInstructionLimit)
+                appView.dexItemFactory(), lambdaRewriter, options.classInliningInstructionLimit)
             : null;
-    this.classStaticizer =
-        options.enableClassStaticizer && appInfo().hasLiveness()
-            ? new ClassStaticizer(appInfo().withLiveness(), this)
-            : null;
-    this.deadCodeRemover = new DeadCodeRemover(appView, appInfo(), codeRewriter, options);
+    this.deadCodeRemover = new DeadCodeRemover(appView, codeRewriter);
     this.idempotentFunctionCallCanonicalizer =
-        new IdempotentFunctionCallCanonicalizer(appInfo().dexItemFactory);
+        new IdempotentFunctionCallCanonicalizer(appView.dexItemFactory());
   }
 
   public GraphLense graphLense() {
@@ -264,35 +249,16 @@
     }
   }
 
-  /**
-   * Create an IR converter for processing methods with full program optimization disabled.
-   */
-  public IRConverter(AppInfo appInfo, InternalOptions options) {
-    this(null, options, null, null, MainDexClasses.NONE, null, appInfo);
+  /** Create an IR converter for processing methods with full program optimization disabled. */
+  public IRConverter(AppView<? extends AppInfo> appView) {
+    this(appView, null, null, MainDexClasses.NONE, null);
   }
 
   /**
    * Create an IR converter for processing methods with full program optimization disabled.
    */
   public IRConverter(AppInfo appInfo, InternalOptions options, Timing timing, CfgPrinter printer) {
-    this(null, options, timing, printer, MainDexClasses.NONE, null, appInfo);
-  }
-
-  /**
-   * Create an IR converter for processing methods with full program optimization enabled.
-   */
-  public IRConverter(
-      AppView<? extends AppInfoWithLiveness> appView,
-      InternalOptions options,
-      Timing timing,
-      CfgPrinter printer,
-      MainDexClasses mainDexClasses,
-      RootSet rootSet) {
-    this(appView, options, timing, printer, mainDexClasses, rootSet, null);
-  }
-
-  public AppInfo appInfo() {
-    return appView == null ? appInfoD8 : appView.appInfo();
+    this(AppView.createForD8(appInfo, options), timing, printer, MainDexClasses.NONE, null);
   }
 
   private boolean enableTwrCloseResourceDesugaring() {
@@ -311,7 +277,7 @@
 
   private Set<DexMethod> libraryMethodsReturningReceiver() {
     Set<DexMethod> methods = new HashSet<>();
-    DexItemFactory dexItemFactory = appInfo().dexItemFactory;
+    DexItemFactory dexItemFactory = appView.dexItemFactory();
     dexItemFactory.stringBufferMethods.forEachAppendMethod(methods::add);
     dexItemFactory.stringBuilderMethods.forEachAppendMethod(methods::add);
     return methods;
@@ -329,7 +295,7 @@
 
   private boolean removeLambdaDeserializationMethods() {
     if (lambdaRewriter != null) {
-      return lambdaRewriter.removeLambdaDeserializationMethods(appInfo().classes());
+      return lambdaRewriter.removeLambdaDeserializationMethods(appView.appInfo().classes());
     }
     return false;
   }
@@ -615,7 +581,7 @@
               outliner.identifyOutlineSites(code, method);
             });
         DexProgramClass outlineClass = outliner.buildOutlinerClass(computeOutlineClassType());
-        appInfo().addSynthesizedClass(outlineClass);
+        appView.appInfo().addSynthesizedClass(outlineClass);
         optimizeSynthesizedClass(outlineClass, executorService);
         forEachSelectedOutliningMethod(
             executorService,
@@ -642,12 +608,13 @@
 
     // Check if what we've added to the application builder as synthesized classes are same as
     // what we've added and used through AppInfo.
-    assert appInfo()
+    assert appView
+            .appInfo()
             .getSynthesizedClassesForSanityCheck()
             .containsAll(builder.getSynthesizedClasses())
         && builder
             .getSynthesizedClasses()
-            .containsAll(appInfo().getSynthesizedClassesForSanityCheck());
+            .containsAll(appView.appInfo().getSynthesizedClassesForSanityCheck());
     return builder.build();
   }
 
@@ -662,7 +629,7 @@
   }
 
   public void addWaveDoneAction(Action action) {
-    if (appView == null || !appView.enableWholeProgramOptimizations()) {
+    if (!appView.enableWholeProgramOptimizations()) {
       throw new Unreachable("addWaveDoneAction() should never be used in D8.");
     }
     if (!isInWave()) {
@@ -696,10 +663,10 @@
               () -> {
                 IRCode code =
                     method.buildIR(
-                        appInfo(),
+                        appView.appInfo(),
                         appView.graphLense(),
                         options,
-                        appInfo().originFor(method.method.holder));
+                        appView.appInfo().originFor(method.method.holder));
                 assert code != null;
                 assert !method.getCode().isOutlineCode();
                 // Instead of repeating all the optimizations of rewriteCode(), only run the
@@ -717,7 +684,7 @@
 
   private void collectLambdaMergingCandidates(DexApplication application) {
     if (lambdaMerger != null) {
-      lambdaMerger.collectGroupCandidates(application, appInfo().withLiveness(), options);
+      lambdaMerger.collectGroupCandidates(application, appView.appInfo().withLiveness(), options);
     }
   }
 
@@ -734,7 +701,7 @@
   }
 
   private void clearDexMethodCompilationState() {
-    appInfo().classes().forEach(this::clearDexMethodCompilationState);
+    appView.appInfo().classes().forEach(this::clearDexMethodCompilationState);
   }
 
   private void clearDexMethodCompilationState(DexProgramClass clazz) {
@@ -769,7 +736,7 @@
   private DexType computeOutlineClassType() {
     DexType result;
     int count = 0;
-    AppInfo appInfo = appInfo();
+    AppInfo appInfo = appView.appInfo();
     do {
       String name = OutlineOptions.CLASS_NAME + (count == 0 ? "" : Integer.toString(count));
       count++;
@@ -878,7 +845,7 @@
       feedback.markProcessed(method, ConstraintWithTarget.NEVER);
       return;
     }
-    AppInfo appInfo = appInfo();
+    AppInfo appInfo = appView.appInfo();
     IRCode code =
         method.buildIR(appInfo, graphLense(), options, appInfo.originFor(method.method.holder));
     if (code == null) {
@@ -915,7 +882,7 @@
     }
 
     if (typeChecker != null && !typeChecker.check(code)) {
-      assert enableWholeProgramOptimizations;
+      assert appView.enableWholeProgramOptimizations();
       assert options.testing.allowTypeErrors;
       StringDiagnostic warning =
           new StringDiagnostic(
@@ -998,7 +965,7 @@
 
     assert code.verifyTypes(appInfo, appView, graphLense());
     codeRewriter.removeTrivialCheckCastAndInstanceOfInstructions(
-        code, enableWholeProgramOptimizations);
+        code, appView.enableWholeProgramOptimizations());
 
     codeRewriter.rewriteLongCompareAndRequireNonNull(code, options);
     codeRewriter.commonSubexpressionElimination(code);
@@ -1011,7 +978,8 @@
     codeRewriter.simplifyIf(code);
     // TODO(b/123284765) This produces a runtime-crash in Q. Activate again when fixed.
     // codeRewriter.redundantConstNumberRemoval(code);
-    new RedundantFieldLoadElimination(appInfo, code, enableWholeProgramOptimizations).run();
+    new RedundantFieldLoadElimination(appInfo, code, appView.enableWholeProgramOptimizations())
+        .run();
 
     if (options.testing.invertConditionals) {
       invertConditionalsForTesting(code);
@@ -1127,7 +1095,7 @@
     }
 
     // Track usage of parameters and compute their nullability and possibility of NPE.
-    if (enableWholeProgramOptimizations) {
+    if (appView.enableWholeProgramOptimizations()) {
       if (method.getOptimizationInfo().getNonNullParamOrThrow() == null) {
         computeNonNullParamHints(feedback, method, code);
       }
@@ -1173,7 +1141,6 @@
 
     printMethod(code, "Optimized IR (SSA)", previous);
     finalizeIR(method, code, feedback);
-    assert appInfo == appInfo();
   }
 
   private void computeNonNullParamHints(
@@ -1203,7 +1170,7 @@
       // merging). Then, we find the type that now corresponds to the the original holder.
       DexMethod originalSignature = graphLense().getOriginalMethodSignature(method.method);
       DexClass originalHolder =
-          appInfo().definitionFor(graphLense().lookupType(originalSignature.holder));
+          appView.definitionFor(graphLense().lookupType(originalSignature.holder));
       if (originalHolder.hasKotlinInfo()) {
         KotlinInfo kotlinInfo = originalHolder.getKotlinInfo();
         if (kotlinInfo.hasNonNullParameterHints()) {
@@ -1235,8 +1202,7 @@
               || Streams.stream(code.instructions())
                   .anyMatch(
                       instruction ->
-                          instruction.instructionMayHaveSideEffects(
-                              appInfo(), appView, method.method.holder));
+                          instruction.instructionMayHaveSideEffects(appView, method.method.holder));
       if (!mayHaveSideEffects) {
         feedback.methodMayNotHaveSideEffects(method);
       }
@@ -1266,14 +1232,14 @@
   private void finalizeToCf(DexEncodedMethod method, IRCode code, OptimizationFeedback feedback) {
     assert !method.getCode().isDexCode();
     CfBuilder builder = new CfBuilder(method, code, options.itemFactory);
-    CfCode result = builder.build(codeRewriter, graphLense(), options, appInfo());
+    CfCode result = builder.build(codeRewriter, graphLense(), options, appView.appInfo());
     method.setCode(result);
     markProcessed(method, code, feedback);
   }
 
   private void finalizeToDex(DexEncodedMethod method, IRCode code, OptimizationFeedback feedback) {
     // Workaround massive dex2oat memory use for self-recursive methods.
-    CodeRewriter.disableDex2OatInliningForSelfRecursiveMethods(code, options, appInfo());
+    CodeRewriter.disableDex2OatInliningForSelfRecursiveMethods(code, options, appView.appInfo());
     // Perform register allocation.
     RegisterAllocator registerAllocator = performRegisterAllocation(code, method);
     method.setCode(code, registerAllocator, options);
@@ -1316,7 +1282,7 @@
     materializeInstructionBeforeLongOperationsWorkaround(code);
     workaroundForwardingInitializerBug(code);
     LinearScanRegisterAllocator registerAllocator =
-        new LinearScanRegisterAllocator(appInfo(), code, options);
+        new LinearScanRegisterAllocator(appView.appInfo(), code, options);
     registerAllocator.allocateRegisters();
     if (options.canHaveExceptionTargetingLoopHeaderBug()) {
       codeRewriter.workaroundExceptionTargetingLoopHeaderBug(code);
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java b/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
index 01c1556..b88a262 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
@@ -9,6 +9,7 @@
 import static com.android.tools.r8.ir.code.Invoke.Type.VIRTUAL;
 
 import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.graph.AppInfo;
 import com.android.tools.r8.graph.AppInfoWithSubtyping;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexCallSite;
@@ -69,19 +70,14 @@
 
 public class LensCodeRewriter {
 
-  private final AppInfoWithSubtyping appInfo;
-  private final GraphLense graphLense;
-  private final VerticallyMergedClasses verticallyMergedClasses;
+  private final AppView<? extends AppInfo> appView;
   private final InternalOptions options;
 
   private final Map<DexProto, DexProto> protoFixupCache = new ConcurrentHashMap<>();
 
-  public LensCodeRewriter(
-      AppView<? extends AppInfoWithSubtyping> appView, InternalOptions options) {
-    this.appInfo = appView.appInfo();
-    this.graphLense = appView.graphLense();
-    this.verticallyMergedClasses = appView.verticallyMergedClasses();
-    this.options = options;
+  public LensCodeRewriter(AppView<? extends AppInfoWithSubtyping> appView) {
+    this.appView = appView;
+    this.options = appView.options();
   }
 
   private Value makeOutValue(Instruction insn, IRCode code, Set<Value> collector) {
@@ -98,6 +94,9 @@
    * Replace type appearances, invoke targets and field accesses with actual definitions.
    */
   public void rewrite(IRCode code, DexEncodedMethod method) {
+    AppInfo appInfo = appView.appInfo();
+    GraphLense graphLense = appView.graphLense();
+
     Set<Value> newSSAValues = Sets.newIdentityHashSet();
     ListIterator<BasicBlock> blocks = code.blocks.listIterator();
     boolean mayHaveUnreachableBlocks = false;
@@ -381,12 +380,13 @@
   // A and B although this will lead to invalid code, because this code pattern does generally
   // not occur in practice (it leads to a verification error on the JVM, but not on Art).
   private void checkInvokeDirect(DexMethod method, InvokeDirect invoke) {
+    VerticallyMergedClasses verticallyMergedClasses = appView.verticallyMergedClasses();
     if (verticallyMergedClasses == null) {
       // No need to check the invocation.
       return;
     }
     DexMethod invokedMethod = invoke.getInvokedMethod();
-    if (invokedMethod.name != appInfo.dexItemFactory.constructorMethodName) {
+    if (invokedMethod.name != appView.dexItemFactory().constructorMethodName) {
       // Not a constructor call.
       return;
     }
@@ -431,7 +431,7 @@
     List<BasicBlock> deadCatchHandlers = new ArrayList<>();
     for (int i = 0; i < guards.size(); i++) {
       // The type may have changed due to class merging.
-      DexType guard = graphLense.lookupType(guards.get(i));
+      DexType guard = appView.graphLense().lookupType(guards.get(i));
       boolean guardSeenBefore = !previouslySeenGuards.add(guard);
       if (guardSeenBefore) {
         deadCatchHandlers.add(targets.get(i));
@@ -458,7 +458,7 @@
         newArgument = rewriteDexMethodType(argument.asDexValueMethodType());
       } else if (argument instanceof DexValueType) {
         DexType oldType = ((DexValueType) argument).value;
-        DexType newType = graphLense.lookupType(oldType);
+        DexType newType = appView.graphLense().lookupType(oldType);
         if (newType != oldType) {
           newArgument = new DexValueType(newType);
         }
@@ -489,7 +489,7 @@
       DexMethod invokedMethod = methodHandle.asMethod();
       MethodHandleType oldType = methodHandle.type;
       GraphLenseLookupResult lenseLookup =
-          graphLense.lookupMethod(invokedMethod, context.method, oldType.toInvokeType());
+          appView.graphLense().lookupMethod(invokedMethod, context.method, oldType.toInvokeType());
       DexMethod rewrittenTarget = lenseLookup.getMethod();
       DexMethod actualTarget;
       MethodHandleType newType;
@@ -505,8 +505,9 @@
         // we cannot member rebind. We therefore keep the receiver and also pin the receiver
         // with a keep rule (see Enqueuer.registerMethodHandle).
         actualTarget =
-            appInfo.dexItemFactory.createMethod(
-                invokedMethod.holder, rewrittenTarget.proto, rewrittenTarget.name);
+            appView
+                .dexItemFactory()
+                .createMethod(invokedMethod.holder, rewrittenTarget.proto, rewrittenTarget.name);
         newType = oldType;
         if (oldType.isInvokeDirect()) {
           // For an invoke direct, the rewritten target must have the same holder as the original.
@@ -526,7 +527,7 @@
       }
     } else {
       DexField field = methodHandle.asField();
-      DexField actualField = graphLense.lookupField(field);
+      DexField actualField = appView.graphLense().lookupField(field);
       if (actualField != field) {
         return new DexMethodHandle(methodHandle.type, actualField);
       }
@@ -537,8 +538,9 @@
   private DexValueMethodType rewriteDexMethodType(DexValueMethodType type) {
     DexProto oldProto = type.value;
     DexProto newProto =
-        appInfo.dexItemFactory.applyClassMappingToProto(
-            oldProto, graphLense::lookupType, protoFixupCache);
+        appView
+            .dexItemFactory()
+            .applyClassMappingToProto(oldProto, appView.graphLense()::lookupType, protoFixupCache);
     return newProto != oldProto ? new DexValueMethodType(newProto) : type;
   }
 
@@ -557,7 +559,7 @@
     if (!receiver.getTypeLattice().isClassType()) {
       return target;
     }
-    DexEncodedMethod encodedTarget = appInfo.definitionFor(target);
+    DexEncodedMethod encodedTarget = appView.definitionFor(target);
     if (encodedTarget == null
         || !canInvokeTargetWithInvokeVirtual(encodedTarget)
         || !hasAccessToInvokeTargetFromContext(encodedTarget, context)) {
@@ -565,12 +567,14 @@
       return target;
     }
     DexType receiverType =
-        graphLense.lookupType(receiver.getTypeLattice().asClassTypeLatticeElement().getClassType());
+        appView
+            .graphLense()
+            .lookupType(receiver.getTypeLattice().asClassTypeLatticeElement().getClassType());
     if (receiverType == target.holder) {
       // Virtual invoke is already as specific as it can get.
       return target;
     }
-    DexEncodedMethod newTarget = appInfo.lookupVirtualTarget(receiverType, target);
+    DexEncodedMethod newTarget = appView.appInfo().lookupVirtualTarget(receiverType, target);
     if (newTarget == null || newTarget.method == target) {
       // Most likely due to a missing class, or invoke is already as specific as it gets.
       return target;
@@ -594,7 +598,7 @@
       // It is always safe to invoke a method from the same enclosing class.
       return true;
     }
-    DexClass clazz = appInfo.definitionFor(holder);
+    DexClass clazz = appView.definitionFor(holder);
     if (clazz == null) {
       // Conservatively report an illegal access.
       return false;
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
index c49b0e9..b6bcb9c 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
@@ -5,8 +5,11 @@
 package com.android.tools.r8.ir.desugar;
 
 import com.android.tools.r8.errors.CompilationError;
+import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.MethodAccessFlags;
@@ -26,13 +29,17 @@
 // Adds default interface methods into the class when needed.
 final class ClassProcessor {
 
+  private final AppView<? extends AppInfo> appView;
+  private final DexItemFactory dexItemFactory;
   private final InterfaceMethodRewriter rewriter;
   // Set of already processed classes.
   private final Set<DexClass> processedClasses = Sets.newIdentityHashSet();
   // Maps already created methods into default methods they were generated based on.
   private final Map<DexEncodedMethod, DexEncodedMethod> createdMethods = new IdentityHashMap<>();
 
-  ClassProcessor(InterfaceMethodRewriter rewriter) {
+  ClassProcessor(AppView<? extends AppInfo> appView, InterfaceMethodRewriter rewriter) {
+    this.appView = appView;
+    this.dexItemFactory = appView.dexItemFactory();
     this.rewriter = rewriter;
   }
 
@@ -60,8 +67,8 @@
     DexType superType = clazz.superType;
     // If superClass definition is missing, just skip this part and let real processing of its
     // subclasses report the error if it is required.
-    DexClass superClass = superType == null ? null : rewriter.appInfo().definitionFor(superType);
-    if (superClass != null && superType != rewriter.factory.objectType) {
+    DexClass superClass = superType == null ? null : appView.definitionFor(superType);
+    if (superClass != null && superType != dexItemFactory.objectType) {
       if (superClass.isInterface()) {
         throw new CompilationError("Interface `" + superClass.toSourceString()
             + "` used as super class of `" + clazz.toSourceString() + "`.");
@@ -96,13 +103,13 @@
 
   private DexEncodedMethod addForwardingMethod(DexEncodedMethod defaultMethod, DexClass clazz) {
     DexMethod method = defaultMethod.method;
-    DexClass target = rewriter.appInfo().definitionFor(method.holder);
+    DexClass target = appView.definitionFor(method.holder);
     // NOTE: Never add a forwarding method to methods of classes unknown or coming from android.jar
     // even if this results in invalid code, these classes are never desugared.
     assert target != null && !target.isLibraryClass();
     // New method will have the same name, proto, and also all the flags of the
     // default method, including bridge flag.
-    DexMethod newMethod = rewriter.factory.createMethod(clazz.type, method.proto, method.name);
+    DexMethod newMethod = dexItemFactory.createMethod(clazz.type, method.proto, method.name);
     MethodAccessFlags newFlags = defaultMethod.accessFlags.copy();
     // Some debuggers (like IntelliJ) automatically skip synthetic methods on single step.
     newFlags.setSynthetic();
@@ -140,7 +147,7 @@
     // methods is supposed to fail with a compilation error.
     // Note that this last assumption will be broken if Object API is augmented with a new method in
     // the future.
-    while (current.type != rewriter.factory.objectType) {
+    while (current.type != dexItemFactory.objectType) {
       for (DexType type : current.interfaces.values) {
         helper.merge(rewriter.getOrCreateInterfaceInfo(clazz, current, type));
       }
@@ -168,7 +175,7 @@
       if (current.superType == null) {
         break;
       } else {
-        DexClass superClass = rewriter.appInfo().definitionFor(current.superType);
+        DexClass superClass = appView.definitionFor(current.superType);
         if (superClass != null) {
           current = superClass;
         } else {
@@ -206,11 +213,11 @@
       DexType superType = current.superType;
       DexClass superClass = null;
       if (superType != null) {
-        superClass = rewriter.appInfo().definitionFor(superType);
+        superClass = appView.definitionFor(superType);
         // It's available or we would have failed while analyzing the hierarchy for interfaces.
         assert superClass != null;
       }
-      if (superClass == null || superType == rewriter.factory.objectType) {
+      if (superClass == null || superType == dexItemFactory.objectType) {
         // Note that default interface methods must never have same
         // name/signature as any method in java.lang.Object (JLS §9.4.1.2).
 
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
index 85ff1ba..3551a7c 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
@@ -7,7 +7,6 @@
 import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.errors.Unimplemented;
 import com.android.tools.r8.graph.AppInfo;
-import com.android.tools.r8.graph.AppInfoWithSubtyping;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexApplication.Builder;
 import com.android.tools.r8.graph.DexCallSite;
@@ -33,7 +32,6 @@
 import com.android.tools.r8.ir.conversion.IRConverter;
 import com.android.tools.r8.ir.desugar.DefaultMethodsHelper.Collection;
 import com.android.tools.r8.origin.Origin;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.StringDiagnostic;
 import com.google.common.collect.Sets;
@@ -80,7 +78,7 @@
   public static final String DEFAULT_METHOD_PREFIX = "$default$";
   public static final String PRIVATE_METHOD_PREFIX = "$private$";
 
-  private final AppView<? extends AppInfoWithLiveness> appView;
+  private final AppView<? extends AppInfo> appView;
   private final IRConverter converter;
   private final InternalOptions options;
   final DexItemFactory factory;
@@ -115,19 +113,12 @@
     ExcludeDexResources
   }
 
-  public InterfaceMethodRewriter(
-      AppView<? extends AppInfoWithLiveness> appView,
-      IRConverter converter,
-      InternalOptions options) {
+  public InterfaceMethodRewriter(AppView<? extends AppInfo> appView, IRConverter converter) {
     assert converter != null;
     this.appView = appView;
     this.converter = converter;
-    this.options = options;
-    this.factory = options.itemFactory;
-  }
-
-  public AppInfo appInfo() {
-    return converter.appInfo();
+    this.options = appView.options();
+    this.factory = appView.dexItemFactory();
   }
 
   // Rewrites the references to static and default interface methods.
@@ -138,7 +129,7 @@
     }
 
     ListIterator<BasicBlock> blocks = code.listIterator();
-    AppInfo appInfo = appInfo();
+    AppInfo appInfo = appView.appInfo();
     while (blocks.hasNext()) {
       BasicBlock block = blocks.next();
       InstructionListIterator instructions = block.listIterator();
@@ -281,12 +272,11 @@
         }
       }
     }
-    assert appInfo == appInfo();
   }
 
   private void reportStaticInterfaceMethodHandle(DexMethod referencedFrom, DexMethodHandle handle) {
     if (handle.type.isInvokeStatic()) {
-      DexClass holderClass = appInfo().definitionFor(handle.asMethod().holder);
+      DexClass holderClass = appView.definitionFor(handle.asMethod().holder);
       // NOTE: If the class definition is missing we can't check. Let it be handled as any other
       // missing call target.
       if (holderClass == null) {
@@ -332,7 +322,7 @@
   }
 
   private boolean isInMainDexList(DexType iface) {
-    return appInfo().isInMainDexList(iface);
+    return appView.appInfo().isInMainDexList(iface);
   }
 
   // Represent a static interface method as a method of companion class.
@@ -401,7 +391,7 @@
     // methods to companion class, copy default interface methods to companion classes,
     // make original default methods abstract, remove bridge methods, create dispatch
     // classes if needed.
-    AppInfo appInfo = appInfo();
+    AppInfo appInfo = appView.appInfo();
     for (Entry<DexType, DexProgramClass> entry : processInterfaces(builder, flavour).entrySet()) {
       // Don't need to optimize synthesized class since all of its methods
       // are just moved from interfaces and don't need to be re-processed.
@@ -439,15 +429,14 @@
     for (Entry<DexLibraryClass, Set<DexProgramClass>> entry : requiredDispatchClasses.entrySet()) {
       synthesizedMethods.addAll(processor.process(entry.getKey(), entry.getValue()));
     }
-    if (converter.enableWholeProgramOptimizations) {
-      AppView<? extends AppInfoWithSubtyping> appView = converter.appView;
+    if (appView.enableWholeProgramOptimizations()) {
       appView.setGraphLense(graphLensBuilder.build(appView.dexItemFactory(), appView.graphLense()));
     }
     return processor.syntheticClasses;
   }
 
   private Set<DexEncodedMethod> processClasses(Builder<?> builder, Flavor flavour) {
-    ClassProcessor processor = new ClassProcessor(this);
+    ClassProcessor processor = new ClassProcessor(appView, this);
     for (DexProgramClass clazz : builder.getProgramClasses()) {
       if (shouldProcess(clazz, flavour, false)) {
         processor.process(clazz);
@@ -523,7 +512,7 @@
     if (isCompanionClassType(holder)) {
       holder = getInterfaceClassType(holder);
     }
-    DexClass clazz = appInfo().definitionFor(holder);
+    DexClass clazz = appView.definitionFor(holder);
     return clazz == null ? Origin.unknown() : clazz.getOrigin();
   }
 
@@ -545,7 +534,7 @@
       DexClass implementing,
       DexType iface) {
     DefaultMethodsHelper helper = new DefaultMethodsHelper();
-    DexClass definedInterface = appInfo().definitionFor(iface);
+    DexClass definedInterface = appView.definitionFor(iface);
     if (definedInterface == null) {
       warnMissingInterface(classToDesugar, implementing, iface);
       return helper.wrapInCollection();
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
index 9bd7b9d..c89019c 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
@@ -51,14 +51,13 @@
 // Also moves static interface methods into a companion class.
 final class InterfaceProcessor {
 
-  private final AppView<? extends AppInfoWithLiveness> appView;
+  private final AppView<? extends AppInfo> appView;
   private final InterfaceMethodRewriter rewriter;
 
   // All created companion and dispatch classes indexed by interface type.
   final Map<DexType, DexProgramClass> syntheticClasses = new IdentityHashMap<>();
 
-  InterfaceProcessor(
-      AppView<? extends AppInfoWithLiveness> appView, InterfaceMethodRewriter rewriter) {
+  InterfaceProcessor(AppView<? extends AppInfo> appView, InterfaceMethodRewriter rewriter) {
     this.appView = appView;
     this.rewriter = rewriter;
   }
@@ -308,11 +307,12 @@
   // methods. Bridge methods that does not override an implementation in a super-interface must
   // also be kept (such a situation can happen if the vertical class merger merges two interfaces).
   private boolean interfaceMethodRemovalChangesApi(DexEncodedMethod method, DexClass iface) {
-    if (appView != null && appView.appInfo().isPinned(method.method)) {
-      return true;
+    if (appView.enableWholeProgramOptimizations()) {
+      AppInfoWithLiveness appInfoWithLiveness = appView.appInfo().withLiveness();
+      if (appInfoWithLiveness.isPinned(method.method)) {
+        return true;
+      }
     }
-    AppInfo appInfo = rewriter.appInfo();
-    assert appView == null || appInfo == appView.appInfo();
     if (method.accessFlags.isBridge()) {
       Deque<DexType> worklist = new ArrayDeque<>();
       Set<DexType> seenBefore = new HashSet<>();
@@ -325,7 +325,7 @@
         if (!seenBefore.add(superType)) {
           continue;
         }
-        DexClass clazz = appInfo.definitionFor(superType);
+        DexClass clazz = appView.definitionFor(superType);
         if (clazz != null) {
           if (clazz.lookupVirtualMethod(method.method) != null) {
             return false;
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/Java8MethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/Java8MethodRewriter.java
index 50a2450..9b096a2 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/Java8MethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/Java8MethodRewriter.java
@@ -6,6 +6,7 @@
 
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.ClassAccessFlags;
 import com.android.tools.r8.graph.DexAnnotationSet;
 import com.android.tools.r8.graph.DexApplication.Builder;
@@ -46,15 +47,18 @@
   public static final String UTILITY_CLASS_NAME_PREFIX = "$r8$java8methods$utility";
   private static final String UTILITY_CLASS_DESCRIPTOR_PREFIX = "L$r8$java8methods$utility";
   private final Set<DexType> holders = Sets.newConcurrentHashSet();
+
+  private final AppView<? extends AppInfo> appView;
   private final IRConverter converter;
   private final DexItemFactory factory;
   private final RewritableMethods rewritableMethods;
 
   private Map<DexMethod, MethodGenerator> methodGenerators = new ConcurrentHashMap<>();
 
-  public Java8MethodRewriter(IRConverter converter) {
+  public Java8MethodRewriter(AppView<? extends AppInfo> appView, IRConverter converter) {
+    this.appView = appView;
     this.converter = converter;
-    this.factory = converter.appInfo().dexItemFactory;
+    this.factory = appView.dexItemFactory();
     this.rewritableMethods = new RewritableMethods(factory);
   }
 
@@ -99,7 +103,7 @@
       return;
     }
     Set<DexProgramClass> referencingClasses = Sets.newConcurrentHashSet();
-    AppInfo appInfo = converter.appInfo();
+    AppInfo appInfo = appView.appInfo();
     for (DexType holder : holders) {
       DexClass definitionFor = appInfo.definitionFor(holder);
       if (definitionFor == null) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
index 091ec9f..1bb56ea 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
@@ -95,7 +95,7 @@
         : factory.createField(lambdaClassType, lambdaClassType, rewriter.instanceFieldName);
 
     // We have to register this new class as a subtype of object.
-    rewriter.converter.appInfo().registerNewType(type, factory.objectType);
+    rewriter.converter.appView.appInfo().registerNewType(type, factory.objectType);
   }
 
   // Generate unique lambda class type for lambda descriptor and instantiation point context.
@@ -153,7 +153,7 @@
             synthesizeVirtualMethods(mainMethod),
             rewriter.factory.getSkipNameValidationForTesting());
     // Optimize main method.
-    rewriter.converter.appInfo().addSynthesizedClass(clazz);
+    rewriter.converter.appView.appInfo().addSynthesizedClass(clazz);
     rewriter.converter.optimizeSynthesizedMethod(clazz.lookupVirtualMethod(mainMethod));
 
     // The method addSynthesizedFrom() may be called concurrently. To avoid a Concurrent-
@@ -348,7 +348,7 @@
     // If the lambda$ method is an instance-private method on an interface we convert it into a
     // public static method as it will be placed on the companion class.
     if (implHandle.type.isInvokeDirect()
-        && rewriter.converter.appInfo().definitionFor(implMethod.holder).isInterface()) {
+        && rewriter.converter.appView.definitionFor(implMethod.holder).isInterface()) {
       DexProto implProto = implMethod.proto;
       DexType[] implParams = implProto.parameters.values;
       DexType[] newParams = new DexType[implParams.length + 1];
@@ -470,11 +470,11 @@
     abstract boolean ensureAccessibility();
 
     DexClass definitionFor(DexType type) {
-      return rewriter.converter.appInfo().app.definitionFor(type);
+      return rewriter.converter.appView.appInfo().app.definitionFor(type);
     }
 
     DexProgramClass programDefinitionFor(DexType type) {
-      return rewriter.converter.appInfo().app.programDefinitionFor(type);
+      return rewriter.converter.appView.appInfo().app.programDefinitionFor(type);
     }
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java
index acd199a..92d7a9d 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java
@@ -6,6 +6,7 @@
 
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexApplication.Builder;
 import com.android.tools.r8.graph.DexCallSite;
 import com.android.tools.r8.graph.DexEncodedMethod;
@@ -53,6 +54,7 @@
   static final String EXPECTED_LAMBDA_METHOD_PREFIX = "lambda$";
   static final String LAMBDA_INSTANCE_FIELD_NAME = "INSTANCE";
 
+  private final AppView<? extends AppInfo> appView;
   final IRConverter converter;
   final DexItemFactory factory;
 
@@ -80,10 +82,11 @@
     return clazz.getName().startsWith(LAMBDA_CLASS_NAME_PREFIX);
   }
 
-  public LambdaRewriter(IRConverter converter) {
+  public LambdaRewriter(AppView<? extends AppInfo> appView, IRConverter converter) {
     assert converter != null;
+    this.appView = appView;
     this.converter = converter;
-    this.factory = converter.appInfo().dexItemFactory;
+    this.factory = appView.dexItemFactory();
 
     this.constructorName = factory.createString(Constants.INSTANCE_INITIALIZER_NAME);
     DexProto initProto = factory.createProto(factory.voidType);
@@ -135,7 +138,7 @@
         for (int i = 0; i < methodCount; i++) {
           DexEncodedMethod encoded = directMethods.get(i);
           DexMethod method = encoded.method;
-          if (method.isLambdaDeserializeMethod(converter.appInfo().dexItemFactory)) {
+          if (method.isLambdaDeserializeMethod(appView.dexItemFactory())) {
             assert encoded.accessFlags.isStatic();
             assert encoded.accessFlags.isSynthetic();
             clazz.removeDirectMethod(i);
@@ -161,9 +164,9 @@
       // This call may cause methodMapping to be updated.
       lambdaClass.target.ensureAccessibility();
     }
-    if (converter.enableWholeProgramOptimizations && !methodMapping.isEmpty()) {
-      converter.appView.setGraphLense(
-          new LambdaRewriterGraphLense(methodMapping, converter.appView.graphLense(), factory));
+    if (appView.enableWholeProgramOptimizations() && !methodMapping.isEmpty()) {
+      appView.setGraphLense(
+          new LambdaRewriterGraphLense(methodMapping, appView.graphLense(), factory));
     }
   }
 
@@ -179,7 +182,7 @@
   /** Generates lambda classes and adds them to the builder. */
   public void synthesizeLambdaClasses(Builder<?> builder, ExecutorService executorService)
       throws ExecutionException {
-    AppInfo appInfo = converter.appInfo();
+    AppInfo appInfo = appView.appInfo();
     for (LambdaClass lambdaClass : knownLambdaClasses.values()) {
       DexProgramClass synthesizedClass = lambdaClass.getLambdaClass();
       appInfo.addSynthesizedClass(synthesizedClass);
@@ -210,11 +213,11 @@
     return descriptor != null
         ? descriptor
         : putIfAbsent(
-            knownCallSites, callSite, LambdaDescriptor.infer(callSite, this.converter.appInfo()));
+            knownCallSites, callSite, LambdaDescriptor.infer(callSite, appView.appInfo()));
   }
 
   private boolean isInMainDexList(DexType type) {
-    return converter.appInfo().isInMainDexList(type);
+    return appView.appInfo().isInMainDexList(type);
   }
 
   // Returns a lambda class corresponding to the lambda descriptor and context,
@@ -227,8 +230,7 @@
       lambdaClass = putIfAbsent(knownLambdaClasses, lambdaClassType,
           new LambdaClass(this, accessedFrom, lambdaClassType, descriptor));
     }
-    lambdaClass.addSynthesizedFrom(
-        converter.appInfo().definitionFor(accessedFrom).asProgramClass());
+    lambdaClass.addSynthesizedFrom(appView.definitionFor(accessedFrom).asProgramClass());
     if (isInMainDexList(accessedFrom)) {
       lambdaClass.addToMainDexList.set(true);
     }
@@ -272,7 +274,7 @@
       lambdaInstanceValue =
           code.createValue(
               TypeLatticeElement.fromDexType(
-                  lambdaClass.type, Nullability.maybeNull(), converter.appInfo()));
+                  lambdaClass.type, Nullability.maybeNull(), appView.appInfo()));
     }
 
     // For stateless lambdas we replace InvokeCustom instruction with StaticGet
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/StringConcatRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/StringConcatRewriter.java
index 8bad12a..4e7636c 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/StringConcatRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/StringConcatRewriter.java
@@ -9,6 +9,7 @@
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexCallSite;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexMethod;
@@ -47,7 +48,7 @@
   private static final String TO_STRING = "toString";
   private static final String APPEND = "append";
 
-  private final AppInfo appInfo;
+  private final AppView<? extends AppInfo> appView;
   private final DexItemFactory factory;
 
   private final DexMethod makeConcat;
@@ -59,10 +60,9 @@
   private final Map<DexType, DexMethod> paramTypeToAppendMethod = new IdentityHashMap<>();
   private final DexMethod defaultAppendMethod;
 
-  public StringConcatRewriter(AppInfo appInfo) {
-    this.appInfo = appInfo;
-    assert appInfo.dexItemFactory != null;
-    this.factory = appInfo.dexItemFactory;
+  public StringConcatRewriter(AppView<? extends AppInfo> appView) {
+    this.appView = appView;
+    this.factory = appView.dexItemFactory();
 
     DexType factoryType = factory.createType(CONCAT_FACTORY_TYPE_DESCR);
     DexType callSiteType = factory.createType(CALLSITE_TYPE_DESCR);
@@ -165,7 +165,7 @@
     }
 
     // Collect chunks.
-    ConcatBuilder builder = new ConcatBuilder(appInfo, code, blocks, instructions);
+    ConcatBuilder builder = new ConcatBuilder(appView, code, blocks, instructions);
     for (int i = 0; i < paramCount; i++) {
       builder.addChunk(arguments.get(i),
           paramTypeToAppendMethod.getOrDefault(parameters[i], defaultAppendMethod));
@@ -220,7 +220,7 @@
     String recipe = ((DexValue.DexValueString) recipeValue).getValue().toString();
 
     // Collect chunks and patch the instruction.
-    ConcatBuilder builder = new ConcatBuilder(appInfo, code, blocks, instructions);
+    ConcatBuilder builder = new ConcatBuilder(appView, code, blocks, instructions);
     StringBuilder acc = new StringBuilder();
     int argIndex = 0;
     int constArgIndex = 0;
@@ -282,7 +282,7 @@
   }
 
   private final class ConcatBuilder {
-    private final AppInfo appInfo;
+    private final AppView<? extends AppInfo> appView;
     private final IRCode code;
     private final ListIterator<BasicBlock> blocks;
     private final InstructionListIterator instructions;
@@ -291,11 +291,11 @@
     private final List<Chunk> chunks = new ArrayList<>();
 
     private ConcatBuilder(
-        AppInfo appInfo,
+        AppView<? extends AppInfo> appView,
         IRCode code,
         ListIterator<BasicBlock> blocks,
         InstructionListIterator instructions) {
-      this.appInfo = appInfo;
+      this.appView = appView;
       this.code = code;
       this.blocks = blocks;
       this.instructions = instructions;
@@ -341,7 +341,7 @@
       // new-instance v0, StringBuilder
       TypeLatticeElement stringBuilderTypeLattice =
           TypeLatticeElement.fromDexType(
-              factory.stringBuilderType, definitelyNotNull(), appInfo);
+              factory.stringBuilderType, definitelyNotNull(), appView.appInfo());
       Value sbInstance = code.createValue(stringBuilderTypeLattice);
       appendInstruction(new NewInstance(factory.stringBuilderType, sbInstance));
 
@@ -364,7 +364,8 @@
       if (concatValue == null) {
         // The out value might be empty in case it was optimized out.
         concatValue =
-            code.createValue(TypeLatticeElement.stringClassType(appInfo, definitelyNotNull()));
+            code.createValue(
+                TypeLatticeElement.stringClassType(appView.appInfo(), definitelyNotNull()));
       }
 
       // Replace the instruction.
@@ -443,10 +444,13 @@
       @Override
       Value getOrCreateValue() {
         Value value =
-            code.createValue(TypeLatticeElement.stringClassType(appInfo, definitelyNotNull()));
-        ThrowingInfo throwingInfo =
-            code.options.isGeneratingClassFiles() ? ThrowingInfo.NO_THROW : ThrowingInfo.CAN_THROW;
-        appendInstruction(new ConstString(value, factory.createString(str), throwingInfo));
+            code.createValue(
+                TypeLatticeElement.stringClassType(appView.appInfo(), definitelyNotNull()));
+        appendInstruction(
+            new ConstString(
+                value,
+                factory.createString(str),
+                ThrowingInfo.defaultForConstString(appView.options())));
         return value;
       }
     }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/TwrCloseResourceRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/TwrCloseResourceRewriter.java
index 7fd815e..f8ebb06 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/TwrCloseResourceRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/TwrCloseResourceRewriter.java
@@ -6,6 +6,7 @@
 
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.ClassAccessFlags;
 import com.android.tools.r8.graph.DexAnnotationSet;
 import com.android.tools.r8.graph.DexApplication.Builder;
@@ -51,6 +52,7 @@
   public static final String UTILITY_CLASS_NAME = "$r8$twr$utility";
   public static final String UTILITY_CLASS_DESCRIPTOR = "L$r8$twr$utility;";
 
+  private final AppView<? extends AppInfo> appView;
   private final IRConverter converter;
   private final DexItemFactory factory;
 
@@ -58,9 +60,10 @@
 
   private final Set<DexProgramClass> referencingClasses = Sets.newConcurrentHashSet();
 
-  public TwrCloseResourceRewriter(IRConverter converter) {
+  public TwrCloseResourceRewriter(AppView<? extends AppInfo> appView, IRConverter converter) {
+    this.appView = appView;
     this.converter = converter;
-    this.factory = converter.appInfo().dexItemFactory;
+    this.factory = appView.dexItemFactory();
 
     DexType twrUtilityClass = factory.createType(UTILITY_CLASS_DESCRIPTOR);
     DexProto twrCloseResourceProto = factory.createProto(
@@ -72,14 +75,14 @@
   // Rewrites calls to $closeResource() method. Can be invoked concurrently.
   public void rewriteMethodCode(IRCode code) {
     InstructionIterator iterator = code.instructionIterator();
-    AppInfo appInfo = converter.appInfo();
+    AppInfo appInfo = appView.appInfo();
     while (iterator.hasNext()) {
       Instruction instruction = iterator.next();
       if (!instruction.isInvokeStatic()) {
         continue;
       }
       InvokeStatic invoke = instruction.asInvokeStatic();
-      if (!isSynthesizedCloseResourceMethod(invoke.getInvokedMethod(), converter)) {
+      if (!isSynthesizedCloseResourceMethod(invoke.getInvokedMethod(), appView)) {
         continue;
       }
 
@@ -95,8 +98,9 @@
     }
   }
 
-  public static boolean isSynthesizedCloseResourceMethod(DexMethod method, IRConverter converter) {
-    DexMethod original = converter.graphLense().getOriginalMethodSignature(method);
+  public static boolean isSynthesizedCloseResourceMethod(
+      DexMethod method, AppView<? extends AppInfo> appView) {
+    DexMethod original = appView.graphLense().getOriginalMethodSignature(method);
     assert original != null;
     // We consider all methods of *any* class with expected name and signature
     // to be synthesized by java 9 compiler for try-with-resources, reasoning:
@@ -107,7 +111,7 @@
     //    right attributes, but it still does not guarantee much since we also
     //    need to look into code and doing this seems an overkill
     //
-    DexItemFactory dexItemFactory = converter.appInfo().dexItemFactory;
+    DexItemFactory dexItemFactory = appView.appInfo().dexItemFactory;
     return original.name == dexItemFactory.twrCloseResourceMethodName
         && original.proto == dexItemFactory.twrCloseResourceMethodProto;
   }
@@ -149,7 +153,7 @@
     code.setUpContext(utilityClass);
 
     // Process created class and method.
-    AppInfo appInfo = converter.appInfo();
+    AppInfo appInfo = appView.appInfo();
     boolean addToMainDexList =
         referencingClasses.stream().anyMatch(clazz -> appInfo.isInMainDexList(clazz.type));
     appInfo.addSynthesizedClass(utilityClass);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java b/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java
index bebf225..29b6aa7 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java
@@ -49,7 +49,6 @@
 import com.android.tools.r8.ir.optimize.ReflectionOptimizer.ClassNameComputationInfo;
 import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 import com.android.tools.r8.utils.Action;
-import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.IteratorUtils;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
@@ -92,28 +91,17 @@
     }
   }
 
-  private final AppInfo appInfo;
   private final AppView<? extends AppInfo> appView;
   private final IRConverter converter;
   private final DexItemFactory dexItemFactory;
-  private final InternalOptions options;
 
   private WaveDoneAction waveDoneAction = null;
 
   public ClassInitializerDefaultsOptimization(
-      AppInfo appInfo,
-      AppView<? extends AppInfo> appView,
-      IRConverter converter,
-      InternalOptions options) {
-    this.appInfo = appInfo;
+      AppView<? extends AppInfo> appView, IRConverter converter) {
     this.appView = appView;
     this.converter = converter;
-    this.dexItemFactory = appInfo.dexItemFactory;
-    this.options = options;
-  }
-
-  public AppInfo appInfo() {
-    return appView != null ? appView.appInfo() : appInfo;
+    this.dexItemFactory = appView.dexItemFactory();
   }
 
   public void optimize(DexEncodedMethod method, IRCode code) {
@@ -121,7 +109,7 @@
       return;
     }
 
-    DexClass clazz = appInfo().definitionFor(method.method.holder);
+    DexClass clazz = appView.definitionFor(method.method.holder);
     if (clazz == null) {
       return;
     }
@@ -142,7 +130,7 @@
 
     // Set initial values for static fields from the definitive static put instructions collected.
     for (StaticPut put : finalFieldPuts) {
-      DexEncodedField field = appInfo().resolveField(put.getField());
+      DexEncodedField field = appView.appInfo().resolveField(put.getField());
       DexType fieldType = field.field.type;
       Value inValue = put.inValue();
       if (fieldType == dexItemFactory.stringType) {
@@ -216,14 +204,14 @@
     // that the field is no longer written.
     if (appView != null && appView.enableWholeProgramOptimizations() && converter.isInWave()) {
       if (appView.appInfo().hasLiveness()) {
-        AppView<AppInfoWithLiveness> appViewWithLiveness = appView.withLiveness();
+        AppView<? extends AppInfoWithLiveness> appViewWithLiveness = appView.withLiveness();
         AppInfoWithLiveness appInfoWithLiveness = appViewWithLiveness.appInfo();
 
         // First collect all the candidate fields that are *potentially* no longer being written to.
         Set<DexField> candidates =
             finalFieldPuts.stream()
                 .map(FieldInstruction::getField)
-                .map(field -> appInfo().resolveField(field).field)
+                .map(field -> appInfoWithLiveness.resolveField(field).field)
                 .filter(appInfoWithLiveness::isStaticFieldWrittenOnlyInEnclosingStaticInitializer)
                 .collect(Collectors.toSet());
 
@@ -286,13 +274,13 @@
   }
 
   private DexValue getDexStringValueForInvoke(DexMethod invokedMethod, DexType holder) {
-    DexClass clazz = appInfo().definitionFor(holder);
+    DexClass clazz = appView.definitionFor(holder);
     if (clazz == null) {
       assert false;
       return null;
     }
 
-    if (options.enableMinification && !converter.rootSet.noObfuscation.contains(holder)) {
+    if (appView.options().enableMinification && !converter.rootSet.noObfuscation.contains(holder)) {
       if (invokedMethod == dexItemFactory.classMethods.getName) {
         return new DexItemBasedValueString(holder, new ClassNameComputationInfo(NAME));
       }
@@ -341,10 +329,10 @@
           Instruction instruction = it.next();
           if (instruction.isStaticGet()) {
             StaticGet get = instruction.asStaticGet();
-            DexEncodedField field = appInfo().resolveField(get.getField());
+            DexEncodedField field = appView.appInfo().resolveField(get.getField());
             if (field != null && field.field.clazz == clazz.type) {
               isReadBefore.add(field.field);
-            } else if (instruction.instructionMayHaveSideEffects(appInfo(), appView, clazz.type)) {
+            } else if (instruction.instructionMayHaveSideEffects(appView, clazz.type)) {
               // Reading another field is only OK if the read does not have side-effects.
               return finalFieldPut.values();
             }
@@ -384,7 +372,7 @@
               // Writing another field is not OK.
               return finalFieldPut.values();
             }
-          } else if (instruction.instructionMayHaveSideEffects(appInfo(), appView, clazz.type)) {
+          } else if (instruction.instructionMayHaveSideEffects(appView, clazz.type)) {
             // Some other instruction that has side-effects. Stop here.
             return finalFieldPut.values();
           } else {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
index 86bae46..304c86d 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
@@ -12,7 +12,6 @@
 import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppInfo;
-import com.android.tools.r8.graph.AppInfoWithSubtyping;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DebugLocalInfo;
 import com.android.tools.r8.graph.DexClass;
@@ -153,21 +152,20 @@
   private static final int SELF_RECURSION_LIMIT = 4;
 
   public final IRConverter converter;
-  private final AppInfo appInfo;
+
   private final AppView<? extends AppInfo> appView;
   private final DexItemFactory dexItemFactory;
   private final Set<DexMethod> libraryMethodsReturningReceiver;
   private final InternalOptions options;
 
   public CodeRewriter(
+      AppView<? extends AppInfo> appView,
       IRConverter converter,
-      Set<DexMethod> libraryMethodsReturningReceiver,
-      InternalOptions options) {
+      Set<DexMethod> libraryMethodsReturningReceiver) {
+    this.appView = appView;
     this.converter = converter;
-    this.appInfo = converter.appInfo();
-    this.appView = converter.appView;
-    this.options = options;
-    this.dexItemFactory = appInfo.dexItemFactory;
+    this.options = appView.options();
+    this.dexItemFactory = appView.dexItemFactory();
     this.libraryMethodsReturningReceiver = libraryMethodsReturningReceiver;
   }
 
@@ -884,8 +882,8 @@
         // Pattern match a switch on a switch map as input.
         if (insn.isSwitch()) {
           Switch switchInsn = insn.asSwitch();
-          EnumSwitchInfo info = SwitchUtils
-              .analyzeSwitchOverEnum(switchInsn, appInfo.withLiveness());
+          EnumSwitchInfo info =
+              SwitchUtils.analyzeSwitchOverEnum(switchInsn, appView.withLiveness());
           if (info != null) {
             Int2IntMap targetMap = new Int2IntArrayMap();
             IntList keys = new IntArrayList(switchInsn.numberOfKeys());
@@ -1018,7 +1016,7 @@
   public void identifyInvokeSemanticsForInlining(
       DexEncodedMethod method,
       IRCode code,
-      AppView<? extends AppInfoWithSubtyping> appView,
+      AppView<? extends AppInfo> appView,
       OptimizationFeedback feedback) {
     if (method.isStatic()) {
       // Identifies if the method preserves class initialization after inlining.
@@ -1058,7 +1056,7 @@
       return;
     }
 
-    DexClass clazz = appInfo.definitionFor(method.method.holder);
+    DexClass clazz = appView.definitionFor(method.method.holder);
     if (clazz == null) {
       return;
     }
@@ -1129,6 +1127,7 @@
       return;
     }
 
+    AppInfo appInfo = appView.appInfo();
     DexClass clazz = appInfo.definitionFor(method.method.holder);
     if (clazz == null) {
       return;
@@ -1364,7 +1363,7 @@
    * <p>Note: we do not track phis so we may return false negative. This is a conservative approach.
    */
   public static boolean checksNullBeforeSideEffect(
-      IRCode code, Value value, AppView<? extends AppInfoWithSubtyping> appView) {
+      IRCode code, Value value, AppView<? extends AppInfo> appView) {
     return alwaysTriggerExpectedEffectBeforeAnythingElse(
         code,
         (instr, it) -> {
@@ -1412,8 +1411,7 @@
               // We found a NPE check on the value.
               return InstructionEffect.DESIRED_EFFECT;
             }
-          } else if (instr.instructionMayHaveSideEffects(
-              appView.appInfo(), appView, code.method.method.holder)) {
+          } else if (instr.instructionMayHaveSideEffects(appView, code.method.method.holder)) {
             // If the current instruction is const-string, this could load the parameter name.
             // Just make sure it is indeed not throwing.
             if (instr.isConstString() && !instr.instructionInstanceCanThrow()) {
@@ -1430,7 +1428,7 @@
   // declare a method called checkParameterIsNotNull(parameter, message) or
   // throwParameterIsNullException(parameterName) in a package that starts with "kotlin".
   private static boolean isKotlinNullCheck(
-      Instruction instr, Value value, AppView<? extends AppInfoWithSubtyping> appView) {
+      Instruction instr, Value value, AppView<? extends AppInfo> appView) {
     if (!instr.isInvokeStatic()) {
       return false;
     }
@@ -1485,7 +1483,7 @@
    * <p>Note: we do not track phis so we may return false negative. This is a conservative approach.
    */
   private static boolean triggersClassInitializationBeforeSideEffect(
-      DexType clazz, IRCode code, AppView<? extends AppInfoWithSubtyping> appView) {
+      DexType clazz, IRCode code, AppView<? extends AppInfo> appView) {
     return alwaysTriggerExpectedEffectBeforeAnythingElse(
         code,
         (instruction, it) -> {
@@ -1500,7 +1498,7 @@
               // We found an instruction that preserves initialization of the class.
               return InstructionEffect.DESIRED_EFFECT;
             }
-          } else if (instruction.instructionMayHaveSideEffects(appView.appInfo(), appView, clazz)) {
+          } else if (instruction.instructionMayHaveSideEffects(appView, clazz)) {
             // We found a side effect before class initialization.
             return InstructionEffect.OTHER_EFFECT;
           }
@@ -1581,17 +1579,16 @@
 
   private boolean checkArgumentType(InvokeMethod invoke, int argumentIndex) {
     // TODO(sgjesse): Insert cast if required.
+    AppInfo appInfo = appView.appInfo();
     TypeLatticeElement returnType =
         TypeLatticeElement.fromDexType(
             invoke.getInvokedMethod().proto.returnType, maybeNull(), appInfo);
     TypeLatticeElement argumentType =
         TypeLatticeElement.fromDexType(
             getArgumentType(invoke, argumentIndex), maybeNull(), appInfo);
-    if (appView != null && appView.enableWholeProgramOptimizations()) {
-      return argumentType.lessThanOrEqual(returnType, appInfo);
-    } else {
-      return argumentType.equals(returnType);
-    }
+    return appView.enableWholeProgramOptimizations()
+        ? argumentType.lessThanOrEqual(returnType, appInfo)
+        : argumentType.equals(returnType);
   }
 
   private DexType getArgumentType(InvokeMethod invoke, int argumentIndex) {
@@ -1609,6 +1606,7 @@
     if (options.isGeneratingClassFiles()) {
       return;
     }
+    AppInfo appInfo = appView.appInfo();
     AppInfoWithLiveness appInfoWithLiveness = appInfo.withLiveness();
     Set<Value> needToWidenValues = Sets.newIdentityHashSet();
     Set<Value> needToNarrowValues = Sets.newIdentityHashSet();
@@ -1877,6 +1875,7 @@
   // Returns true if the given check-cast instruction was removed.
   private boolean removeCheckCastInstructionIfTrivial(
       CheckCast checkCast, InstructionIterator it, IRCode code) {
+    AppInfo appInfo = appView.appInfo();
     Value inValue = checkCast.object();
     Value outValue = checkCast.outValue();
     DexType castType = checkCast.getType();
@@ -1901,7 +1900,7 @@
     // We might see chains of casts on subtypes. It suffices to cast to the lowest subtype,
     // as that will fail if a cast on a supertype would have failed.
     Predicate<Instruction> isCheckcastToSubtype =
-        user -> user.isCheckCast() && user.asCheckCast().getType().isSubtypeOf(castType, appInfo);
+        user -> user.isCheckCast() && user.asCheckCast().getType().isSubtypeOf(castType, appView);
     if (!checkCast.getBlock().hasCatchHandlers()
         && outValue.isUsed()
         && outValue.numberOfPhiUsers() == 0
@@ -1941,6 +1940,7 @@
   }
 
   private boolean isTypeInaccessibleInCurrentContext(DexType type, DexEncodedMethod context) {
+    AppInfo appInfo = appView.appInfo();
     DexType baseType = type.toBaseType(appInfo.dexItemFactory);
     if (baseType.isPrimitiveType()) {
       return false;
@@ -1965,6 +1965,7 @@
       return false;
     }
 
+    AppInfo appInfo = appView.appInfo();
     Value inValue = instanceOf.value();
     TypeLatticeElement inType = inValue.getTypeLattice();
     TypeLatticeElement instanceOfType =
@@ -2013,6 +2014,7 @@
   }
 
   private boolean isNeverInstantiatedDirectlyOrIndirectly(DexType type) {
+    AppInfo appInfo = appView.appInfo();
     assert appInfo.hasLiveness();
     assert type.isClassType();
     DexClass clazz = appInfo.definitionFor(type);
@@ -2929,7 +2931,7 @@
     }
     Set<Value> affectedValues = code.removeUnreachableBlocks();
     if (!affectedValues.isEmpty()) {
-      new TypeAnalysis(appInfo, code.method).narrowing(affectedValues);
+      new TypeAnalysis(appView.appInfo(), code.method).narrowing(affectedValues);
     }
     assert code.isConsistentSSA();
   }
@@ -3130,7 +3132,7 @@
       }
 
       if (dominatorTree.get().dominatedBy(block, dominator)) {
-        if (newValue.getTypeLattice().lessThanOrEqual(value.getTypeLattice(), appInfo)) {
+        if (newValue.getTypeLattice().lessThanOrEqual(value.getTypeLattice(), appView.appInfo())) {
           value.replaceUsers(newValue);
           block.listIterator(constNumber).removeOrReplaceByDebugLocalRead();
           constantWithValueIterator.remove();
@@ -3154,7 +3156,7 @@
   // null value (which should result in NPE). Note that this throw is not
   // expected to be ever reached, but is intended to satisfy verifier.
   public void processMethodsNeverReturningNormally(IRCode code) {
-    AppInfoWithLiveness appInfoWithLiveness = appInfo.withLiveness();
+    AppInfoWithLiveness appInfoWithLiveness = appView.appInfo().withLiveness();
     if (appInfoWithLiveness == null) {
       return;
     }
@@ -3623,7 +3625,7 @@
       if (type == dexItemFactory.throwableType) {
         return true;
       }
-      DexClass dexClass = appInfo.definitionFor(type);
+      DexClass dexClass = appView.definitionFor(type);
       if (dexClass == null) {
         throw new CompilationError("Class or interface " + type.toSourceString() +
             " required for desugaring of try-with-resources is not found.");
@@ -3635,7 +3637,7 @@
 
   private Value addConstString(IRCode code, InstructionListIterator iterator, String s) {
     TypeLatticeElement typeLattice =
-        TypeLatticeElement.stringClassType(appInfo, definitelyNotNull());
+        TypeLatticeElement.stringClassType(appView.appInfo(), definitelyNotNull());
     Value value = code.createValue(typeLattice);
     ThrowingInfo throwingInfo =
         options.isGeneratingClassFiles() ? ThrowingInfo.NO_THROW : ThrowingInfo.CAN_THROW;
@@ -3667,8 +3669,10 @@
     assert !block.hasCatchHandlers();
     DexType javaLangSystemType = dexItemFactory.createType("Ljava/lang/System;");
     DexType javaIoPrintStreamType = dexItemFactory.createType("Ljava/io/PrintStream;");
-    Value out = code.createValue(
-        TypeLatticeElement.fromDexType(javaIoPrintStreamType, definitelyNotNull(), appInfo));
+    Value out =
+        code.createValue(
+            TypeLatticeElement.fromDexType(
+                javaIoPrintStreamType, definitelyNotNull(), appView.appInfo()));
 
     DexProto proto = dexItemFactory.createProto(dexItemFactory.voidType, dexItemFactory.objectType);
     DexMethod print = dexItemFactory.createMethod(javaIoPrintStreamType, proto, "print");
@@ -3733,7 +3737,9 @@
         iterator.add(new InvokeVirtual(print, null, ImmutableList.of(out, nul)));
         iterator = isNotNullBlock.listIterator();
         iterator.setInsertionPosition(position);
-        value = code.createValue(TypeLatticeElement.classClassType(appInfo, definitelyNotNull()));
+        value =
+            code.createValue(
+                TypeLatticeElement.classClassType(appView.appInfo(), definitelyNotNull()));
         iterator.add(new InvokeVirtual(dexItemFactory.objectMethods.getClass, value,
             ImmutableList.of(arguments.get(i))));
         iterator.add(new InvokeVirtual(print, null, ImmutableList.of(out, value)));
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java b/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java
index 9c8168e..04227ac 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java
@@ -16,7 +16,6 @@
 import com.android.tools.r8.ir.code.Phi;
 import com.android.tools.r8.ir.code.Value;
 import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
-import com.android.tools.r8.utils.InternalOptions;
 import com.google.common.collect.ImmutableList;
 import java.util.Collection;
 import java.util.Iterator;
@@ -25,27 +24,12 @@
 
 public class DeadCodeRemover {
 
-  private final AppView<? extends AppInfoWithLiveness> appView;
-  private final AppInfo appInfo;
+  private final AppView<? extends AppInfo> appView;
   private final CodeRewriter codeRewriter;
-  private final InternalOptions options;
-  private final boolean enableWholeProgramOptimizations;
 
-  public DeadCodeRemover(
-      AppView<? extends AppInfoWithLiveness> appView,
-      AppInfo appInfo,
-      CodeRewriter codeRewriter,
-      InternalOptions options) {
+  public DeadCodeRemover(AppView<? extends AppInfo> appView, CodeRewriter codeRewriter) {
     this.appView = appView;
-    this.appInfo = appInfo;
     this.codeRewriter = codeRewriter;
-    this.options = options;
-    this.enableWholeProgramOptimizations =
-        appView != null && appView.enableWholeProgramOptimizations();
-  }
-
-  public AppInfo appInfo() {
-    return appView != null ? appView.appInfo() : appInfo;
   }
 
   public void run(IRCode code) {
@@ -92,7 +76,7 @@
     Iterator<Phi> phiIt = block.getPhis().iterator();
     while (phiIt.hasNext()) {
       Phi phi = phiIt.next();
-      if (phi.isDead(appView, appInfo(), code)) {
+      if (phi.isDead(appView, code)) {
         phiIt.remove();
         for (Value operand : phi.getOperands()) {
           operand.removePhiUser(phi);
@@ -112,11 +96,11 @@
           && !current.outValue().isUsed()) {
         current.setOutValue(null);
       }
-      if (!current.canBeDeadCode(appView, appInfo(), code)) {
+      if (!current.canBeDeadCode(appView, code)) {
         continue;
       }
       Value outValue = current.outValue();
-      if (outValue != null && !outValue.isDead(appView, appInfo(), code)) {
+      if (outValue != null && !outValue.isDead(appView, code)) {
         continue;
       }
       updateWorklist(worklist, current);
@@ -134,7 +118,7 @@
     for (BasicBlock block : code.blocks) {
       if (block.hasCatchHandlers()) {
         if (block.canThrow()) {
-          if (enableWholeProgramOptimizations) {
+          if (appView.enableWholeProgramOptimizations()) {
             Collection<CatchHandler<BasicBlock>> deadCatchHandlers = getDeadCatchHandlers(block);
             if (!deadCatchHandlers.isEmpty()) {
               for (CatchHandler<BasicBlock> catchHandler : deadCatchHandlers) {
@@ -163,7 +147,7 @@
    * Returns the catch handlers of the given block that are dead, if any.
    */
   private Collection<CatchHandler<BasicBlock>> getDeadCatchHandlers(BasicBlock block) {
-    AppInfoWithLiveness appInfoWithLiveness = appInfo().withLiveness();
+    AppInfoWithLiveness appInfoWithLiveness = appView.appInfo().withLiveness();
     ImmutableList.Builder<CatchHandler<BasicBlock>> builder = ImmutableList.builder();
     CatchHandlers<BasicBlock> catchHandlers = block.getCatchHandlers();
     for (int i = 0; i < catchHandlers.size(); ++i) {
@@ -175,7 +159,7 @@
       boolean isSubsumedByPreviousGuard = false;
       for (int j = 0; j < i; ++j) {
         DexType previousGuard = catchHandlers.getGuards().get(j);
-        if (guard.isSubtypeOf(previousGuard, appInfo())) {
+        if (guard.isSubtypeOf(previousGuard, appView)) {
           isSubsumedByPreviousGuard = true;
           break;
         }
@@ -187,8 +171,8 @@
 
       // We can exploit that a catch handler must be dead if its guard is never instantiated
       // directly or indirectly.
-      if (appInfoWithLiveness != null && options.enableUninstantiatedTypeOptimization) {
-        DexClass clazz = appInfo().definitionFor(guard);
+      if (appInfoWithLiveness != null && appView.options().enableUninstantiatedTypeOptimization) {
+        DexClass clazz = appView.definitionFor(guard);
         if (clazz != null
             && clazz.isProgramClass()
             && !appInfoWithLiveness.isInstantiatedDirectlyOrIndirectly(guard)) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java b/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java
index 93c8add..019c3ac 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java
@@ -78,7 +78,7 @@
         invoke.lookupSingleTarget(inliner.appView.appInfo(), invocationContext);
     if ((candidate == null)
         || (candidate.getCode() == null)
-        || inliner.appView.appInfo().definitionFor(candidate.method.getHolder()).isLibraryClass()) {
+        || inliner.appView.definitionFor(candidate.method.getHolder()).isLibraryClass()) {
       if (info != null) {
         info.exclude(invoke, "No inlinee");
       }
@@ -132,7 +132,7 @@
     if (method.method.holder.isSubtypeOf(targetHolder, appView.appInfo())) {
       return true;
     }
-    DexClass clazz = inliner.appView.appInfo().definitionFor(targetHolder);
+    DexClass clazz = inliner.appView.definitionFor(targetHolder);
     assert clazz != null;
     if (target.getOptimizationInfo().triggersClassInitBeforeAnySideEffect()) {
       return true;
@@ -198,7 +198,7 @@
       return false;
     }
 
-    DexClass holder = inliner.appView.appInfo().definitionFor(candidate.method.getHolder());
+    DexClass holder = inliner.appView.definitionFor(candidate.method.getHolder());
 
     if (holder.isInterface()) {
       // Art978_virtual_interfaceTest correctly expects an IncompatibleClassChangeError exception at
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java b/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java
index b045d44..930ac78 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java
@@ -113,7 +113,7 @@
           continue;
         }
         DexType holderType = target.method.getHolder();
-        DexClass holderClass = appView.appInfo().definitionFor(holderType);
+        DexClass holderClass = appView.definitionFor(holderType);
         // Make sure we are not landing on another interface, e.g., interface's default method.
         if (holderClass == null || holderClass.isInterface()) {
           continue;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/EnumOrdinalMapCollector.java b/src/main/java/com/android/tools/r8/ir/optimize/EnumOrdinalMapCollector.java
index 8c8f428..fd387a3 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/EnumOrdinalMapCollector.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/EnumOrdinalMapCollector.java
@@ -37,10 +37,10 @@
 
   private final Map<DexType, Reference2IntMap<DexField>> ordinalsMaps = new IdentityHashMap<>();
 
-  public EnumOrdinalMapCollector(AppView<AppInfoWithLiveness> appView, InternalOptions options) {
+  public EnumOrdinalMapCollector(AppView<? extends AppInfoWithLiveness> appView) {
     this.appInfo = appView.appInfo();
     this.graphLense = appView.graphLense();
-    this.options = options;
+    this.options = appView.options();
   }
 
   public AppInfoWithLiveness run() {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
index aa42b7b..299181e 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
@@ -81,7 +81,7 @@
   public boolean isBlackListed(DexMethod method) {
     return blackList.contains(appView.graphLense().getOriginalMethodSignature(method))
         || appView.appInfo().neverInline.contains(method)
-        || TwrCloseResourceRewriter.isSynthesizedCloseResourceMethod(method, converter);
+        || TwrCloseResourceRewriter.isSynthesizedCloseResourceMethod(method, appView);
   }
 
   private ConstraintWithTarget instructionAllowedForInlining(
@@ -117,7 +117,7 @@
       return false;
     }
     // The class needs also to be visible for us to have access.
-    DexClass targetClass = appView.appInfo().definitionFor(target.method.holder);
+    DexClass targetClass = appView.definitionFor(target.method.holder);
     return isVisibleWithFlags(target.method.holder, method.method.holder, targetClass.accessFlags);
   }
 
@@ -438,7 +438,7 @@
           callerPosition,
           origin);
       if (!target.isProcessed()) {
-        new LensCodeRewriter(appView, options).rewrite(code, target);
+        new LensCodeRewriter(appView).rewrite(code, target);
       }
       return new InlineeWithReason(code, reason);
     }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java b/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java
index 5f2e41c..002461f 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java
@@ -295,7 +295,7 @@
       // be updated outside the class constructor, e.g. via reflections), it is safe
       // to assume that the static-get instruction reads the value it initialized value
       // in class initializer and is never null.
-      DexClass holderDefinition = appView.appInfo().definitionFor(field.getHolder());
+      DexClass holderDefinition = appView.definitionFor(field.getHolder());
       if (holderDefinition != null
           && holderDefinition.accessFlags.isFinal()
           && !field.getHolder().initializationOfParentTypesMayHaveSideEffects(appView.appInfo())) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/SwitchMapCollector.java b/src/main/java/com/android/tools/r8/ir/optimize/SwitchMapCollector.java
index a620ea9..47284cc 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/SwitchMapCollector.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/SwitchMapCollector.java
@@ -70,10 +70,10 @@
 
   private final Map<DexField, Int2ReferenceMap<DexField>> switchMaps = new IdentityHashMap<>();
 
-  public SwitchMapCollector(AppView<AppInfoWithLiveness> appView, InternalOptions options) {
+  public SwitchMapCollector(AppView<? extends AppInfoWithLiveness> appView) {
     this.appInfo = appView.appInfo();
     this.graphLense = appView.graphLense();
-    this.options = options;
+    this.options = appView.options();
     switchMapPrefix = appInfo.dexItemFactory.createString("$SwitchMap$");
     intArrayType = appInfo.dexItemFactory.createType("[I");
   }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/SwitchUtils.java b/src/main/java/com/android/tools/r8/ir/optimize/SwitchUtils.java
index 035f3d1..7331b00 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/SwitchUtils.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/SwitchUtils.java
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.ir.optimize;
 
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexField;
 import com.android.tools.r8.graph.DexItemFactory;
@@ -43,18 +44,22 @@
   /**
    * Looks for a switch statement over the enum companion class of the form
    *
-   * <blockquote><pre>
+   * <blockquote>
+   *
+   * <pre>
    * switch(CompanionClass.$switchmap$field[enumValue.ordinal()]) {
    *   ...
    * }
-   * </pre></blockquote>
+   * </pre>
    *
-   * and extracts the components and the index and ordinal maps. See
-   * {@link EnumOrdinalMapCollector} and
-   * {@link SwitchMapCollector} for details.
+   * </blockquote>
+   *
+   * and extracts the components and the index and ordinal maps. See {@link EnumOrdinalMapCollector}
+   * and {@link SwitchMapCollector} for details.
    */
-  public static EnumSwitchInfo analyzeSwitchOverEnum(Instruction switchInsn,
-      AppInfoWithLiveness appInfo) {
+  public static EnumSwitchInfo analyzeSwitchOverEnum(
+      Instruction switchInsn, AppView<? extends AppInfoWithLiveness> appView) {
+    AppInfoWithLiveness appInfo = appView.appInfo();
     Instruction input = switchInsn.inValues().get(0).definition;
     if (input == null || !input.isArrayGet()) {
       return null;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java b/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java
index ff330e1..4daeb9e 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java
@@ -452,7 +452,7 @@
     if (isAlwaysNull(fieldType)) {
       // Before trying to remove this instruction, we need to be sure that the field actually
       // exists. Otherwise this instruction would throw a NoSuchFieldError exception.
-      DexEncodedField field = appView.appInfo().definitionFor(instruction.getField());
+      DexEncodedField field = appView.definitionFor(instruction.getField());
       if (field == null) {
         return;
       }
@@ -460,7 +460,7 @@
       // We also need to be sure that this field instruction cannot trigger static class
       // initialization.
       if (field.field.clazz != code.method.method.holder) {
-        DexClass enclosingClass = appView.appInfo().definitionFor(code.method.method.holder);
+        DexClass enclosingClass = appView.definitionFor(code.method.method.holder);
         if (enclosingClass == null
             || enclosingClass.classInitializationMayHaveSideEffects(appView.appInfo())) {
           return;
@@ -608,7 +608,7 @@
 
   private boolean isAlwaysNull(DexType type) {
     if (type.isClassType()) {
-      DexClass clazz = appView.appInfo().definitionFor(type);
+      DexClass clazz = appView.definitionFor(type);
       return clazz != null
           && clazz.isProgramClass()
           && !appView.appInfo().isInstantiatedDirectlyOrIndirectly(type);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/UnusedArgumentsCollector.java b/src/main/java/com/android/tools/r8/ir/optimize/UnusedArgumentsCollector.java
index ad5f3be..96bce47 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/UnusedArgumentsCollector.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/UnusedArgumentsCollector.java
@@ -40,7 +40,7 @@
 
 public class UnusedArgumentsCollector {
 
-  private final AppView<AppInfoWithLiveness> appView;
+  private final AppView<? extends AppInfoWithLiveness> appView;
 
   private final BiMap<DexMethod, DexMethod> methodMapping = HashBiMap.create();
   private final Map<DexMethod, RemovedArgumentsInfo> removedArguments = new IdentityHashMap<>();
@@ -81,7 +81,7 @@
     }
   }
 
-  public UnusedArgumentsCollector(AppView<AppInfoWithLiveness> appView) {
+  public UnusedArgumentsCollector(AppView<? extends AppInfoWithLiveness> appView) {
     this.appView = appView;
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/CodeProcessor.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/CodeProcessor.java
index 030cd4f..854ac19 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/CodeProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/CodeProcessor.java
@@ -6,6 +6,7 @@
 
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexField;
 import com.android.tools.r8.graph.DexItemFactory;
@@ -140,7 +141,7 @@
     }
   };
 
-  public final AppInfo appInfo;
+  public final AppView<? extends AppInfo> appView;
   public final DexItemFactory factory;
   public final Kotlin kotlin;
 
@@ -159,14 +160,14 @@
   private InstructionListIterator instructions;
 
   CodeProcessor(
-      AppInfo appInfo,
+      AppView<? extends AppInfo> appView,
       Function<DexType, Strategy> strategyProvider,
       LambdaTypeVisitor lambdaChecker,
-      DexEncodedMethod method, IRCode code) {
-
-    this.appInfo = appInfo;
+      DexEncodedMethod method,
+      IRCode code) {
+    this.appView = appView;
     this.strategyProvider = strategyProvider;
-    this.factory = appInfo.dexItemFactory;
+    this.factory = appView.dexItemFactory();
     this.kotlin = factory.kotlin;
     this.lambdaChecker = lambdaChecker;
     this.method = method;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaGroup.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaGroup.java
index f3fecde..b0af387 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaGroup.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaGroup.java
@@ -7,6 +7,7 @@
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppInfo;
 import com.android.tools.r8.graph.AppInfoWithSubtyping;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexEncodedField;
 import com.android.tools.r8.graph.DexItemFactory;
@@ -89,11 +90,11 @@
     return false;
   }
 
-  final boolean shouldAddToMainDex(AppInfo appInfo) {
+  final boolean shouldAddToMainDex(AppView<? extends AppInfo> appView) {
     // We add the group class to main index if any of the
     // lambda classes it replaces is added to main index.
     for (DexType type : lambdas.keySet()) {
-      if (appInfo.isInMainDexList(type)) {
+      if (appView.appInfo().isInMainDexList(type)) {
         return true;
       }
     }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java
index 586297d..3538e8c 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java
@@ -8,6 +8,7 @@
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppInfo;
 import com.android.tools.r8.graph.AppInfoWithSubtyping;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexApplication;
 import com.android.tools.r8.graph.DexApplication.Builder;
 import com.android.tools.r8.graph.DexClass;
@@ -100,7 +101,7 @@
   // should not be happening very frequently and we ignore possible overhead.
   private final Set<DexEncodedMethod> methodsToReprocess = Sets.newIdentityHashSet();
 
-  private final AppInfo appInfo;
+  private final AppView<? extends AppInfo> appView;
   private final DexItemFactory factory;
   private final Kotlin kotlin;
   private final DiagnosticsHandler reporter;
@@ -112,11 +113,11 @@
   // Lambda visitor throwing Unreachable on each lambdas it sees.
   private final LambdaTypeVisitor lambdaChecker;
 
-  public LambdaMerger(AppInfo appInfo, DiagnosticsHandler reporter) {
-    this.appInfo = appInfo;
-    this.factory = appInfo.dexItemFactory;
+  public LambdaMerger(AppView<? extends AppInfo> appView) {
+    this.appView = appView;
+    this.factory = appView.dexItemFactory();
     this.kotlin = factory.kotlin;
-    this.reporter = reporter;
+    this.reporter = appView.options().reporter;
 
     this.lambdaInvalidator = new LambdaTypeVisitor(factory, this::isMergeableLambda,
         this::invalidateLambda);
@@ -206,13 +207,14 @@
     analyzeReferencesInProgramClasses(app, executorService);
 
     // Analyse more complex aspects of lambda classes including method code.
-    assert converter.appInfo().hasSubtyping();
-    AppInfoWithSubtyping appInfo = converter.appInfo().withSubtyping();
-    analyzeLambdaClassesStructure(appInfo, executorService);
+    assert appView.appInfo().hasSubtyping();
+    AppInfoWithSubtyping appInfoWithSubtyping = appView.appInfo().withSubtyping();
+    analyzeLambdaClassesStructure(appInfoWithSubtyping, executorService);
 
     // Remove invalidated lambdas, compact groups to ensure
     // sequential lambda ids, create group lambda classes.
-    Map<LambdaGroup, DexProgramClass> lambdaGroupsClasses = finalizeLambdaGroups(appInfo);
+    Map<LambdaGroup, DexProgramClass> lambdaGroupsClasses =
+        finalizeLambdaGroups(appInfoWithSubtyping);
 
     // Switch to APPLY strategy.
     this.strategyFactory = ApplyStrategy::new;
@@ -221,9 +223,8 @@
 
     for (Entry<LambdaGroup, DexProgramClass> entry : lambdaGroupsClasses.entrySet()) {
       DexProgramClass synthesizedClass = entry.getValue();
-      converter.appInfo().addSynthesizedClass(synthesizedClass);
-      builder.addSynthesizedClass(
-          synthesizedClass, entry.getKey().shouldAddToMainDex(converter.appInfo()));
+      appView.appInfo().addSynthesizedClass(synthesizedClass);
+      builder.addSynthesizedClass(synthesizedClass, entry.getKey().shouldAddToMainDex(appView));
       // Eventually, we need to process synthesized methods in the lambda group.
       // Otherwise, abstract SynthesizedCode will be flown to Enqueuer.
       // But that process should not see the holder. Otherwise, lambda calls in the main dispatch
@@ -323,7 +324,7 @@
     }
     Set<DexEncodedMethod> methods =
         methodsToReprocess.stream()
-            .map(method -> converter.graphLense().mapDexEncodedMethod(method, converter.appInfo()))
+            .map(method -> converter.graphLense().mapDexEncodedMethod(method, appView.appInfo()))
             .collect(Collectors.toSet());
     List<Future<?>> futures = new ArrayList<>();
     for (DexEncodedMethod method : methods) {
@@ -379,8 +380,12 @@
 
   private final class AnalysisStrategy extends CodeProcessor {
     private AnalysisStrategy(DexEncodedMethod method, IRCode code) {
-      super(LambdaMerger.this.appInfo,
-          LambdaMerger.this::strategyProvider, lambdaInvalidator, method, code);
+      super(
+          LambdaMerger.this.appView,
+          LambdaMerger.this::strategyProvider,
+          lambdaInvalidator,
+          method,
+          code);
     }
 
     @Override
@@ -416,8 +421,12 @@
 
   private final class ApplyStrategy extends CodeProcessor {
     private ApplyStrategy(DexEncodedMethod method, IRCode code) {
-      super(LambdaMerger.this.appInfo,
-          LambdaMerger.this::strategyProvider, lambdaChecker, method, code);
+      super(
+          LambdaMerger.this.appView,
+          LambdaMerger.this::strategyProvider,
+          lambdaChecker,
+          method,
+          code);
     }
 
     @Override
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupCodeStrategy.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupCodeStrategy.java
index 71fbf44..144487b 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupCodeStrategy.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupCodeStrategy.java
@@ -115,11 +115,12 @@
 
   @Override
   public void patch(CodeProcessor context, NewInstance newInstance) {
-    NewInstance patchedNewInstance = new NewInstance(
-        group.getGroupClassType(),
-        context.code.createValue(
-            TypeLatticeElement.fromDexType(
-                newInstance.clazz, definitelyNotNull(), context.appInfo)));
+    NewInstance patchedNewInstance =
+        new NewInstance(
+            group.getGroupClassType(),
+            context.code.createValue(
+                TypeLatticeElement.fromDexType(
+                    newInstance.clazz, definitelyNotNull(), context.appView.appInfo())));
     context.instructions().replaceCurrentInstruction(patchedNewInstance);
   }
 
@@ -166,7 +167,7 @@
     // Since all captured values of non-primitive types are stored in fields of type
     // java.lang.Object, we need to cast them to appropriate type to satisfy the verifier.
     TypeLatticeElement castTypeLattice =
-        TypeLatticeElement.fromDexType(fieldType, definitelyNotNull(), context.appInfo);
+        TypeLatticeElement.fromDexType(fieldType, definitelyNotNull(), context.appView.appInfo());
     Value newValue = context.code.createValue(castTypeLattice, newInstanceGet.getLocalInfo());
     newInstanceGet.outValue().replaceUsers(newValue);
     CheckCast cast = new CheckCast(newValue, newInstanceGet.outValue(), fieldType);
@@ -189,11 +190,14 @@
 
   @Override
   public void patch(CodeProcessor context, StaticGet staticGet) {
-    context.instructions().replaceCurrentInstruction(
-        new StaticGet(
-            context.code.createValue(
-                TypeLatticeElement.fromDexType(staticGet.getField().type, maybeNull(), context.appInfo)),
-            mapSingletonInstanceField(context.factory, staticGet.getField())));
+    context
+        .instructions()
+        .replaceCurrentInstruction(
+            new StaticGet(
+                context.code.createValue(
+                    TypeLatticeElement.fromDexType(
+                        staticGet.getField().type, maybeNull(), context.appView.appInfo())),
+                mapSingletonInstanceField(context.factory, staticGet.getField())));
   }
 
   private void patchInitializer(CodeProcessor context, InvokeDirect invoke) {
@@ -225,9 +229,10 @@
   }
 
   private Value createValueForType(CodeProcessor context, DexType returnType) {
-    return returnType == context.factory.voidType ? null :
-        context.code.createValue(
-            TypeLatticeElement.fromDexType(returnType, maybeNull(), context.appInfo));
+    return returnType == context.factory.voidType
+        ? null
+        : context.code.createValue(
+            TypeLatticeElement.fromDexType(returnType, maybeNull(), context.appView.appInfo()));
   }
 
   private List<Value> mapInitializerArgs(
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java
index 443a2f4..d69190f 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java
@@ -4,6 +4,8 @@
 
 package com.android.tools.r8.ir.optimize.staticizer;
 
+import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexApplication;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexEncodedField;
@@ -43,7 +45,8 @@
 import java.util.function.BiConsumer;
 
 public final class ClassStaticizer {
-  final AppInfoWithLiveness appInfo;
+
+  final AppView<? extends AppInfoWithLiveness> appView;
   final DexItemFactory factory;
   final IRConverter converter;
 
@@ -86,7 +89,7 @@
     }
 
     DexClass hostClass() {
-      DexClass hostClass = appInfo.definitionFor(hostType());
+      DexClass hostClass = appView.definitionFor(hostType());
       assert hostClass != null;
       return hostClass;
     }
@@ -100,9 +103,9 @@
   // The map storing all the potential candidates for staticizing.
   final ConcurrentHashMap<DexType, CandidateInfo> candidates = new ConcurrentHashMap<>();
 
-  public ClassStaticizer(AppInfoWithLiveness appInfo, IRConverter converter) {
-    this.appInfo = appInfo;
-    this.factory = appInfo.dexItemFactory;
+  public ClassStaticizer(AppView<? extends AppInfoWithLiveness> appView, IRConverter converter) {
+    this.appView = appView;
+    this.factory = appView.dexItemFactory();
     this.converter = converter;
   }
 
@@ -178,6 +181,7 @@
   }
 
   private boolean isPinned(DexClass clazz, DexEncodedField singletonField) {
+    AppInfoWithLiveness appInfo = appView.appInfo();
     if (appInfo.isPinned(clazz.type) || appInfo.isPinned(singletonField.field)) {
       return true;
     }
@@ -423,7 +427,8 @@
 
     // Check constructor.
     InvokeDirect invoke = instruction.asInvokeDirect();
-    DexEncodedMethod methodInvoked = appInfo.lookupDirectTarget(invoke.getInvokedMethod());
+    DexEncodedMethod methodInvoked =
+        appView.appInfo().lookupDirectTarget(invoke.getInvokedMethod());
     List<Value> values = invoke.inValues();
 
     if (values.lastIndexOf(candidateValue) != 0 ||
@@ -450,7 +455,7 @@
     // Allow single assignment to a singleton field.
     StaticPut staticPut = instruction.asStaticPut();
     DexEncodedField fieldAccessed =
-        appInfo.lookupStaticTarget(staticPut.getField().clazz, staticPut.getField());
+        appView.appInfo().lookupStaticTarget(staticPut.getField().clazz, staticPut.getField());
     return fieldAccessed == info.singletonField;
   }
 
@@ -465,7 +470,7 @@
       return null;
     }
 
-    assert candidateInfo.singletonField == appInfo.lookupStaticTarget(field.clazz, field)
+    assert candidateInfo.singletonField == appView.appInfo().lookupStaticTarget(field.clazz, field)
         : "Added reference after collectCandidates(...)?";
 
     Value singletonValue = staticGet.dest();
@@ -499,6 +504,7 @@
           }
           return candidateInfo.invalidate();
         }
+        AppInfo appInfo = appView.appInfo();
         DexEncodedMethod methodInvoked = user.isInvokeDirect()
             ? appInfo.lookupDirectTarget(methodReferenced)
             : appInfo.lookupVirtualTarget(methodReferenced.holder, methodReferenced);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
index 0fd8cc4..7106005 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
@@ -413,11 +413,9 @@
               new StaticGet(
                   code.createValue(
                       TypeLatticeElement.fromDexType(
-                          field.type, maybeNull(), classStaticizer.appInfo),
+                          field.type, maybeNull(), classStaticizer.appView.appInfo()),
                       outValue.getLocalInfo()),
-                  field
-              )
-          );
+                  field));
         }
         continue;
       }
@@ -438,11 +436,13 @@
         if (hostType != null) {
           DexMethod newMethod = factory().createMethod(hostType, method.proto, method.name);
           Value outValue = invoke.outValue();
-          Value newOutValue = method.proto.returnType.isVoidType() ? null
-              : code.createValue(
-                  TypeLatticeElement.fromDexType(
-                      method.proto.returnType, maybeNull(), classStaticizer.appInfo),
-                  outValue == null ? null : outValue.getLocalInfo());
+          Value newOutValue =
+              method.proto.returnType.isVoidType()
+                  ? null
+                  : code.createValue(
+                      TypeLatticeElement.fromDexType(
+                          method.proto.returnType, maybeNull(), classStaticizer.appView.appInfo()),
+                      outValue == null ? null : outValue.getLocalInfo());
           it.replaceCurrentInstruction(
               new InvokeStatic(newMethod, newOutValue, invoke.inValues()));
         }
@@ -490,7 +490,7 @@
       // Consider moving static members from candidate into host.
       DexType hostType = candidate.hostType();
       if (candidateClass.type != hostType) {
-        DexClass hostClass = classStaticizer.appInfo.definitionFor(hostType);
+        DexClass hostClass = classStaticizer.appView.definitionFor(hostType);
         assert hostClass != null;
         if (!classMembersConflict(candidateClass, hostClass)) {
           // Move all members of the candidate class into host class.
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/string/StringOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/string/StringOptimizer.java
index f18d26d..942265e 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/string/StringOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/string/StringOptimizer.java
@@ -12,6 +12,7 @@
 import static com.android.tools.r8.utils.DescriptorUtils.INNER_CLASS_SEPARATOR;
 
 import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexItemFactory;
@@ -33,7 +34,6 @@
 import com.android.tools.r8.ir.code.Value;
 import com.android.tools.r8.ir.optimize.ReflectionOptimizer.ClassNameComputationInfo;
 import com.android.tools.r8.shaking.RootSetBuilder.RootSet;
-import com.android.tools.r8.utils.InternalOutputMode;
 import com.google.common.annotations.VisibleForTesting;
 import java.util.Set;
 import java.util.function.BiFunction;
@@ -41,15 +41,14 @@
 
 public class StringOptimizer {
 
-  private final AppInfo appInfo;
+  private final AppView<? extends AppInfo> appView;
   private final DexItemFactory factory;
   private final ThrowingInfo throwingInfo;
 
-  public StringOptimizer(AppInfo appInfo, InternalOutputMode outputMode) {
-    this.appInfo = appInfo;
-    this.factory = appInfo.dexItemFactory;
-    this.throwingInfo =
-        outputMode.isGeneratingClassFiles() ? ThrowingInfo.NO_THROW : ThrowingInfo.CAN_THROW;
+  public StringOptimizer(AppView<? extends AppInfo> appView) {
+    this.appView = appView;
+    this.factory = appView.dexItemFactory();
+    this.throwingInfo = ThrowingInfo.defaultForConstString(appView.options());
   }
 
   // int String#length()
@@ -83,7 +82,7 @@
         continue;
       }
       DexMethod invokedMethod = invoke.getInvokedMethod();
-      if (invokedMethod.name == appInfo.dexItemFactory.substringName) {
+      if (invokedMethod.name == factory.substringName) {
         assert invoke.inValues().size() == 2 || invoke.inValues().size() == 3;
         Value rcv = invoke.getReceiver().getAliasedValue();
         if (rcv.definition == null
@@ -121,7 +120,7 @@
         String sub = rcvString.substring(beginIndexValue, endIndexValue);
         Value stringValue =
             code.createValue(
-                TypeLatticeElement.stringClassType(appInfo, definitelyNotNull()),
+                TypeLatticeElement.stringClassType(appView.appInfo(), definitelyNotNull()),
                 invoke.getLocalInfo());
         it.replaceCurrentInstruction(
             new ConstString(stringValue, factory.createString(sub), throwingInfo));
@@ -234,7 +233,8 @@
       // case, the result of this optimization can lead to a regression if the corresponding class
       // is in a deep package hierarchy.
       if (!code.options.testing.forceNameReflectionOptimization
-          && !hasPotentialReadOutside(appInfo, code.method, EscapeAnalysis.escape(code, out))) {
+          && !hasPotentialReadOutside(
+              appView.appInfo(), code.method, EscapeAnalysis.escape(code, out))) {
         continue;
       }
 
@@ -265,7 +265,7 @@
       if (!baseType.isClassType()) {
         continue;
       }
-      DexClass holder = appInfo.definitionFor(baseType);
+      DexClass holder = appView.definitionFor(baseType);
       if (holder == null) {
         continue;
       }
@@ -335,7 +335,7 @@
       if (name != null) {
         Value stringValue =
             code.createValue(
-                TypeLatticeElement.stringClassType(appInfo, definitelyNotNull()),
+                TypeLatticeElement.stringClassType(appView.appInfo(), definitelyNotNull()),
                 invoke.getLocalInfo());
         ConstString constString = new ConstString(stringValue, name, throwingInfo);
         it.replaceCurrentInstruction(constString);
@@ -401,7 +401,7 @@
         if (inType.isNullType()) {
           Value nullStringValue =
               code.createValue(
-                  TypeLatticeElement.stringClassType(appInfo, definitelyNotNull()),
+                  TypeLatticeElement.stringClassType(appView.appInfo(), definitelyNotNull()),
                   invoke.getLocalInfo());
           ConstString nullString =
               new ConstString(nullStringValue, factory.createString("null"), throwingInfo);
diff --git a/src/main/java/com/android/tools/r8/naming/ApplyMappingError.java b/src/main/java/com/android/tools/r8/naming/ApplyMappingError.java
new file mode 100644
index 0000000..597dfbc
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/naming/ApplyMappingError.java
@@ -0,0 +1,43 @@
+// Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.naming;
+
+import com.android.tools.r8.errors.CompilationError;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.position.Position;
+
+public class ApplyMappingError extends CompilationError {
+
+  private static final String EXISTING_MESSAGE_START =
+      "'%s' cannot be mapped to '%s' because it is in conflict with an existing ";
+  private static final String EXISTING_MESSAGE_END =
+      ". This usually happens when compiling a test application against a source application and "
+          + "having short generic names in the test application. Try giving '%s' a more specific "
+          + "name or add a keep rule to keep '%s'.";
+
+  protected static final String EXISTING_CLASS_MESSAGE =
+      EXISTING_MESSAGE_START + "class with the same name" + EXISTING_MESSAGE_END;
+  protected static final String EXISTING_MEMBER_MESSAGE =
+      EXISTING_MESSAGE_START + "member with the same signature" + EXISTING_MESSAGE_END;
+
+  private ApplyMappingError(String message, Position position) {
+    super(message, null, Origin.unknown(), position);
+  }
+
+  static ApplyMappingError mapToExistingClass(
+      String originalName, String renamedName, Position position) {
+    return new ApplyMappingError(
+        String.format(EXISTING_CLASS_MESSAGE, originalName, renamedName, renamedName, originalName),
+        position);
+  }
+
+  static ApplyMappingError mapToExistingMember(
+      String originalName, String renamedName, Position position) {
+    return new ApplyMappingError(
+        String.format(
+            EXISTING_MEMBER_MESSAGE, originalName, renamedName, renamedName, originalName),
+        position);
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/naming/ClassNameMapper.java b/src/main/java/com/android/tools/r8/naming/ClassNameMapper.java
index bcc0af3..1e7094d 100644
--- a/src/main/java/com/android/tools/r8/naming/ClassNameMapper.java
+++ b/src/main/java/com/android/tools/r8/naming/ClassNameMapper.java
@@ -13,6 +13,7 @@
 import com.android.tools.r8.naming.MemberNaming.FieldSignature;
 import com.android.tools.r8.naming.MemberNaming.MethodSignature;
 import com.android.tools.r8.naming.MemberNaming.Signature;
+import com.android.tools.r8.position.Position;
 import com.android.tools.r8.utils.BiMapContainer;
 import com.google.common.collect.BiMap;
 import com.google.common.collect.ImmutableBiMap;
@@ -32,7 +33,6 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.function.Consumer;
 
 public class ClassNameMapper implements ProguardMap {
 
@@ -50,7 +50,7 @@
 
     @Override
     public ClassNamingForNameMapper.Builder classNamingBuilder(
-        String renamedName, String originalName) {
+        String renamedName, String originalName, Position position) {
       ClassNamingForNameMapper.Builder classNamingBuilder =
           ClassNamingForNameMapper.builder(renamedName, originalName);
       mapBuilder.put(renamedName, classNamingBuilder);
@@ -181,10 +181,6 @@
     }
   }
 
-  public void forAllClassNamings(Consumer<ClassNaming> consumer) {
-    classNameMappings.values().forEach(consumer);
-  }
-
   @Override
   public String toString() {
     try {
diff --git a/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java b/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
index 92c07d1..c073bb5 100644
--- a/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
@@ -39,7 +39,7 @@
 
 class ClassNameMinifier {
 
-  private final AppView<AppInfoWithLiveness> appView;
+  private final AppView<? extends AppInfoWithLiveness> appView;
   private final AppInfoWithLiveness appInfo;
   private final ClassNamingStrategy classNamingStrategy;
   private final PackageNamingStrategy packageNamingStrategy;
@@ -62,7 +62,7 @@
   private final Namespace topLevelState;
 
   ClassNameMinifier(
-      AppView<AppInfoWithLiveness> appView,
+      AppView<? extends AppInfoWithLiveness> appView,
       RootSet rootSet,
       ClassNamingStrategy classNamingStrategy,
       PackageNamingStrategy packageNamingStrategy,
diff --git a/src/main/java/com/android/tools/r8/naming/ClassNamingForMapApplier.java b/src/main/java/com/android/tools/r8/naming/ClassNamingForMapApplier.java
index ba7963b..4c24731 100644
--- a/src/main/java/com/android/tools/r8/naming/ClassNamingForMapApplier.java
+++ b/src/main/java/com/android/tools/r8/naming/ClassNamingForMapApplier.java
@@ -10,6 +10,8 @@
 import com.android.tools.r8.naming.MemberNaming.MethodSignature;
 import com.android.tools.r8.naming.MemberNaming.Signature;
 import com.android.tools.r8.naming.MemberNaming.Signature.SignatureKind;
+import com.android.tools.r8.position.Position;
+import com.android.tools.r8.utils.Reporter;
 import com.android.tools.r8.utils.ThrowingConsumer;
 import com.google.common.collect.ImmutableMap;
 import java.util.Arrays;
@@ -32,12 +34,16 @@
   public static class Builder extends ClassNaming.Builder {
     private final String originalName;
     private final String renamedName;
+    private final Position position;
+    private final Reporter reporter;
     private final Map<MethodSignature, MemberNaming> methodMembers = new HashMap<>();
     private final Map<FieldSignature, MemberNaming> fieldMembers = new HashMap<>();
 
-    private Builder(String renamedName, String originalName) {
+    private Builder(String renamedName, String originalName, Position position, Reporter reporter) {
       this.originalName = originalName;
       this.renamedName = renamedName;
+      this.position = position;
+      this.reporter = reporter;
     }
 
     @Override
@@ -45,16 +51,27 @@
       // Unlike {@link ClassNamingForNameMapper.Builder#addMemberEntry},
       // the key is original signature.
       if (entry.isMethodNaming()) {
-        methodMembers.put((MethodSignature) entry.getOriginalSignature(), entry);
+        MethodSignature signature = (MethodSignature) entry.getOriginalSignature();
+        if (methodMembers.put(signature, entry) != null) {
+          reporter.error(
+              ProguardMapError.duplicateSourceMember(
+                  signature.toString(), this.originalName, entry.position));
+        }
       } else {
-        fieldMembers.put((FieldSignature) entry.getOriginalSignature(), entry);
+        FieldSignature signature = (FieldSignature) entry.getOriginalSignature();
+        if (fieldMembers.put(signature, entry) != null) {
+          reporter.error(
+              ProguardMapError.duplicateSourceMember(
+                  signature.toString(), this.originalName, entry.position));
+        }
       }
       return this;
     }
 
     @Override
     public ClassNamingForMapApplier build() {
-      return new ClassNamingForMapApplier(renamedName, originalName, methodMembers, fieldMembers);
+      return new ClassNamingForMapApplier(
+          renamedName, originalName, position, methodMembers, fieldMembers);
     }
 
     @Override
@@ -66,28 +83,37 @@
         String obfuscatedName) {}
   }
 
-  static Builder builder(String renamedName, String originalName) {
-    return new Builder(renamedName, originalName);
+  static Builder builder(
+      String renamedName, String originalName, Position position, Reporter reporter) {
+    return new Builder(renamedName, originalName, position, reporter);
   }
 
   private final String originalName;
   final String renamedName;
+  final Position position;
 
   private final ImmutableMap<MethodSignature, MemberNaming> methodMembers;
   private final ImmutableMap<FieldSignature, MemberNaming> fieldMembers;
 
   // Constructor to help chaining {@link ClassNamingForMapApplier} according to class hierarchy.
   ClassNamingForMapApplier(ClassNamingForMapApplier proxy) {
-    this(proxy.renamedName, proxy.originalName, proxy.methodMembers, proxy.fieldMembers);
+    this(
+        proxy.renamedName,
+        proxy.originalName,
+        proxy.position,
+        proxy.methodMembers,
+        proxy.fieldMembers);
   }
 
   private ClassNamingForMapApplier(
       String renamedName,
       String originalName,
+      Position position,
       Map<MethodSignature, MemberNaming> methodMembers,
       Map<FieldSignature, MemberNaming> fieldMembers) {
     this.renamedName = renamedName;
     this.originalName = originalName;
+    this.position = position;
     this.methodMembers = ImmutableMap.copyOf(methodMembers);
     this.fieldMembers = ImmutableMap.copyOf(fieldMembers);
   }
diff --git a/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java b/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
index 1247b90..577da26 100644
--- a/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
@@ -20,7 +20,9 @@
 class FieldNameMinifier extends MemberNameMinifier<DexField, DexType> {
 
   FieldNameMinifier(
-      AppView<AppInfoWithLiveness> appView, RootSet rootSet, MemberNamingStrategy strategy) {
+      AppView<? extends AppInfoWithLiveness> appView,
+      RootSet rootSet,
+      MemberNamingStrategy strategy) {
     super(appView, rootSet, strategy);
   }
 
diff --git a/src/main/java/com/android/tools/r8/naming/MemberNameMinifier.java b/src/main/java/com/android/tools/r8/naming/MemberNameMinifier.java
index 6f6b64b..42e3f76 100644
--- a/src/main/java/com/android/tools/r8/naming/MemberNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/MemberNameMinifier.java
@@ -22,7 +22,7 @@
 
 abstract class MemberNameMinifier<MemberType, StateType extends CachedHashValueDexItem> {
 
-  protected final AppView<AppInfoWithLiveness> appView;
+  protected final AppView<? extends AppInfoWithLiveness> appView;
   protected final AppInfoWithLiveness appInfo;
   protected final RootSet rootSet;
   protected final InternalOptions options;
@@ -41,7 +41,9 @@
   private final BiMap<DexType, NamingState<StateType, ?>> states = HashBiMap.create();
 
   MemberNameMinifier(
-      AppView<AppInfoWithLiveness> appView, RootSet rootSet, MemberNamingStrategy strategy) {
+      AppView<? extends AppInfoWithLiveness> appView,
+      RootSet rootSet,
+      MemberNamingStrategy strategy) {
     this.appView = appView;
     this.appInfo = appView.appInfo();
     this.rootSet = rootSet;
@@ -104,5 +106,7 @@
     DexString next(DexReference source, InternalState internalState);
 
     boolean bypassDictionary();
+
+    boolean breakOnNotAvailable(DexReference source, DexString name);
   }
 }
diff --git a/src/main/java/com/android/tools/r8/naming/MemberNaming.java b/src/main/java/com/android/tools/r8/naming/MemberNaming.java
index db57862..e8ea970 100644
--- a/src/main/java/com/android/tools/r8/naming/MemberNaming.java
+++ b/src/main/java/com/android/tools/r8/naming/MemberNaming.java
@@ -12,6 +12,7 @@
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.naming.MemberNaming.Signature.SignatureKind;
+import com.android.tools.r8.position.Position;
 import com.android.tools.r8.utils.DescriptorUtils;
 import java.io.IOException;
 import java.io.StringWriter;
@@ -47,18 +48,21 @@
     return result;
   }
 
-  /**
-   * Original signature of the member
-   */
+  /** Original signature of the member. */
   final Signature signature;
-  /**
-   * Renamed signature where the name (but not the types) have been renamed.
-   */
+  /** Renamed signature where the name (but not the types) have been renamed. */
   final Signature renamedSignature;
+  /** Position of the member in the file. */
+  final Position position;
 
   public MemberNaming(Signature signature, String renamedName) {
+    this(signature, renamedName, Position.UNKNOWN);
+  }
+
+  public MemberNaming(Signature signature, String renamedName, Position position) {
     this.signature = signature;
     this.renamedSignature = signature.asRenamed(renamedName);
+    this.position = position;
   }
 
   public Signature getOriginalSignature() {
@@ -81,6 +85,10 @@
     return signature.kind() == SignatureKind.METHOD;
   }
 
+  public Position getPosition() {
+    return position;
+  }
+
   @Override
   public String toString() {
     return signature.toString() + " -> " + renamedSignature.name;
diff --git a/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java b/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
index e9932e1..50b22b0 100644
--- a/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
@@ -94,7 +94,9 @@
   private final MemberNamingStrategy strategy;
 
   MethodNameMinifier(
-      AppView<AppInfoWithLiveness> appView, RootSet rootSet, MemberNamingStrategy strategy) {
+      AppView<? extends AppInfoWithLiveness> appView,
+      RootSet rootSet,
+      MemberNamingStrategy strategy) {
     super(appView, rootSet, strategy);
     this.strategy = strategy;
     equivalence =
diff --git a/src/main/java/com/android/tools/r8/naming/Minifier.java b/src/main/java/com/android/tools/r8/naming/Minifier.java
index 9aa8502..96b174e 100644
--- a/src/main/java/com/android/tools/r8/naming/Minifier.java
+++ b/src/main/java/com/android/tools/r8/naming/Minifier.java
@@ -28,14 +28,14 @@
 
 public class Minifier {
 
-  private final AppView<AppInfoWithLiveness> appView;
+  private final AppView<? extends AppInfoWithLiveness> appView;
   private final AppInfoWithLiveness appInfo;
   private final RootSet rootSet;
   private final Set<DexCallSite> desugaredCallSites;
   private final InternalOptions options;
 
   public Minifier(
-      AppView<AppInfoWithLiveness> appView,
+      AppView<? extends AppInfoWithLiveness> appView,
       RootSet rootSet,
       Set<DexCallSite> desugaredCallSites) {
     this.appView = appView;
@@ -156,5 +156,10 @@
     public boolean bypassDictionary() {
       return false;
     }
+
+    @Override
+    public boolean breakOnNotAvailable(DexReference source, DexString name) {
+      return false;
+    }
   }
 }
diff --git a/src/main/java/com/android/tools/r8/naming/NamingState.java b/src/main/java/com/android/tools/r8/naming/NamingState.java
index a3352ad..c44c70d 100644
--- a/src/main/java/com/android/tools/r8/naming/NamingState.java
+++ b/src/main/java/com/android/tools/r8/naming/NamingState.java
@@ -234,7 +234,7 @@
       }
       do {
         name = nextSuggestedName(source);
-      } while (!isAvailable(name));
+      } while (!isAvailable(name) && !strategy.breakOnNotAvailable(source, name));
       if (markAsUsed) {
         addRenaming(original, proto, name);
       }
diff --git a/src/main/java/com/android/tools/r8/naming/ProguardMap.java b/src/main/java/com/android/tools/r8/naming/ProguardMap.java
index 5b5c76e..221f064 100644
--- a/src/main/java/com/android/tools/r8/naming/ProguardMap.java
+++ b/src/main/java/com/android/tools/r8/naming/ProguardMap.java
@@ -4,11 +4,14 @@
 package com.android.tools.r8.naming;
 
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.position.Position;
 
 public interface ProguardMap {
 
   abstract class Builder {
-    abstract ClassNaming.Builder classNamingBuilder(String renamedName, String originalName);
+    abstract ClassNaming.Builder classNamingBuilder(
+        String renamedName, String originalName, Position position);
+
     abstract ProguardMap build();
   }
 
diff --git a/src/main/java/com/android/tools/r8/naming/ProguardMapApplier.java b/src/main/java/com/android/tools/r8/naming/ProguardMapApplier.java
index a447e37..f8b690b 100644
--- a/src/main/java/com/android/tools/r8/naming/ProguardMapApplier.java
+++ b/src/main/java/com/android/tools/r8/naming/ProguardMapApplier.java
@@ -37,7 +37,7 @@
   private final GraphLense previousLense;
   private final SeedMapper seedMapper;
 
-  public ProguardMapApplier(AppView<AppInfoWithLiveness> appView, SeedMapper seedMapper) {
+  public ProguardMapApplier(AppView<? extends AppInfoWithLiveness> appView, SeedMapper seedMapper) {
     assert appView.graphLense().isContextFreeForMethods();
     this.appInfo = appView.appInfo();
     this.previousLense = appView.graphLense();
diff --git a/src/main/java/com/android/tools/r8/naming/ProguardMapError.java b/src/main/java/com/android/tools/r8/naming/ProguardMapError.java
index 684c79b..cb06a96 100644
--- a/src/main/java/com/android/tools/r8/naming/ProguardMapError.java
+++ b/src/main/java/com/android/tools/r8/naming/ProguardMapError.java
@@ -7,16 +7,47 @@
 import com.android.tools.r8.graph.DexField;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.naming.MemberNaming.Signature;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.position.Position;
 
 public class ProguardMapError extends CompilationError {
+
+  protected static final String DUPLICATE_TARGET_MESSAGE = "'%s' and '%s' map to same name: '%s'";
+  protected static final String DUPLICATE_SOURCE_MESSAGE = "'%s' already has a mapping";
+
   private ProguardMapError(String message) {
     super(message);
   }
 
-  private ProguardMapError(String message, Throwable cause) {
-    super(message, cause);
+  private ProguardMapError(String message, Position position) {
+    super(message, null, Origin.unknown(), position);
   }
 
+  static ProguardMapError duplicateSourceClass(String typeName, Position position) {
+    return new ProguardMapError(String.format(DUPLICATE_SOURCE_MESSAGE, typeName), position);
+  }
+
+  static ProguardMapError duplicateSourceMember(
+      String signature, String typeName, Position position) {
+    return new ProguardMapError(
+        String.format(DUPLICATE_SOURCE_MESSAGE, signature, typeName), position);
+  }
+
+  static ProguardMapError duplicateTargetClass(
+      String source, String other, String mappedName, Position position) {
+    return new ProguardMapError(
+        String.format(DUPLICATE_TARGET_MESSAGE, source, other, mappedName), position);
+  }
+
+  static ProguardMapError duplicateTargetSignature(
+      Signature source, Signature other, String mappedName, Position position) {
+    return new ProguardMapError(
+        String.format(DUPLICATE_TARGET_MESSAGE, source.toString(), other.toString(), mappedName),
+        position);
+  }
+
+  // TODO(mkroghj) Remove these and when the ProguardMapApplier is removed.
   static ProguardMapError keptTypeWasRenamed(DexType type, String keptName, String rename) {
     return new ProguardMapError(
         type + createMessageForConflict(keptName, rename));
diff --git a/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java b/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java
index 42a574d..227a0b4 100644
--- a/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java
@@ -24,8 +24,10 @@
 import com.android.tools.r8.naming.MethodNameMinifier.MethodRenaming;
 import com.android.tools.r8.naming.Minifier.MinificationPackageNamingStrategy;
 import com.android.tools.r8.naming.NamingState.InternalState;
+import com.android.tools.r8.position.Position;
 import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 import com.android.tools.r8.shaking.RootSetBuilder.RootSet;
+import com.android.tools.r8.utils.Reporter;
 import com.android.tools.r8.utils.Timing;
 import java.util.ArrayList;
 import java.util.IdentityHashMap;
@@ -35,7 +37,7 @@
 
 public class ProguardMapMinifier {
 
-  private final AppView<AppInfoWithLiveness> appView;
+  private final AppView<? extends AppInfoWithLiveness> appView;
   private final AppInfoWithLiveness appInfo;
   private final RootSet rootSet;
   private final SeedMapper seedMapper;
@@ -43,7 +45,7 @@
   private final DexItemFactory factory;
 
   public ProguardMapMinifier(
-      AppView<AppInfoWithLiveness> appView,
+      AppView<? extends AppInfoWithLiveness> appView,
       RootSet rootSet,
       SeedMapper seedMapper,
       Set<DexCallSite> desugaredCallSites) {
@@ -64,8 +66,9 @@
 
     Map<DexType, DexString> mappedNames = new IdentityHashMap<>();
     List<DexClass> mappedClasses = new ArrayList<>();
-    Map<DexReference, DexString> memberNames = new IdentityHashMap<>();
+    Map<DexReference, MemberNaming> memberNames = new IdentityHashMap<>();
     for (String key : seedMapper.getKeyset()) {
+      ClassNamingForMapApplier classNaming = seedMapper.getMapping(key);
       DexType type = factory.lookupType(factory.createString(key));
       if (type == null) {
         // The map contains additional mapping of classes compared to what we have seen. This should
@@ -76,33 +79,47 @@
       if (dexClass == null) {
         continue;
       }
-      ClassNamingForMapApplier classNaming = seedMapper.getClassNaming(type);
-      mappedNames.put(type, factory.createString(classNaming.renamedName));
+      DexString mappedName = factory.createString(classNaming.renamedName);
+      DexType mappedType = factory.lookupType(mappedName);
+      // The mappedType has to be available:
+      // - If it is null we have not seen it.
+      // - If the mapped type is itself the name is already reserved (by itself).
+      // - If the there is no definition for the mapped type we will not get a naming clash.
+      // Otherwise, there will be a naming conflict.
+      if (mappedType != null && type != mappedType && appInfo.definitionFor(mappedType) != null) {
+        appView
+            .options()
+            .reporter
+            .error(
+                ApplyMappingError.mapToExistingClass(
+                    type.toString(), mappedType.toString(), classNaming.position));
+      }
+      mappedNames.put(type, mappedName);
       mappedClasses.add(dexClass);
       classNaming.forAllMethodNaming(
           memberNaming -> {
-            Signature signature =  memberNaming.getOriginalSignature();
+            Signature signature = memberNaming.getOriginalSignature();
             if (signature.isQualified()) {
               return;
             }
             DexMethod originalMethod = ((MethodSignature) signature).toDexMethod(factory, type);
             assert !memberNames.containsKey(originalMethod);
-            memberNames.put(
-                originalMethod, factory.createString(memberNaming.getRenamedName()));
+            memberNames.put(originalMethod, memberNaming);
           });
       classNaming.forAllFieldNaming(
           memberNaming -> {
-            Signature signature =  memberNaming.getOriginalSignature();
+            Signature signature = memberNaming.getOriginalSignature();
             if (signature.isQualified()) {
               return;
             }
             DexField originalField = ((FieldSignature) signature).toDexField(factory, type);
             assert !memberNames.containsKey(originalField);
-            memberNames.put(
-                originalField, factory.createString(memberNaming.getRenamedName()));
+            memberNames.put(originalField, memberNaming);
           });
     }
 
+    appView.options().reporter.failIfPendingErrors();
+
     ClassNameMinifier classNameMinifier =
         new ClassNameMinifier(
             appView,
@@ -118,7 +135,8 @@
     timing.end();
 
     ApplyMappingMemberNamingStrategy nameStrategy =
-        new ApplyMappingMemberNamingStrategy(memberNames);
+        new ApplyMappingMemberNamingStrategy(
+            memberNames, appInfo.dexItemFactory, appView.options().reporter);
     timing.begin("MinifyMethods");
     MethodRenaming methodRenaming =
         new MethodNameMinifier(appView, rootSet, nameStrategy)
@@ -130,6 +148,8 @@
         new FieldNameMinifier(appView, rootSet, nameStrategy).computeRenaming(timing);
     timing.end();
 
+    appView.options().reporter.failIfPendingErrors();
+
     NamingLens lens =
         new MinifiedRenaming(classRenaming, methodRenaming, fieldRenaming, appView.appInfo());
     return lens;
@@ -156,16 +176,21 @@
 
   static class ApplyMappingMemberNamingStrategy implements MemberNamingStrategy {
 
-    private final Map<DexReference, DexString> mappedNames;
+    private final Map<DexReference, MemberNaming> mappedNames;
+    private final DexItemFactory factory;
+    private final Reporter reporter;
 
-    public ApplyMappingMemberNamingStrategy(Map<DexReference, DexString> mappedNames) {
+    public ApplyMappingMemberNamingStrategy(
+        Map<DexReference, MemberNaming> mappedNames, DexItemFactory factory, Reporter reporter) {
       this.mappedNames = mappedNames;
+      this.factory = factory;
+      this.reporter = reporter;
     }
 
     @Override
     public DexString next(DexReference reference, InternalState internalState) {
       if (mappedNames.containsKey(reference)) {
-        return mappedNames.get(reference);
+        return factory.createString(mappedNames.get(reference).getRenamedName());
       } else if (reference.isDexMethod()) {
         return reference.asDexMethod().name;
       } else {
@@ -178,5 +203,19 @@
     public boolean bypassDictionary() {
       return true;
     }
+
+    @Override
+    public boolean breakOnNotAvailable(DexReference source, DexString name) {
+      // This is an error where we have renamed a member to an name that exists in a subtype or
+      // renamed a field to something that exists in a subclass.
+      MemberNaming memberNaming = mappedNames.get(source);
+      assert source.isDexMethod() || source.isDexField();
+      reporter.error(
+          ApplyMappingError.mapToExistingMember(
+              source.toSourceString(),
+              name.toString(),
+              memberNaming == null ? Position.UNKNOWN : memberNaming.position));
+      return true;
+    }
   }
 }
diff --git a/src/main/java/com/android/tools/r8/naming/ProguardMapReader.java b/src/main/java/com/android/tools/r8/naming/ProguardMapReader.java
index 8a1bb87..a21adfa 100644
--- a/src/main/java/com/android/tools/r8/naming/ProguardMapReader.java
+++ b/src/main/java/com/android/tools/r8/naming/ProguardMapReader.java
@@ -6,6 +6,7 @@
 import com.android.tools.r8.naming.MemberNaming.FieldSignature;
 import com.android.tools.r8.naming.MemberNaming.MethodSignature;
 import com.android.tools.r8.naming.MemberNaming.Signature;
+import com.android.tools.r8.position.TextPosition;
 import com.android.tools.r8.utils.IdentifierUtils;
 import java.io.BufferedReader;
 import java.io.IOException;
@@ -185,7 +186,8 @@
       skipWhitespace();
       String after = parseType(false);
       expect(':');
-      ClassNaming.Builder currentClassBuilder = mapBuilder.classNamingBuilder(after, before);
+      ClassNaming.Builder currentClassBuilder =
+          mapBuilder.classNamingBuilder(after, before, getPosition());
       if (nextLine()) {
         parseMemberMappings(currentClassBuilder);
       }
@@ -260,7 +262,8 @@
           }
         }
         if (activeMemberNaming == null) {
-          activeMemberNaming = new MemberNaming(previousSignature, previousRenamedName);
+          activeMemberNaming =
+              new MemberNaming(previousSignature, previousRenamedName, getPosition());
         }
       }
 
@@ -280,7 +283,7 @@
         if (activeMemberNaming != null) {
           classNamingBuilder.addMemberEntry(activeMemberNaming);
         }
-        activeMemberNaming = new MemberNaming(signature, renamedName);
+        activeMemberNaming = new MemberNaming(signature, renamedName, getPosition());
       } else {
 
         // Note that at this point originalRange may be null which either means, it's the same as
@@ -304,6 +307,10 @@
     }
   }
 
+  private TextPosition getPosition() {
+    return new TextPosition(0, lineNo, 1);
+  }
+
   // Parsing of components
 
   private void skipIdentifier(boolean allowInit) {
diff --git a/src/main/java/com/android/tools/r8/naming/SeedMapper.java b/src/main/java/com/android/tools/r8/naming/SeedMapper.java
index 895605f..8d0ece57 100644
--- a/src/main/java/com/android/tools/r8/naming/SeedMapper.java
+++ b/src/main/java/com/android/tools/r8/naming/SeedMapper.java
@@ -3,10 +3,14 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.naming;
 
+import static com.android.tools.r8.utils.DescriptorUtils.descriptorToInternalName;
+import static com.android.tools.r8.utils.DescriptorUtils.descriptorToJavaType;
 import static com.android.tools.r8.utils.DescriptorUtils.javaTypeToDescriptor;
 
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.naming.MemberNaming.Signature;
+import com.android.tools.r8.position.Position;
+import com.android.tools.r8.utils.Reporter;
 import com.google.common.collect.ImmutableMap;
 import java.io.BufferedReader;
 import java.io.IOException;
@@ -15,6 +19,7 @@
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
+import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
 
@@ -31,52 +36,93 @@
 public class SeedMapper implements ProguardMap {
 
   static class Builder extends ProguardMap.Builder {
-    final ImmutableMap.Builder<String, ClassNamingForMapApplier.Builder> mapBuilder;
+    final Map<String, ClassNamingForMapApplier.Builder> map = new HashMap<>();
+    private final Reporter reporter;
 
-    private Builder() {
-      mapBuilder = ImmutableMap.builder();
+    private Builder(Reporter reporter) {
+      this.reporter = reporter;
     }
 
     @Override
-    ClassNamingForMapApplier.Builder classNamingBuilder(String renamedName, String originalName) {
+    ClassNamingForMapApplier.Builder classNamingBuilder(
+        String renamedName, String originalName, Position position) {
       String originalDescriptor = javaTypeToDescriptor(originalName);
       ClassNamingForMapApplier.Builder classNamingBuilder =
-          ClassNamingForMapApplier.builder(javaTypeToDescriptor(renamedName), originalDescriptor);
-      mapBuilder.put(originalDescriptor, classNamingBuilder);
+          ClassNamingForMapApplier.builder(
+              javaTypeToDescriptor(renamedName), originalDescriptor, position, reporter);
+      if (map.put(originalDescriptor, classNamingBuilder) != null) {
+        reporter.error(ProguardMapError.duplicateSourceClass(originalName, position));
+      }
       return classNamingBuilder;
     }
 
     @Override
     SeedMapper build() {
-      return new SeedMapper(mapBuilder.build());
+      reporter.failIfPendingErrors();
+      return new SeedMapper(ImmutableMap.copyOf(map), reporter);
     }
   }
 
-  static Builder builder() {
-    return new Builder();
+  static Builder builder(Reporter reporter) {
+    return new Builder(reporter);
   }
 
-  private static SeedMapper seedMapperFromInputStream(InputStream in) throws IOException {
+  private static SeedMapper seedMapperFromInputStream(Reporter reporter, InputStream in)
+      throws IOException {
     BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
     try (ProguardMapReader proguardReader = new ProguardMapReader(reader)) {
-      SeedMapper.Builder builder = SeedMapper.builder();
+      SeedMapper.Builder builder = SeedMapper.builder(reporter);
       proguardReader.parse(builder);
       return builder.build();
     }
   }
 
-  public static SeedMapper seedMapperFromFile(Path path) throws IOException {
-    return seedMapperFromInputStream(Files.newInputStream(path));
+  public static SeedMapper seedMapperFromFile(Reporter reporter, Path path) throws IOException {
+    return seedMapperFromInputStream(reporter, Files.newInputStream(path));
   }
 
   private final ImmutableMap<String, ClassNamingForMapApplier> mappings;
+  private final Reporter reporter;
 
-  private SeedMapper(Map<String, ClassNamingForMapApplier.Builder> mappings) {
+  private SeedMapper(Map<String, ClassNamingForMapApplier.Builder> mappings, Reporter reporter) {
+    this.reporter = reporter;
     ImmutableMap.Builder<String, ClassNamingForMapApplier> builder = ImmutableMap.builder();
     for(Map.Entry<String, ClassNamingForMapApplier.Builder> entry : mappings.entrySet()) {
       builder.put(entry.getKey(), entry.getValue().build());
     }
     this.mappings = builder.build();
+    verifyMappingsAreConflictFree();
+  }
+
+  private void verifyMappingsAreConflictFree() {
+    Map<String, String> seenMappings = new HashMap<>();
+    for (String key : mappings.keySet()) {
+      ClassNamingForMapApplier classNaming = mappings.get(key);
+      String existing = seenMappings.put(classNaming.renamedName, key);
+      if (existing != null) {
+        reporter.error(
+            ProguardMapError.duplicateTargetClass(
+                descriptorToJavaType(key),
+                descriptorToJavaType(existing),
+                descriptorToInternalName(classNaming.renamedName),
+                classNaming.position));
+      }
+      Map<Signature, MemberNaming> seenMembers = new HashMap<>();
+      classNaming.forAllMemberNaming(
+          memberNaming -> {
+            MemberNaming existingMember =
+                seenMembers.put(memberNaming.renamedSignature, memberNaming);
+            if (existingMember != null) {
+              reporter.error(
+                  ProguardMapError.duplicateTargetSignature(
+                      existingMember.signature,
+                      memberNaming.signature,
+                      memberNaming.getRenamedName(),
+                      memberNaming.position));
+            }
+          });
+    }
+    reporter.failIfPendingErrors();
   }
 
   @Override
@@ -92,4 +138,8 @@
   public Set<String> getKeyset() {
     return mappings.keySet();
   }
+
+  public ClassNamingForMapApplier getMapping(String key) {
+    return mappings.get(key);
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureRewriter.java b/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureRewriter.java
index 20f4bc2..1f9570c 100644
--- a/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureRewriter.java
+++ b/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureRewriter.java
@@ -28,17 +28,17 @@
 
 public class GenericSignatureRewriter {
 
-  private final AppView<AppInfoWithLiveness> appView;
+  private final AppView<? extends AppInfoWithLiveness> appView;
   private final AppInfoWithLiveness appInfo;
   private final Map<DexType, DexString> renaming;
   private final Reporter reporter;
 
-  public GenericSignatureRewriter(AppView<AppInfoWithLiveness> appView) {
+  public GenericSignatureRewriter(AppView<? extends AppInfoWithLiveness> appView) {
     this(appView, Maps.newIdentityHashMap());
   }
 
   public GenericSignatureRewriter(
-      AppView<AppInfoWithLiveness> appView, Map<DexType, DexString> renaming) {
+      AppView<? extends AppInfoWithLiveness> appView, Map<DexType, DexString> renaming) {
     this.appView = appView;
     this.appInfo = appView.appInfo();
     this.renaming = renaming;
diff --git a/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java b/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
index 871525d..e751336 100644
--- a/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
+++ b/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
@@ -36,11 +36,11 @@
 
   private final MemberRebindingLense.Builder builder;
 
-  public MemberRebindingAnalysis(AppView<AppInfoWithLiveness> appView, InternalOptions options) {
+  public MemberRebindingAnalysis(AppView<? extends AppInfoWithLiveness> appView) {
     assert appView.graphLense().isContextFreeForMethods();
     this.appInfo = appView.appInfo();
     this.lense = appView.graphLense();
-    this.options = options;
+    this.options = appView.options();
     this.builder = MemberRebindingLense.builder(appInfo);
     this.searchInLibrary = options.getProguardConfiguration().hasApplyMappingFile();
   }
diff --git a/src/main/java/com/android/tools/r8/optimize/PublicizerLense.java b/src/main/java/com/android/tools/r8/optimize/PublicizerLense.java
index 29ecf33..ab8999a 100644
--- a/src/main/java/com/android/tools/r8/optimize/PublicizerLense.java
+++ b/src/main/java/com/android/tools/r8/optimize/PublicizerLense.java
@@ -55,7 +55,7 @@
     GraphLenseLookupResult lookup =
         appView.graphLense().lookupMethod(method, context, Type.VIRTUAL);
     DexMethod signatureInCurrentWorld = lookup.getMethod();
-    DexClass clazz = appView.appInfo().definitionFor(signatureInCurrentWorld.holder);
+    DexClass clazz = appView.definitionFor(signatureInCurrentWorld.holder);
     assert clazz != null;
     DexEncodedMethod actualEncodedTarget = clazz.lookupVirtualMethod(signatureInCurrentWorld);
     assert actualEncodedTarget != null;
diff --git a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
index 2b1a6cd..208fb9c 100644
--- a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
+++ b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
@@ -328,7 +328,7 @@
             // -keep rule may vary (due to back references). So, we need to try all pairs of -if
             // rule and live types.
             for (DexType type : liveTypes) {
-              DexClass clazz = appView.appInfo().definitionFor(type);
+              DexClass clazz = appView.definitionFor(type);
               if (clazz == null) {
                 continue;
               }
@@ -343,7 +343,7 @@
                   // `sourceType` is still available until the second round of tree shaking. This
                   // way
                   // we can still retrieve the access flags of `sourceType`.
-                  DexClass sourceClass = appView.appInfo().definitionFor(sourceType);
+                  DexClass sourceClass = appView.definitionFor(sourceType);
                   assert sourceClass != null;
                   evaluateIfRule(ifRule, sourceClass, clazz);
                 }
@@ -740,8 +740,7 @@
         && appView.verticallyMergedClasses().getSourcesFor(clazz.type).stream()
             .filter(
                 sourceType ->
-                    appView.appInfo().definitionFor(sourceType).accessFlags.isInterface()
-                        == isInterface)
+                    appView.definitionFor(sourceType).accessFlags.isInterface() == isInterface)
             .anyMatch(rule.getInheritanceClassName()::matches);
   }
 
@@ -871,7 +870,7 @@
     if (type.isPrimitiveType()) {
       return;
     }
-    DexClass definition = appView.appInfo().definitionFor(type);
+    DexClass definition = appView.definitionFor(type);
     if (definition == null || definition.isLibraryClass()) {
       return;
     }
@@ -916,7 +915,7 @@
         if (options.isInterfaceMethodDesugaringEnabled()
             && encodedMethod.hasCode()
             && (encodedMethod.isPrivateMethod() || encodedMethod.isStaticMember())) {
-          DexClass holder = appView.appInfo().definitionFor(encodedMethod.method.getHolder());
+          DexClass holder = appView.definitionFor(encodedMethod.method.getHolder());
           if (holder != null && holder.isInterface()) {
             if (rule.isSpecific()) {
               options.reporter.warning(
diff --git a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
index 2152d3c..613ec66 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
@@ -229,7 +229,7 @@
 
   public VerticalClassMerger(
       DexApplication application,
-      AppView<AppInfoWithLiveness> appView,
+      AppView<? extends AppInfoWithLiveness> appView,
       ExecutorService executorService,
       InternalOptions options,
       Timing timing,
@@ -1761,7 +1761,7 @@
           checkTypeReference(field.clazz);
           checkTypeReference(field.type);
 
-          DexEncodedField definition = appView.appInfo().definitionFor(field);
+          DexEncodedField definition = appView.definitionFor(field);
           if (definition == null || !definition.accessFlags.isPublic()) {
             foundIllegalAccess = true;
           }
@@ -1780,7 +1780,7 @@
           for (DexType type : method.proto.parameters.values) {
             checkTypeReference(type);
           }
-          DexEncodedMethod definition = appView.appInfo().definitionFor(method);
+          DexEncodedMethod definition = appView.definitionFor(method);
           if (definition == null || !definition.accessFlags.isPublic()) {
             foundIllegalAccess = true;
           }
@@ -1794,7 +1794,7 @@
         DexType baseType =
             appView.graphLense().lookupType(type.toBaseType(appView.dexItemFactory()));
         if (baseType.isClassType() && baseType.isSamePackage(source.type)) {
-          DexClass clazz = appView.appInfo().definitionFor(baseType);
+          DexClass clazz = appView.definitionFor(baseType);
           if (clazz == null || !clazz.accessFlags.isPublic()) {
             foundIllegalAccess = true;
           }
diff --git a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
index 427341f..c60ba34 100644
--- a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
+++ b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
@@ -180,7 +180,8 @@
               () ->
                   classNameMapperBuilder.classNamingBuilder(
                       DescriptorUtils.descriptorToJavaType(renamedClassName.toString()),
-                      originalType.toSourceString()));
+                      originalType.toSourceString(),
+                      com.android.tools.r8.position.Position.UNKNOWN));
 
       // If the class is renamed add it to the classNamingBuilder.
       addClassToClassNaming(originalType, renamedClassName, onDemandClassNamingBuilder);
diff --git a/src/test/java/com/android/tools/r8/R8UnreachableCodeTest.java b/src/test/java/com/android/tools/r8/R8UnreachableCodeTest.java
index bfd929e..ff3d385 100644
--- a/src/test/java/com/android/tools/r8/R8UnreachableCodeTest.java
+++ b/src/test/java/com/android/tools/r8/R8UnreachableCodeTest.java
@@ -8,6 +8,7 @@
 
 import com.android.tools.r8.dex.ApplicationReader;
 import com.android.tools.r8.graph.AppInfoWithSubtyping;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.DirectMappedDexApplication;
@@ -42,7 +43,8 @@
     options.programConsumer = DexIndexedConsumer.emptyConsumer();
     DirectMappedDexApplication application =
         new ApplicationReader(input, options, timing).read(executorService).toDirect();
-    IRConverter converter = new IRConverter(new AppInfoWithSubtyping(application), options);
+    IRConverter converter =
+        new IRConverter(AppView.createForR8(new AppInfoWithSubtyping(application), options));
     converter.optimize(application);
     DexProgramClass clazz = application.classes().iterator().next();
     assertEquals(4, clazz.directMethods().size());
diff --git a/src/test/java/com/android/tools/r8/desugar/DesugaredLambdaImplementationInliningTest.java b/src/test/java/com/android/tools/r8/desugar/DesugaredLambdaImplementationInliningTest.java
new file mode 100644
index 0000000..9453575
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/DesugaredLambdaImplementationInliningTest.java
@@ -0,0 +1,55 @@
+// Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.desugar;
+
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.R8TestRunResult;
+import com.android.tools.r8.TestBase;
+import org.junit.Test;
+
+// Test if the static method of the lambda implementation (SINGLE_CALLER) is inlined into the
+// interface method of the lambda class.
+public class DesugaredLambdaImplementationInliningTest extends TestBase {
+  @Test
+  public void test() throws Exception {
+    class Counter {
+      private int i = 0;
+    }
+    Counter counter = new Counter();
+    R8TestRunResult result =
+        testForR8Compat(Backend.DEX)
+            .addInnerClasses(DesugaredLambdaImplementationInliningTest.class)
+            .addKeepMainRule(DesugaredLambdaImplementationInliningTest.TestClass.class)
+            .noMinification()
+            .run(TestClass.class)
+            .assertSuccess()
+            .inspect(
+                inspector -> {
+                  inspector
+                      .clazz(DesugaredLambdaImplementationInliningTest.TestClass.class)
+                      .forAllMethods(
+                          fms -> {
+                            if (fms.isStatic() && !fms.getOriginalName().equals("main")) {
+                              ++counter.i;
+                            }
+                          });
+                });
+
+    // TODO(b/126323172) Change expected value to zero after fixed.
+    assertEquals(2, counter.i);
+  }
+
+  static class TestClass {
+    public static void main(String[] args) {
+      Runnable runnable = () -> System.out.println("Running desugared stateless lambda.");
+      runnable.run();
+
+      String s = "lambda-state";
+      runnable = () -> System.out.println("Running desugared stateful lambda: " + s + ".");
+      runnable.run();
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/dex/SharedClassWritingTest.java b/src/test/java/com/android/tools/r8/dex/SharedClassWritingTest.java
index 298ffe1..df2d769 100644
--- a/src/test/java/com/android/tools/r8/dex/SharedClassWritingTest.java
+++ b/src/test/java/com/android/tools/r8/dex/SharedClassWritingTest.java
@@ -48,6 +48,7 @@
 import java.util.concurrent.ExecutorService;
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 
 public class SharedClassWritingTest {
@@ -110,6 +111,7 @@
         synthesizedFrom);
   }
 
+  @Ignore("b/128281550")
   @Test
   public void manyFilesWithSharedSynthesizedClass() throws ExecutionException, IOException {
 
diff --git a/src/test/java/com/android/tools/r8/ir/IrInjectionTestBase.java b/src/test/java/com/android/tools/r8/ir/IrInjectionTestBase.java
index 066c51a..0251cf3 100644
--- a/src/test/java/com/android/tools/r8/ir/IrInjectionTestBase.java
+++ b/src/test/java/com/android/tools/r8/ir/IrInjectionTestBase.java
@@ -6,6 +6,7 @@
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.dex.ApplicationReader;
 import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexApplication;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.ir.code.BasicBlock;
@@ -131,11 +132,10 @@
 
     public String run() throws IOException {
       AppInfo appInfo = new AppInfo(application);
-      IRConverter converter = new IRConverter(appInfo, options);
+      IRConverter converter = new IRConverter(AppView.createForD8(appInfo, options));
       converter.replaceCodeForTesting(method, code);
       AndroidApp app = writeDex(application, options);
       return runOnArtRaw(app, DEFAULT_MAIN_CLASS_NAME).stdout;
     }
   }
-
 }
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/NonNullTrackerTestBase.java b/src/test/java/com/android/tools/r8/ir/optimize/NonNullTrackerTestBase.java
index ede89dc..61421a8 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/NonNullTrackerTestBase.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/NonNullTrackerTestBase.java
@@ -9,7 +9,6 @@
 import com.android.tools.r8.graph.AppInfoWithSubtyping;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexApplication;
-import com.android.tools.r8.graph.GraphLense;
 import com.android.tools.r8.shaking.Enqueuer;
 import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 import com.android.tools.r8.shaking.ProguardClassFilter;
@@ -31,9 +30,8 @@
     AndroidApp app = buildAndroidApp(ToolHelper.getClassAsBytes(mainClass));
     DexApplication dexApplication =
         new ApplicationReader(app, TEST_OPTIONS, timing).read().toDirect();
-    AppView<AppInfoWithSubtyping> appView =
-        new AppView<>(
-            new AppInfoWithSubtyping(dexApplication), GraphLense.getIdentityLense(), TEST_OPTIONS);
+    AppView<? extends AppInfoWithSubtyping> appView =
+        AppView.createForR8(new AppInfoWithSubtyping(dexApplication), TEST_OPTIONS);
     ExecutorService executorService = ThreadUtils.getExecutorService(TEST_OPTIONS);
     RootSet rootSet =
         new RootSetBuilder(
diff --git a/src/test/java/com/android/tools/r8/kotlin/AbstractR8KotlinTestBase.java b/src/test/java/com/android/tools/r8/kotlin/AbstractR8KotlinTestBase.java
index b722683..a60be5d 100644
--- a/src/test/java/com/android/tools/r8/kotlin/AbstractR8KotlinTestBase.java
+++ b/src/test/java/com/android/tools/r8/kotlin/AbstractR8KotlinTestBase.java
@@ -121,6 +121,13 @@
     return classSubject;
   }
 
+  protected void checkClassIsRemoved(CodeInspector inspector, String className) {
+    checkClassExistsInInput(className);
+    ClassSubject classSubject = inspector.clazz(className);
+    assertNotNull(classSubject);
+    assertThat(classSubject, not(isPresent()));
+  }
+
   protected FieldSubject checkFieldIsKept(
       ClassSubject classSubject, String fieldType, String fieldName) {
     // Field must exist in the input.
@@ -138,8 +145,6 @@
   }
 
   protected void checkFieldIsAbsent(ClassSubject classSubject, String fieldType, String fieldName) {
-    // Field must NOT exist in the input.
-    checkFieldPresenceInInput(classSubject.getOriginalName(), fieldType, fieldName, false);
     FieldSubject fieldSubject = classSubject.field(fieldType, fieldName);
     assertNotNull(fieldSubject);
     assertFalse(fieldSubject.isPresent());
@@ -162,6 +167,12 @@
     return checkMethodIsKeptOrRemoved(classSubject, methodSignature, true);
   }
 
+  protected MethodSubject checkMethodIsMoved(
+      String inputClassName, ClassSubject outputClassSubject, MethodSignature methodSignature) {
+    checkMethodPresenceInInput(inputClassName, methodSignature, true);
+    return checkMethodPresenceInOutput(outputClassSubject, methodSignature, true);
+  }
+
   protected MethodSubject checkMethodIsKept(ClassSubject classSubject, String methodName) {
     MethodSubject methodSubject = classSubject.uniqueMethodWithName(methodName);
     assertThat(methodSubject, isPresent());
diff --git a/src/test/java/com/android/tools/r8/kotlin/KotlinClassStaticizerTest.java b/src/test/java/com/android/tools/r8/kotlin/KotlinClassStaticizerTest.java
index 3f02c70..15015cd 100644
--- a/src/test/java/com/android/tools/r8/kotlin/KotlinClassStaticizerTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/KotlinClassStaticizerTest.java
@@ -4,15 +4,16 @@
 
 package com.android.tools.r8.kotlin;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
 
 import com.android.tools.r8.ToolHelper.KotlinTargetVersion;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
-import java.util.concurrent.atomic.AtomicInteger;
+import com.android.tools.r8.utils.codeinspector.FoundMethodSubject;
 import org.junit.Test;
 
 public class KotlinClassStaticizerTest extends AbstractR8KotlinTestBase {
@@ -28,32 +29,34 @@
     final String mainClassName = "class_staticizer.MainKt";
 
     // Without class staticizer.
-    runTest("class_staticizer", mainClassName, false, (app) -> {
-      CodeInspector inspector = new CodeInspector(app);
-      assertTrue(inspector.clazz("class_staticizer.Regular$Companion").isPresent());
-      assertTrue(inspector.clazz("class_staticizer.Derived$Companion").isPresent());
+    runTest(
+        "class_staticizer",
+        mainClassName,
+        false,
+        (app) -> {
+          CodeInspector inspector = new CodeInspector(app);
+          assertThat(inspector.clazz("class_staticizer.Regular$Companion"), not(isPresent()));
+          assertThat(inspector.clazz("class_staticizer.Derived$Companion"), not(isPresent()));
 
-      ClassSubject utilClass = inspector.clazz("class_staticizer.Util");
-      assertTrue(utilClass.isPresent());
-      AtomicInteger nonStaticMethodCount = new AtomicInteger();
-      utilClass.forAllMethods(method -> {
-        if (!method.isStatic()) {
-          nonStaticMethodCount.incrementAndGet();
-        }
-      });
-      assertEquals(4, nonStaticMethodCount.get());
-    });
+          ClassSubject utilClass = inspector.clazz("class_staticizer.Util");
+          assertThat(utilClass, isPresent());
+          assertTrue(utilClass.allMethods().stream().allMatch(FoundMethodSubject::isStatic));
+        });
 
     // With class staticizer.
-    runTest("class_staticizer", mainClassName, true, (app) -> {
-      CodeInspector inspector = new CodeInspector(app);
-      assertFalse(inspector.clazz("class_staticizer.Regular$Companion").isPresent());
-      assertFalse(inspector.clazz("class_staticizer.Derived$Companion").isPresent());
+    runTest(
+        "class_staticizer",
+        mainClassName,
+        true,
+        (app) -> {
+          CodeInspector inspector = new CodeInspector(app);
+          assertThat(inspector.clazz("class_staticizer.Regular$Companion"), not(isPresent()));
+          assertThat(inspector.clazz("class_staticizer.Derived$Companion"), not(isPresent()));
 
-      ClassSubject utilClass = inspector.clazz("class_staticizer.Util");
-      assertTrue(utilClass.isPresent());
-      utilClass.forAllMethods(method -> assertTrue(method.isStatic()));
-    });
+          ClassSubject utilClass = inspector.clazz("class_staticizer.Util");
+          assertThat(utilClass, isPresent());
+          assertTrue(utilClass.allMethods().stream().allMatch(FoundMethodSubject::isStatic));
+        });
   }
 
   protected void runTest(String folder, String mainClass,
diff --git a/src/test/java/com/android/tools/r8/kotlin/R8KotlinAccessorTest.java b/src/test/java/com/android/tools/r8/kotlin/R8KotlinAccessorTest.java
index 0048b1b..5630c1f 100644
--- a/src/test/java/com/android/tools/r8/kotlin/R8KotlinAccessorTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/R8KotlinAccessorTest.java
@@ -75,28 +75,31 @@
     final TestKotlinCompanionClass testedClass = COMPANION_PROPERTY_CLASS;
     String mainClass = addMainToClasspath("properties.CompanionPropertiesKt",
         "companionProperties_usePrimitiveProp");
-    runTest(PROPERTIES_PACKAGE_NAME, mainClass, disableClassStaticizer, (app) -> {
-      CodeInspector codeInspector = new CodeInspector(app);
-      ClassSubject outerClass = checkClassIsKept(codeInspector, testedClass.getOuterClassName());
-      String propertyName = "primitiveProp";
-      FieldSubject fieldSubject = checkFieldIsKept(outerClass, "int", propertyName);
-      assertTrue(fieldSubject.getField().accessFlags.isStatic());
+    runTest(
+        PROPERTIES_PACKAGE_NAME,
+        mainClass,
+        disableClassStaticizer,
+        (app) -> {
+          CodeInspector codeInspector = new CodeInspector(app);
+          ClassSubject outerClass =
+              checkClassIsKept(codeInspector, testedClass.getOuterClassName());
+          String propertyName = "primitiveProp";
+          FieldSubject fieldSubject = checkFieldIsKept(outerClass, "int", propertyName);
+          assertTrue(fieldSubject.getField().accessFlags.isStatic());
 
-      MemberNaming.MethodSignature getterAccessor = testedClass
-          .getGetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
-      MemberNaming.MethodSignature setterAccessor = testedClass
-          .getSetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
+          MemberNaming.MethodSignature getterAccessor =
+              testedClass.getGetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
+          MemberNaming.MethodSignature setterAccessor =
+              testedClass.getSetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
+          checkMethodIsRemoved(outerClass, getterAccessor);
+          checkMethodIsRemoved(outerClass, setterAccessor);
 
-      if (allowAccessModification) {
-        assertTrue(fieldSubject.getField().accessFlags.isPublic());
-        checkMethodIsRemoved(outerClass, getterAccessor);
-        checkMethodIsRemoved(outerClass, setterAccessor);
-      } else {
-        assertTrue(fieldSubject.getField().accessFlags.isPrivate());
-        checkMethodIsKept(outerClass, getterAccessor);
-        checkMethodIsKept(outerClass, setterAccessor);
-      }
-    });
+          if (allowAccessModification) {
+            assertTrue(fieldSubject.getField().accessFlags.isPublic());
+          } else {
+            assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+          }
+        });
   }
 
   @Test
@@ -104,29 +107,31 @@
     final TestKotlinCompanionClass testedClass = COMPANION_PROPERTY_CLASS;
     String mainClass = addMainToClasspath("properties.CompanionPropertiesKt",
         "companionProperties_usePrivateProp");
-    runTest(PROPERTIES_PACKAGE_NAME, mainClass, disableClassStaticizer, (app) -> {
-      CodeInspector codeInspector = new CodeInspector(app);
-      ClassSubject outerClass = checkClassIsKept(codeInspector, testedClass.getOuterClassName());
-      String propertyName = "privateProp";
-      FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
-      assertTrue(fieldSubject.getField().accessFlags.isStatic());
+    runTest(
+        PROPERTIES_PACKAGE_NAME,
+        mainClass,
+        disableClassStaticizer,
+        (app) -> {
+          CodeInspector codeInspector = new CodeInspector(app);
+          ClassSubject outerClass =
+              checkClassIsKept(codeInspector, testedClass.getOuterClassName());
+          String propertyName = "privateProp";
+          FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
+          assertTrue(fieldSubject.getField().accessFlags.isStatic());
 
-      MemberNaming.MethodSignature getterAccessor = testedClass
-          .getGetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
-      MemberNaming.MethodSignature setterAccessor = testedClass
-          .getSetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
-      if (allowAccessModification) {
-        assertTrue(fieldSubject.getField().accessFlags.isPublic());
+          MemberNaming.MethodSignature getterAccessor =
+              testedClass.getGetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
+          MemberNaming.MethodSignature setterAccessor =
+              testedClass.getSetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
+          checkMethodIsRemoved(outerClass, getterAccessor);
+          checkMethodIsRemoved(outerClass, setterAccessor);
 
-        checkMethodIsRemoved(outerClass, getterAccessor);
-        checkMethodIsRemoved(outerClass, setterAccessor);
-      } else {
-        assertTrue(fieldSubject.getField().accessFlags.isPrivate());
-
-        checkMethodIsKept(outerClass, getterAccessor);
-        checkMethodIsKept(outerClass, setterAccessor);
-      }
-    });
+          if (allowAccessModification) {
+            assertTrue(fieldSubject.getField().accessFlags.isPublic());
+          } else {
+            assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+          }
+        });
   }
 
   @Test
@@ -134,28 +139,31 @@
     final TestKotlinCompanionClass testedClass = COMPANION_PROPERTY_CLASS;
     String mainClass = addMainToClasspath("properties.CompanionPropertiesKt",
         "companionProperties_useInternalProp");
-    runTest(PROPERTIES_PACKAGE_NAME, mainClass, disableClassStaticizer, (app) -> {
-      CodeInspector codeInspector = new CodeInspector(app);
-      ClassSubject outerClass = checkClassIsKept(codeInspector, testedClass.getOuterClassName());
-      String propertyName = "internalProp";
-      FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
-      assertTrue(fieldSubject.getField().accessFlags.isStatic());
+    runTest(
+        PROPERTIES_PACKAGE_NAME,
+        mainClass,
+        disableClassStaticizer,
+        (app) -> {
+          CodeInspector codeInspector = new CodeInspector(app);
+          ClassSubject outerClass =
+              checkClassIsKept(codeInspector, testedClass.getOuterClassName());
+          String propertyName = "internalProp";
+          FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
+          assertTrue(fieldSubject.getField().accessFlags.isStatic());
 
-      MemberNaming.MethodSignature getterAccessor = testedClass
-          .getGetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
-      MemberNaming.MethodSignature setterAccessor = testedClass
-          .getSetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
+          MemberNaming.MethodSignature getterAccessor =
+              testedClass.getGetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
+          MemberNaming.MethodSignature setterAccessor =
+              testedClass.getSetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
+          checkMethodIsRemoved(outerClass, getterAccessor);
+          checkMethodIsRemoved(outerClass, setterAccessor);
 
-      if (allowAccessModification) {
-        assertTrue(fieldSubject.getField().accessFlags.isPublic());
-        checkMethodIsRemoved(outerClass, getterAccessor);
-        checkMethodIsRemoved(outerClass, setterAccessor);
-      } else {
-        assertTrue(fieldSubject.getField().accessFlags.isPrivate());
-        checkMethodIsKept(outerClass, getterAccessor);
-        checkMethodIsKept(outerClass, setterAccessor);
-      }
-    });
+          if (allowAccessModification) {
+            assertTrue(fieldSubject.getField().accessFlags.isPublic());
+          } else {
+            assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+          }
+        });
   }
 
   @Test
@@ -163,28 +171,31 @@
     final TestKotlinCompanionClass testedClass = COMPANION_PROPERTY_CLASS;
     String mainClass = addMainToClasspath("properties.CompanionPropertiesKt",
         "companionProperties_usePublicProp");
-    runTest(PROPERTIES_PACKAGE_NAME, mainClass, disableClassStaticizer, (app) -> {
-      CodeInspector codeInspector = new CodeInspector(app);
-      ClassSubject outerClass = checkClassIsKept(codeInspector, testedClass.getOuterClassName());
-      String propertyName = "publicProp";
-      FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
-      assertTrue(fieldSubject.getField().accessFlags.isStatic());
+    runTest(
+        PROPERTIES_PACKAGE_NAME,
+        mainClass,
+        disableClassStaticizer,
+        (app) -> {
+          CodeInspector codeInspector = new CodeInspector(app);
+          ClassSubject outerClass =
+              checkClassIsKept(codeInspector, testedClass.getOuterClassName());
+          String propertyName = "publicProp";
+          FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
+          assertTrue(fieldSubject.getField().accessFlags.isStatic());
 
-      MemberNaming.MethodSignature getterAccessor = testedClass
-          .getGetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
-      MemberNaming.MethodSignature setterAccessor = testedClass
-          .getSetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
+          MemberNaming.MethodSignature getterAccessor =
+              testedClass.getGetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
+          MemberNaming.MethodSignature setterAccessor =
+              testedClass.getSetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
+          checkMethodIsRemoved(outerClass, getterAccessor);
+          checkMethodIsRemoved(outerClass, setterAccessor);
 
-      if (allowAccessModification) {
-        assertTrue(fieldSubject.getField().accessFlags.isPublic());
-        checkMethodIsRemoved(outerClass, getterAccessor);
-        checkMethodIsRemoved(outerClass, setterAccessor);
-      } else {
-        assertTrue(fieldSubject.getField().accessFlags.isPrivate());
-        checkMethodIsKept(outerClass, getterAccessor);
-        checkMethodIsKept(outerClass, setterAccessor);
-      }
-    });
+          if (allowAccessModification) {
+            assertTrue(fieldSubject.getField().accessFlags.isPublic());
+          } else {
+            assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+          }
+        });
   }
 
   @Test
@@ -192,27 +203,32 @@
     final TestKotlinCompanionClass testedClass = COMPANION_LATE_INIT_PROPERTY_CLASS;
     String mainClass = addMainToClasspath("properties.CompanionLateInitPropertiesKt",
         "companionLateInitProperties_usePrivateLateInitProp");
-    runTest(PROPERTIES_PACKAGE_NAME, mainClass, disableClassStaticizer, (app) -> {
-      CodeInspector codeInspector = new CodeInspector(app);
-      ClassSubject outerClass = checkClassIsKept(codeInspector, testedClass.getOuterClassName());
-      String propertyName = "privateLateInitProp";
-      FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
-      assertTrue(fieldSubject.getField().accessFlags.isStatic());
+    runTest(
+        PROPERTIES_PACKAGE_NAME,
+        mainClass,
+        disableClassStaticizer,
+        (app) -> {
+          CodeInspector codeInspector = new CodeInspector(app);
+          ClassSubject outerClass =
+              checkClassIsKept(codeInspector, testedClass.getOuterClassName());
+          String propertyName = "privateLateInitProp";
+          FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
+          assertTrue(fieldSubject.getField().accessFlags.isStatic());
 
-      MemberNaming.MethodSignature getterAccessor = testedClass
-          .getGetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
-      MemberNaming.MethodSignature setterAccessor = testedClass
-          .getSetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
-      if (allowAccessModification) {
-        assertTrue(fieldSubject.getField().accessFlags.isPublic());
-        checkMethodIsRemoved(outerClass, getterAccessor);
-        checkMethodIsRemoved(outerClass, setterAccessor);
-      } else {
-        assertTrue(fieldSubject.getField().accessFlags.isPrivate());
-        checkMethodIsKept(outerClass, getterAccessor);
-        checkMethodIsKept(outerClass, setterAccessor);
-      }
-    });
+          MemberNaming.MethodSignature getterAccessor =
+              testedClass.getGetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
+          MemberNaming.MethodSignature setterAccessor =
+              testedClass.getSetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
+          checkMethodIsRemoved(outerClass, setterAccessor);
+
+          if (allowAccessModification) {
+            assertTrue(fieldSubject.getField().accessFlags.isPublic());
+            checkMethodIsRemoved(outerClass, getterAccessor);
+          } else {
+            assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+            checkMethodIsKept(outerClass, getterAccessor);
+          }
+        });
   }
 
   @Test
@@ -276,23 +292,18 @@
           CodeInspector codeInspector = new CodeInspector(app);
           ClassSubject outerClass =
               checkClassIsKept(codeInspector, testedClass.getOuterClassName());
-          ClassSubject companionClass = checkClassIsKept(codeInspector, testedClass.getClassName());
+
+          // Companion class has been removed because of class staticizing.
+          String companionClassName = testedClass.getClassName();
+          checkClassIsRemoved(codeInspector, companionClassName);
+
           String propertyName = "property";
-          FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
-          assertTrue(fieldSubject.getField().accessFlags.isStatic());
+          checkFieldIsAbsent(outerClass, JAVA_LANG_STRING, propertyName);
 
           // The getter is always inlined since it just calls into the accessor.
-          MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
-          checkMethodIsAbsent(companionClass, getter);
-
           MemberNaming.MethodSignature getterAccessor =
               testedClass.getGetterAccessorForProperty(propertyName, AccessorKind.FROM_COMPANION);
-          if (allowAccessModification) {
-            assertTrue(fieldSubject.getField().accessFlags.isPublic());
-          } else {
-            assertTrue(fieldSubject.getField().accessFlags.isPrivate());
-          }
-          checkMethodIsKept(outerClass, getterAccessor);
+          checkMethodIsRemoved(outerClass, getterAccessor);
         });
   }
 
diff --git a/src/test/java/com/android/tools/r8/kotlin/R8KotlinPropertiesTest.java b/src/test/java/com/android/tools/r8/kotlin/R8KotlinPropertiesTest.java
index d310c6e..c76798e 100644
--- a/src/test/java/com/android/tools/r8/kotlin/R8KotlinPropertiesTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/R8KotlinPropertiesTest.java
@@ -389,127 +389,148 @@
   public void testCompanionProperty_primitivePropertyCannotBeInlined() throws Exception {
     String mainClass = addMainToClasspath(
         "properties.CompanionPropertiesKt", "companionProperties_usePrimitiveProp");
-    runTest(PACKAGE_NAME, mainClass, disableAggressiveClassOptimizations, (app) -> {
-      CodeInspector codeInspector = new CodeInspector(app);
-      ClassSubject outerClass = checkClassIsKept(codeInspector,
-          "properties.CompanionProperties");
-      ClassSubject companionClass = checkClassIsKept(codeInspector,
-          COMPANION_PROPERTY_CLASS.getClassName());
-      String propertyName = "primitiveProp";
-      FieldSubject fieldSubject = checkFieldIsKept(outerClass, "int", propertyName);
-      assertTrue(fieldSubject.getField().accessFlags.isStatic());
+    runTest(
+        PACKAGE_NAME,
+        mainClass,
+        disableAggressiveClassOptimizations,
+        (app) -> {
+          CodeInspector codeInspector = new CodeInspector(app);
+          ClassSubject outerClass =
+              checkClassIsKept(codeInspector, "properties.CompanionProperties");
 
-      MemberNaming.MethodSignature getter = COMPANION_PROPERTY_CLASS
-          .getGetterForProperty(propertyName);
-      MemberNaming.MethodSignature setter = COMPANION_PROPERTY_CLASS
-          .getSetterForProperty(propertyName);
+          // Companion class has been removed because of class staticizing.
+          String companionClassName = COMPANION_PROPERTY_CLASS.getClassName();
+          checkClassIsRemoved(codeInspector, companionClassName);
 
-      // Getter and setter cannot be inlined because we don't know if null check semantic is
-      // preserved.
-      checkMethodIsKept(companionClass, getter);
-      checkMethodIsKept(companionClass, setter);
-      if (allowAccessModification) {
-        assertTrue(fieldSubject.getField().accessFlags.isPublic());
-      } else {
-        assertTrue(fieldSubject.getField().accessFlags.isPrivate());
-      }
-    });
+          String propertyName = "primitiveProp";
+          FieldSubject fieldSubject = checkFieldIsKept(outerClass, "int", propertyName);
+          assertTrue(fieldSubject.getField().accessFlags.isStatic());
+
+          if (allowAccessModification) {
+            assertTrue(fieldSubject.getField().accessFlags.isPublic());
+          } else {
+            assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+          }
+        });
   }
 
   @Test
   public void testCompanionProperty_privatePropertyIsAlwaysInlined() throws Exception {
     String mainClass = addMainToClasspath(
         "properties.CompanionPropertiesKt", "companionProperties_usePrivateProp");
-    runTest(PACKAGE_NAME, mainClass, disableAggressiveClassOptimizations, (app) -> {
-      CodeInspector codeInspector = new CodeInspector(app);
-      ClassSubject outerClass = checkClassIsKept(codeInspector,
-          "properties.CompanionProperties");
-      ClassSubject companionClass = checkClassIsKept(codeInspector,
-          COMPANION_PROPERTY_CLASS.getClassName());
-      String propertyName = "privateProp";
-      FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
-      assertTrue(fieldSubject.getField().accessFlags.isStatic());
+    runTest(
+        PACKAGE_NAME,
+        mainClass,
+        disableAggressiveClassOptimizations,
+        (app) -> {
+          CodeInspector codeInspector = new CodeInspector(app);
+          ClassSubject outerClass =
+              checkClassIsKept(codeInspector, "properties.CompanionProperties");
 
-      MemberNaming.MethodSignature getter = COMPANION_PROPERTY_CLASS
-          .getGetterForProperty(propertyName);
-      MemberNaming.MethodSignature setter = COMPANION_PROPERTY_CLASS
-          .getSetterForProperty(propertyName);
+          // Companion class has been removed because of class staticizing.
+          String companionClassName = COMPANION_PROPERTY_CLASS.getClassName();
+          checkClassIsRemoved(codeInspector, companionClassName);
 
-      // Because the getter/setter are private, they can only be called from another method in the
-      // class. If this is an instance method, they will be called on 'this' which is known to be
-      // non-null, thus the getter/setter can be inlined if their code is small enough.
-      // Because the backing field is private, they will call into an accessor (static) method. If
-      // access relaxation is enabled, this accessor can be removed.
-      checkMethodIsAbsent(companionClass, getter);
-      checkMethodIsAbsent(companionClass, setter);
-      if (allowAccessModification) {
-        assertTrue(fieldSubject.getField().accessFlags.isPublic());
-      } else {
-        assertTrue(fieldSubject.getField().accessFlags.isPrivate());
-      }
-    });
+          String propertyName = "privateProp";
+          FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
+          assertTrue(fieldSubject.getField().accessFlags.isStatic());
+
+          MemberNaming.MethodSignature getter =
+              COMPANION_PROPERTY_CLASS.getGetterForProperty(propertyName);
+          MemberNaming.MethodSignature setter =
+              COMPANION_PROPERTY_CLASS.getSetterForProperty(propertyName);
+
+          // Because the getter/setter are private, they can only be called from another method in
+          // the class. If this is an instance method, they will be called on 'this' which is known
+          // to be non-null, thus the getter/setter can be inlined if their code is small enough.
+          // Because the backing field is private, they will call into an accessor (static) method.
+          // If access relaxation is enabled, this accessor can be removed.
+          checkMethodIsAbsent(outerClass, getter);
+          checkMethodIsAbsent(outerClass, setter);
+
+          if (allowAccessModification) {
+            assertTrue(fieldSubject.getField().accessFlags.isPublic());
+          } else {
+            assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+          }
+        });
   }
 
   @Test
   public void testCompanionProperty_internalPropertyCannotBeInlined() throws Exception {
     String mainClass = addMainToClasspath(
         "properties.CompanionPropertiesKt", "companionProperties_useInternalProp");
-    runTest(PACKAGE_NAME, mainClass, disableAggressiveClassOptimizations, (app) -> {
-      CodeInspector codeInspector = new CodeInspector(app);
-      ClassSubject outerClass = checkClassIsKept(codeInspector,
-          "properties.CompanionProperties");
-      ClassSubject companionClass = checkClassIsKept(codeInspector,
-          COMPANION_PROPERTY_CLASS.getClassName());
-      String propertyName = "internalProp";
-      FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
-      assertTrue(fieldSubject.getField().accessFlags.isStatic());
+    runTest(
+        PACKAGE_NAME,
+        mainClass,
+        disableAggressiveClassOptimizations,
+        (app) -> {
+          CodeInspector codeInspector = new CodeInspector(app);
+          ClassSubject outerClass =
+              checkClassIsKept(codeInspector, "properties.CompanionProperties");
 
-      MemberNaming.MethodSignature getter = COMPANION_PROPERTY_CLASS
-          .getGetterForProperty(propertyName);
-      MemberNaming.MethodSignature setter = COMPANION_PROPERTY_CLASS
-          .getSetterForProperty(propertyName);
+          // Companion class has been removed because of class staticizing.
+          String companionClassName = COMPANION_PROPERTY_CLASS.getClassName();
+          checkClassIsRemoved(codeInspector, companionClassName);
 
-      // Getter and setter cannot be inlined because we don't know if null check semantic is
-      // preserved.
-      checkMethodIsKept(companionClass, getter);
-      checkMethodIsKept(companionClass, setter);
-      if (allowAccessModification) {
-        assertTrue(fieldSubject.getField().accessFlags.isPublic());
-      } else {
-        assertTrue(fieldSubject.getField().accessFlags.isPrivate());
-      }
-    });
+          String propertyName = "internalProp";
+          FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
+          assertTrue(fieldSubject.getField().accessFlags.isStatic());
+
+          MemberNaming.MethodSignature getter =
+              COMPANION_PROPERTY_CLASS.getGetterForProperty(propertyName);
+          MemberNaming.MethodSignature setter =
+              COMPANION_PROPERTY_CLASS.getSetterForProperty(propertyName);
+
+          // Getter and setter cannot be inlined because we don't know if null check semantic is
+          // preserved.
+          checkMethodIsMoved(companionClassName, outerClass, getter);
+          checkMethodIsMoved(companionClassName, outerClass, setter);
+          if (allowAccessModification) {
+            assertTrue(fieldSubject.getField().accessFlags.isPublic());
+          } else {
+            assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+          }
+        });
   }
 
   @Test
   public void testCompanionProperty_publicPropertyCannotBeInlined() throws Exception {
     String mainClass = addMainToClasspath(
         "properties.CompanionPropertiesKt", "companionProperties_usePublicProp");
-    runTest(PACKAGE_NAME, mainClass, disableAggressiveClassOptimizations, (app) -> {
-      CodeInspector codeInspector = new CodeInspector(app);
-      ClassSubject outerClass = checkClassIsKept(codeInspector,
-          "properties.CompanionProperties");
-      ClassSubject companionClass = checkClassIsKept(codeInspector,
-          COMPANION_PROPERTY_CLASS.getClassName());
-      String propertyName = "publicProp";
-      FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
-      assertTrue(fieldSubject.getField().accessFlags.isStatic());
+    runTest(
+        PACKAGE_NAME,
+        mainClass,
+        disableAggressiveClassOptimizations,
+        (app) -> {
+          CodeInspector codeInspector = new CodeInspector(app);
+          ClassSubject outerClass =
+              checkClassIsKept(codeInspector, "properties.CompanionProperties");
 
-      MemberNaming.MethodSignature getter = COMPANION_PROPERTY_CLASS
-          .getGetterForProperty(propertyName);
-      MemberNaming.MethodSignature setter = COMPANION_PROPERTY_CLASS
-          .getSetterForProperty(propertyName);
+          // Companion class has been removed because of class staticizing.
+          String companionClassName = COMPANION_PROPERTY_CLASS.getClassName();
+          checkClassIsRemoved(codeInspector, companionClassName);
 
-      // Getter and setter cannot be inlined because we don't know if null check semantic is
-      // preserved.
-      checkMethodIsKept(companionClass, getter);
-      checkMethodIsKept(companionClass, setter);
-      if (allowAccessModification) {
-        assertTrue(fieldSubject.getField().accessFlags.isPublic());
-      } else {
-        assertTrue(fieldSubject.getField().accessFlags.isPrivate());
-      }
-    });
+          String propertyName = "publicProp";
+          FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
+          assertTrue(fieldSubject.getField().accessFlags.isStatic());
+
+          MemberNaming.MethodSignature getter =
+              COMPANION_PROPERTY_CLASS.getGetterForProperty(propertyName);
+          MemberNaming.MethodSignature setter =
+              COMPANION_PROPERTY_CLASS.getSetterForProperty(propertyName);
+
+          // Getter and setter cannot be inlined because we don't know if null check semantic is
+          // preserved.
+          checkMethodIsMoved(companionClassName, outerClass, getter);
+          checkMethodIsMoved(companionClassName, outerClass, setter);
+
+          if (allowAccessModification) {
+            assertTrue(fieldSubject.getField().accessFlags.isPublic());
+          } else {
+            assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+          }
+        });
   }
 
   @Test
@@ -517,30 +538,28 @@
     final TestKotlinCompanionClass testedClass = COMPANION_LATE_INIT_PROPERTY_CLASS;
     String mainClass = addMainToClasspath("properties.CompanionLateInitPropertiesKt",
         "companionLateInitProperties_usePrivateLateInitProp");
-    runTest(PACKAGE_NAME, mainClass, disableAggressiveClassOptimizations, (app) -> {
-      CodeInspector codeInspector = new CodeInspector(app);
-      ClassSubject outerClass = checkClassIsKept(codeInspector, testedClass.getOuterClassName());
-      ClassSubject companionClass = checkClassIsKept(codeInspector, testedClass.getClassName());
-      String propertyName = "privateLateInitProp";
-      FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
-      assertTrue(fieldSubject.getField().accessFlags.isStatic());
+    runTest(
+        PACKAGE_NAME,
+        mainClass,
+        disableAggressiveClassOptimizations,
+        (app) -> {
+          CodeInspector codeInspector = new CodeInspector(app);
+          ClassSubject outerClass =
+              checkClassIsKept(codeInspector, testedClass.getOuterClassName());
 
-      MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
-      MemberNaming.MethodSignature setter = testedClass.getSetterForProperty(propertyName);
+          // Companion class has been removed because of class staticizing.
+          String companionClassName = testedClass.getClassName();
+          checkClassIsRemoved(codeInspector, companionClassName);
 
-      // Because the getter/setter are private, they can only be called from another method in the
-      // class. If this is an instance method, they will be called on 'this' which is known to be
-      // non-null, thus the getter/setter can be inlined if their code is small enough.
-      // Because the backing field is private, they will call into an accessor (static) method. If
-      // access relaxation is enabled, this accessor can be removed.
-      checkMethodIsAbsent(companionClass, getter);
-      checkMethodIsAbsent(companionClass, setter);
-      if (allowAccessModification) {
-        assertTrue(fieldSubject.getField().accessFlags.isPublic());
-      } else {
-        assertTrue(fieldSubject.getField().accessFlags.isPrivate());
-      }
-    });
+          String propertyName = "privateLateInitProp";
+          FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
+          assertTrue(fieldSubject.getField().accessFlags.isStatic());
+          if (allowAccessModification) {
+            assertTrue(fieldSubject.getField().accessFlags.isPublic());
+          } else {
+            assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+          }
+        });
   }
 
   @Test
@@ -548,23 +567,32 @@
     final TestKotlinCompanionClass testedClass = COMPANION_LATE_INIT_PROPERTY_CLASS;
     String mainClass = addMainToClasspath("properties.CompanionLateInitPropertiesKt",
         "companionLateInitProperties_useInternalLateInitProp");
-    runTest(PACKAGE_NAME, mainClass, disableAggressiveClassOptimizations, (app) -> {
-      CodeInspector codeInspector = new CodeInspector(app);
-      ClassSubject outerClass = checkClassIsKept(codeInspector, testedClass.getOuterClassName());
-      ClassSubject companionClass = checkClassIsKept(codeInspector, testedClass.getClassName());
-      String propertyName = "internalLateInitProp";
-      FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
-      assertTrue(fieldSubject.getField().accessFlags.isStatic());
+    runTest(
+        PACKAGE_NAME,
+        mainClass,
+        disableAggressiveClassOptimizations,
+        (app) -> {
+          CodeInspector codeInspector = new CodeInspector(app);
+          ClassSubject outerClass =
+              checkClassIsKept(codeInspector, testedClass.getOuterClassName());
 
-      MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
-      MemberNaming.MethodSignature setter = testedClass.getSetterForProperty(propertyName);
+          // Companion class has been removed because of class staticizing.
+          String companionClassName = testedClass.getClassName();
+          checkClassIsRemoved(codeInspector, companionClassName);
 
-      // Getter and setter cannot be inlined because we don't know if null check semantic is
-      // preserved.
-      checkMethodIsKept(companionClass, getter);
-      checkMethodIsKept(companionClass, setter);
-      assertTrue(fieldSubject.getField().accessFlags.isPublic());
-    });
+          String propertyName = "internalLateInitProp";
+          FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
+          assertTrue(fieldSubject.getField().accessFlags.isStatic());
+
+          MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
+          MemberNaming.MethodSignature setter = testedClass.getSetterForProperty(propertyName);
+
+          // Getter and setter cannot be inlined because we don't know if null check semantic is
+          // preserved.
+          checkMethodIsMoved(companionClassName, outerClass, getter);
+          checkMethodIsMoved(companionClassName, outerClass, setter);
+          assertTrue(fieldSubject.getField().accessFlags.isPublic());
+        });
   }
 
   @Test
@@ -572,23 +600,32 @@
     final TestKotlinCompanionClass testedClass = COMPANION_LATE_INIT_PROPERTY_CLASS;
     String mainClass = addMainToClasspath("properties.CompanionLateInitPropertiesKt",
         "companionLateInitProperties_usePublicLateInitProp");
-    runTest(PACKAGE_NAME, mainClass, disableAggressiveClassOptimizations, (app) -> {
-      CodeInspector codeInspector = new CodeInspector(app);
-      ClassSubject outerClass = checkClassIsKept(codeInspector, testedClass.getOuterClassName());
-      ClassSubject companionClass = checkClassIsKept(codeInspector, testedClass.getClassName());
-      String propertyName = "publicLateInitProp";
-      FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
-      assertTrue(fieldSubject.getField().accessFlags.isStatic());
+    runTest(
+        PACKAGE_NAME,
+        mainClass,
+        disableAggressiveClassOptimizations,
+        (app) -> {
+          CodeInspector codeInspector = new CodeInspector(app);
+          ClassSubject outerClass =
+              checkClassIsKept(codeInspector, testedClass.getOuterClassName());
 
-      MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
-      MemberNaming.MethodSignature setter = testedClass.getSetterForProperty(propertyName);
+          // Companion class has been removed because of class staticizing.
+          String companionClassName = testedClass.getClassName();
+          checkClassIsRemoved(codeInspector, companionClassName);
 
-      // Getter and setter cannot be inlined because we don't know if null check semantic is
-      // preserved.
-      checkMethodIsKept(companionClass, getter);
-      checkMethodIsKept(companionClass, setter);
-      assertTrue(fieldSubject.getField().accessFlags.isPublic());
-    });
+          String propertyName = "publicLateInitProp";
+          FieldSubject fieldSubject = checkFieldIsKept(outerClass, JAVA_LANG_STRING, propertyName);
+          assertTrue(fieldSubject.getField().accessFlags.isStatic());
+
+          MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
+          MemberNaming.MethodSignature setter = testedClass.getSetterForProperty(propertyName);
+
+          // Getter and setter cannot be inlined because we don't know if null check semantic is
+          // preserved.
+          checkMethodIsMoved(companionClassName, outerClass, getter);
+          checkMethodIsMoved(companionClassName, outerClass, setter);
+          assertTrue(fieldSubject.getField().accessFlags.isPublic());
+        });
   }
 
   @Test
@@ -773,26 +810,28 @@
     final TestKotlinClass testedClass = FILE_PROPERTY_CLASS;
     String mainClass = addMainToClasspath(
         "properties.FilePropertiesKt", "fileProperties_usePrimitiveProp");
-    runTest(PACKAGE_NAME, mainClass, disableAggressiveClassOptimizations, (app) -> {
-      CodeInspector codeInspector = new CodeInspector(app);
-      ClassSubject objectClass = checkClassIsKept(codeInspector, testedClass.getClassName());
-      String propertyName = "primitiveProp";
-      FieldSubject fieldSubject = checkFieldIsKept(objectClass, "int", propertyName);
-      assertTrue(fieldSubject.getField().accessFlags.isStatic());
+    runTest(
+        PACKAGE_NAME,
+        mainClass,
+        disableAggressiveClassOptimizations,
+        (app) -> {
+          CodeInspector codeInspector = new CodeInspector(app);
+          ClassSubject objectClass = checkClassIsKept(codeInspector, testedClass.getClassName());
+          String propertyName = "primitiveProp";
+          FieldSubject fieldSubject = checkFieldIsKept(objectClass, "int", propertyName);
+          assertTrue(fieldSubject.getField().accessFlags.isStatic());
 
-      MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
-      MemberNaming.MethodSignature setter = testedClass.getSetterForProperty(propertyName);
+          MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
+          MemberNaming.MethodSignature setter = testedClass.getSetterForProperty(propertyName);
+          checkMethodIsRemoved(objectClass, getter);
+          checkMethodIsRemoved(objectClass, setter);
 
-      if (allowAccessModification) {
-        assertTrue(fieldSubject.getField().accessFlags.isPublic());
-        checkMethodIsRemoved(objectClass, getter);
-        checkMethodIsRemoved(objectClass, setter);
-      } else {
-        assertTrue(fieldSubject.getField().accessFlags.isPrivate());
-        checkMethodIsKept(objectClass, getter);
-        checkMethodIsKept(objectClass, setter);
-      }
-    });
+          if (allowAccessModification) {
+            assertTrue(fieldSubject.getField().accessFlags.isPublic());
+          } else {
+            assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+          }
+        });
   }
 
   @Test
@@ -826,25 +865,29 @@
     final TestKotlinClass testedClass = FILE_PROPERTY_CLASS;
     String mainClass = addMainToClasspath(
         "properties.FilePropertiesKt", "fileProperties_useInternalProp");
-    runTest(PACKAGE_NAME, mainClass, disableAggressiveClassOptimizations, (app) -> {
-      CodeInspector codeInspector = new CodeInspector(app);
-      ClassSubject objectClass = checkClassIsKept(codeInspector, testedClass.getClassName());
-      String propertyName = "internalProp";
-      FieldSubject fieldSubject = checkFieldIsKept(objectClass, JAVA_LANG_STRING, propertyName);
-      assertTrue(fieldSubject.getField().accessFlags.isStatic());
+    runTest(
+        PACKAGE_NAME,
+        mainClass,
+        disableAggressiveClassOptimizations,
+        (app) -> {
+          CodeInspector codeInspector = new CodeInspector(app);
+          ClassSubject objectClass = checkClassIsKept(codeInspector, testedClass.getClassName());
+          String propertyName = "internalProp";
+          FieldSubject fieldSubject = checkFieldIsKept(objectClass, JAVA_LANG_STRING, propertyName);
+          assertTrue(fieldSubject.getField().accessFlags.isStatic());
 
-      // We expect getter to be inlined when access (of the backing field) is relaxed to public.
-      // Note: the setter is considered as a regular method (because of KotlinC adding extra null
-      // checks), thus we cannot say if the setter would be inlined or not by R8.
-      MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
-      if (allowAccessModification) {
-        assertTrue(fieldSubject.getField().accessFlags.isPublic());
-        checkMethodIsRemoved(objectClass, getter);
-      } else {
-        assertTrue(fieldSubject.getField().accessFlags.isPrivate());
-        checkMethodIsKept(objectClass, getter);
-      }
-    });
+          // We expect getter to be inlined when access (of the backing field) is relaxed to public.
+          // Note: the setter is considered as a regular method (because of KotlinC adding extra
+          // null checks), thus we cannot say if the setter would be inlined or not by R8.
+          MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
+          checkMethodIsRemoved(objectClass, getter);
+
+          if (allowAccessModification) {
+            assertTrue(fieldSubject.getField().accessFlags.isPublic());
+          } else {
+            assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+          }
+        });
   }
 
   @Test
@@ -852,26 +895,29 @@
     final TestKotlinClass testedClass = FILE_PROPERTY_CLASS;
     String mainClass = addMainToClasspath(
         "properties.FilePropertiesKt", "fileProperties_usePublicProp");
-    runTest(PACKAGE_NAME, mainClass, disableAggressiveClassOptimizations, (app) -> {
-      CodeInspector codeInspector = new CodeInspector(app);
-      ClassSubject objectClass = checkClassIsKept(codeInspector, testedClass.getClassName());
-      String propertyName = "publicProp";
-      FieldSubject fieldSubject = checkFieldIsKept(objectClass, JAVA_LANG_STRING, propertyName);
-      assertTrue(fieldSubject.getField().accessFlags.isStatic());
+    runTest(
+        PACKAGE_NAME,
+        mainClass,
+        disableAggressiveClassOptimizations,
+        (app) -> {
+          CodeInspector codeInspector = new CodeInspector(app);
+          ClassSubject objectClass = checkClassIsKept(codeInspector, testedClass.getClassName());
+          String propertyName = "publicProp";
+          FieldSubject fieldSubject = checkFieldIsKept(objectClass, JAVA_LANG_STRING, propertyName);
+          assertTrue(fieldSubject.getField().accessFlags.isStatic());
 
-      // We expect getter to be inlined when access (of the backing field) is relaxed to public.
-      // On the other hand, the setter is considered as a regular method (because of null checks),
-      // thus we cannot say if it can be inlined or not.
-      MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
+          // We expect getter to be inlined when access (of the backing field) is relaxed to public.
+          // On the other hand, the setter is considered as a regular method (because of null
+          // checks), thus we cannot say if it can be inlined or not.
+          MemberNaming.MethodSignature getter = testedClass.getGetterForProperty(propertyName);
+          checkMethodIsRemoved(objectClass, getter);
 
-      if (allowAccessModification) {
-        assertTrue(fieldSubject.getField().accessFlags.isPublic());
-        checkMethodIsRemoved(objectClass, getter);
-      } else {
-        assertTrue(fieldSubject.getField().accessFlags.isPrivate());
-        checkMethodIsKept(objectClass, getter);
-      }
-    });
+          if (allowAccessModification) {
+            assertTrue(fieldSubject.getField().accessFlags.isPublic());
+          } else {
+            assertTrue(fieldSubject.getField().accessFlags.isPrivate());
+          }
+        });
   }
 
   @Test
diff --git a/src/test/java/com/android/tools/r8/naming/NamingTestBase.java b/src/test/java/com/android/tools/r8/naming/NamingTestBase.java
index 1e5d3f6..5cba429 100644
--- a/src/test/java/com/android/tools/r8/naming/NamingTestBase.java
+++ b/src/test/java/com/android/tools/r8/naming/NamingTestBase.java
@@ -8,7 +8,6 @@
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexApplication;
 import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.GraphLense;
 import com.android.tools.r8.shaking.Enqueuer;
 import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 import com.android.tools.r8.shaking.ProguardConfiguration;
@@ -69,18 +68,15 @@
 
     ExecutorService executor = ThreadUtils.getExecutorService(1);
 
-    AppView<AppInfoWithSubtyping> appView =
-        new AppView<>(new AppInfoWithSubtyping(program), GraphLense.getIdentityLense(), options);
+    AppView<? extends AppInfoWithSubtyping> appView =
+        AppView.createForR8(new AppInfoWithSubtyping(program), options);
     RootSet rootSet =
         new RootSetBuilder(appView, program, configuration.getRules(), options).run(executor);
 
     Enqueuer enqueuer = new Enqueuer(appView, options, null);
     AppInfoWithLiveness appInfo =
         enqueuer.traceApplication(rootSet, configuration.getDontWarnPatterns(), executor, timing);
-    return new Minifier(
-        new AppView<>(appInfo, GraphLense.getIdentityLense(), options),
-        rootSet,
-        Collections.emptySet())
+    return new Minifier(AppView.createForR8(appInfo, options), rootSet, Collections.emptySet())
         .run(timing);
   }
 
diff --git a/src/test/java/com/android/tools/r8/naming/ProguardMapReaderTest.java b/src/test/java/com/android/tools/r8/naming/ProguardMapReaderTest.java
index 7cb49d3..841b6cd 100644
--- a/src/test/java/com/android/tools/r8/naming/ProguardMapReaderTest.java
+++ b/src/test/java/com/android/tools/r8/naming/ProguardMapReaderTest.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.naming;
 
 import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.position.Position;
 import com.google.common.collect.ImmutableList;
 import java.io.IOException;
 import java.nio.file.Paths;
@@ -51,7 +52,7 @@
   public void parseIdentifierArrowAmbiguity1() throws IOException {
     ClassNameMapper mapper = ClassNameMapper.mapperFromString("a->b:");
     ClassNameMapper.Builder builder = ClassNameMapper.builder();
-    builder.classNamingBuilder("b", "a");
+    builder.classNamingBuilder("b", "a", Position.UNKNOWN);
     Assert.assertEquals(builder.build(), mapper);
   }
 
@@ -59,7 +60,7 @@
   public void parseIdentifierArrowAmbiguity2() throws IOException {
     ClassNameMapper mapper = ClassNameMapper.mapperFromString("-->b:");
     ClassNameMapper.Builder builder = ClassNameMapper.builder();
-    builder.classNamingBuilder("b", "-");
+    builder.classNamingBuilder("b", "-", Position.UNKNOWN);
     Assert.assertEquals(builder.build(), mapper);
   }
 
diff --git a/src/test/java/com/android/tools/r8/naming/SeedMapperTests.java b/src/test/java/com/android/tools/r8/naming/SeedMapperTests.java
new file mode 100644
index 0000000..91da18d
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/naming/SeedMapperTests.java
@@ -0,0 +1,165 @@
+// Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.naming;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import com.android.tools.r8.Diagnostic;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestDiagnosticMessagesImpl;
+import com.android.tools.r8.position.TextPosition;
+import com.android.tools.r8.utils.AbortException;
+import com.android.tools.r8.utils.FileUtils;
+import com.android.tools.r8.utils.Reporter;
+import java.io.IOException;
+import java.nio.file.Path;
+import org.junit.Test;
+
+public class SeedMapperTests extends TestBase {
+
+  private Path getApplyMappingFile(String... pgMap) throws IOException {
+    Path mapPath = temp.newFile().toPath();
+    FileUtils.writeTextFile(mapPath, pgMap);
+    return mapPath;
+  }
+
+  @Test
+  public void testNoDuplicates() throws IOException {
+    Path applyMappingFile =
+        getApplyMappingFile(
+            "A.B.C -> a:",
+            "  int aaaa(B) -> a",
+            "  int bbbb(B) -> b",
+            "  void cccc() -> a",
+            "  B foo       -> a",
+            "A.B.D -> b:",
+            "  int aaaa(B) -> a");
+    TestDiagnosticMessagesImpl testDiagnosticMessages = new TestDiagnosticMessagesImpl();
+    Reporter reporter = new Reporter(testDiagnosticMessages);
+    SeedMapper.seedMapperFromFile(reporter, applyMappingFile);
+    testDiagnosticMessages.assertNoMessages();
+  }
+
+  @Test
+  public void testDuplicateSourceClasses() throws IOException {
+    Path applyMappingFile = getApplyMappingFile("A.B.C -> a:", "A.B.C -> b:");
+    TestDiagnosticMessagesImpl testDiagnosticMessages = new TestDiagnosticMessagesImpl();
+    Reporter reporter = new Reporter(testDiagnosticMessages);
+    try {
+      SeedMapper.seedMapperFromFile(reporter, applyMappingFile);
+      fail("Should have thrown an error");
+    } catch (AbortException e) {
+      assertEquals(1, testDiagnosticMessages.getErrors().size());
+      Diagnostic diagnostic = testDiagnosticMessages.getErrors().get(0);
+      assertEquals(
+          String.format(ProguardMapError.DUPLICATE_SOURCE_MESSAGE, "A.B.C"),
+          diagnostic.getDiagnosticMessage());
+      assertEquals(2, ((TextPosition) diagnostic.getPosition()).getLine());
+    }
+  }
+
+  @Test
+  public void testDuplicateSourceMethods() throws IOException {
+    Path applyMappingFile =
+        getApplyMappingFile(
+            "A.B.C -> a:",
+            "  int aaaa(B) -> a",
+            "  int aaaa(B) -> a",
+            "A.B.D -> b:");
+    TestDiagnosticMessagesImpl testDiagnosticMessages = new TestDiagnosticMessagesImpl();
+    Reporter reporter = new Reporter(testDiagnosticMessages);
+    try {
+      SeedMapper.seedMapperFromFile(reporter, applyMappingFile);
+      fail("Should have thrown an error");
+    } catch (AbortException e) {
+      assertEquals(1, testDiagnosticMessages.getErrors().size());
+      Diagnostic diagnostic = testDiagnosticMessages.getErrors().get(0);
+      assertEquals(
+          String.format(ProguardMapError.DUPLICATE_SOURCE_MESSAGE, "int aaaa(B)"),
+          diagnostic.getDiagnosticMessage());
+      assertEquals(3, ((TextPosition) diagnostic.getPosition()).getLine());
+    }
+  }
+
+  @Test
+  public void testDuplicateSourceFields() throws IOException {
+    Path applyMappingFile =
+        getApplyMappingFile(
+            "A.B.C -> a:",
+            "  int aaaa -> a",
+            "  int aaaa -> a",
+            "A.B.D -> b:");
+    TestDiagnosticMessagesImpl testDiagnosticMessages = new TestDiagnosticMessagesImpl();
+    Reporter reporter = new Reporter(testDiagnosticMessages);
+    try {
+      SeedMapper.seedMapperFromFile(reporter, applyMappingFile);
+      fail("Should have thrown an error");
+    } catch (AbortException e) {
+      assertEquals(1, testDiagnosticMessages.getErrors().size());
+      Diagnostic diagnostic = testDiagnosticMessages.getErrors().get(0);
+      assertEquals(
+          String.format(ProguardMapError.DUPLICATE_SOURCE_MESSAGE, "int aaaa"),
+          diagnostic.getDiagnosticMessage());
+      assertEquals(3, ((TextPosition) diagnostic.getPosition()).getLine());
+    }
+  }
+
+  @Test
+  public void testDuplicateClassTargets() throws IOException {
+    Path applyMappingFile = getApplyMappingFile("A.B.C -> a:", "A.B.D -> a:");
+    TestDiagnosticMessagesImpl testDiagnosticMessages = new TestDiagnosticMessagesImpl();
+    Reporter reporter = new Reporter(testDiagnosticMessages);
+    try {
+      SeedMapper.seedMapperFromFile(reporter, applyMappingFile);
+      fail("Should have thrown an error");
+    } catch (AbortException e) {
+      assertEquals(1, testDiagnosticMessages.getErrors().size());
+      Diagnostic diagnostic = testDiagnosticMessages.getErrors().get(0);
+      assertEquals(
+          String.format(ProguardMapError.DUPLICATE_TARGET_MESSAGE, "A.B.D", "A.B.C", "a"),
+          diagnostic.getDiagnosticMessage());
+      assertEquals(2, ((TextPosition) diagnostic.getPosition()).getLine());
+    }
+  }
+
+  @Test
+  public void testSameNameMethodTargets() throws IOException {
+    Path applyMappingFile =
+        getApplyMappingFile(
+            "A.B.C -> A:",
+            "  int foo(A) -> a",
+            "  int bar(B) -> a",
+            "  int baz(A,B) -> a",
+            "A.B.D -> b:");
+    TestDiagnosticMessagesImpl testDiagnosticMessages = new TestDiagnosticMessagesImpl();
+    Reporter reporter = new Reporter(testDiagnosticMessages);
+    SeedMapper.seedMapperFromFile(reporter, applyMappingFile);
+    testDiagnosticMessages.assertNoMessages();
+  }
+
+  @Test
+  public void testDuplicateMethodTargets() throws IOException {
+    Path applyMappingFile =
+        getApplyMappingFile(
+            "A.B.C -> a:",
+            "  int foo(A) -> a",
+            "  int bar(A) -> a",
+            "A.B.D -> b:");
+    TestDiagnosticMessagesImpl testDiagnosticMessages = new TestDiagnosticMessagesImpl();
+    Reporter reporter = new Reporter(testDiagnosticMessages);
+    try {
+      SeedMapper.seedMapperFromFile(reporter, applyMappingFile);
+      fail("Should have thrown an error");
+    } catch (AbortException e) {
+      assertEquals(1, testDiagnosticMessages.getErrors().size());
+      Diagnostic diagnostic = testDiagnosticMessages.getErrors().get(0);
+      assertEquals(
+          String.format(ProguardMapError.DUPLICATE_TARGET_MESSAGE, "int bar(A)", "int foo(A)", "a"),
+          diagnostic.getDiagnosticMessage());
+      assertEquals(2, ((TextPosition) diagnostic.getPosition()).getLine());
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/naming/applymapping/shared/NameClashTest.java b/src/test/java/com/android/tools/r8/naming/applymapping/shared/NameClashTest.java
index 048f281..0fdbe2d 100644
--- a/src/test/java/com/android/tools/r8/naming/applymapping/shared/NameClashTest.java
+++ b/src/test/java/com/android/tools/r8/naming/applymapping/shared/NameClashTest.java
@@ -76,7 +76,7 @@
   // 2) otherwise, those classes/members will be renamed if minification is enabled, resulting in
   //   no name clash, which is definitely not intended.
 
-  private String mappingToExistingClassName() {
+  private String mappingToAlreadyMappedName() {
     return StringUtils.lines(
         LibraryClass.class.getTypeName()
             + " -> " + AnotherLibraryClass.class.getTypeName() + ":",
@@ -102,6 +102,13 @@
     );
   }
 
+  private String mappingToExistingClassName() {
+    return StringUtils.lines(
+        LibraryClass.class.getTypeName() + " -> " + ProgramClass.class.getTypeName() + ":",
+        "  void foo() -> bar",
+        AnotherLibraryClass.class.getTypeName() + " -> B:");
+  }
+
   private String mappingToTheSameMethodName() {
     return StringUtils.lines(
         LibraryClass.class.getTypeName() + " -> A:",
@@ -188,7 +195,7 @@
 
   @Test
   public void testProguard_prgClassRenamedToExistingPrgClass() throws Exception {
-    FileUtils.writeTextFile(mappingFile, mappingToExistingClassName());
+    FileUtils.writeTextFile(mappingFile, mappingToAlreadyMappedName());
     try {
       testProguard_inputJar(mappingFile);
       fail("Expect compilation failure.");
@@ -198,22 +205,22 @@
     }
   }
 
-  @Ignore("b/123092153")
   @Test
   public void testR8_prgClassRenamedToExistingPrgClass() throws Exception {
-    FileUtils.writeTextFile(mappingFile, mappingToExistingClassName());
+    FileUtils.writeTextFile(mappingFile, mappingToAlreadyMappedName());
     try {
       testR8_inputJar(mappingFile);
       fail("Expect compilation failure.");
     } catch (CompilationFailedException e) {
-      assertThat(e.getCause().getMessage(), containsString("Program type already present"));
-      assertThat(e.getCause().getMessage(), containsString("AnotherLibraryClass"));
+      assertThat(e.getCause().getMessage(), containsString("map to same name"));
+      assertThat(e.getCause().getMessage(), containsString("$AnotherLibraryClass"));
+      assertThat(e.getCause().getMessage(), containsString("$LibraryClass"));
     }
   }
 
   @Test
   public void testProguard_originalLibClassRenamedToExistingLibClass() throws Exception {
-    FileUtils.writeTextFile(mappingFile, mappingToExistingClassName());
+    FileUtils.writeTextFile(mappingFile, mappingToAlreadyMappedName());
     try {
       testProguard_originalLibraryJar(mappingFile);
       fail("Expect compilation failure.");
@@ -223,11 +230,17 @@
     }
   }
 
-  @Ignore("b/123092153")
   @Test
-  public void testR8_originalLibClassRenamedToExistingLibClass() throws Exception {
-    FileUtils.writeTextFile(mappingFile, mappingToExistingClassName());
-    testR8_originalLibraryJar(mappingFile);
+  public void testR8_originalLibClassRenamedToSameLibClass() throws Exception {
+    FileUtils.writeTextFile(mappingFile, mappingToAlreadyMappedName());
+    try {
+      testR8_originalLibraryJar(mappingFile);
+      fail("Expect compilation failure.");
+    } catch (CompilationFailedException e) {
+      assertThat(e.getCause().getMessage(), containsString("map to same name"));
+      assertThat(e.getCause().getMessage(), containsString("$AnotherLibraryClass"));
+      assertThat(e.getCause().getMessage(), containsString("$LibraryClass"));
+    }
   }
 
   @Test
@@ -241,7 +254,6 @@
     }
   }
 
-  @Ignore("b/123092153")
   @Test
   public void testR8_prgClassesRenamedToSameName() throws Exception {
     FileUtils.writeTextFile(mappingFile, mappingToTheSameClassName());
@@ -249,7 +261,7 @@
       testR8_inputJar(mappingFile);
       fail("Expect compilation failure.");
     } catch (CompilationFailedException e) {
-      assertThat(e.getCause().getMessage(), containsString("Program type already present"));
+      assertThat(e.getCause().getMessage(), containsString("map to same name"));
       assertThat(e.getCause().getMessage(), containsString("Clash"));
     }
   }
@@ -266,11 +278,16 @@
     }
   }
 
-  @Ignore("b/123092153")
   @Test
   public void testR8_originalLibClassesRenamedToSameName() throws Exception {
     FileUtils.writeTextFile(mappingFile, mappingToTheSameClassName());
-    testR8_originalLibraryJar(mappingFile);
+    try {
+      testR8_originalLibraryJar(mappingFile);
+      fail("Expect compilation failure.");
+    } catch (CompilationFailedException e) {
+      assertThat(e.getCause().getMessage(), containsString("map to same name"));
+      assertThat(e.getCause().getMessage(), containsString("Clash"));
+    }
   }
 
   @Test
@@ -286,7 +303,6 @@
     }
   }
 
-  @Ignore("b/123092153")
   @Test
   public void testR8_prgMethodRenamedToExistingName() throws Exception {
     FileUtils.writeTextFile(mappingFile, mappingToExistingMethodName());
@@ -294,9 +310,13 @@
       testR8_inputJar(mappingFile);
       fail("Expect compilation failure.");
     } catch (CompilationFailedException e) {
-      assertThat(e.getMessage(), containsString("method 'void bar()' can't be mapped to 'bar'"));
-      assertThat(e.getMessage(), containsString("it would conflict with method 'foo'"));
-      assertThat(e.getMessage(), containsString("which is already being mapped to 'bar'"));
+      assertThat(e.getCause().getMessage(), containsString("cannot be mapped to 'bar'"));
+      assertThat(
+          e.getCause().getMessage(),
+          containsString(
+              "because it is in conflict with an existing member with the same signature."));
+      assertThat(
+          e.getCause().getMessage(), containsString(ProgramClass.class.getTypeName() + ".bar()"));
     }
   }
 
@@ -312,11 +332,21 @@
     }
   }
 
-  @Ignore("b/123092153")
   @Test
   public void testR8_originalLibMethodRenamedToExistingName() throws Exception {
     FileUtils.writeTextFile(mappingFile, mappingToExistingMethodName());
-    testR8_originalLibraryJar(mappingFile);
+    try {
+      testR8_originalLibraryJar(mappingFile);
+      fail("Expect compilation failure.");
+    } catch (CompilationFailedException e) {
+      assertThat(e.getCause().getMessage(), containsString("cannot be mapped to 'bar'"));
+      assertThat(
+          e.getCause().getMessage(),
+          containsString(
+              "because it is in conflict with an existing member with the same signature."));
+      assertThat(
+          e.getCause().getMessage(), containsString(ProgramClass.class.getTypeName() + ".bar()"));
+    }
   }
 
   @Test
@@ -332,7 +362,6 @@
     }
   }
 
-  @Ignore("b/123092153")
   @Test
   public void testR8_prgMethodRenamedToSameName() throws Exception {
     FileUtils.writeTextFile(mappingFile, mappingToTheSameMethodName());
@@ -340,9 +369,13 @@
       testR8_inputJar(mappingFile);
       fail("Expect compilation failure.");
     } catch (CompilationFailedException e) {
-      assertThat(e.getMessage(), containsString("method 'void bar()' can't be mapped to 'bar'"));
-      assertThat(e.getMessage(), containsString("it would conflict with method 'foo'"));
-      assertThat(e.getMessage(), containsString("which is already being mapped to 'bar'"));
+      assertThat(e.getCause().getMessage(), containsString("cannot be mapped to 'clash'"));
+      assertThat(
+          e.getCause().getMessage(),
+          containsString(
+              "because it is in conflict with an existing member with the same signature."));
+      assertThat(
+          e.getCause().getMessage(), containsString(ProgramClass.class.getTypeName() + ".bar()"));
     }
   }
 
@@ -358,11 +391,36 @@
     }
   }
 
-  @Ignore("b/123092153")
   @Test
   public void testR8_originalLibMethodRenamedToSameName() throws Exception {
     FileUtils.writeTextFile(mappingFile, mappingToTheSameMethodName());
-    testR8_originalLibraryJar(mappingFile);
+    try {
+      testR8_originalLibraryJar(mappingFile);
+      fail("Expect compilation failure.");
+    } catch (CompilationFailedException e) {
+      assertThat(e.getCause().getMessage(), containsString("cannot be mapped to 'clash'"));
+      assertThat(
+          e.getCause().getMessage(),
+          containsString(
+              "because it is in conflict with an existing member with the same signature."));
+      assertThat(
+          e.getCause().getMessage(), containsString(ProgramClass.class.getTypeName() + ".bar()"));
+    }
+  }
+
+  @Test
+  public void testR8_originalLibClassRenamedToExistingName() throws Exception {
+    FileUtils.writeTextFile(mappingFile, mappingToExistingClassName());
+    try {
+      testR8_originalLibraryJar(mappingFile);
+      fail("Expect compilation failure.");
+    } catch (CompilationFailedException e) {
+      assertThat(e.getCause().getMessage(), containsString("cannot be mapped to"));
+      assertThat(
+          e.getCause().getMessage(),
+          containsString("because it is in conflict with an existing class with the same name."));
+      assertThat(e.getCause().getMessage(), containsString(ProgramClass.class.getTypeName()));
+    }
   }
 
   @Test
diff --git a/src/test/java/com/android/tools/r8/resolution/SingleTargetLookupTest.java b/src/test/java/com/android/tools/r8/resolution/SingleTargetLookupTest.java
index 7ec1613..a9ce818 100644
--- a/src/test/java/com/android/tools/r8/resolution/SingleTargetLookupTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/SingleTargetLookupTest.java
@@ -12,7 +12,6 @@
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.GraphLense;
 import com.android.tools.r8.resolution.singletarget.Main;
 import com.android.tools.r8.resolution.singletarget.one.AbstractSubClass;
 import com.android.tools.r8.resolution.singletarget.one.AbstractTopClass;
@@ -105,8 +104,7 @@
     AndroidApp app = readClassesAndAsmDump(CLASSES, ASM_CLASSES);
     DexApplication application = new ApplicationReader(app, options, timing).read().toDirect();
     AppView<? extends AppInfoWithSubtyping> appView =
-        new AppView<>(
-            new AppInfoWithSubtyping(application), GraphLense.getIdentityLense(), options);
+        AppView.createForR8(new AppInfoWithSubtyping(application), options);
 
     ExecutorService executor = Executors.newSingleThreadExecutor();
     RootSet rootSet =
diff --git a/third_party/opensource_apps.tar.gz.sha1 b/third_party/opensource_apps.tar.gz.sha1
index 1c81fa1..cf48de7 100644
--- a/third_party/opensource_apps.tar.gz.sha1
+++ b/third_party/opensource_apps.tar.gz.sha1
@@ -1 +1 @@
-402a7c84fe03ecba7e6c0ee7947fd215d981fd2e
\ No newline at end of file
+0d99c09e8fd3ab48bae4642147bcbff26a474ca8
\ No newline at end of file
diff --git a/tools/run_on_as_app.py b/tools/run_on_as_app.py
index b9e17ab..e0e2df1 100755
--- a/tools/run_on_as_app.py
+++ b/tools/run_on_as_app.py
@@ -138,7 +138,7 @@
   Repo({
       'name': 'chanu',
       'url': 'https://github.com/mkj-gram/chanu.git',
-      'revision': '04ade1e9c33d707f0850d5eb9d6fa5e8af814a26',
+      'revision': 'f5dae10b965974f7bf7cf75b8fa80ba9c844f102',
       'apps': [
           App({
               'id': 'com.chanapps.four.activity'
@@ -208,7 +208,7 @@
   Repo({
       'name': 'rover-android',
       'url': 'https://github.com/mkj-gram/rover-android.git',
-      'revision': '859af82ba56fe9035ae9949156c7a88e6012d930',
+      'revision': 'a5e155a1ed7d19b1cecd9a7b075e2852623a06bf',
       'apps': [
           App({
               'id': 'io.rover.app.debug',
@@ -219,7 +219,7 @@
   Repo({
       'name': 'Signal-Android',
       'url': 'https://github.com/mkj-gram/Signal-Android.git',
-      'revision': 'a45d0c1fed20fa39e8b9445fe7790326f46b3166',
+      'revision': 'cd542cab9bf860e71504ecb1caaf0a8476ba3989',
       'apps': [
           App({
               'id': 'org.thoughtcrime.securesms',
@@ -284,7 +284,7 @@
   Repo({
       'name': 'Tusky',
       'url': 'https://github.com/mkj-gram/Tusky.git',
-      'revision': 'b794f3ab90388add98461ffe70edb65c39351c33',
+      'revision': 'e7fbd190fb53bf9fde72253b816920cb6fe34518',
       'apps': [
           App({
               'id': 'com.keylesspalace.tusky',
@@ -295,7 +295,7 @@
   Repo({
       'name': 'Vungle-Android-SDK',
       'url': 'https://github.com/mkj-gram/Vungle-Android-SDK.git',
-      'revision': '3e231396ea7ce97b2655e03607497c75730e45f6',
+      'revision': '138d3f18c027b61b195c98911f1c5ab7d87ad18b',
       'apps': [
           App({
               'id': 'com.publisher.vungle.sample'