Keep track of metadata being rewritten and use original

This will allow us to almost not regress any size in D8. We cannot
enable this for R8 unless we keep track of what input was in the original.

Bug: 185756596
Change-Id: I436996f5e66c10179f380406d4d4c6a8e2570e04
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinAnnotationArgumentInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinAnnotationArgumentInfo.java
index 953766c..883be66 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinAnnotationArgumentInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinAnnotationArgumentInfo.java
@@ -10,14 +10,13 @@
 import com.android.tools.r8.kotlin.Kotlin.ClassClassifiers;
 import com.android.tools.r8.naming.NamingLens;
 import com.android.tools.r8.shaking.EnqueuerMetadataTraceable;
-import com.android.tools.r8.utils.Box;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import java.util.ArrayList;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
-import kotlinx.metadata.KmAnnotation;
+import java.util.function.Consumer;
 import kotlinx.metadata.KmAnnotationArgument;
 import kotlinx.metadata.KmAnnotationArgument.AnnotationValue;
 import kotlinx.metadata.KmAnnotationArgument.ArrayValue;
@@ -29,7 +28,8 @@
   private static final Map<String, KotlinAnnotationArgumentInfo> EMPTY_ARGUMENTS =
       ImmutableMap.of();
 
-  abstract KmAnnotationArgument<?> rewrite(AppView<?> appView, NamingLens namingLens);
+  abstract boolean rewrite(
+      Consumer<KmAnnotationArgument<?>> consumer, AppView<?> appView, NamingLens namingLens);
 
   private static KotlinAnnotationArgumentInfo createArgument(
       KmAnnotationArgument<?> arg, DexItemFactory factory) {
@@ -75,9 +75,13 @@
     }
 
     @Override
-    KmAnnotationArgument<?> rewrite(AppView<?> appView, NamingLens namingLens) {
-      return new KClassValue(
-          value.toRenamedBinaryNameOrDefault(appView, namingLens, ClassClassifiers.anyName));
+    boolean rewrite(
+        Consumer<KmAnnotationArgument<?>> consumer, AppView<?> appView, NamingLens namingLens) {
+      return value.toRenamedBinaryNameOrDefault(
+          rewrittenValue -> consumer.accept(new KClassValue(rewrittenValue)),
+          appView,
+          namingLens,
+          ClassClassifiers.anyName);
     }
   }
 
@@ -103,10 +107,14 @@
     }
 
     @Override
-    KmAnnotationArgument<?> rewrite(AppView<?> appView, NamingLens namingLens) {
-      return new EnumValue(
-          enumClassName.toRenamedBinaryNameOrDefault(appView, namingLens, ClassClassifiers.anyName),
-          enumEntryName);
+    boolean rewrite(
+        Consumer<KmAnnotationArgument<?>> consumer, AppView<?> appView, NamingLens namingLens) {
+      return enumClassName.toRenamedBinaryNameOrDefault(
+          rewrittenEnumClassName ->
+              consumer.accept(new EnumValue(rewrittenEnumClassName, enumEntryName)),
+          appView,
+          namingLens,
+          ClassClassifiers.anyName);
     }
   }
 
@@ -130,13 +138,16 @@
     }
 
     @Override
-    KmAnnotationArgument<?> rewrite(AppView<?> appView, NamingLens namingLens) {
-      Box<KmAnnotation> rewrittenAnnotation = new Box<>();
-      value.rewrite(rewrittenAnnotation::set, appView, namingLens);
-      if (rewrittenAnnotation.isSet()) {
-        return new AnnotationValue(rewrittenAnnotation.get());
-      }
-      return null;
+    boolean rewrite(
+        Consumer<KmAnnotationArgument<?>> consumer, AppView<?> appView, NamingLens namingLens) {
+      return value.rewrite(
+          rewrittenAnnotation -> {
+            if (rewrittenAnnotation != null) {
+              consumer.accept(new AnnotationValue(rewrittenAnnotation));
+            }
+          },
+          appView,
+          namingLens);
     }
   }
 
@@ -170,16 +181,23 @@
     }
 
     @Override
-    KmAnnotationArgument<?> rewrite(AppView<?> appView, NamingLens namingLens) {
+    boolean rewrite(
+        Consumer<KmAnnotationArgument<?>> consumer, AppView<?> appView, NamingLens namingLens) {
       List<KmAnnotationArgument<?>> rewrittenArguments = new ArrayList<>();
+      boolean rewritten = false;
       for (KotlinAnnotationArgumentInfo kotlinAnnotationArgumentInfo : value) {
-        KmAnnotationArgument<?> rewrittenArg =
-            kotlinAnnotationArgumentInfo.rewrite(appView, namingLens);
-        if (rewrittenArg != null) {
-          rewrittenArguments.add(rewrittenArg);
-        }
+        rewritten |=
+            kotlinAnnotationArgumentInfo.rewrite(
+                rewrittenArg -> {
+                  if (rewrittenArg != null) {
+                    rewrittenArguments.add(rewrittenArg);
+                  }
+                },
+                appView,
+                namingLens);
       }
-      return new ArrayValue(rewrittenArguments);
+      consumer.accept(new ArrayValue(rewrittenArguments));
+      return rewritten;
     }
   }
 
@@ -201,8 +219,10 @@
     }
 
     @Override
-    KmAnnotationArgument<?> rewrite(AppView<?> appView, NamingLens namingLens) {
-      return argument;
+    boolean rewrite(
+        Consumer<KmAnnotationArgument<?>> consumer, AppView<?> appView, NamingLens namingLens) {
+      consumer.accept(argument);
+      return false;
     }
   }
 }
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinAnnotationInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinAnnotationInfo.java
index 45adb46..fd036d8 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinAnnotationInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinAnnotationInfo.java
@@ -9,6 +9,7 @@
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.naming.NamingLens;
 import com.android.tools.r8.shaking.EnqueuerMetadataTraceable;
+import com.android.tools.r8.utils.BooleanBox;
 import com.android.tools.r8.utils.DescriptorUtils;
 import com.google.common.collect.ImmutableList;
 import java.util.LinkedHashMap;
@@ -48,26 +49,38 @@
     return builder.build();
   }
 
-  public void rewrite(
+  boolean rewrite(
       KmVisitorProviders.KmAnnotationVisitorProvider visitorProvider,
       AppView<?> appView,
       NamingLens namingLens) {
-    String renamedDescriptor =
-        annotationType.toRenamedDescriptorOrDefault(appView, namingLens, null);
-    if (renamedDescriptor == null) {
-      // The type has been pruned
-      return;
-    }
-    String classifier = DescriptorUtils.descriptorToKotlinClassifier(renamedDescriptor);
-    Map<String, KmAnnotationArgument<?>> rewrittenArguments = new LinkedHashMap<>();
-    arguments.forEach(
-        (key, arg) -> {
-          KmAnnotationArgument<?> rewrittenArg = arg.rewrite(appView, namingLens);
-          if (rewrittenArg != null) {
-            rewrittenArguments.put(key, rewrittenArg);
-          }
-        });
-    visitorProvider.get(new KmAnnotation(classifier, rewrittenArguments));
+    BooleanBox rewritten = new BooleanBox(false);
+    rewritten.or(
+        annotationType.toRenamedDescriptorOrDefault(
+            renamedDescriptor -> {
+              if (renamedDescriptor == null) {
+                // The type has been pruned
+                rewritten.set(true);
+                return;
+              }
+              String classifier = DescriptorUtils.descriptorToKotlinClassifier(renamedDescriptor);
+              Map<String, KmAnnotationArgument<?>> rewrittenArguments = new LinkedHashMap<>();
+              arguments.forEach(
+                  (key, arg) ->
+                      rewritten.or(
+                          arg.rewrite(
+                              rewrittenArg -> {
+                                if (rewrittenArg != null) {
+                                  rewrittenArguments.put(key, rewrittenArg);
+                                }
+                              },
+                              appView,
+                              namingLens)));
+              visitorProvider.get(new KmAnnotation(classifier, rewrittenArguments));
+            },
+            appView,
+            namingLens,
+            null));
+    return rewritten.get();
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinClassInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinClassInfo.java
index 2e78e71..64a3103 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinClassInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinClassInfo.java
@@ -17,6 +17,7 @@
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.naming.NamingLens;
 import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.Pair;
 import com.android.tools.r8.utils.Reporter;
 import com.google.common.collect.ImmutableList;
 import java.util.HashMap;
@@ -193,7 +194,7 @@
     }
     for (DexEncodedField field : hostClass.fields()) {
       if (field.getReference().name.toString().equals(companionObjectName)) {
-        field.setKotlinMemberInfo(new KotlinCompanionInfo());
+        field.setKotlinMemberInfo(new KotlinCompanionInfo(companionObjectName));
         return;
       }
     }
@@ -212,7 +213,8 @@
   }
 
   @Override
