Move out inner classes of GraphLens to graph.lens

Change-Id: If12479ce237d2359106cbaa769657e6c2a27e29e
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java b/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java
index 0942ee5..a0f3d5e 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java
@@ -19,8 +19,8 @@
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.graph.UseRegistry;
 import com.android.tools.r8.graph.lens.GraphLens;
-import com.android.tools.r8.graph.lens.GraphLens.MethodLookupResult;
 import com.android.tools.r8.graph.lens.InitClassLens;
+import com.android.tools.r8.graph.lens.MethodLookupResult;
 import com.android.tools.r8.ir.code.InvokeType;
 import com.android.tools.r8.ir.code.ValueType;
 import com.android.tools.r8.ir.conversion.CfSourceCode;
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexFormat45cc.java b/src/main/java/com/android/tools/r8/dex/code/DexFormat45cc.java
index 40f1e17..0718573 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexFormat45cc.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexFormat45cc.java
@@ -12,7 +12,7 @@
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.graph.lens.GraphLens;
-import com.android.tools.r8.graph.lens.GraphLens.MethodLookupResult;
+import com.android.tools.r8.graph.lens.MethodLookupResult;
 import com.android.tools.r8.ir.code.InvokeType;
 import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.utils.RetracerForCodePrinting;
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexFormat4rcc.java b/src/main/java/com/android/tools/r8/dex/code/DexFormat4rcc.java
index 8249a35..e4ec21d 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexFormat4rcc.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexFormat4rcc.java
@@ -12,7 +12,7 @@
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.graph.lens.GraphLens;
-import com.android.tools.r8.graph.lens.GraphLens.MethodLookupResult;
+import com.android.tools.r8.graph.lens.MethodLookupResult;
 import com.android.tools.r8.ir.code.InvokeType;
 import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.utils.RetracerForCodePrinting;
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexInvokeMethod.java b/src/main/java/com/android/tools/r8/dex/code/DexInvokeMethod.java
index b39e748..763b823 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexInvokeMethod.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexInvokeMethod.java
@@ -9,7 +9,7 @@
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.graph.lens.GraphLens;
-import com.android.tools.r8.graph.lens.GraphLens.MethodLookupResult;
+import com.android.tools.r8.graph.lens.MethodLookupResult;
 import com.android.tools.r8.ir.code.InvokeType;
 import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import java.nio.ShortBuffer;
diff --git a/src/main/java/com/android/tools/r8/dex/code/DexInvokeMethodRange.java b/src/main/java/com/android/tools/r8/dex/code/DexInvokeMethodRange.java
index d274de0..8809f06 100644
--- a/src/main/java/com/android/tools/r8/dex/code/DexInvokeMethodRange.java
+++ b/src/main/java/com/android/tools/r8/dex/code/DexInvokeMethodRange.java
@@ -9,7 +9,7 @@
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.graph.lens.GraphLens;
-import com.android.tools.r8.graph.lens.GraphLens.MethodLookupResult;
+import com.android.tools.r8.graph.lens.MethodLookupResult;
 import com.android.tools.r8.ir.code.InvokeType;
 import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import java.nio.ShortBuffer;
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 4d3f51c..919de23 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -15,8 +15,8 @@
 import com.android.tools.r8.graph.classmerging.MergedClassesCollection;
 import com.android.tools.r8.graph.classmerging.VerticallyMergedClasses;
 import com.android.tools.r8.graph.lens.GraphLens;
-import com.android.tools.r8.graph.lens.GraphLens.NonIdentityGraphLens;
 import com.android.tools.r8.graph.lens.InitClassLens;
+import com.android.tools.r8.graph.lens.NonIdentityGraphLens;
 import com.android.tools.r8.horizontalclassmerging.HorizontalClassMerger;
 import com.android.tools.r8.horizontalclassmerging.HorizontallyMergedClasses;
 import com.android.tools.r8.ir.analysis.inlining.SimpleInliningConstraintFactory;
diff --git a/src/main/java/com/android/tools/r8/graph/DefaultInstanceInitializerCode.java b/src/main/java/com/android/tools/r8/graph/DefaultInstanceInitializerCode.java
index 1bae17e..06fd92e 100644
--- a/src/main/java/com/android/tools/r8/graph/DefaultInstanceInitializerCode.java
+++ b/src/main/java/com/android/tools/r8/graph/DefaultInstanceInitializerCode.java
@@ -17,7 +17,7 @@
 import com.android.tools.r8.graph.DexCode.Try;
 import com.android.tools.r8.graph.DexCode.TryHandler;
 import com.android.tools.r8.graph.lens.GraphLens;
-import com.android.tools.r8.graph.lens.GraphLens.MethodLookupResult;
+import com.android.tools.r8.graph.lens.MethodLookupResult;
 import com.android.tools.r8.graph.proto.RewrittenPrototypeDescription;
 import com.android.tools.r8.ir.code.IRCode;
 import com.android.tools.r8.ir.code.NumberGenerator;
diff --git a/src/main/java/com/android/tools/r8/graph/MethodAccessInfoCollection.java b/src/main/java/com/android/tools/r8/graph/MethodAccessInfoCollection.java
index e2eaa8a..b4dbc3d 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodAccessInfoCollection.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodAccessInfoCollection.java
@@ -5,7 +5,7 @@
 package com.android.tools.r8.graph;
 
 import com.android.tools.r8.graph.lens.GraphLens;
-import com.android.tools.r8.graph.lens.GraphLens.MethodLookupResult;
+import com.android.tools.r8.graph.lens.MethodLookupResult;
 import com.android.tools.r8.ir.code.InvokeType;
 import com.android.tools.r8.utils.ConsumerUtils;
 import com.android.tools.r8.utils.collections.ProgramMethodSet;
diff --git a/src/main/java/com/android/tools/r8/graph/lens/AppliedGraphLens.java b/src/main/java/com/android/tools/r8/graph/lens/AppliedGraphLens.java
index 707cf1e..d5c02df 100644
--- a/src/main/java/com/android/tools/r8/graph/lens/AppliedGraphLens.java
+++ b/src/main/java/com/android/tools/r8/graph/lens/AppliedGraphLens.java
@@ -12,7 +12,6 @@
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.lens.GraphLens.NonIdentityGraphLens;
 import com.android.tools.r8.graph.proto.RewrittenPrototypeDescription;
 import com.android.tools.r8.utils.MapUtils;
 import com.android.tools.r8.utils.collections.BidirectionalManyToOneRepresentativeHashMap;