-  public KotlinClassHeader rewrite(DexClass clazz, AppView<?> appView, NamingLens namingLens) {
+  public Pair<KotlinClassHeader, Boolean> rewrite(
+      DexClass clazz, AppView<?> appView, NamingLens namingLens) {
     KmClass kmClass = new KmClass();
     // TODO(b/154348683): Set flags.
     kmClass.setFlags(flags);
@@ -222,88 +224,113 @@
     // If the original descriptor equals the rewritten descriptor, we pick the original name
     // to preserve potential errors in the original name. As an example, the kotlin stdlib has
     // name: .kotlin/collections/CollectionsKt___CollectionsKt$groupingBy$1, which seems incorrect.
+    boolean rewritten = !originalDescriptor.equals(rewrittenDescriptor);
     kmClass.setName(
-        originalDescriptor.equals(rewrittenDescriptor)
+        !rewritten
             ? this.name
             : DescriptorUtils.getBinaryNameFromDescriptor(rewrittenDescriptor.toString()));
     // Find a companion object.
     for (DexEncodedField field : clazz.fields()) {
       if (field.getKotlinMemberInfo().isCompanion()) {
-        field
-            .getKotlinMemberInfo()
-            .asCompanion()
-            .rewrite(kmClass, field.getReference(), namingLens);
+        rewritten |=
+            field
+                .getKotlinMemberInfo()
+                .asCompanion()
+                .rewrite(kmClass, field.getReference(), namingLens);
       }
     }
     // Take all not backed constructors because we will never find them in definitions.
     for (KotlinConstructorInfo constructorInfo : constructorsWithNoBacking) {
-      constructorInfo.rewrite(kmClass, null, appView, namingLens);
+      rewritten |= constructorInfo.rewrite(kmClass, null, appView, namingLens);
     }
     // Find all constructors.
     for (DexEncodedMethod method : clazz.methods()) {
       if (method.getKotlinMemberInfo().isConstructor()) {
         KotlinConstructorInfo constructorInfo = method.getKotlinMemberInfo().asConstructor();
-        constructorInfo.rewrite(kmClass, method, appView, namingLens);
+        rewritten |= constructorInfo.rewrite(kmClass, method, appView, namingLens);
       }
     }
     // Rewrite functions, type-aliases and type-parameters.
-    declarationContainerInfo.rewrite(
-        kmClass::visitFunction,
-        kmClass::visitProperty,
-        kmClass::visitTypeAlias,
-        clazz,
-        appView,
-        namingLens);
+    rewritten |=
+        declarationContainerInfo.rewrite(
+            kmClass::visitFunction,
+            kmClass::visitProperty,
+            kmClass::visitTypeAlias,
+            clazz,
+            appView,
+            namingLens);
     // Rewrite type parameters.
     for (KotlinTypeParameterInfo typeParameter : typeParameters) {
-      typeParameter.rewrite(kmClass::visitTypeParameter, appView, namingLens);
+      rewritten |= typeParameter.rewrite(kmClass::visitTypeParameter, appView, namingLens);
     }
     // Rewrite super types.
     for (KotlinTypeInfo superType : superTypes) {
       // Ensure the rewritten super type is not this type.
       if (clazz.getType() != superType.rewriteType(appView.graphLens())) {
-        superType.rewrite(kmClass::visitSupertype, appView, namingLens);
+        rewritten |= superType.rewrite(kmClass::visitSupertype, appView, namingLens);
+      } else {
+        rewritten = true;
       }
     }
     // Rewrite nested classes.
     for (KotlinTypeReference nestedClass : nestedClasses) {
-      String nestedDescriptor = nestedClass.toRenamedBinaryNameOrDefault(appView, namingLens, null);
-      if (nestedDescriptor != null) {
-        // If the class is a nested class, it should be on the form Foo.Bar$Baz, where Baz is the
-        // name we should record.
-        int innerClassIndex = nestedDescriptor.lastIndexOf(DescriptorUtils.INNER_CLASS_SEPARATOR);
-        kmClass.visitNestedClass(nestedDescriptor.substring(innerClassIndex + 1));
-      }
+      rewritten |=
+          nestedClass.toRenamedBinaryNameOrDefault(
+              nestedDescriptor -> {
+                if (nestedDescriptor != null) {
+                  // If the class is a nested class, it should be on the form Foo.Bar$Baz, where Baz
+                  // is the
+                  // name we should record.
+                  int innerClassIndex =
+                      nestedDescriptor.lastIndexOf(DescriptorUtils.INNER_CLASS_SEPARATOR);
+                  kmClass.visitNestedClass(nestedDescriptor.substring(innerClassIndex + 1));
+                }
+              },
+              appView,
+              namingLens,
+              null);
     }
     // Rewrite sealed sub classes.
     for (KotlinTypeReference sealedSubClass : sealedSubClasses) {
-      String sealedDescriptor =
-          sealedSubClass.toRenamedBinaryNameOrDefault(appView, namingLens, null);
-      if (sealedDescriptor != null) {
-        kmClass.visitSealedSubclass(
-            sealedDescriptor.replace(
-                DescriptorUtils.INNER_CLASS_SEPARATOR, DescriptorUtils.JAVA_PACKAGE_SEPARATOR));
-      }
+      rewritten |=
+          sealedSubClass.toRenamedBinaryNameOrDefault(
+              sealedDescriptor -> {
+                if (sealedDescriptor != null) {
+                  kmClass.visitSealedSubclass(
+                      sealedDescriptor.replace(
+                          DescriptorUtils.INNER_CLASS_SEPARATOR,
+                          DescriptorUtils.JAVA_PACKAGE_SEPARATOR));
+                }
+              },
+              appView,
+              namingLens,
+              null);
     }
     // TODO(b/154347404): Understand enum entries.
     kmClass.getEnumEntries().addAll(enumEntries);
-    versionRequirements.rewrite(kmClass::visitVersionRequirement);
+    rewritten |= versionRequirements.rewrite(kmClass::visitVersionRequirement);
     JvmClassExtensionVisitor extensionVisitor =
         (JvmClassExtensionVisitor) kmClass.visitExtensions(JvmClassExtensionVisitor.TYPE);
     extensionVisitor.visitModuleName(moduleName);
     if (anonymousObjectOrigin != null) {
-      String renamedAnon =
-          anonymousObjectOrigin.toRenamedBinaryNameOrDefault(appView, namingLens, null);
-      if (renamedAnon != null) {
-        extensionVisitor.visitAnonymousObjectOriginName(renamedAnon);
-      }
+      rewritten |=
+          anonymousObjectOrigin.toRenamedBinaryNameOrDefault(
+              renamedAnon -> {
+                if (renamedAnon != null) {
+                  extensionVisitor.visitAnonymousObjectOriginName(renamedAnon);
+                }
+              },
+              appView,
+              namingLens,
+              null);
     }
-    localDelegatedProperties.rewrite(
-        extensionVisitor::visitLocalDelegatedProperty, appView, namingLens);
+    rewritten |=
+        localDelegatedProperties.rewrite(
+            extensionVisitor::visitLocalDelegatedProperty, appView, namingLens);
     extensionVisitor.visitEnd();
     KotlinClassMetadata.Class.Writer writer = new KotlinClassMetadata.Class.Writer();
     kmClass.accept(writer);
-    return writer.write().getHeader();
+    return Pair.create(writer.write().getHeader(), rewritten);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinClassLevelInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinClassLevelInfo.java
index 1d968d2..34c60de 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinClassLevelInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinClassLevelInfo.java
@@ -8,6 +8,7 @@
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.naming.NamingLens;
 import com.android.tools.r8.shaking.EnqueuerMetadataTraceable;
+import com.android.tools.r8.utils.Pair;
 import kotlinx.metadata.jvm.KotlinClassHeader;
 
 public interface KotlinClassLevelInfo extends EnqueuerMetadataTraceable {
@@ -56,7 +57,8 @@
     return null;
   }
 
-  KotlinClassHeader rewrite(DexClass clazz, AppView<?> appView, NamingLens namingLens);
+  Pair<KotlinClassHeader, Boolean> rewrite(
+      DexClass clazz, AppView<?> appView, NamingLens namingLens);
 
   String getPackageName();
 
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinClassifierInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinClassifierInfo.java
index 54b8054..5f5b696 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinClassifierInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinClassifierInfo.java
@@ -48,7 +48,7 @@
     }
   }
 
-  abstract void rewrite(KmTypeVisitor visitor, AppView<?> appView, NamingLens namingLens);
+  abstract boolean rewrite(KmTypeVisitor visitor, AppView<?> appView, NamingLens namingLens);
 
   public DexType rewriteType(GraphLens graphLens) {
     return null;
@@ -65,16 +65,20 @@
     }
 
     @Override
-    void rewrite(KmTypeVisitor visitor, AppView<?> appView, NamingLens namingLens) {
-      String descriptor =
-          type.toRenamedDescriptorOrDefault(appView, namingLens, ClassClassifiers.anyDescriptor);
-      // For local or anonymous classes, the classifier is prefixed with '.' and inner classes are
-      // separated with '$'.
-      if (isLocalOrAnonymous) {
-        visitor.visitClass("." + DescriptorUtils.getBinaryNameFromDescriptor(descriptor));
-      } else {
-        visitor.visitClass(DescriptorUtils.descriptorToKotlinClassifier(descriptor));
-      }
+    boolean rewrite(KmTypeVisitor visitor, AppView<?> appView, NamingLens namingLens) {
+      return type.toRenamedDescriptorOrDefault(
+          descriptor -> {
+            // For local or anonymous classes, the classifier is prefixed with '.' and inner classes
+            // are separated with '$'.
+            if (isLocalOrAnonymous) {
+              visitor.visitClass("." + DescriptorUtils.getBinaryNameFromDescriptor(descriptor));
+            } else {
+              visitor.visitClass(DescriptorUtils.descriptorToKotlinClassifier(descriptor));
+            }
+          },
+          appView,
+          namingLens,
+          ClassClassifiers.anyDescriptor);
     }
 
     @Override
@@ -97,8 +101,9 @@
     }
 
     @Override
-    void rewrite(KmTypeVisitor visitor, AppView<?> appView, NamingLens namingLens) {
+    boolean rewrite(KmTypeVisitor visitor, AppView<?> appView, NamingLens namingLens) {
       visitor.visitTypeParameter(typeId);
+      return false;
     }
 
     @Override
@@ -116,8 +121,9 @@
     }
 
     @Override
-    void rewrite(KmTypeVisitor visitor, AppView<?> appView, NamingLens namingLens) {
+    boolean rewrite(KmTypeVisitor visitor, AppView<?> appView, NamingLens namingLens) {
       visitor.visitTypeAlias(typeAlias);
+      return false;
     }
 
     @Override
@@ -134,8 +140,9 @@
     }
 
     @Override
-    void rewrite(KmTypeVisitor visitor, AppView<?> appView, NamingLens namingLens) {
+    boolean rewrite(KmTypeVisitor visitor, AppView<?> appView, NamingLens namingLens) {
       visitor.visitClass(classifier);
+      return false;
     }
 
     @Override
@@ -152,8 +159,9 @@
     }
 
     @Override
-    void rewrite(KmTypeVisitor visitor, AppView<?> appView, NamingLens namingLens) {
+    boolean rewrite(KmTypeVisitor visitor, AppView<?> appView, NamingLens namingLens) {
       visitor.visitTypeAlias(classifier);
+      return false;
     }
 
     @Override
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinCompanionInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinCompanionInfo.java
index 1e19f1a..f90ed3a 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinCompanionInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinCompanionInfo.java
@@ -13,6 +13,12 @@
 // Structure around a kotlin companion object that can be assigned to a field.
 public class KotlinCompanionInfo implements KotlinFieldLevelInfo {
 
+  private final String companionObjectFieldName;
+
+  public KotlinCompanionInfo(String companionObjectFieldName) {
+    this.companionObjectFieldName = companionObjectFieldName;
+  }
+
   @Override
   public boolean isCompanion() {
     return true;
@@ -23,10 +29,11 @@
     return this;
   }
 
-  public void rewrite(KmClassVisitor visitor, DexField field, NamingLens lens) {
+  boolean rewrite(KmClassVisitor visitor, DexField field, NamingLens lens) {
     DexString dexString = lens.lookupName(field);
     String finalName = dexString.toString();
     visitor.visitCompanionObject(finalName);
+    return !finalName.equals(companionObjectFieldName);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinConstructorInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinConstructorInfo.java
index eb8421a..dd82d58 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinConstructorInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinConstructorInfo.java
@@ -55,20 +55,28 @@
             : null);
   }
 
-  public void rewrite(
+  boolean rewrite(
       KmClass kmClass, DexEncodedMethod method, AppView<?> appView, NamingLens namingLens) {
     // Note that JvmExtensionsKt.setSignature does not have an overload for KmConstructorVisitor,
     // thus we rely on creating the KmConstructor manually.
     // TODO(b/154348683): Check for special flags to pass in.
     KmConstructor kmConstructor = new KmConstructor(flags);
+    boolean rewritten = false;
     if (signature != null) {
-      JvmExtensionsKt.setSignature(kmConstructor, signature.rewrite(method, appView, namingLens));
+      rewritten =
+          signature.rewrite(
+              rewrittenSignature -> JvmExtensionsKt.setSignature(kmConstructor, rewrittenSignature),
+              method,
+              appView,
+              namingLens);
     }
     for (KotlinValueParameterInfo valueParameterInfo : valueParameters) {
-      valueParameterInfo.rewrite(kmConstructor::visitValueParameter, appView, namingLens);
+      rewritten |=
+          valueParameterInfo.rewrite(kmConstructor::visitValueParameter, appView, namingLens);
     }
-    versionRequirements.rewrite(kmConstructor::visitVersionRequirement);
+    rewritten |= versionRequirements.rewrite(kmConstructor::visitVersionRequirement);
     kmClass.getConstructors().add(kmConstructor);
+    return rewritten;
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinContractInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinContractInfo.java
index fd0d60d..2afb66e 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinContractInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinContractInfo.java
@@ -49,17 +49,19 @@
     forEachApply(effects, effect -> effect::trace, definitionSupplier);
   }
 
-  public void rewrite(
+  boolean rewrite(
       KmVisitorProviders.KmContractVisitorProvider visitorProvider,
       AppView<?> appView,
       NamingLens namingLens) {
     if (this == NO_EFFECT) {
-      return;
+      return false;
     }
+    boolean rewritten = false;
     KmContractVisitor kmContractVisitor = visitorProvider.get();
     for (KotlinEffectInfo effect : effects) {
-      effect.rewrite(kmContractVisitor::visitEffect, appView, namingLens);
+      rewritten |= effect.rewrite(kmContractVisitor::visitEffect, appView, namingLens);
     }
     kmContractVisitor.visitEnd();
+    return rewritten;
   }
 }
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinDeclarationContainerInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinDeclarationContainerInfo.java
index 92db593..7d5499a 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinDeclarationContainerInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinDeclarationContainerInfo.java
@@ -155,7 +155,7 @@
     return builder.build();
   }
 
-  public void rewrite(
+  boolean rewrite(
       KmVisitorProviders.KmFunctionVisitorProvider functionProvider,
       KmVisitorProviders.KmPropertyVisitorProvider propertyProvider,
       KmVisitorProviders.KmTypeAliasVisitorProvider typeAliasProvider,
@@ -163,8 +163,9 @@
       AppView<?> appView,
       NamingLens namingLens) {
     // Type aliases only have a representation here, so we can generate them directly.
+    boolean rewritten = false;
     for (KotlinTypeAliasInfo typeAlias : typeAliases) {
-      typeAlias.rewrite(typeAliasProvider, appView, namingLens);
+      rewritten |= typeAlias.rewrite(typeAliasProvider, appView, namingLens);
     }
     // For properties, we need to combine potentially a field, setter and getter.
     Map<KotlinPropertyInfo, KotlinPropertyGroup> properties = new IdentityHashMap<>();
@@ -199,21 +200,24 @@
     }
     for (KotlinPropertyInfo kotlinPropertyInfo : properties.keySet()) {
       KotlinPropertyGroup kotlinPropertyGroup = properties.get(kotlinPropertyInfo);
-      kotlinPropertyInfo.rewrite(
-          propertyProvider,
-          kotlinPropertyGroup.backingField,
-          kotlinPropertyGroup.getter,
-          kotlinPropertyGroup.setter,
-          appView,
-          namingLens);
+      rewritten |=
+          kotlinPropertyInfo.rewrite(
+              propertyProvider,
+              kotlinPropertyGroup.backingField,
+              kotlinPropertyGroup.getter,
+              kotlinPropertyGroup.setter,
+              appView,
+              namingLens);
     }
     // Add all not backed functions and properties.
     for (KotlinFunctionInfo notBackedFunction : functionsWithNoBacking) {
-      notBackedFunction.rewrite(functionProvider, null, appView, namingLens);
+      rewritten |= notBackedFunction.rewrite(functionProvider, null, appView, namingLens);
     }
     for (KotlinPropertyInfo notBackedProperty : propertiesWithNoBacking) {
-      notBackedProperty.rewrite(propertyProvider, null, null, null, appView, namingLens);
+      rewritten |=
+          notBackedProperty.rewrite(propertyProvider, null, null, null, appView, namingLens);
     }
+    return rewritten;
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinEffectExpressionInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinEffectExpressionInfo.java
index d6664d1..bc7cda0 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinEffectExpressionInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinEffectExpressionInfo.java
@@ -85,25 +85,27 @@
     forEachApply(orArguments, arg -> arg::trace, definitionSupplier);
   }
 
-  public void rewrite(
+  boolean rewrite(
       KmEffectExpressionVisitorProvider provider, AppView<?> appView, NamingLens namingLens) {
     if (this == NO_EXPRESSION) {
-      return;
+      return false;
     }
     KmEffectExpressionVisitor visitor = provider.get();
     visitor.visit(flags, parameterIndex);
     if (constantValue != null) {
       visitor.visitConstantValue(constantValue.getValue());
     }
+    boolean rewritten = false;
     if (isInstanceType != null) {
-      isInstanceType.rewrite(visitor::visitIsInstanceType, appView, namingLens);
+      rewritten |= isInstanceType.rewrite(visitor::visitIsInstanceType, appView, namingLens);
     }
     for (KotlinEffectExpressionInfo andArgument : andArguments) {
-      andArgument.rewrite(visitor::visitAndArgument, appView, namingLens);
+      rewritten |= andArgument.rewrite(visitor::visitAndArgument, appView, namingLens);
     }
     for (KotlinEffectExpressionInfo orArgument : orArguments) {
-      orArgument.rewrite(visitor::visitAndArgument, appView, namingLens);
+      rewritten |= orArgument.rewrite(visitor::visitAndArgument, appView, namingLens);
     }
     visitor.visitEnd();
+    return rewritten;
   }
 }
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinEffectInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinEffectInfo.java
index 3b1c748..e581526 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinEffectInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinEffectInfo.java
@@ -51,12 +51,18 @@
     conclusion.trace(definitionSupplier);
   }
 
-  void rewrite(KmEffectVisitorProvider visitorProvider, AppView<?> appView, NamingLens namingLens) {
+  boolean rewrite(
+      KmEffectVisitorProvider visitorProvider, AppView<?> appView, NamingLens namingLens) {
     KmEffectVisitor kmEffectVisitor = visitorProvider.get(type, invocationKind);
-    conclusion.rewrite(kmEffectVisitor::visitConclusionOfConditionalEffect, appView, namingLens);
+    boolean rewritten =
+        conclusion.rewrite(
+            kmEffectVisitor::visitConclusionOfConditionalEffect, appView, namingLens);
     for (KotlinEffectExpressionInfo constructorArgument : constructorArguments) {
-      constructorArgument.rewrite(kmEffectVisitor::visitConstructorArgument, appView, namingLens);
+      rewritten |=
+          constructorArgument.rewrite(
+              kmEffectVisitor::visitConstructorArgument, appView, namingLens);
     }
     kmEffectVisitor.visitEnd();
+    return rewritten;
   }
 }
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinFileFacadeInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinFileFacadeInfo.java
index 6d1d831..7981195 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinFileFacadeInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinFileFacadeInfo.java
@@ -9,6 +9,7 @@
 import com.android.tools.r8.graph.DexDefinitionSupplier;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.naming.NamingLens;
+import com.android.tools.r8.utils.Pair;
 import java.util.function.Consumer;
 import kotlinx.metadata.KmPackage;
 import kotlinx.metadata.jvm.KotlinClassHeader;
@@ -57,12 +58,13 @@
   }
 
   @Override