diff --git a/src/main/java/com/android/tools/r8/graph/lens/ClearCodeRewritingGraphLens.java b/src/main/java/com/android/tools/r8/graph/lens/ClearCodeRewritingGraphLens.java
new file mode 100644
index 0000000..029ccdd
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/lens/ClearCodeRewritingGraphLens.java
@@ -0,0 +1,109 @@
+// Copyright (c) 2023, 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.lens;
+
+import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.graph.DexField;
+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.proto.RewrittenPrototypeDescription;
+import com.android.tools.r8.ir.code.InvokeType;
+
+// This lens clears all code rewriting (lookup methods mimics identity lens behavior) but still
+// relies on the previous lens for names (getRenamed/Original methods).
+public class ClearCodeRewritingGraphLens extends NonIdentityGraphLens {
+
+  public ClearCodeRewritingGraphLens(DexItemFactory dexItemFactory, GraphLens previousLens) {
+    super(dexItemFactory, previousLens);
+  }
+
+  @Override
+  public DexType getOriginalType(DexType type) {
+    return getPrevious().getOriginalType(type);
+  }
+
+  @Override
+  public Iterable<DexType> getOriginalTypes(DexType type) {
+    return getPrevious().getOriginalTypes(type);
+  }
+
+  @Override
+  public DexField getOriginalFieldSignature(DexField field) {
+    return getPrevious().getOriginalFieldSignature(field);
+  }
+
+  @Override
+  public DexField getRenamedFieldSignature(DexField originalField, GraphLens codeLens) {
+    return this != codeLens ? getPrevious().getRenamedFieldSignature(originalField) : originalField;
+  }
+
+  @Override
+  public DexMethod getRenamedMethodSignature(DexMethod originalMethod, GraphLens applied) {
+    return this != applied
+        ? getPrevious().getRenamedMethodSignature(originalMethod, applied)
+        : originalMethod;
+  }
+
+  @Override
+  public boolean isClearCodeRewritingLens() {
+    return true;
+  }
+
+  @Override
+  public RewrittenPrototypeDescription lookupPrototypeChangesForMethodDefinition(
+      DexMethod method, GraphLens codeLens) {
+    return getIdentityLens().lookupPrototypeChangesForMethodDefinition(method, codeLens);
+  }
+
+  @Override
+  public final DexType internalDescribeLookupClassType(DexType previous) {
+    return previous;
+  }
+
+  @Override
+  protected FieldLookupResult internalLookupField(
+      DexField reference, GraphLens codeLens, LookupFieldContinuation continuation) {
+    return getIdentityLens().internalLookupField(reference, codeLens, continuation);
+  }
+
+  @Override
+  protected FieldLookupResult internalDescribeLookupField(FieldLookupResult previous) {
+    throw new Unreachable();
+  }
+
+  @Override
+  protected MethodLookupResult internalLookupMethod(
+      DexMethod reference,
+      DexMethod context,
+      InvokeType type,
+      GraphLens codeLens,
+      LookupMethodContinuation continuation) {
+    assert codeLens == null || codeLens == this;
+    GraphLens identityLens = getIdentityLens();
+    return identityLens.internalLookupMethod(reference, context, type, identityLens, continuation);
+  }
+
+  @Override
+  public MethodLookupResult internalDescribeLookupMethod(
+      MethodLookupResult previous, DexMethod context) {
+    throw new Unreachable();
+  }
+
+  @Override
+  public DexMethod getPreviousMethodSignature(DexMethod method) {
+    return method;
+  }
+
+  @Override
+  public DexMethod getNextMethodSignature(DexMethod method) {
+    return method;
+  }
+
+  @Override
+  public boolean isContextFreeForMethods() {
+    return getIdentityLens().isContextFreeForMethods();
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/graph/lens/FieldLookupResult.java b/src/main/java/com/android/tools/r8/graph/lens/FieldLookupResult.java
new file mode 100644
index 0000000..b031af1
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/lens/FieldLookupResult.java
@@ -0,0 +1,85 @@
+// Copyright (c) 2023, 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.lens;
+
+import com.android.tools.r8.graph.DexField;
+import com.android.tools.r8.graph.DexType;
+import java.util.function.Function;
+
+/**
+ * Intermediate result of a field lookup that stores the actual non-rebound reference and the
+ * rebound reference that points to the definition of the field.
+ */
+public class FieldLookupResult extends MemberLookupResult<DexField> {
+
+  private final DexType readCastType;
+  private final DexType writeCastType;
+
+  private FieldLookupResult(
+      DexField reference, DexField reboundReference, DexType readCastType, DexType writeCastType) {
+    super(reference, reboundReference);
+    this.readCastType = readCastType;
+    this.writeCastType = writeCastType;
+  }
+
+  public static Builder builder(GraphLens lens) {
+    return new Builder(lens);
+  }
+
+  public boolean hasReadCastType() {
+    return readCastType != null;
+  }
+
+  public DexType getReadCastType() {
+    return readCastType;
+  }
+
+  public DexType getRewrittenReadCastType(Function<DexType, DexType> fn) {
+    return hasReadCastType() ? fn.apply(readCastType) : null;
+  }
+
+  public boolean hasWriteCastType() {
+    return writeCastType != null;
+  }
+
+  public DexType getWriteCastType() {
+    return writeCastType;
+  }
+
+  public DexType getRewrittenWriteCastType(Function<DexType, DexType> fn) {
+    return hasWriteCastType() ? fn.apply(writeCastType) : null;
+  }
+
+  public static class Builder extends MemberLookupResult.Builder<DexField, Builder> {
+
+    private DexType readCastType;
+    private DexType writeCastType;
+    private GraphLens lens;
+
+    private Builder(GraphLens lens) {
+      this.lens = lens;
+    }
+
+    public Builder setReadCastType(DexType readCastType) {
+      this.readCastType = readCastType;
+      return this;
+    }
+
+    public Builder setWriteCastType(DexType writeCastType) {
+      this.writeCastType = writeCastType;
+      return this;
+    }
+
+    @Override
+    public Builder self() {
+      return this;
+    }
+
+    public FieldLookupResult build() {
+      // TODO(b/168282032): All non-identity graph lenses should set the rebound reference.
+      return new FieldLookupResult(reference, reboundReference, readCastType, writeCastType);
+    }
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/graph/lens/GraphLens.java b/src/main/java/com/android/tools/r8/graph/lens/GraphLens.java
index 1e326e3..bd71700 100644
--- a/src/main/java/com/android/tools/r8/graph/lens/GraphLens.java
+++ b/src/main/java/com/android/tools/r8/graph/lens/GraphLens.java
@@ -5,7 +5,6 @@
 
 import static com.android.tools.r8.graph.DexProgramClass.asProgramClassOrNull;
 
-import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexApplication;
 import com.android.tools.r8.graph.DexCallSite;
@@ -29,13 +28,10 @@
 import com.android.tools.r8.optimize.MemberRebindingIdentityLens;
 import com.android.tools.r8.optimize.MemberRebindingLens;
 import com.android.tools.r8.shaking.KeepInfoCollection;
-import com.android.tools.r8.utils.Action;
 import com.android.tools.r8.utils.InternalOptions;
-import com.android.tools.r8.utils.IterableUtils;
 import com.android.tools.r8.utils.ListUtils;
 import com.android.tools.r8.utils.SetUtils;
 import com.android.tools.r8.utils.collections.BidirectionalManyToOneRepresentativeHashMap;
-import com.android.tools.r8.utils.collections.BidirectionalManyToOneRepresentativeMap;
 import com.android.tools.r8.utils.collections.MutableBidirectionalManyToOneRepresentativeMap;
 import com.android.tools.r8.utils.collections.ProgramMethodSet;
 import com.google.common.collect.ImmutableMap;
@@ -48,10 +44,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
 import java.util.function.BiFunction;
-import java.util.function.Function;
-import java.util.function.Predicate;
 
 /**
  * A GraphLens implements a virtual view on top of the graph, used to delay global rewrites until
@@ -71,211 +64,6 @@
  */
 public abstract class GraphLens {
 
-  abstract static class MemberLookupResult<R extends DexMember<?, R>> {
-
-    private final R reference;
-    private final R reboundReference;
-
-    private MemberLookupResult(R reference, R reboundReference) {
-      this.reference = reference;
-      this.reboundReference = reboundReference;
-    }
-
-    public R getReference() {
-      return reference;
-    }
-
-    public R getRewrittenReference(BidirectionalManyToOneRepresentativeMap<R, R> rewritings) {
-      return rewritings.getOrDefault(reference, reference);
-    }
-
-    public R getRewrittenReference(Map<R, R> rewritings) {
-      return rewritings.getOrDefault(reference, reference);
-    }
-
-    public boolean hasReboundReference() {
-      return reboundReference != null;
-    }
-
-    public R getReboundReference() {
-      return reboundReference;
-    }
-
-    public R getRewrittenReboundReference(
-        BidirectionalManyToOneRepresentativeMap<R, R> rewritings) {
-      return rewritings.getOrDefault(reboundReference, reboundReference);
-    }
-
-    public R getRewrittenReboundReference(Function<R, R> rewritings) {
-      R rewrittenReboundReference = rewritings.apply(reboundReference);
-      return rewrittenReboundReference != null ? rewrittenReboundReference : reboundReference;
-    }
-
-    abstract static class Builder<R extends DexMember<?, R>, Self extends Builder<R, Self>> {
-
-      R reference;
-      R reboundReference;
-
-      public Self setReference(R reference) {
-        this.reference = reference;
-        return self();
-      }
-
-      public Self setReboundReference(R reboundReference) {
-        this.reboundReference = reboundReference;
-        return self();
-      }
-
-      public abstract Self self();
-    }
-  }
-
-  /**
-   * Intermediate result of a field lookup that stores the actual non-rebound reference and the
-   * rebound reference that points to the definition of the field.
-   */
-  public static class FieldLookupResult extends MemberLookupResult<DexField> {
-
-    private final DexType readCastType;
-    private final DexType writeCastType;
-
-    private FieldLookupResult(
-        DexField reference,
-        DexField reboundReference,
-        DexType readCastType,
-        DexType writeCastType) {
-      super(reference, reboundReference);
-      this.readCastType = readCastType;
-      this.writeCastType = writeCastType;
-    }
-
-    public static Builder builder(GraphLens lens) {
-      return new Builder(lens);
-    }
-
-    public boolean hasReadCastType() {
-      return readCastType != null;
-    }
-
-    public DexType getReadCastType() {
-      return readCastType;
-    }
-
-    public DexType getRewrittenReadCastType(Function<DexType, DexType> fn) {
-      return hasReadCastType() ? fn.apply(readCastType) : null;
-    }
-
-    public boolean hasWriteCastType() {
-      return writeCastType != null;
-    }
-
-    public DexType getWriteCastType() {
-      return writeCastType;
-    }
-
-    public DexType getRewrittenWriteCastType(Function<DexType, DexType> fn) {
-      return hasWriteCastType() ? fn.apply(writeCastType) : null;
-    }
-
-    public static class Builder extends MemberLookupResult.Builder<DexField, Builder> {
-
-      private DexType readCastType;
-      private DexType writeCastType;
-      private GraphLens lens;
-
-      private Builder(GraphLens lens) {
-        this.lens = lens;
-      }
-
-      public Builder setReadCastType(DexType readCastType) {
-        this.readCastType = readCastType;
-        return this;
-      }
-
-      public Builder setWriteCastType(DexType writeCastType) {
-        this.writeCastType = writeCastType;
-        return this;
-      }
-
-      @Override
-      public Builder self() {
-        return this;
-      }
-
-      public FieldLookupResult build() {
-        // TODO(b/168282032): All non-identity graph lenses should set the rebound reference.
-        return new FieldLookupResult(reference, reboundReference, readCastType, writeCastType);
-      }
-    }
-  }
-
-  /**
-   * Result of a method lookup in a GraphLens.
-   *
-   * <p>This provides the new target and invoke type to use, along with a description of the
-   * prototype changes that have been made to the target method and the corresponding required
-   * changes to the invoke arguments.
-   */
-  public static class MethodLookupResult extends MemberLookupResult<DexMethod> {
-
-    private final InvokeType type;
-    private final RewrittenPrototypeDescription prototypeChanges;
-
-    public MethodLookupResult(
-        DexMethod reference,
-        DexMethod reboundReference,
-        InvokeType type,
-        RewrittenPrototypeDescription prototypeChanges) {
-      super(reference, reboundReference);
-      this.type = type;
-      this.prototypeChanges = prototypeChanges;
-    }
-
-    public static Builder builder(GraphLens lens) {
-      return new Builder(lens);
-    }
-
-    public InvokeType getType() {
-      return type;
-    }
-
-    public RewrittenPrototypeDescription getPrototypeChanges() {
-      return prototypeChanges;
-    }
-
-    public static class Builder extends MemberLookupResult.Builder<DexMethod, Builder> {
-
-      private final GraphLens lens;
-      private RewrittenPrototypeDescription prototypeChanges = RewrittenPrototypeDescription.none();
-      private InvokeType type;
-
-      private Builder(GraphLens lens) {
-        this.lens = lens;
-      }
-
-      public Builder setPrototypeChanges(RewrittenPrototypeDescription prototypeChanges) {
-        this.prototypeChanges = prototypeChanges;
-        return this;
-      }
-
-      public Builder setType(InvokeType type) {
-        this.type = type;
-        return this;
-      }
-
-      public MethodLookupResult build() {
-        assert reference != null;
-        // TODO(b/168282032): All non-identity graph lenses should set the rebound reference.
-        return new MethodLookupResult(reference, reboundReference, type, prototypeChanges);
-      }
-
-      @Override
-      public Builder self() {
-        return this;
-      }
-    }
-  }
-
   public abstract static class Builder {
 
     protected final MutableBidirectionalManyToOneRepresentativeMap<DexField, DexField> fieldMap =
@@ -311,10 +99,10 @@
   }
 
   /**
-   * Intentionally private. All graph lenses except for {@link IdentityGraphLens} should inherit
-   * from {@link NonIdentityGraphLens}.
+   * Intentionally package private. All graph lenses except for {@link IdentityGraphLens} should
+   * inherit from {@link NonIdentityGraphLens}.
    */
-  private GraphLens() {}
+  GraphLens() {}
 
   public boolean isSyntheticFinalizationGraphLens() {
     return false;
@@ -854,386 +642,4 @@
     return true;
   }
 
-  public abstract static class NonIdentityGraphLens extends GraphLens {
-
-    private final DexItemFactory dexItemFactory;
-    private GraphLens previousLens;
-
-    private final Map<DexType, DexType> arrayTypeCache = new ConcurrentHashMap<>();
-
-    public NonIdentityGraphLens(AppView<?> appView) {
-      this(appView.dexItemFactory(), appView.graphLens());
-    }
-
-    public NonIdentityGraphLens(DexItemFactory dexItemFactory, GraphLens previousLens) {
-      this.dexItemFactory = dexItemFactory;
-      this.previousLens = previousLens;
-    }
-
-    public final DexItemFactory dexItemFactory() {
-      return dexItemFactory;
-    }
-
-    public final GraphLens getPrevious() {
-      return previousLens;
-    }
-
-    @SuppressWarnings("unchecked")
-    public final <T extends NonIdentityGraphLens> T find(
-        Predicate<NonIdentityGraphLens> predicate) {
-      GraphLens current = this;
-      while (current.isNonIdentityLens()) {
-        NonIdentityGraphLens nonIdentityGraphLens = current.asNonIdentityLens();
-        if (predicate.test(nonIdentityGraphLens)) {
-          return (T) nonIdentityGraphLens;
-        }
-        current = nonIdentityGraphLens.getPrevious();
-      }
-      return null;
-    }
-
-    @SuppressWarnings("unchecked")
-    public final <T extends NonIdentityGraphLens> T findPrevious(
-        Predicate<NonIdentityGraphLens> predicate) {
-      GraphLens previous = getPrevious();
-      return previous.isNonIdentityLens() ? previous.asNonIdentityLens().find(predicate) : null;
-    }
-
-    public final <T extends NonIdentityGraphLens> T findPreviousUntil(
-        Predicate<NonIdentityGraphLens> predicate,
-        Predicate<NonIdentityGraphLens> stoppingCriterion) {
-      T found = findPrevious(predicate.or(stoppingCriterion));
-      return (found == null || stoppingCriterion.test(found)) ? null : found;
-    }
-
-    public final void withAlternativeParentLens(GraphLens lens, Action action) {
-      GraphLens oldParent = getPrevious();
-      previousLens = lens;
-      action.execute();
-      previousLens = oldParent;
-    }
-
-    @Override
-    public MethodLookupResult lookupMethod(
-        DexMethod method, DexMethod context, InvokeType type, GraphLens codeLens) {
-      if (method.getHolderType().isArrayType()) {
-        assert lookupType(method.getReturnType()) == method.getReturnType();
-        assert method.getParameters().stream()
-            .allMatch(parameterType -> lookupType(parameterType) == parameterType);
-        return MethodLookupResult.builder(this)
-            .setReference(method.withHolder(lookupType(method.getHolderType()), dexItemFactory))
-            .setType(type)
-            .build();
-      }
-      assert method.getHolderType().isClassType();
-      return internalLookupMethod(method, context, type, codeLens, result -> result);
-    }
-
-    @Override
-    public String lookupPackageName(String pkg) {
-      return getPrevious().lookupPackageName(pkg);
-    }
-
-    @Override
-    public final DexType lookupType(DexType type, GraphLens applied) {
-      if (this == applied) {
-        return type;
-      }
-      if (type.isPrimitiveType() || type.isVoidType() || type.isNullValueType()) {
-        return type;
-      }
-      if (type.isArrayType()) {
-        DexType result = arrayTypeCache.get(type);
-        if (result == null) {
-          DexType baseType = type.toBaseType(dexItemFactory);
-          DexType newType = lookupType(baseType);
-          result = baseType == newType ? type : type.replaceBaseType(newType, dexItemFactory);
-          arrayTypeCache.put(type, result);
-        }
-        return result;
-      }
-      return lookupClassType(type);
-    }
-
-    @Override
-    public final DexType lookupClassType(DexType type, GraphLens applied) {
-      assert type.isClassType() : "Expected class type, but was `" + type.toSourceString() + "`";
-      if (this == applied) {
-        return type;
-      }
-      return internalDescribeLookupClassType(getPrevious().lookupClassType(type));
-    }
-
-    @Override
-    protected FieldLookupResult internalLookupField(
-        DexField reference, GraphLens codeLens, LookupFieldContinuation continuation) {
-      if (this == codeLens) {
-        return getIdentityLens().internalLookupField(reference, codeLens, continuation);
-      }
-      return previousLens.internalLookupField(
-          reference,
-          codeLens,
-          previous -> continuation.lookupField(internalDescribeLookupField(previous)));
-    }
-
-    @Override
-    protected MethodLookupResult internalLookupMethod(
-        DexMethod reference,
-        DexMethod context,
-        InvokeType type,
-        GraphLens codeLens,
-        LookupMethodContinuation continuation) {
-      if (this == codeLens) {
-        GraphLens identityLens = getIdentityLens();
-        return identityLens.internalLookupMethod(
-            reference, context, type, identityLens, continuation);
-      }
-      return previousLens.internalLookupMethod(
-          reference,
-          getPreviousMethodSignature(context),
-          type,
-          codeLens,
-          previous -> continuation.lookupMethod(internalDescribeLookupMethod(previous, context)));
-    }
-
-    protected abstract FieldLookupResult internalDescribeLookupField(FieldLookupResult previous);
-
-    protected abstract MethodLookupResult internalDescribeLookupMethod(
-        MethodLookupResult previous, DexMethod context);
-
-    protected abstract DexType internalDescribeLookupClassType(DexType previous);
-
-    public abstract DexMethod getPreviousMethodSignature(DexMethod method);
-
-    /***
-     * The previous mapping for a method often coincides with the previous method signature, but it
-     * may not, for example for bridges inserted in vertically merged classes where the original
-     * signature is used for computing invoke-super but should not be used for mapping output.
-     */
-    public DexMethod getPreviousMethodSignatureForMapping(DexMethod method) {
-      return getPreviousMethodSignature(method);
-    }
-
-    public abstract DexMethod getNextMethodSignature(DexMethod method);
-
-    @Override
-    public final boolean isIdentityLens() {
-      return false;
-    }
-
-    @Override
-    public final boolean isNonIdentityLens() {
-      return true;
-    }
-
-    @Override
-    public final NonIdentityGraphLens asNonIdentityLens() {
-      return this;
-    }
-  }
-
-  private static final class IdentityGraphLens extends GraphLens {
-
-    private static IdentityGraphLens INSTANCE = new IdentityGraphLens();
-
-    private IdentityGraphLens() {}
-
-    private static IdentityGraphLens getInstance() {
-      return INSTANCE;
-    }
-
-    @Override
-    public boolean isIdentityLens() {
-      return true;
-    }
-
-    @Override
-    public boolean isNonIdentityLens() {
-      return false;
-    }
-
-    @Override
-    public DexType getOriginalType(DexType type) {
-      return type;
-    }
-
-    @Override
-    public Iterable<DexType> getOriginalTypes(DexType type) {
-      return IterableUtils.singleton(type);
-    }
-
-    @Override
-    public DexField getOriginalFieldSignature(DexField field) {
-      return field;
-    }
-
-    @Override
-    public DexField getRenamedFieldSignature(DexField originalField, GraphLens codeLens) {
-      return originalField;
-    }
-
-    @Override
-    public DexMethod getRenamedMethodSignature(DexMethod originalMethod, GraphLens applied) {
-      return originalMethod;
-    }
-
-    @Override
-    public String lookupPackageName(String pkg) {
-      return pkg;
-    }
-
-    @Override
-    public DexType lookupType(DexType type, GraphLens applied) {
-      return type;
-    }
-
-    @Override
-    public DexType lookupClassType(DexType type, GraphLens applied) {
-      assert type.isClassType();
-      return type;
-    }
-
-    @Override
-    public MethodLookupResult lookupMethod(
-        DexMethod method, DexMethod context, InvokeType type, GraphLens codeLens) {
-      assert codeLens == null || codeLens.isIdentityLens();
-      return MethodLookupResult.builder(this).setReference(method).setType(type).build();
-    }
-
-    @Override
-    public RewrittenPrototypeDescription lookupPrototypeChangesForMethodDefinition(
-        DexMethod method, GraphLens codeLens) {
-      return RewrittenPrototypeDescription.none();
-    }
-
-    @Override
-    protected FieldLookupResult internalLookupField(
-        DexField reference, GraphLens codeLens, LookupFieldContinuation continuation) {
-      // Passes the field reference back to the next graph lens. The identity lens intentionally
-      // does not set the rebound field reference, since it does not know what that is.
-      return continuation.lookupField(
-          FieldLookupResult.builder(this).setReference(reference).build());
-    }
-
-    @Override
-    protected MethodLookupResult internalLookupMethod(
-        DexMethod reference,
-        DexMethod context,
-        InvokeType type,
-        GraphLens codeLens,
-        LookupMethodContinuation continuation) {
-      // Passes the method reference back to the next graph lens. The identity lens intentionally
-      // does not set the rebound method reference, since it does not know what that is.
-      return continuation.lookupMethod(lookupMethod(reference, context, type, codeLens));
-    }
-
-    @Override
-    public boolean isContextFreeForMethods() {
-      return true;
-    }
-
-    @Override
-    public boolean hasCodeRewritings() {
-      return false;
-    }
-  }
-
-  // This lens clears all code rewriting (lookup methods mimics identity lens behavior) but still
-  // relies on the previous lens for names (getRenamed/Original methods).
-  public static class ClearCodeRewritingGraphLens extends NonIdentityGraphLens {
-
-    public ClearCodeRewritingGraphLens(DexItemFactory dexItemFactory, GraphLens previousLens) {
-      super(dexItemFactory, previousLens);
-    }
-
-    @Override
-    public DexType getOriginalType(DexType type) {
-      return getPrevious().getOriginalType(type);
-    }
-
-    @Override
-    public Iterable<DexType> getOriginalTypes(DexType type) {
-      return getPrevious().getOriginalTypes(type);
-    }
-
-    @Override
-    public DexField getOriginalFieldSignature(DexField field) {
-      return getPrevious().getOriginalFieldSignature(field);
-    }
-
-    @Override
-    public DexField getRenamedFieldSignature(DexField originalField, GraphLens codeLens) {
-      return this != codeLens
-          ? getPrevious().getRenamedFieldSignature(originalField)
-          : originalField;
-    }
-
-    @Override
-    public DexMethod getRenamedMethodSignature(DexMethod originalMethod, GraphLens applied) {
-      return this != applied
-          ? getPrevious().getRenamedMethodSignature(originalMethod, applied)
-          : originalMethod;
-    }
-
-    @Override
-    public boolean isClearCodeRewritingLens() {
-      return true;
-    }
-
-    @Override
-    public RewrittenPrototypeDescription lookupPrototypeChangesForMethodDefinition(
-        DexMethod method, GraphLens codeLens) {
-      return getIdentityLens().lookupPrototypeChangesForMethodDefinition(method, codeLens);
-    }
-
-    @Override
-    public final DexType internalDescribeLookupClassType(DexType previous) {
-      return previous;
-    }
-
-    @Override
-    protected FieldLookupResult internalLookupField(
-        DexField reference, GraphLens codeLens, LookupFieldContinuation continuation) {
-      return getIdentityLens().internalLookupField(reference, codeLens, continuation);
-    }
-
-    @Override
-    protected FieldLookupResult internalDescribeLookupField(FieldLookupResult previous) {
-      throw new Unreachable();
-    }
-
-    @Override
-    protected MethodLookupResult internalLookupMethod(
-        DexMethod reference,
-        DexMethod context,
-        InvokeType type,
-        GraphLens codeLens,
-        LookupMethodContinuation continuation) {
-      assert codeLens == null || codeLens == this;
-      GraphLens identityLens = getIdentityLens();
-      return identityLens.internalLookupMethod(
-          reference, context, type, identityLens, continuation);
-    }
-
-    @Override
-    public MethodLookupResult internalDescribeLookupMethod(
-        MethodLookupResult previous, DexMethod context) {
-      throw new Unreachable();
-    }
-
-    @Override
-    public DexMethod getPreviousMethodSignature(DexMethod method) {
-      return method;
-    }
-
-    @Override
-    public DexMethod getNextMethodSignature(DexMethod method) {
-      return method;
-    }
-
-    @Override
-    public boolean isContextFreeForMethods() {
-      return getIdentityLens().isContextFreeForMethods();
-    }
-  }
 }
diff --git a/src/main/java/com/android/tools/r8/graph/lens/IdentityGraphLens.java b/src/main/java/com/android/tools/r8/graph/lens/IdentityGraphLens.java
new file mode 100644
index 0000000..ce9aca7
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/lens/IdentityGraphLens.java
@@ -0,0 +1,118 @@
+// Copyright (c) 2023, 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.lens;
+
+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.graph.proto.RewrittenPrototypeDescription;
+import com.android.tools.r8.ir.code.InvokeType;
+import com.android.tools.r8.utils.IterableUtils;
+
+final class IdentityGraphLens extends GraphLens {
+
+  private static IdentityGraphLens INSTANCE = new IdentityGraphLens();
+
+  private IdentityGraphLens() {}
+
+  static IdentityGraphLens getInstance() {
+    return INSTANCE;
+  }
+
+  @Override
+  public boolean isIdentityLens() {
+    return true;
+  }
+
+  @Override
+  public boolean isNonIdentityLens() {
+    return false;
+  }
+
+  @Override
+  public DexType getOriginalType(DexType type) {
+    return type;
+  }
+
+  @Override
+  public Iterable<DexType> getOriginalTypes(DexType type) {
+    return IterableUtils.singleton(type);
+  }
+
+  @Override
+  public DexField getOriginalFieldSignature(DexField field) {
+    return field;
+  }
+
+  @Override
+  public DexField getRenamedFieldSignature(DexField originalField, GraphLens codeLens) {
+    return originalField;
+  }
+
+  @Override
+  public DexMethod getRenamedMethodSignature(DexMethod originalMethod, GraphLens applied) {
+    return originalMethod;
+  }
+
+  @Override
+  public String lookupPackageName(String pkg) {
+    return pkg;
+  }
+
+  @Override
+  public DexType lookupType(DexType type, GraphLens applied) {
+    return type;
+  }
+
+  @Override
+  public DexType lookupClassType(DexType type, GraphLens applied) {
+    assert type.isClassType();
+    return type;
+  }
+
+  @Override
+  public MethodLookupResult lookupMethod(
+      DexMethod method, DexMethod context, InvokeType type, GraphLens codeLens) {
+    assert codeLens == null || codeLens.isIdentityLens();
+    return MethodLookupResult.builder(this).setReference(method).setType(type).build();
+  }
+
+  @Override
+  public RewrittenPrototypeDescription lookupPrototypeChangesForMethodDefinition(
+      DexMethod method, GraphLens codeLens) {
+    return RewrittenPrototypeDescription.none();
+  }
+
+  @Override
+  protected FieldLookupResult internalLookupField(
+      DexField reference, GraphLens codeLens, LookupFieldContinuation continuation) {
+    // Passes the field reference back to the next graph lens. The identity lens intentionally
+    // does not set the rebound field reference, since it does not know what that is.
+    return continuation.lookupField(
+        FieldLookupResult.builder(this).setReference(reference).build());
+  }
+
+  @Override
+  protected MethodLookupResult internalLookupMethod(
+      DexMethod reference,
+      DexMethod context,
+      InvokeType type,
+      GraphLens codeLens,
+      LookupMethodContinuation continuation) {
+    // Passes the method reference back to the next graph lens. The identity lens intentionally
+    // does not set the rebound method reference, since it does not know what that is.
+    return continuation.lookupMethod(lookupMethod(reference, context, type, codeLens));
+  }
+
+  @Override
+  public boolean isContextFreeForMethods() {
+    return true;
+  }
+
+  @Override
+  public boolean hasCodeRewritings() {
+    return false;
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/graph/lens/MemberLookupResult.java b/src/main/java/com/android/tools/r8/graph/lens/MemberLookupResult.java
new file mode 100644
index 0000000..7ec7c85
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/lens/MemberLookupResult.java
@@ -0,0 +1,68 @@
+// Copyright (c) 2023, 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.lens;
+
+import com.android.tools.r8.graph.DexMember;
+import com.android.tools.r8.utils.collections.BidirectionalManyToOneRepresentativeMap;
+import java.util.Map;
+import java.util.function.Function;
+
+abstract class MemberLookupResult<R extends DexMember<?, R>> {
+
+  private final R reference;
+  private final R reboundReference;
+
+  MemberLookupResult(R reference, R reboundReference) {
+    this.reference = reference;
+    this.reboundReference = reboundReference;
+  }
+
+  public R getReference() {
+    return reference;
+  }
+
+  public R getRewrittenReference(BidirectionalManyToOneRepresentativeMap<R, R> rewritings) {
+    return rewritings.getOrDefault(reference, reference);
+  }
+
+  public R getRewrittenReference(Map<R, R> rewritings) {
+    return rewritings.getOrDefault(reference, reference);
+  }
+
+  public boolean hasReboundReference() {
+    return reboundReference != null;
+  }
+
+  public R getReboundReference() {
+    return reboundReference;
+  }
+
+  public R getRewrittenReboundReference(BidirectionalManyToOneRepresentativeMap<R, R> rewritings) {
+    return rewritings.getOrDefault(reboundReference, reboundReference);
+  }
+
+  public R getRewrittenReboundReference(Function<R, R> rewritings) {
+    R rewrittenReboundReference = rewritings.apply(reboundReference);
+    return rewrittenReboundReference != null ? rewrittenReboundReference : reboundReference;
+  }
+
+  abstract static class Builder<R extends DexMember<?, R>, Self extends Builder<R, Self>> {
+
+    R reference;
+    R reboundReference;
+
+    public Self setReference(R reference) {
+      this.reference = reference;
+      return self();
+    }
+
+    public Self setReboundReference(R reboundReference) {
+      this.reboundReference = reboundReference;
+      return self();
+    }
+
+    public abstract Self self();
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/graph/lens/MethodLookupResult.java b/src/main/java/com/android/tools/r8/graph/lens/MethodLookupResult.java
new file mode 100644
index 0000000..a69267e
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/lens/MethodLookupResult.java
@@ -0,0 +1,76 @@
+// Copyright (c) 2023, 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.lens;
+
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.proto.RewrittenPrototypeDescription;
+import com.android.tools.r8.ir.code.InvokeType;
+
+/**
+ * Result of a method lookup in a GraphLens.
+ *
+ * <p>This provides the new target and invoke type to use, along with a description of the prototype
+ * changes that have been made to the target method and the corresponding required changes to the
+ * invoke arguments.
+ */
+public class MethodLookupResult extends MemberLookupResult<DexMethod> {
+
+  private final InvokeType type;
+  private final RewrittenPrototypeDescription prototypeChanges;
+
+  public MethodLookupResult(
+      DexMethod reference,
+      DexMethod reboundReference,
+      InvokeType type,
+      RewrittenPrototypeDescription prototypeChanges) {
+    super(reference, reboundReference);
+    this.type = type;
+    this.prototypeChanges = prototypeChanges;
+  }
+
+  public static Builder builder(GraphLens lens) {
+    return new Builder(lens);
+  }
+
+  public InvokeType getType() {
+    return type;
+  }
+
+  public RewrittenPrototypeDescription getPrototypeChanges() {
+    return prototypeChanges;
+  }
+
+  public static class Builder extends MemberLookupResult.Builder<DexMethod, Builder> {
+
+    private final GraphLens lens;
+    private RewrittenPrototypeDescription prototypeChanges = RewrittenPrototypeDescription.none();
+    private InvokeType type;
+
+    private Builder(GraphLens lens) {
+      this.lens = lens;
+    }
+
+    public Builder setPrototypeChanges(RewrittenPrototypeDescription prototypeChanges) {
+      this.prototypeChanges = prototypeChanges;
+      return this;
+    }
+
+    public Builder setType(InvokeType type) {
+      this.type = type;
+      return this;
+    }
+
+    public MethodLookupResult build() {
+      assert reference != null;
+      // TODO(b/168282032): All non-identity graph lenses should set the rebound reference.
+      return new MethodLookupResult(reference, reboundReference, type, prototypeChanges);
+    }
+
+    @Override
+    public Builder self() {
+      return this;
+    }
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/graph/lens/NestedGraphLens.java b/src/main/java/com/android/tools/r8/graph/lens/NestedGraphLens.java
index 6f57d80..7c921ca 100644
--- a/src/main/java/com/android/tools/r8/graph/lens/NestedGraphLens.java
+++ b/src/main/java/com/android/tools/r8/graph/lens/NestedGraphLens.java
@@ -10,7 +10,6 @@
 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.graph.lens.GraphLens.NonIdentityGraphLens;
 import com.android.tools.r8.graph.proto.RewrittenPrototypeDescription;
 import com.android.tools.r8.ir.code.InvokeType;
 import com.android.tools.r8.utils.IterableUtils;
diff --git a/src/main/java/com/android/tools/r8/graph/lens/NonIdentityGraphLens.java b/src/main/java/com/android/tools/r8/graph/lens/NonIdentityGraphLens.java
new file mode 100644
index 0000000..fb0c944
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/lens/NonIdentityGraphLens.java
@@ -0,0 +1,195 @@
+// Copyright (c) 2023, 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.lens;
+
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexField;
+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.ir.code.InvokeType;
+import com.android.tools.r8.utils.Action;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Predicate;
+
+public abstract class NonIdentityGraphLens extends GraphLens {
+
+  private final DexItemFactory dexItemFactory;
+  private GraphLens previousLens;
+
+  private final Map<DexType, DexType> arrayTypeCache = new ConcurrentHashMap<>();
+
+  public NonIdentityGraphLens(AppView<?> appView) {
+    this(appView.dexItemFactory(), appView.graphLens());
+  }
+
+  public NonIdentityGraphLens(DexItemFactory dexItemFactory, GraphLens previousLens) {
+    this.dexItemFactory = dexItemFactory;
+    this.previousLens = previousLens;
+  }
+
+  public final DexItemFactory dexItemFactory() {
+    return dexItemFactory;
+  }
+
+  public final GraphLens getPrevious() {
+    return previousLens;
+  }
+
+  @SuppressWarnings("unchecked")
+  public final <T extends com.android.tools.r8.graph.lens.NonIdentityGraphLens> T find(
+      Predicate<com.android.tools.r8.graph.lens.NonIdentityGraphLens> predicate) {
+    GraphLens current = this;
+    while (current.isNonIdentityLens()) {
+      com.android.tools.r8.graph.lens.NonIdentityGraphLens nonIdentityGraphLens =
+          current.asNonIdentityLens();
+      if (predicate.test(nonIdentityGraphLens)) {
+        return (T) nonIdentityGraphLens;
+      }
+      current = nonIdentityGraphLens.getPrevious();
+    }
+    return null;
+  }
+
+  @SuppressWarnings("unchecked")
+  public final <T extends com.android.tools.r8.graph.lens.NonIdentityGraphLens> T findPrevious(
+      Predicate<com.android.tools.r8.graph.lens.NonIdentityGraphLens> predicate) {
+    GraphLens previous = getPrevious();
+    return previous.isNonIdentityLens() ? previous.asNonIdentityLens().find(predicate) : null;
+  }
+
+  public final <T extends com.android.tools.r8.graph.lens.NonIdentityGraphLens> T findPreviousUntil(
+      Predicate<com.android.tools.r8.graph.lens.NonIdentityGraphLens> predicate,
+      Predicate<com.android.tools.r8.graph.lens.NonIdentityGraphLens> stoppingCriterion) {
+    T found = findPrevious(predicate.or(stoppingCriterion));
+    return (found == null || stoppingCriterion.test(found)) ? null : found;
+  }
+
+  public final void withAlternativeParentLens(GraphLens lens, Action action) {
+    GraphLens oldParent = getPrevious();
+    previousLens = lens;
+    action.execute();
+    previousLens = oldParent;
+  }
+
+  @Override
+  public MethodLookupResult lookupMethod(
+      DexMethod method, DexMethod context, InvokeType type, GraphLens codeLens) {
+    if (method.getHolderType().isArrayType()) {
+      assert lookupType(method.getReturnType()) == method.getReturnType();
+      assert method.getParameters().stream()
+          .allMatch(parameterType -> lookupType(parameterType) == parameterType);
+      return MethodLookupResult.builder(this)
+          .setReference(method.withHolder(lookupType(method.getHolderType()), dexItemFactory))
+          .setType(type)
+          .build();
+    }
+    assert method.getHolderType().isClassType();
+    return internalLookupMethod(method, context, type, codeLens, result -> result);
+  }
+
+  @Override
+  public String lookupPackageName(String pkg) {
+    return getPrevious().lookupPackageName(pkg);
+  }
+
+  @Override
+  public final DexType lookupType(DexType type, GraphLens applied) {
+    if (this == applied) {
+      return type;
+    }
+    if (type.isPrimitiveType() || type.isVoidType() || type.isNullValueType()) {
+      return type;
+    }
+    if (type.isArrayType()) {
+      DexType result = arrayTypeCache.get(type);
+      if (result == null) {
+        DexType baseType = type.toBaseType(dexItemFactory);
+        DexType newType = lookupType(baseType);
+        result = baseType == newType ? type : type.replaceBaseType(newType, dexItemFactory);
+        arrayTypeCache.put(type, result);
+      }
+      return result;
+    }
+    return lookupClassType(type);
+  }
+
+  @Override
+  public final DexType lookupClassType(DexType type, GraphLens applied) {
+    assert type.isClassType() : "Expected class type, but was `" + type.toSourceString() + "`";
+    if (this == applied) {
+      return type;
+    }
+    return internalDescribeLookupClassType(getPrevious().lookupClassType(type));
+  }
+
+  @Override
+  protected FieldLookupResult internalLookupField(
+      DexField reference, GraphLens codeLens, LookupFieldContinuation continuation) {
+    if (this == codeLens) {
+      return getIdentityLens().internalLookupField(reference, codeLens, continuation);
+    }
+    return previousLens.internalLookupField(
+        reference,
+        codeLens,
+        previous -> continuation.lookupField(internalDescribeLookupField(previous)));
+  }
+
+  @Override
+  protected MethodLookupResult internalLookupMethod(
+      DexMethod reference,
+      DexMethod context,
+      InvokeType type,
+      GraphLens codeLens,
+      LookupMethodContinuation continuation) {
+    if (this == codeLens) {
+      GraphLens identityLens = getIdentityLens();
+      return identityLens.internalLookupMethod(
+          reference, context, type, identityLens, continuation);
+    }
+    return previousLens.internalLookupMethod(
+        reference,
+        getPreviousMethodSignature(context),
+        type,
+        codeLens,
+        previous -> continuation.lookupMethod(internalDescribeLookupMethod(previous, context)));
+  }
+
+  protected abstract FieldLookupResult internalDescribeLookupField(FieldLookupResult previous);
+
+  protected abstract MethodLookupResult internalDescribeLookupMethod(
+      MethodLookupResult previous, DexMethod context);
+
+  protected abstract DexType internalDescribeLookupClassType(DexType previous);
+
+  public abstract DexMethod getPreviousMethodSignature(DexMethod method);
+
+  /***
+   * The previous mapping for a method often coincides with the previous method signature, but it
+   * may not, for example for bridges inserted in vertically merged classes where the original
+   * signature is used for computing invoke-super but should not be used for mapping output.
+   */
+  public DexMethod getPreviousMethodSignatureForMapping(DexMethod method) {
+    return getPreviousMethodSignature(method);
+  }
+
+  public abstract DexMethod getNextMethodSignature(DexMethod method);
+
+  @Override
+  public final boolean isIdentityLens() {
+    return false;
+  }
+
+  @Override
+  public final boolean isNonIdentityLens() {
+    return true;
+  }
+
+  @Override
+  public final com.android.tools.r8.graph.lens.NonIdentityGraphLens asNonIdentityLens() {
+    return this;
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
index ec92df0..1fbc713 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
@@ -14,7 +14,7 @@
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.graph.PrunedItems;
-import com.android.tools.r8.graph.lens.GraphLens.MethodLookupResult;
+import com.android.tools.r8.graph.lens.MethodLookupResult;
 import com.android.tools.r8.horizontalclassmerging.code.SyntheticInitializerConverter;
 import com.android.tools.r8.ir.code.InvokeType;
 import com.android.tools.r8.profile.art.ArtProfileCompletenessChecker;
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMergerGraphLens.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMergerGraphLens.java
index 8cd7e42..72e96a7 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMergerGraphLens.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMergerGraphLens.java
@@ -11,6 +11,8 @@
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.graph.lens.FieldLookupResult;
+import com.android.tools.r8.graph.lens.MethodLookupResult;
 import com.android.tools.r8.graph.lens.NestedGraphLens;
 import com.android.tools.r8.ir.conversion.ExtraParameter;
 import com.android.tools.r8.utils.IterableUtils;
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/IncompleteMergedInstanceInitializerCode.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/IncompleteMergedInstanceInitializerCode.java
index 0dd7bcb..15f0d57 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/IncompleteMergedInstanceInitializerCode.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/IncompleteMergedInstanceInitializerCode.java
@@ -25,7 +25,7 @@
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.graph.lens.GraphLens;
-import com.android.tools.r8.graph.lens.GraphLens.MethodLookupResult;
+import com.android.tools.r8.graph.lens.MethodLookupResult;
 import com.android.tools.r8.ir.analysis.value.SingleConstValue;
 import com.android.tools.r8.ir.analysis.value.SingleDexItemBasedStringValue;
 import com.android.tools.r8.ir.code.Position;
diff --git a/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java b/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java
index 2646a1b..bef0a26 100644
--- a/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java
+++ b/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java
@@ -15,7 +15,7 @@
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.graph.UseRegistry;
 import com.android.tools.r8.graph.lens.GraphLens;
-import com.android.tools.r8.graph.lens.GraphLens.NonIdentityGraphLens;
+import com.android.tools.r8.graph.lens.NonIdentityGraphLens;
 import com.android.tools.r8.ir.analysis.VerifyTypesHelper;
 import com.android.tools.r8.ir.analysis.type.Nullability;
 import com.android.tools.r8.ir.analysis.type.TypeElement;
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeType.java b/src/main/java/com/android/tools/r8/ir/code/InvokeType.java
index a5322a1..bed9095 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeType.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeType.java
@@ -27,7 +27,7 @@
 import com.android.tools.r8.graph.DexMethodHandle.MethodHandleType;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.lens.GraphLens;
-import com.android.tools.r8.graph.lens.GraphLens.MethodLookupResult;
+import com.android.tools.r8.graph.lens.MethodLookupResult;
 import org.objectweb.asm.Opcodes;
 
 public enum InvokeType {
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 d6989ad..1efe772 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
@@ -51,10 +51,10 @@
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.graph.classmerging.VerticallyMergedClasses;
+import com.android.tools.r8.graph.lens.FieldLookupResult;
 import com.android.tools.r8.graph.lens.GraphLens;
-import com.android.tools.r8.graph.lens.GraphLens.FieldLookupResult;
-import com.android.tools.r8.graph.lens.GraphLens.MethodLookupResult;
-import com.android.tools.r8.graph.lens.GraphLens.NonIdentityGraphLens;
+import com.android.tools.r8.graph.lens.MethodLookupResult;
+import com.android.tools.r8.graph.lens.NonIdentityGraphLens;
 import com.android.tools.r8.graph.proto.ArgumentInfo;
 import com.android.tools.r8.graph.proto.ArgumentInfoCollection;
 import com.android.tools.r8.graph.proto.RemovedArgumentInfo;
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriterUtils.java b/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriterUtils.java
index 903d72e..b82af15 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriterUtils.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriterUtils.java
@@ -26,7 +26,7 @@
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.graph.UseRegistry.MethodHandleUse;
 import com.android.tools.r8.graph.lens.GraphLens;
-import com.android.tools.r8.graph.lens.GraphLens.MethodLookupResult;
+import com.android.tools.r8.graph.lens.MethodLookupResult;
 import com.android.tools.r8.ir.code.InvokeType;
 import com.android.tools.r8.ir.desugar.LambdaDescriptor;
 import java.util.ArrayList;
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/callgraph/InvokeExtractor.java b/src/main/java/com/android/tools/r8/ir/conversion/callgraph/InvokeExtractor.java
index 7307617..38bc387 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/callgraph/InvokeExtractor.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/callgraph/InvokeExtractor.java
@@ -15,7 +15,7 @@
 import com.android.tools.r8.graph.MethodResolutionResult;
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.graph.UseRegistry;
-import com.android.tools.r8.graph.lens.GraphLens.MethodLookupResult;
+import com.android.tools.r8.graph.lens.MethodLookupResult;
 import com.android.tools.r8.ir.code.InvokeType;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.android.tools.r8.utils.collections.ProgramMethodSet;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxerImpl.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxerImpl.java
index 388b5dd..4666036 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxerImpl.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxerImpl.java
@@ -44,7 +44,7 @@
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.graph.PrunedItems;
 import com.android.tools.r8.graph.lens.GraphLens;
-import com.android.tools.r8.graph.lens.GraphLens.NonIdentityGraphLens;
+import com.android.tools.r8.graph.lens.NonIdentityGraphLens;
 import com.android.tools.r8.graph.proto.RewrittenPrototypeDescription;
 import com.android.tools.r8.ir.analysis.fieldvalueanalysis.StaticFieldValues;
 import com.android.tools.r8.ir.analysis.fieldvalueanalysis.StaticFieldValues.EnumStaticFieldValues;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingTreeFixer.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingTreeFixer.java
index 4e2b0cb..67efedd 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingTreeFixer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingTreeFixer.java
@@ -22,7 +22,7 @@
 import com.android.tools.r8.graph.ProgramField;
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.graph.PrunedItems;
-import com.android.tools.r8.graph.lens.GraphLens.MethodLookupResult;
+import com.android.tools.r8.graph.lens.MethodLookupResult;
 import com.android.tools.r8.graph.proto.RewrittenPrototypeDescription;
 import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
 import com.android.tools.r8.ir.analysis.type.TypeElement;
diff --git a/src/main/java/com/android/tools/r8/optimize/FieldRebindingIdentityLens.java b/src/main/java/com/android/tools/r8/optimize/FieldRebindingIdentityLens.java
index 7441262..4e542e2 100644
--- a/src/main/java/com/android/tools/r8/optimize/FieldRebindingIdentityLens.java
+++ b/src/main/java/com/android/tools/r8/optimize/FieldRebindingIdentityLens.java
@@ -8,8 +8,10 @@
 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.lens.FieldLookupResult;
 import com.android.tools.r8.graph.lens.GraphLens;
-import com.android.tools.r8.graph.lens.GraphLens.NonIdentityGraphLens;
+import com.android.tools.r8.graph.lens.MethodLookupResult;
+import com.android.tools.r8.graph.lens.NonIdentityGraphLens;
 import com.android.tools.r8.graph.proto.RewrittenPrototypeDescription;
 import java.util.IdentityHashMap;
 import java.util.Map;
diff --git a/src/main/java/com/android/tools/r8/optimize/MemberRebindingIdentityLens.java b/src/main/java/com/android/tools/r8/optimize/MemberRebindingIdentityLens.java
index fed8858..6f99cd5 100644
--- a/src/main/java/com/android/tools/r8/optimize/MemberRebindingIdentityLens.java
+++ b/src/main/java/com/android/tools/r8/optimize/MemberRebindingIdentityLens.java
@@ -13,8 +13,10 @@
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.FieldAccessInfo;
 import com.android.tools.r8.graph.MethodResolutionResult.SingleResolutionResult;
+import com.android.tools.r8.graph.lens.FieldLookupResult;
 import com.android.tools.r8.graph.lens.GraphLens;
-import com.android.tools.r8.graph.lens.GraphLens.NonIdentityGraphLens;
+import com.android.tools.r8.graph.lens.MethodLookupResult;
+import com.android.tools.r8.graph.lens.NonIdentityGraphLens;
 import com.android.tools.r8.graph.proto.RewrittenPrototypeDescription;
 import java.util.IdentityHashMap;
 import java.util.Map;
diff --git a/src/main/java/com/android/tools/r8/optimize/MemberRebindingLens.java b/src/main/java/com/android/tools/r8/optimize/MemberRebindingLens.java
index 5dabe2f..247940f 100644
--- a/src/main/java/com/android/tools/r8/optimize/MemberRebindingLens.java
+++ b/src/main/java/com/android/tools/r8/optimize/MemberRebindingLens.java
@@ -13,8 +13,10 @@
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.FieldAccessInfo;
+import com.android.tools.r8.graph.lens.FieldLookupResult;
 import com.android.tools.r8.graph.lens.GraphLens;
-import com.android.tools.r8.graph.lens.GraphLens.NonIdentityGraphLens;
+import com.android.tools.r8.graph.lens.MethodLookupResult;
+import com.android.tools.r8.graph.lens.NonIdentityGraphLens;
 import com.android.tools.r8.graph.proto.RewrittenPrototypeDescription;
 import com.android.tools.r8.ir.code.InvokeType;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
diff --git a/src/main/java/com/android/tools/r8/optimize/PublicizerLens.java b/src/main/java/com/android/tools/r8/optimize/PublicizerLens.java
index 28846b3..54d66e4 100644
--- a/src/main/java/com/android/tools/r8/optimize/PublicizerLens.java
+++ b/src/main/java/com/android/tools/r8/optimize/PublicizerLens.java
@@ -7,7 +7,9 @@
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.lens.FieldLookupResult;
 import com.android.tools.r8.graph.lens.GraphLens;
+import com.android.tools.r8.graph.lens.MethodLookupResult;
 import com.android.tools.r8.graph.lens.NestedGraphLens;
 import com.android.tools.r8.ir.code.InvokeType;
 import com.google.common.collect.Sets;
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorGraphLens.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorGraphLens.java
index 89e5529..42213aa 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorGraphLens.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorGraphLens.java
@@ -7,6 +7,7 @@
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexField;
 import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.lens.FieldLookupResult;
 import com.android.tools.r8.graph.lens.NestedGraphLens;
 import com.android.tools.r8.graph.proto.RewrittenPrototypeDescription;
 import com.android.tools.r8.ir.code.InvokeType;
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/lenscoderewriter/NullCheckInserter.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/lenscoderewriter/NullCheckInserter.java
index 0e2ca5a..468b735 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/lenscoderewriter/NullCheckInserter.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/lenscoderewriter/NullCheckInserter.java
@@ -9,8 +9,8 @@
 import com.android.tools.r8.graph.DexField;
 import com.android.tools.r8.graph.FieldResolutionResult;
 import com.android.tools.r8.graph.lens.GraphLens;
-import com.android.tools.r8.graph.lens.GraphLens.MethodLookupResult;
-import com.android.tools.r8.graph.lens.GraphLens.NonIdentityGraphLens;
+import com.android.tools.r8.graph.lens.MethodLookupResult;
+import com.android.tools.r8.graph.lens.NonIdentityGraphLens;
 import com.android.tools.r8.graph.proto.ArgumentInfo;
 import com.android.tools.r8.ir.analysis.type.TypeElement;
 import com.android.tools.r8.ir.code.BasicBlock;
diff --git a/src/main/java/com/android/tools/r8/optimize/bridgehoisting/BridgeHoistingLens.java b/src/main/java/com/android/tools/r8/optimize/bridgehoisting/BridgeHoistingLens.java
index adb4689..2c3af38 100644
--- a/src/main/java/com/android/tools/r8/optimize/bridgehoisting/BridgeHoistingLens.java
+++ b/src/main/java/com/android/tools/r8/optimize/bridgehoisting/BridgeHoistingLens.java
@@ -8,8 +8,10 @@
 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.graph.lens.FieldLookupResult;
 import com.android.tools.r8.graph.lens.GraphLens;
-import com.android.tools.r8.graph.lens.GraphLens.NonIdentityGraphLens;
+import com.android.tools.r8.graph.lens.MethodLookupResult;
+import com.android.tools.r8.graph.lens.NonIdentityGraphLens;
 import com.android.tools.r8.graph.proto.RewrittenPrototypeDescription;
 import com.android.tools.r8.utils.collections.BidirectionalManyToOneMap;
 import java.util.Set;
diff --git a/src/main/java/com/android/tools/r8/optimize/proto/ProtoNormalizerGraphLens.java b/src/main/java/com/android/tools/r8/optimize/proto/ProtoNormalizerGraphLens.java
index 794c78f..dc9258b 100644
--- a/src/main/java/com/android/tools/r8/optimize/proto/ProtoNormalizerGraphLens.java
+++ b/src/main/java/com/android/tools/r8/optimize/proto/ProtoNormalizerGraphLens.java
@@ -9,8 +9,10 @@
 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.graph.lens.FieldLookupResult;
 import com.android.tools.r8.graph.lens.GraphLens;
-import com.android.tools.r8.graph.lens.GraphLens.NonIdentityGraphLens;
+import com.android.tools.r8.graph.lens.MethodLookupResult;
+import com.android.tools.r8.graph.lens.NonIdentityGraphLens;
 import com.android.tools.r8.graph.proto.ArgumentInfoCollection;
 import com.android.tools.r8.graph.proto.ArgumentPermutation;
 import com.android.tools.r8.graph.proto.RewrittenPrototypeDescription;
diff --git a/src/main/java/com/android/tools/r8/optimize/redundantbridgeremoval/RedundantBridgeRemovalLens.java b/src/main/java/com/android/tools/r8/optimize/redundantbridgeremoval/RedundantBridgeRemovalLens.java
index 95f36bd..f7fc31e 100644
--- a/src/main/java/com/android/tools/r8/optimize/redundantbridgeremoval/RedundantBridgeRemovalLens.java
+++ b/src/main/java/com/android/tools/r8/optimize/redundantbridgeremoval/RedundantBridgeRemovalLens.java
@@ -10,8 +10,10 @@
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.graph.lens.FieldLookupResult;
 import com.android.tools.r8.graph.lens.GraphLens;
-import com.android.tools.r8.graph.lens.GraphLens.NonIdentityGraphLens;
+import com.android.tools.r8.graph.lens.MethodLookupResult;
+import com.android.tools.r8.graph.lens.NonIdentityGraphLens;
 import com.android.tools.r8.graph.proto.RewrittenPrototypeDescription;
 import com.android.tools.r8.ir.code.InvokeType;
 import com.google.common.collect.Sets;
diff --git a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
index fdb2a17..39d8035 100644
--- a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
+++ b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
@@ -46,7 +46,7 @@
 import com.android.tools.r8.graph.PrunedItems;
 import com.android.tools.r8.graph.SubtypingInfo;
 import com.android.tools.r8.graph.lens.GraphLens;
-import com.android.tools.r8.graph.lens.GraphLens.NonIdentityGraphLens;
+import com.android.tools.r8.graph.lens.NonIdentityGraphLens;
 import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
 import com.android.tools.r8.ir.analysis.type.DynamicType;
 import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
diff --git a/src/main/java/com/android/tools/r8/shaking/KeepInfoCollection.java b/src/main/java/com/android/tools/r8/shaking/KeepInfoCollection.java
index 4c028b4..9491483 100644
--- a/src/main/java/com/android/tools/r8/shaking/KeepInfoCollection.java
+++ b/src/main/java/com/android/tools/r8/shaking/KeepInfoCollection.java
@@ -25,7 +25,7 @@
 import com.android.tools.r8.graph.ProgramMember;
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.graph.PrunedItems;
-import com.android.tools.r8.graph.lens.GraphLens.NonIdentityGraphLens;
+import com.android.tools.r8.graph.lens.NonIdentityGraphLens;
 import com.android.tools.r8.shaking.KeepFieldInfo.Joiner;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.MapUtils;
diff --git a/src/main/java/com/android/tools/r8/shaking/RuntimeTypeCheckInfo.java b/src/main/java/com/android/tools/r8/shaking/RuntimeTypeCheckInfo.java
index a2ff4e9..cb0f347 100644
--- a/src/main/java/com/android/tools/r8/shaking/RuntimeTypeCheckInfo.java
+++ b/src/main/java/com/android/tools/r8/shaking/RuntimeTypeCheckInfo.java
@@ -13,6 +13,7 @@
 import com.android.tools.r8.graph.analysis.EnqueuerExceptionGuardAnalysis;
 import com.android.tools.r8.graph.analysis.EnqueuerInstanceOfAnalysis;
 import com.android.tools.r8.graph.lens.GraphLens;
+import com.android.tools.r8.graph.lens.NonIdentityGraphLens;
 import com.android.tools.r8.utils.SetUtils;
 import com.google.common.collect.Sets;
 import java.util.Set;
@@ -106,7 +107,7 @@
     return isInstanceOfType(clazz) || isCheckCastType(clazz) || isExceptionGuardType(clazz);
   }
 
-  public RuntimeTypeCheckInfo rewriteWithLens(GraphLens.NonIdentityGraphLens graphLens) {
+  public RuntimeTypeCheckInfo rewriteWithLens(NonIdentityGraphLens graphLens) {
     return new RuntimeTypeCheckInfo(
         SetUtils.mapIdentityHashSet(instanceOfTypes, graphLens::lookupType),
         SetUtils.mapIdentityHashSet(checkCastTypes, graphLens::lookupType),
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 7f33f6b..91c86e3 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
@@ -60,9 +60,10 @@
 import com.android.tools.r8.graph.UseRegistry;
 import com.android.tools.r8.graph.UseRegistryWithResult;
 import com.android.tools.r8.graph.classmerging.VerticallyMergedClasses;
+import com.android.tools.r8.graph.lens.FieldLookupResult;
 import com.android.tools.r8.graph.lens.GraphLens;
-import com.android.tools.r8.graph.lens.GraphLens.MethodLookupResult;
-import com.android.tools.r8.graph.lens.GraphLens.NonIdentityGraphLens;
+import com.android.tools.r8.graph.lens.MethodLookupResult;
+import com.android.tools.r8.graph.lens.NonIdentityGraphLens;
 import com.android.tools.r8.graph.proto.RewrittenPrototypeDescription;
 import com.android.tools.r8.ir.code.InvokeType;
 import com.android.tools.r8.ir.code.Position.SyntheticPosition;
diff --git a/src/main/java/com/android/tools/r8/shaking/VerticalClassMergerGraphLens.java b/src/main/java/com/android/tools/r8/shaking/VerticalClassMergerGraphLens.java
index e11801d..0b4a990 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMergerGraphLens.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMergerGraphLens.java
@@ -12,6 +12,7 @@
 import com.android.tools.r8.graph.DexProto;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.classmerging.VerticallyMergedClasses;
+import com.android.tools.r8.graph.lens.MethodLookupResult;
 import com.android.tools.r8.graph.lens.NestedGraphLens;
 import com.android.tools.r8.graph.proto.ArgumentInfoCollection;
 import com.android.tools.r8.graph.proto.RewrittenPrototypeDescription;
diff --git a/src/main/java/com/android/tools/r8/synthesis/CommittedSyntheticsCollection.java b/src/main/java/com/android/tools/r8/synthesis/CommittedSyntheticsCollection.java
index 541bad8..c4152fa 100644
--- a/src/main/java/com/android/tools/r8/synthesis/CommittedSyntheticsCollection.java
+++ b/src/main/java/com/android/tools/r8/synthesis/CommittedSyntheticsCollection.java
@@ -8,7 +8,7 @@
 import com.android.tools.r8.graph.DexApplication;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.PrunedItems;
-import com.android.tools.r8.graph.lens.GraphLens.NonIdentityGraphLens;
+import com.android.tools.r8.graph.lens.NonIdentityGraphLens;
 import com.android.tools.r8.synthesis.SyntheticItems.ContextsForGlobalSynthetics;
 import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
 import com.android.tools.r8.utils.IterableUtils;
diff --git a/src/main/java/com/android/tools/r8/synthesis/Rewritable.java b/src/main/java/com/android/tools/r8/synthesis/Rewritable.java
index 06f41ce..f48e058 100644
--- a/src/main/java/com/android/tools/r8/synthesis/Rewritable.java
+++ b/src/main/java/com/android/tools/r8/synthesis/Rewritable.java
@@ -4,7 +4,7 @@
 package com.android.tools.r8.synthesis;
 
 import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.lens.GraphLens.NonIdentityGraphLens;
+import com.android.tools.r8.graph.lens.NonIdentityGraphLens;
 
 public interface Rewritable<R extends Rewritable<R>> {
 
diff --git a/src/main/java/com/android/tools/r8/synthesis/SynthesizingContext.java b/src/main/java/com/android/tools/r8/synthesis/SynthesizingContext.java
index e2f5e8b..21fd289 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SynthesizingContext.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SynthesizingContext.java
@@ -13,7 +13,7 @@
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.ProgramDefinition;
-import com.android.tools.r8.graph.lens.GraphLens.NonIdentityGraphLens;
+import com.android.tools.r8.graph.lens.NonIdentityGraphLens;
 import com.android.tools.r8.origin.GlobalSyntheticOrigin;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.shaking.MainDexInfo;
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticClasspathClassReference.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticClasspathClassReference.java
index ecf96e8..cd6fcbf 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticClasspathClassReference.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticClasspathClassReference.java
@@ -6,7 +6,7 @@
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexClasspathClass;
 import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.lens.GraphLens.NonIdentityGraphLens;
+import com.android.tools.r8.graph.lens.NonIdentityGraphLens;
 import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
 import java.util.function.Function;
 
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
index 7682aa6..68c2918 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
@@ -22,8 +22,8 @@
 import com.android.tools.r8.graph.PrunedItems;
 import com.android.tools.r8.graph.TreeFixerBase;
 import com.android.tools.r8.graph.lens.GraphLens;
-import com.android.tools.r8.graph.lens.GraphLens.NonIdentityGraphLens;
 import com.android.tools.r8.graph.lens.NestedGraphLens;
+import com.android.tools.r8.graph.lens.NonIdentityGraphLens;
 import com.android.tools.r8.ir.code.NumberGenerator;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.android.tools.r8.shaking.KeepInfoCollection;
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
index a9ba818..24dab29 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
@@ -35,7 +35,7 @@
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.graph.ProgramOrClasspathDefinition;
 import com.android.tools.r8.graph.PrunedItems;
-import com.android.tools.r8.graph.lens.GraphLens.NonIdentityGraphLens;
+import com.android.tools.r8.graph.lens.NonIdentityGraphLens;
 import com.android.tools.r8.horizontalclassmerging.HorizontalClassMerger;
 import com.android.tools.r8.naming.NamingLens;
 import com.android.tools.r8.origin.Origin;
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodReference.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodReference.java
index afc7d09..8853f7c8 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodReference.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodReference.java
@@ -8,7 +8,7 @@
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.ProgramMethod;
-import com.android.tools.r8.graph.lens.GraphLens.NonIdentityGraphLens;
+import com.android.tools.r8.graph.lens.NonIdentityGraphLens;
 import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
 import java.util.function.Consumer;
 import java.util.function.Function;
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticProgramClassReference.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticProgramClassReference.java
index 884c48a..4845892 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticProgramClassReference.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticProgramClassReference.java
@@ -6,7 +6,7 @@
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.lens.GraphLens.NonIdentityGraphLens;
+import com.android.tools.r8.graph.lens.NonIdentityGraphLens;
 import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
 import java.util.function.Consumer;
 import java.util.function.Function;
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticReference.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticReference.java
index 0f30160..801204a 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticReference.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticReference.java
@@ -6,7 +6,7 @@
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexReference;
 import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.lens.GraphLens.NonIdentityGraphLens;
+import com.android.tools.r8.graph.lens.NonIdentityGraphLens;
 import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
 import java.util.function.Function;
 
diff --git a/src/main/java/com/android/tools/r8/tracereferences/Tracer.java b/src/main/java/com/android/tools/r8/tracereferences/Tracer.java
index 0ea11fe..b1d434a 100644
--- a/src/main/java/com/android/tools/r8/tracereferences/Tracer.java
+++ b/src/main/java/com/android/tools/r8/tracereferences/Tracer.java
@@ -30,9 +30,9 @@
 import com.android.tools.r8.graph.ProgramField;
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.graph.UseRegistry;
+import com.android.tools.r8.graph.lens.FieldLookupResult;
 import com.android.tools.r8.graph.lens.GraphLens;
-import com.android.tools.r8.graph.lens.GraphLens.FieldLookupResult;
-import com.android.tools.r8.graph.lens.GraphLens.MethodLookupResult;
+import com.android.tools.r8.graph.lens.MethodLookupResult;
 import com.android.tools.r8.ir.desugar.LambdaDescriptor;
 import com.android.tools.r8.references.ClassReference;
 import com.android.tools.r8.references.FieldReference;
diff --git a/src/main/java/com/android/tools/r8/verticalclassmerging/EmptyInterfaceTypeToClassTypeLensCodeRewriterHelper.java b/src/main/java/com/android/tools/r8/verticalclassmerging/EmptyInterfaceTypeToClassTypeLensCodeRewriterHelper.java
index 06befef..b4c0163 100644
--- a/src/main/java/com/android/tools/r8/verticalclassmerging/EmptyInterfaceTypeToClassTypeLensCodeRewriterHelper.java
+++ b/src/main/java/com/android/tools/r8/verticalclassmerging/EmptyInterfaceTypeToClassTypeLensCodeRewriterHelper.java
@@ -4,7 +4,7 @@
 
 package com.android.tools.r8.verticalclassmerging;
 
-import com.android.tools.r8.graph.lens.GraphLens.MethodLookupResult;
+import com.android.tools.r8.graph.lens.MethodLookupResult;
 import com.android.tools.r8.ir.code.BasicBlock;
 import com.android.tools.r8.ir.code.BasicBlockIterator;
 import com.android.tools.r8.ir.code.FieldPut;
diff --git a/src/main/java/com/android/tools/r8/verticalclassmerging/InterfaceTypeToClassTypeLensCodeRewriterHelper.java b/src/main/java/com/android/tools/r8/verticalclassmerging/InterfaceTypeToClassTypeLensCodeRewriterHelper.java
index d8af88b..d365ddd 100644
--- a/src/main/java/com/android/tools/r8/verticalclassmerging/InterfaceTypeToClassTypeLensCodeRewriterHelper.java
+++ b/src/main/java/com/android/tools/r8/verticalclassmerging/InterfaceTypeToClassTypeLensCodeRewriterHelper.java
@@ -7,8 +7,8 @@
 import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.lens.GraphLens;
-import com.android.tools.r8.graph.lens.GraphLens.MethodLookupResult;
-import com.android.tools.r8.graph.lens.GraphLens.NonIdentityGraphLens;
+import com.android.tools.r8.graph.lens.MethodLookupResult;
+import com.android.tools.r8.graph.lens.NonIdentityGraphLens;
 import com.android.tools.r8.ir.code.BasicBlock;
 import com.android.tools.r8.ir.code.BasicBlockIterator;
 import com.android.tools.r8.ir.code.FieldPut;
diff --git a/src/main/java/com/android/tools/r8/verticalclassmerging/InterfaceTypeToClassTypeLensCodeRewriterHelperImpl.java b/src/main/java/com/android/tools/r8/verticalclassmerging/InterfaceTypeToClassTypeLensCodeRewriterHelperImpl.java
index 203b103..3087061 100644
--- a/src/main/java/com/android/tools/r8/verticalclassmerging/InterfaceTypeToClassTypeLensCodeRewriterHelperImpl.java
+++ b/src/main/java/com/android/tools/r8/verticalclassmerging/InterfaceTypeToClassTypeLensCodeRewriterHelperImpl.java
@@ -12,7 +12,7 @@
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.lens.GraphLens.MethodLookupResult;
+import com.android.tools.r8.graph.lens.MethodLookupResult;
 import com.android.tools.r8.ir.analysis.type.TypeElement;
 import com.android.tools.r8.ir.code.BasicBlock;
 import com.android.tools.r8.ir.code.BasicBlockIterator;