-  public KotlinClassHeader rewrite(DexClass clazz, AppView<?> appView, NamingLens namingLens) {
-    KotlinClassMetadata.FileFacade.Writer writer = new KotlinClassMetadata.FileFacade.Writer();
+  public Pair<KotlinClassHeader, Boolean> rewrite(
+      DexClass clazz, AppView<?> appView, NamingLens namingLens) {
     KmPackage kmPackage = new KmPackage();
-    packageInfo.rewrite(kmPackage, clazz, appView, namingLens);
+    boolean rewritten = packageInfo.rewrite(kmPackage, clazz, appView, namingLens);
+    KotlinClassMetadata.FileFacade.Writer writer = new KotlinClassMetadata.FileFacade.Writer();
     kmPackage.accept(writer);
-    return writer.write().getHeader();
+    return Pair.create(writer.write().getHeader(), rewritten);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinFlexibleTypeUpperBoundInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinFlexibleTypeUpperBoundInfo.java
index 91413c7..f2a6eb4 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinFlexibleTypeUpperBoundInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinFlexibleTypeUpperBoundInfo.java
@@ -62,15 +62,16 @@
         flexibleTypeUpperBound.getTypeFlexibilityId());
   }
 
-  public void rewrite(
+  boolean rewrite(
       KmVisitorProviders.KmFlexibleUpperBoundVisitorProvider visitorProvider,
       AppView<?> appView,
       NamingLens namingLens) {
     if (this == NO_FLEXIBLE_UPPER_BOUND) {
       // Nothing to do.
-      return;
+      return false;
     }
-    super.rewrite(flags -> visitorProvider.get(flags, typeFlexibilityId), appView, namingLens);
+    return super.rewrite(
+        flags -> visitorProvider.get(flags, typeFlexibilityId), appView, namingLens);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinFunctionInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinFunctionInfo.java
index 057f8bc..e6a249c 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinFunctionInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinFunctionInfo.java
@@ -115,46 +115,56 @@
     return name;
   }
 
-  public void rewrite(
+  boolean rewrite(
       KmVisitorProviders.KmFunctionVisitorProvider visitorProvider,
       DexEncodedMethod method,
       AppView<?> appView,
       NamingLens namingLens) {
     // TODO(b/154348683): Check method for flags to pass in.
+    boolean rewritten = false;
     String finalName = this.name;
     if (method != null) {
       String methodName = method.getReference().name.toString();
       String rewrittenName = namingLens.lookupName(method.getReference()).toString();
       if (!methodName.equals(rewrittenName)) {
+        rewritten = true;
         finalName = rewrittenName;
       }
     }
     KmFunctionVisitor kmFunction = visitorProvider.get(flags, finalName);
     // TODO(b/154348149): ReturnType could have been merged to a subtype.
-    returnType.rewrite(kmFunction::visitReturnType, appView, namingLens);
+    rewritten |= returnType.rewrite(kmFunction::visitReturnType, appView, namingLens);
     for (KotlinValueParameterInfo valueParameterInfo : valueParameters) {
-      valueParameterInfo.rewrite(kmFunction::visitValueParameter, appView, namingLens);
+      rewritten |= valueParameterInfo.rewrite(kmFunction::visitValueParameter, appView, namingLens);
     }
     for (KotlinTypeParameterInfo typeParameterInfo : typeParameters) {
-      typeParameterInfo.rewrite(kmFunction::visitTypeParameter, appView, namingLens);
+      rewritten |= typeParameterInfo.rewrite(kmFunction::visitTypeParameter, appView, namingLens);
     }
     if (receiverParameterType != null) {
-      receiverParameterType.rewrite(kmFunction::visitReceiverParameterType, appView, namingLens);
+      rewritten |=
+          receiverParameterType.rewrite(
+              kmFunction::visitReceiverParameterType, appView, namingLens);
     }
-    versionRequirements.rewrite(kmFunction::visitVersionRequirement);
+    rewritten |= versionRequirements.rewrite(kmFunction::visitVersionRequirement);
     JvmFunctionExtensionVisitor extensionVisitor =
         (JvmFunctionExtensionVisitor) kmFunction.visitExtensions(JvmFunctionExtensionVisitor.TYPE);
     if (signature != null && extensionVisitor != null) {
-      extensionVisitor.visit(signature.rewrite(method, appView, namingLens));
+      rewritten |= signature.rewrite(extensionVisitor::visit, method, appView, namingLens);
     }
     if (lambdaClassOrigin != null && extensionVisitor != null) {
-      String lambdaClassOriginName =
-          lambdaClassOrigin.toRenamedBinaryNameOrDefault(appView, namingLens, null);
-      if (lambdaClassOriginName != null) {
-        extensionVisitor.visitLambdaClassOriginName(lambdaClassOriginName);
-      }
+      rewritten |=
+          lambdaClassOrigin.toRenamedBinaryNameOrDefault(
+              lambdaClassOriginName -> {
+                if (lambdaClassOriginName != null) {
+                  extensionVisitor.visitLambdaClassOriginName(lambdaClassOriginName);
+                }
+              },
+              appView,
+              namingLens,
+              null);
     }
-    contract.rewrite(kmFunction::visitContract, appView, namingLens);
+    rewritten |= contract.rewrite(kmFunction::visitContract, appView, namingLens);
+    return rewritten;
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinJvmFieldSignatureInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinJvmFieldSignatureInfo.java
index 2606807..340275a 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinJvmFieldSignatureInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinJvmFieldSignatureInfo.java
@@ -10,6 +10,8 @@
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.naming.NamingLens;
 import com.android.tools.r8.shaking.EnqueuerMetadataTraceable;
+import com.android.tools.r8.utils.Box;
+import java.util.function.Consumer;
 import kotlinx.metadata.jvm.JvmFieldSignature;
 
 /**
@@ -36,19 +38,27 @@
         KotlinTypeReference.fromDescriptor(fieldSignature.getDesc(), factory));
   }
 
-  public JvmFieldSignature rewrite(
-      DexEncodedField field, AppView<?> appView, NamingLens namingLens) {
+  boolean rewrite(
+      Consumer<JvmFieldSignature> consumer,
+      DexEncodedField field,
+      AppView<?> appView,
+      NamingLens namingLens) {
+    boolean rewritten = false;
     String finalName = name;
     if (field != null) {
       String fieldName = field.getReference().name.toString();
       String rewrittenName = namingLens.lookupName(field.getReference()).toString();
       if (!fieldName.equals(rewrittenName)) {
+        rewritten = true;
         finalName = rewrittenName;
       }
     }
     String defValue = appView.dexItemFactory().objectType.toDescriptorString();
-    return new JvmFieldSignature(
-        finalName, type.toRenamedDescriptorOrDefault(appView, namingLens, defValue));
+    Box<String> renamedDescriptor = new Box<>();
+    rewritten |=
+        type.toRenamedDescriptorOrDefault(renamedDescriptor::set, appView, namingLens, defValue);
+    consumer.accept(new JvmFieldSignature(finalName, renamedDescriptor.get()));
+    return rewritten;
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinJvmMethodSignatureInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinJvmMethodSignatureInfo.java
index 400e66b..5cfa5ac 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinJvmMethodSignatureInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinJvmMethodSignatureInfo.java
@@ -15,6 +15,7 @@
 import com.android.tools.r8.utils.DescriptorUtils;
 import com.google.common.collect.ImmutableList;
 import java.util.List;
+import java.util.function.Consumer;
 import kotlinx.metadata.jvm.JvmMethodSignature;
 
 /**
@@ -70,29 +71,39 @@
     return new KotlinJvmMethodSignatureInfo(name, returnType, parameters.build());
   }
 
-  public JvmMethodSignature rewrite(
-      DexEncodedMethod method, AppView<?> appView, NamingLens namingLens) {
+  boolean rewrite(
+      Consumer<JvmMethodSignature> consumer,
+      DexEncodedMethod method,
+      AppView<?> appView,
+      NamingLens namingLens) {
     if (invalidDescriptor != null) {
-      return new JvmMethodSignature(name, invalidDescriptor);
+      consumer.accept(new JvmMethodSignature(name, invalidDescriptor));
+      return false;
     }
     assert returnType != null;
     String finalName = name;
+    boolean rewritten = false;
     if (method != null) {
       String methodName = method.getReference().name.toString();
       String rewrittenName = namingLens.lookupName(method.getReference()).toString();
       if (!methodName.equals(rewrittenName)) {
         finalName = rewrittenName;
+        rewritten = true;
       }
     }
     StringBuilder descBuilder = new StringBuilder();
     descBuilder.append("(");
     String defValue = appView.dexItemFactory().objectType.toDescriptorString();
     for (KotlinTypeReference parameter : parameters) {
-      descBuilder.append(parameter.toRenamedDescriptorOrDefault(appView, namingLens, defValue));
+      rewritten |=
+          parameter.toRenamedDescriptorOrDefault(
+              descBuilder::append, appView, namingLens, defValue);
     }
     descBuilder.append(")");
-    descBuilder.append(returnType.toRenamedDescriptorOrDefault(appView, namingLens, defValue));
-    return new JvmMethodSignature(finalName, descBuilder.toString());
+    rewritten |=
+        returnType.toRenamedDescriptorOrDefault(descBuilder::append, appView, namingLens, defValue);
+    consumer.accept(new JvmMethodSignature(finalName, descBuilder.toString()));
+    return rewritten;
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinLambdaInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinLambdaInfo.java
index df28ccf..9e10721 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinLambdaInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinLambdaInfo.java
@@ -80,8 +80,7 @@
           .info(KotlinMetadataDiagnostic.lambdaBackingNotFound(clazz.type, function.getName()));
       return false;
     }
-    function.rewrite(visitorProvider.get()::visitFunction, backing, appView, namingLens);
-    return true;
+    return function.rewrite(visitorProvider.get()::visitFunction, backing, appView, namingLens);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinLocalDelegatedPropertyInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinLocalDelegatedPropertyInfo.java
index fca17cf..9548bde 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinLocalDelegatedPropertyInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinLocalDelegatedPropertyInfo.java
@@ -52,10 +52,12 @@
     forEachApply(propertyInfos, prop -> prop::trace, definitionSupplier);
   }
 
-  public void rewrite(
+  boolean rewrite(
       KmPropertyVisitorProvider visitorProvider, AppView<?> appView, NamingLens namingLens) {
+    boolean rewritten = false;
     for (KotlinPropertyInfo propertyInfo : propertyInfos) {
-      propertyInfo.rewrite(visitorProvider, null, null, null, appView, namingLens);
+      rewritten |= propertyInfo.rewrite(visitorProvider, null, null, null, appView, namingLens);
     }
+    return rewritten;
   }
 }
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java
index fb12564..bd43d4f 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java
@@ -20,6 +20,7 @@
 import com.android.tools.r8.graph.DexValue.DexValueString;
 import com.android.tools.r8.naming.NamingLens;
 import com.android.tools.r8.utils.ConsumerUtils;
+import com.android.tools.r8.utils.Pair;
 import com.android.tools.r8.utils.ThreadUtils;
 import java.util.ArrayList;
 import java.util.List;
@@ -155,10 +156,15 @@
       DexAnnotation oldMeta,
       WriteMetadataFieldInfo writeMetadataFieldInfo) {
     try {
-      KotlinClassHeader kotlinClassHeader = kotlinInfo.rewrite(clazz, appView, lens);
+      Pair<KotlinClassHeader, Boolean> kotlinClassHeader = kotlinInfo.rewrite(clazz, appView, lens);
+      // TODO(b/185756596): Remove when special handling is no longer needed.
+      if (!kotlinClassHeader.getSecond() && !appView.enableWholeProgramOptimizations()) {
+        // No rewrite occurred and the data is the same as before.
+        return;
+      }
       DexAnnotation newMeta =
           createKotlinMetadataAnnotation(
-              kotlinClassHeader,
+              kotlinClassHeader.getFirst(),
               kotlinInfo.getPackageName(),
               getMaxVersion(METADATA_VERSION_1_4, kotlinInfo.getMetadataVersion()),
               writeMetadataFieldInfo);
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataUtils.java b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataUtils.java
index fad37c6..921c08b 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataUtils.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataUtils.java
@@ -19,6 +19,7 @@
 import com.android.tools.r8.shaking.ProguardKeepRule;
 import com.android.tools.r8.shaking.ProguardKeepRuleType;
 import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.Pair;
 import kotlinx.metadata.KmExtensionType;
 import kotlinx.metadata.KmProperty;
 import kotlinx.metadata.KmPropertyExtensionVisitor;
@@ -48,7 +49,8 @@
     }
 
     @Override
-    public KotlinClassHeader rewrite(DexClass clazz, AppView<?> appView, NamingLens namingLens) {
+    public Pair<KotlinClassHeader, Boolean> rewrite(
+        DexClass clazz, AppView<?> appView, NamingLens namingLens) {
       throw new Unreachable("Should never be called");
     }
 
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassFacadeInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassFacadeInfo.java
index ec31d79..7088c7f 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassFacadeInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassFacadeInfo.java
@@ -11,6 +11,7 @@
 import com.android.tools.r8.graph.DexDefinitionSupplier;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.naming.NamingLens;
+import com.android.tools.r8.utils.Pair;
 import com.google.common.collect.ImmutableList;
 import java.util.ArrayList;
 import java.util.List;
@@ -55,17 +56,25 @@
   }
 
   @Override
-  public KotlinClassHeader rewrite(DexClass clazz, AppView<?> appView, NamingLens namingLens) {
+  public Pair<KotlinClassHeader, Boolean> rewrite(
+      DexClass clazz, AppView<?> appView, NamingLens namingLens) {
+    List<String> partClassNameStrings = new ArrayList<>(partClassNames.size());
+    boolean rewritten = false;
+    for (KotlinTypeReference partClassName : partClassNames) {
+      rewritten |=
+          partClassName.toRenamedBinaryNameOrDefault(
+              binaryName -> {
+                if (binaryName != null) {
+                  partClassNameStrings.add(binaryName);
+                }
+              },
+              appView,
+              namingLens,
+              null);
+    }
     KotlinClassMetadata.MultiFileClassFacade.Writer writer =
         new KotlinClassMetadata.MultiFileClassFacade.Writer();
-    List<String> partClassNameStrings = new ArrayList<>(partClassNames.size());
-    for (KotlinTypeReference partClassName : partClassNames) {
-      String binaryName = partClassName.toRenamedBinaryNameOrDefault(appView, namingLens, null);
-      if (binaryName != null) {
-        partClassNameStrings.add(binaryName);
-      }
-    }
-    return writer.write(partClassNameStrings).getHeader();
+    return Pair.create(writer.write(partClassNameStrings).getHeader(), rewritten);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassPartInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassPartInfo.java
index ba56b39..24cb385 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassPartInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassPartInfo.java
@@ -9,6 +9,7 @@
 import com.android.tools.r8.graph.DexDefinitionSupplier;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.naming.NamingLens;
+import com.android.tools.r8.utils.Pair;
 import java.util.function.Consumer;
 import kotlinx.metadata.KmPackage;
 import kotlinx.metadata.jvm.KotlinClassHeader;
@@ -64,13 +65,14 @@
   }
 
   @Override
-  public KotlinClassHeader rewrite(DexClass clazz, AppView<?> appView, NamingLens namingLens) {
+  public Pair<KotlinClassHeader, Boolean> rewrite(
+      DexClass clazz, AppView<?> appView, NamingLens namingLens) {
+    KmPackage kmPackage = new KmPackage();
+    boolean rewritten = packageInfo.rewrite(kmPackage, clazz, appView, namingLens);
     KotlinClassMetadata.MultiFileClassPart.Writer writer =
         new KotlinClassMetadata.MultiFileClassPart.Writer();
-    KmPackage kmPackage = new KmPackage();
-    packageInfo.rewrite(kmPackage, clazz, appView, namingLens);
     kmPackage.accept(writer);
-    return writer.write(facadeClassName).getHeader();
+    return Pair.create(writer.write(facadeClassName).getHeader(), rewritten);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinPackageInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinPackageInfo.java
index 28b81fa..d28e7c3 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinPackageInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinPackageInfo.java
@@ -67,21 +67,23 @@
             appView.reporter()));
   }
 
-  public void rewrite(
-      KmPackage kmPackage, DexClass clazz, AppView<?> appView, NamingLens namingLens) {
-    containerInfo.rewrite(
-        kmPackage::visitFunction,
-        kmPackage::visitProperty,
-        kmPackage::visitTypeAlias,
-        clazz,
-        appView,
-        namingLens);
+  boolean rewrite(KmPackage kmPackage, DexClass clazz, AppView<?> appView, NamingLens namingLens) {
+    boolean rewritten =
+        containerInfo.rewrite(
+            kmPackage::visitFunction,
+            kmPackage::visitProperty,
+            kmPackage::visitTypeAlias,
+            clazz,
+            appView,
+            namingLens);
     JvmPackageExtensionVisitor extensionVisitor =
         (JvmPackageExtensionVisitor) kmPackage.visitExtensions(JvmPackageExtensionVisitor.TYPE);
-    localDelegatedProperties.rewrite(
-        extensionVisitor::visitLocalDelegatedProperty, appView, namingLens);
+    rewritten |=
+        localDelegatedProperties.rewrite(
+            extensionVisitor::visitLocalDelegatedProperty, appView, namingLens);
     extensionVisitor.visitModuleName(moduleName);
     extensionVisitor.visitEnd();
+    return rewritten;
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinPropertyInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinPropertyInfo.java
index 6fceb06..11a8a33 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinPropertyInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinPropertyInfo.java
@@ -12,11 +12,14 @@
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.naming.NamingLens;
+import com.android.tools.r8.utils.Box;
 import com.android.tools.r8.utils.Reporter;
 import java.util.List;
 import kotlinx.metadata.KmProperty;
 import kotlinx.metadata.KmPropertyVisitor;
 import kotlinx.metadata.jvm.JvmExtensionsKt;
+import kotlinx.metadata.jvm.JvmFieldSignature;
+import kotlinx.metadata.jvm.JvmMethodSignature;
 import kotlinx.metadata.jvm.JvmPropertyExtensionVisitor;
 
 // Holds information about KmProperty
@@ -140,7 +143,7 @@
     return setterSignature;
   }
 
-  void rewrite(
+  boolean rewrite(
       KmVisitorProviders.KmPropertyVisitorProvider visitorProvider,
       DexEncodedField field,
       DexEncodedMethod getter,
@@ -150,32 +153,52 @@
     // TODO(b/154348683): Flags again.
     KmPropertyVisitor kmProperty = visitorProvider.get(flags, name, getterFlags, setterFlags);
     // TODO(b/154348149): ReturnType could have been merged to a subtype.
+    boolean rewritten = false;
     if (returnType != null) {
-      returnType.rewrite(kmProperty::visitReturnType, appView, namingLens);
+      rewritten = returnType.rewrite(kmProperty::visitReturnType, appView, namingLens);
     }
     if (receiverParameterType != null) {
-      receiverParameterType.rewrite(kmProperty::visitReceiverParameterType, appView, namingLens);
+      rewritten |=
+          receiverParameterType.rewrite(
+              kmProperty::visitReceiverParameterType, appView, namingLens);
     }
     if (setterParameter != null) {
-      setterParameter.rewrite(kmProperty::visitSetterParameter, appView, namingLens);
+      rewritten |= setterParameter.rewrite(kmProperty::visitSetterParameter, appView, namingLens);
     }
     for (KotlinTypeParameterInfo typeParameter : typeParameters) {
-      typeParameter.rewrite(kmProperty::visitTypeParameter, appView, namingLens);
+      rewritten |= typeParameter.rewrite(kmProperty::visitTypeParameter, appView, namingLens);
     }
-    versionRequirements.rewrite(kmProperty::visitVersionRequirement);
+    rewritten |= versionRequirements.rewrite(kmProperty::visitVersionRequirement);
     JvmPropertyExtensionVisitor extensionVisitor =
         (JvmPropertyExtensionVisitor) kmProperty.visitExtensions(JvmPropertyExtensionVisitor.TYPE);
     if (extensionVisitor != null) {
+      Box<JvmFieldSignature> rewrittenFieldSignature = new Box<>();
+      if (fieldSignature != null) {
+        rewritten |=
+            fieldSignature.rewrite(rewrittenFieldSignature::set, field, appView, namingLens);
+      }
+      Box<JvmMethodSignature> rewrittenGetterSignature = new Box<>();
+      if (getterSignature != null) {
+        rewritten |=
+            getterSignature.rewrite(rewrittenGetterSignature::set, getter, appView, namingLens);
+      }
+      Box<JvmMethodSignature> rewrittenSetterSignature = new Box<>();
+      if (setterSignature != null) {
+        rewritten |=
+            setterSignature.rewrite(rewrittenSetterSignature::set, setter, appView, namingLens);
+      }
       extensionVisitor.visit(
           jvmFlags,
-          fieldSignature == null ? null : fieldSignature.rewrite(field, appView, namingLens),
-          getterSignature == null ? null : getterSignature.rewrite(getter, appView, namingLens),
-          setterSignature == null ? null : setterSignature.rewrite(setter, appView, namingLens));
+          rewrittenFieldSignature.get(),
+          rewrittenGetterSignature.get(),
+          rewrittenSetterSignature.get());
       if (syntheticMethodForAnnotations != null) {
-        extensionVisitor.visitSyntheticMethodForAnnotations(
-            syntheticMethodForAnnotations.rewrite(null, appView, namingLens));
+        rewritten |=
+            syntheticMethodForAnnotations.rewrite(
+                extensionVisitor::visitSyntheticMethodForAnnotations, null, appView, namingLens);
       }
     }
+    return rewritten;
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinSyntheticClassInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinSyntheticClassInfo.java
index 898d28c..08e95b3 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinSyntheticClassInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinSyntheticClassInfo.java
@@ -8,6 +8,7 @@
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexDefinitionSupplier;
 import com.android.tools.r8.naming.NamingLens;
+import com.android.tools.r8.utils.Pair;
 import kotlinx.metadata.KmLambda;
 import kotlinx.metadata.jvm.KotlinClassHeader;
 import kotlinx.metadata.jvm.KotlinClassMetadata;
@@ -82,15 +83,16 @@
   }
 
   @Override
-  public KotlinClassHeader rewrite(DexClass clazz, AppView<?> appView, NamingLens namingLens) {
+  public Pair<KotlinClassHeader, Boolean> rewrite(
+      DexClass clazz, AppView<?> appView, NamingLens namingLens) {
     Writer writer = new Writer();
+    boolean rewritten = false;
     if (lambda != null) {
       KmLambda kmLambda = new KmLambda();
-      if (lambda.rewrite(() -> kmLambda, clazz, appView, namingLens)) {
-        kmLambda.accept(writer);
-      }
+      rewritten = lambda.rewrite(() -> kmLambda, clazz, appView, namingLens);
+      kmLambda.accept(writer);
     }
-    return writer.write().getHeader();
+    return Pair.create(writer.write().getHeader(), rewritten);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeAliasInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeAliasInfo.java
index 3ecbc2c..c4e307b 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeAliasInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeAliasInfo.java
@@ -58,20 +58,23 @@
         KotlinVersionRequirementInfo.create(alias.getVersionRequirements()));
   }
 
-  void rewrite(
+  boolean rewrite(
       KmVisitorProviders.KmTypeAliasVisitorProvider visitorProvider,
       AppView<?> appView,
       NamingLens namingLens) {
     KmTypeAliasVisitor kmTypeAliasVisitor = visitorProvider.get(flags, name);
-    underlyingType.rewrite(kmTypeAliasVisitor::visitUnderlyingType, appView, namingLens);
-    expandedType.rewrite(kmTypeAliasVisitor::visitExpandedType, appView, namingLens);
+    boolean rewritten =
+        underlyingType.rewrite(kmTypeAliasVisitor::visitUnderlyingType, appView, namingLens);
+    rewritten |= expandedType.rewrite(kmTypeAliasVisitor::visitExpandedType, appView, namingLens);
     for (KotlinTypeParameterInfo typeParameter : typeParameters) {
-      typeParameter.rewrite(kmTypeAliasVisitor::visitTypeParameter, appView, namingLens);
+      rewritten |=
+          typeParameter.rewrite(kmTypeAliasVisitor::visitTypeParameter, appView, namingLens);
     }
     for (KotlinAnnotationInfo annotation : annotations) {
-      annotation.rewrite(kmTypeAliasVisitor::visitAnnotation, appView, namingLens);
+      rewritten |= annotation.rewrite(kmTypeAliasVisitor::visitAnnotation, appView, namingLens);
     }
-    versionRequirements.rewrite(kmTypeAliasVisitor::visitVersionRequirement);
+    rewritten |= versionRequirements.rewrite(kmTypeAliasVisitor::visitVersionRequirement);
+    return rewritten;
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeInfo.java
index 7f068f6..9503404 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeInfo.java
@@ -79,34 +79,42 @@
     return arguments.build();
   }
 
-  public void rewrite(
+  boolean rewrite(
       KmVisitorProviders.KmTypeVisitorProvider visitorProvider,
       AppView<?> appView,
       NamingLens namingLens) {
     // TODO(b/154348683): Check for correct flags
     KmTypeVisitor kmTypeVisitor = visitorProvider.get(flags);
-    classifier.rewrite(kmTypeVisitor, appView, namingLens);
+    boolean rewritten = classifier.rewrite(kmTypeVisitor, appView, namingLens);
     if (abbreviatedType != null) {
-      abbreviatedType.rewrite(kmTypeVisitor::visitAbbreviatedType, appView, namingLens);
+      rewritten |=
+          abbreviatedType.rewrite(kmTypeVisitor::visitAbbreviatedType, appView, namingLens);
     }
     if (outerType != null) {
-      outerType.rewrite(kmTypeVisitor::visitOuterType, appView, namingLens);
+      rewritten |= outerType.rewrite(kmTypeVisitor::visitOuterType, appView, namingLens);
     }
     for (KotlinTypeProjectionInfo argument : arguments) {
-      argument.rewrite(
-          kmTypeVisitor::visitArgument, kmTypeVisitor::visitStarProjection, appView, namingLens);
+      rewritten |=
+          argument.rewrite(
+              kmTypeVisitor::visitArgument,
+              kmTypeVisitor::visitStarProjection,
+              appView,
+              namingLens);
     }
-    flexibleTypeUpperBound.rewrite(kmTypeVisitor::visitFlexibleTypeUpperBound, appView, namingLens);
+    rewritten |=
+        flexibleTypeUpperBound.rewrite(
+            kmTypeVisitor::visitFlexibleTypeUpperBound, appView, namingLens);
     if (annotations.isEmpty()) {
-      return;
+      return rewritten;
     }
     JvmTypeExtensionVisitor extensionVisitor =
         (JvmTypeExtensionVisitor) kmTypeVisitor.visitExtensions(JvmTypeExtensionVisitor.TYPE);
     if (extensionVisitor != null) {
       for (KotlinAnnotationInfo annotation : annotations) {
-        annotation.rewrite(extensionVisitor::visitAnnotation, appView, namingLens);
+        rewritten |= annotation.rewrite(extensionVisitor::visitAnnotation, appView, namingLens);
       }
     }
+    return rewritten;
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeParameterInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeParameterInfo.java
index d8457ed..21aeaa1 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeParameterInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeParameterInfo.java
@@ -84,23 +84,28 @@
     return builder.build();
   }
 
-  void rewrite(
+  boolean rewrite(
       KmVisitorProviders.KmTypeParameterVisitorProvider visitorProvider,
       AppView<?> appView,
       NamingLens namingLens) {
     KmTypeParameterVisitor kmTypeParameterVisitor = visitorProvider.get(flags, name, id, variance);
+    boolean rewritten = false;
     for (KotlinTypeInfo originalUpperBound : originalUpperBounds) {
-      originalUpperBound.rewrite(kmTypeParameterVisitor::visitUpperBound, appView, namingLens);
+      rewritten |=
+          originalUpperBound.rewrite(kmTypeParameterVisitor::visitUpperBound, appView, namingLens);
     }
     if (annotations.isEmpty()) {
-      return;
+      return rewritten;
     }
     JvmTypeParameterExtensionVisitor extensionVisitor =
         (JvmTypeParameterExtensionVisitor)
             kmTypeParameterVisitor.visitExtensions(JvmTypeParameterExtensionVisitor.TYPE);
-    for (KotlinAnnotationInfo annotation : annotations) {
-      annotation.rewrite(extensionVisitor::visitAnnotation, appView, namingLens);
+    if (extensionVisitor != null) {
+      for (KotlinAnnotationInfo annotation : annotations) {
+        rewritten |= annotation.rewrite(extensionVisitor::visitAnnotation, appView, namingLens);
+      }
     }
+    return rewritten;
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeProjectionInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeProjectionInfo.java
index 1f2ce01..3f83e53 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeProjectionInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeProjectionInfo.java
@@ -35,7 +35,7 @@
     return variance == null && typeInfo == null;
   }
 
-  public void rewrite(
+  boolean rewrite(
       KmVisitorProviders.KmTypeProjectionVisitorProvider visitorProvider,
       KmVisitorProviders.KmTypeStarProjectionVisitorProvider starProjectionProvider,
       AppView<?> appView,
@@ -45,6 +45,7 @@
     } else {
       typeInfo.rewrite(flags -> visitorProvider.get(flags, variance), appView, namingLens);
     }
+    return false;
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeReference.java b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeReference.java
index 2e1ddf9..4d0d990 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeReference.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeReference.java
@@ -12,6 +12,7 @@
 import com.android.tools.r8.naming.NamingLens;
 import com.android.tools.r8.shaking.EnqueuerMetadataTraceable;
 import com.android.tools.r8.utils.DescriptorUtils;
+import java.util.function.Consumer;
 
 /**
  * To account for invalid type references in kotlin metadata, the class KotlinTypeReference will
@@ -60,34 +61,48 @@
     return new KotlinTypeReference(unknownValue);
   }
 
-  String toRenamedDescriptorOrDefault(
-      AppView<?> appView, NamingLens namingLens, String defaultValue) {
+  boolean toRenamedDescriptorOrDefault(
+      Consumer<String> rewrittenConsumer,
+      AppView<?> appView,
+      NamingLens namingLens,
+      String defaultValue) {
     if (unknown != null) {
-      return unknown;
+      rewrittenConsumer.accept(unknown);
+      return false;
     }
     assert known != null;
     DexType rewrittenType = toRewrittenTypeOrNull(appView, known);
     if (rewrittenType == null) {
-      return defaultValue;
+      rewrittenConsumer.accept(defaultValue);
+      return true;
     }
-    return namingLens.lookupDescriptor(rewrittenType).toString();
+    String renamedString = namingLens.lookupDescriptor(rewrittenType).toString();
+    rewrittenConsumer.accept(renamedString);
+    return !known.toDescriptorString().equals(renamedString);
   }
 
-  String toRenamedBinaryNameOrDefault(
-      AppView<?> appView, NamingLens namingLens, String defaultValue) {
+  boolean toRenamedBinaryNameOrDefault(
+      Consumer<String> rewrittenConsumer,
+      AppView<?> appView,
+      NamingLens namingLens,
+      String defaultValue) {
     if (unknown != null) {
       // Unknown values are always on the input form, so we can just return it.
-      return unknown;
+      rewrittenConsumer.accept(unknown);
+      return false;
     }
-    String descriptor = toRenamedDescriptorOrDefault(appView, namingLens, defaultValue);
-    if (descriptor == null) {
-      return null;
-    }
-    if (descriptor.equals(defaultValue)) {
-      // We assume that the default value passed in is already a binary name.
-      return descriptor;
-    }
-    return DescriptorUtils.getBinaryNameFromDescriptor(descriptor);
+    return toRenamedDescriptorOrDefault(
+        descriptor -> {
+          // We assume that the default value passed in is already a binary name.
+          if (descriptor == null || descriptor.equals(defaultValue)) {
+            rewrittenConsumer.accept(descriptor);
+          } else {
+            rewrittenConsumer.accept(DescriptorUtils.getBinaryNameFromDescriptor(descriptor));
+          }
+        },
+        appView,
+        namingLens,
+        defaultValue);
   }
 
   private static DexType toRewrittenTypeOrNull(AppView<?> appView, DexType type) {
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinValueParameterInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinValueParameterInfo.java
index db54d35..293c35a 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinValueParameterInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinValueParameterInfo.java
@@ -66,16 +66,18 @@
     return builder.build();
   }
 
-  void rewrite(
+  boolean rewrite(
       KmVisitorProviders.KmValueParameterVisitorProvider visitorProvider,
       AppView<?> appView,
       NamingLens namingLens) {
     KmValueParameterVisitor kmValueParameterVisitor = visitorProvider.get(flags, name);
-    type.rewrite(kmValueParameterVisitor::visitType, appView, namingLens);
+    boolean rewritten = type.rewrite(kmValueParameterVisitor::visitType, appView, namingLens);
     if (varargElementType != null) {
-      varargElementType.rewrite(
-          kmValueParameterVisitor::visitVarargElementType, appView, namingLens);
+      rewritten |=
+          varargElementType.rewrite(
+              kmValueParameterVisitor::visitVarargElementType, appView, namingLens);
     }
+    return rewritten;
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinVersionRequirementInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinVersionRequirementInfo.java
index 9530f4c..3ab63f9 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinVersionRequirementInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinVersionRequirementInfo.java
@@ -34,13 +34,14 @@
     return new KotlinVersionRequirementInfo(builder.build());
   }
 
-  public void rewrite(KmVisitorProviders.KmVersionRequirementVisitorProvider visitorProvider) {
+  boolean rewrite(KmVisitorProviders.KmVersionRequirementVisitorProvider visitorProvider) {
     if (this == NO_VERSION_REQUIREMENTS) {
-      return;
+      return false;
     }
     for (KotlinVersionRequirementPoint versionRequirement : versionRequirements) {
       versionRequirement.rewrite(visitorProvider.get());
     }
+    return false;
   }
 
   private static class KotlinVersionRequirementPoint {
diff --git a/src/main/java/com/android/tools/r8/utils/Pair.java b/src/main/java/com/android/tools/r8/utils/Pair.java
index c2f3489..24007cc 100644
--- a/src/main/java/com/android/tools/r8/utils/Pair.java
+++ b/src/main/java/com/android/tools/r8/utils/Pair.java
@@ -55,4 +55,8 @@
   public String toString() {
     return "Pair{" + first + ", " + second + '}';
   }
+
+  public static <T, S> Pair<T, S> create(T t, S s) {
+    return new Pair<>(t, s);
+  }
 }
diff --git a/src/test/java/com/android/tools/r8/TestCompileResult.java b/src/test/java/com/android/tools/r8/TestCompileResult.java
index 97b1a5c..f7395d1 100644
--- a/src/test/java/com/android/tools/r8/TestCompileResult.java
+++ b/src/test/java/com/android/tools/r8/TestCompileResult.java
@@ -379,6 +379,11 @@
     return self();
   }
 
+  public CR assertWarningThatMatches(Matcher<Diagnostic> matcher) {
+    getDiagnosticMessages().assertWarningThatMatches(matcher);
+    return self();
+  }
+
   public CR assertAllWarningMessagesMatch(Matcher<String> matcher) {
     getDiagnosticMessages().assertHasWarnings().assertAllWarningsMatch(diagnosticMessage(matcher));
     return self();
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewritePassThroughTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewritePassThroughTest.java
index 39b540f..80578a3 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewritePassThroughTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewritePassThroughTest.java
@@ -8,12 +8,16 @@
 import static com.android.tools.r8.ToolHelper.getKotlinStdlibJar;
 import static org.hamcrest.CoreMatchers.equalTo;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeTrue;
 
 import com.android.tools.r8.KotlinCompilerTool.KotlinCompilerVersion;
 import com.android.tools.r8.KotlinTestParameters;
 import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper.KotlinTargetVersion;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.shaking.ProguardKeepAttributes;
+import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import java.util.Collection;
 import org.junit.Test;
@@ -26,8 +30,11 @@
   @Parameterized.Parameters(name = "{0}, {1}")
   public static Collection<Object[]> data() {
     return buildParameters(
-        getTestParameters().withCfRuntimes().build(),
-        getKotlinTestParameters().withAllCompilersAndTargetVersions().build());
+        getTestParameters().withCfRuntimes().withNoneRuntime().build(),
+        getKotlinTestParameters()
+            .withAllCompilers()
+            .withTargetVersion(KotlinTargetVersion.JAVA_8)
+            .build());
   }
 
   private final TestParameters parameters;
@@ -64,6 +71,7 @@
 
   @Test
   public void testKotlinStdLib() throws Exception {
+    assumeFalse(parameters.isNoneRuntime());
     testForR8(parameters.getBackend())
         .addProgramFiles(getKotlinStdlibJar(kotlinc), getKotlinAnnotationJar(kotlinc))
         .setMinApi(parameters.getApiLevel())
@@ -83,4 +91,25 @@
                       assertEquals(getExpectedNonInitAddedCount(), addedNonInitStrings.intValue());
                     }));
   }
+
+  @Test
+  public void testKotlinStdLibD8() throws Exception {
+    assumeTrue(parameters.isNoneRuntime());
+    testForD8(Backend.DEX)
+        .addProgramFiles(getKotlinStdlibJar(kotlinc), getKotlinAnnotationJar(kotlinc))
+        .setMinApi(AndroidApiLevel.B)
+        // Enable record desugaring support to force a non-identity naming lens
+        .addOptionsModification(
+            options -> options.testing.enableExperimentalRecordDesugaring = true)
+        .compile()
+        .inspect(
+            inspector ->
+                assertEqualMetadata(
+                    new CodeInspector(getKotlinStdlibJar(kotlinc)),
+                    inspector,
+                    (addedStrings, addedNonInitStrings) -> {
+                      assertEquals(0, addedStrings.intValue());
+                      assertEquals(0, addedNonInitStrings.intValue());
+                    }));
+  }
 }