Version 2.1.65

Cherry-pick: Bump kotlin metadataVersion to 1.4.0 if the read input is
less
CL: https://r8-review.googlesource.com/52907

Bug: 161885097
Change-Id: I14d06b44f5864eef74d739285e2d0ffce3ee8dc5
diff --git a/src/main/java/com/android/tools/r8/Version.java b/src/main/java/com/android/tools/r8/Version.java
index 8a1d666..b9a633b 100644
--- a/src/main/java/com/android/tools/r8/Version.java
+++ b/src/main/java/com/android/tools/r8/Version.java
@@ -11,7 +11,7 @@
 
   // This field is accessed from release scripts using simple pattern matching.
   // Therefore, changing this field could break our release scripts.
-  public static final String LABEL = "2.1.64";
+  public static final String LABEL = "2.1.65";
 
   private Version() {
   }
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 24947bf..00e689c 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinClassInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinClassInfo.java
@@ -48,6 +48,7 @@
   private final KotlinTypeReference anonymousObjectOrigin;
   private final String packageName;
   private final KotlinLocalDelegatedPropertyInfo localDelegatedProperties;
+  private final int[] metadataVersion;
 
   private KotlinClassInfo(
       int flags,
@@ -63,7 +64,8 @@
       KotlinVersionRequirementInfo versionRequirements,
       KotlinTypeReference anonymousObjectOrigin,
       String packageName,
-      KotlinLocalDelegatedPropertyInfo localDelegatedProperties) {
+      KotlinLocalDelegatedPropertyInfo localDelegatedProperties,
+      int[] metadataVersion) {
     this.flags = flags;
     this.name = name;
     this.moduleName = moduleName;
@@ -78,11 +80,13 @@
     this.anonymousObjectOrigin = anonymousObjectOrigin;
     this.packageName = packageName;
     this.localDelegatedProperties = localDelegatedProperties;
+    this.metadataVersion = metadataVersion;
   }
 
   public static KotlinClassInfo create(
       KmClass kmClass,
       String packageName,
+      int[] metadataVersion,
       DexClass hostClass,
       DexItemFactory factory,
       Reporter reporter,
@@ -129,7 +133,8 @@
         getAnonymousObjectOrigin(kmClass, factory),
         packageName,
         KotlinLocalDelegatedPropertyInfo.create(
-            JvmExtensionsKt.getLocalDelegatedProperties(kmClass), factory, reporter));
+            JvmExtensionsKt.getLocalDelegatedProperties(kmClass), factory, reporter),
+        metadataVersion);
   }
 
   private static KotlinTypeReference getAnonymousObjectOrigin(
@@ -293,6 +298,11 @@
   }
 
   @Override
+  public int[] getMetadataVersion() {
+    return metadataVersion;
+  }
+
+  @Override
   public void trace(DexDefinitionSupplier definitionSupplier) {
     forEachApply(constructorsWithNoBacking, constructor -> constructor::trace, definitionSupplier);
     declarationContainerInfo.trace(definitionSupplier);
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 fdb326e..1d968d2 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinClassLevelInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinClassLevelInfo.java
@@ -59,4 +59,6 @@
   KotlinClassHeader rewrite(DexClass clazz, AppView<?> appView, NamingLens namingLens);
 
   String getPackageName();
+
+  int[] getMetadataVersion();
 }
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinClassMetadataReader.java b/src/main/java/com/android/tools/r8/kotlin/KotlinClassMetadataReader.java
index 281950c..45cbd27 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinClassMetadataReader.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinClassMetadataReader.java
@@ -112,10 +112,12 @@
       Reporter reporter,
       Consumer<DexEncodedMethod> keepByteCode) {
     String packageName = kMetadata.getHeader().getPackageName();
+    int[] metadataVersion = kMetadata.getHeader().getMetadataVersion();
     if (kMetadata instanceof KotlinClassMetadata.Class) {
       return KotlinClassInfo.create(
           ((KotlinClassMetadata.Class) kMetadata).toKmClass(),
           packageName,
+          metadataVersion,
           clazz,
           factory,
           reporter,
@@ -125,6 +127,7 @@
       return KotlinFileFacadeInfo.create(
           (KotlinClassMetadata.FileFacade) kMetadata,
           packageName,
+          metadataVersion,
           clazz,
           factory,
           reporter,
@@ -132,12 +135,16 @@
     } else if (kMetadata instanceof KotlinClassMetadata.MultiFileClassFacade) {
       // multi-file class with the same @JvmName.
       return KotlinMultiFileClassFacadeInfo.create(
-          (KotlinClassMetadata.MultiFileClassFacade) kMetadata, packageName, factory);
+          (KotlinClassMetadata.MultiFileClassFacade) kMetadata,
+          packageName,
+          metadataVersion,
+          factory);
     } else if (kMetadata instanceof KotlinClassMetadata.MultiFileClassPart) {
       // A single file, which is part of multi-file class.
       return KotlinMultiFileClassPartInfo.create(
           (KotlinClassMetadata.MultiFileClassPart) kMetadata,
           packageName,
+          metadataVersion,
           clazz,
           factory,
           reporter,
@@ -146,6 +153,7 @@
       return KotlinSyntheticClassInfo.create(
           (KotlinClassMetadata.SyntheticClass) kMetadata,
           packageName,
+          metadataVersion,
           clazz,
           kotlin,
           factory,
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 886281f..b012758 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinFileFacadeInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinFileFacadeInfo.java
@@ -22,15 +22,19 @@
 
   private final KotlinPackageInfo packageInfo;
   private final String packageName;
+  private final int[] metadataVersion;
 
-  private KotlinFileFacadeInfo(KotlinPackageInfo packageInfo, String packageName) {
+  private KotlinFileFacadeInfo(
+      KotlinPackageInfo packageInfo, String packageName, int[] metadataVersion) {
     this.packageInfo = packageInfo;
     this.packageName = packageName;
+    this.metadataVersion = metadataVersion;
   }
 
   public static KotlinFileFacadeInfo create(
       FileFacade kmFileFacade,
       String packageName,
+      int[] metadataVersion,
       DexClass clazz,
       DexItemFactory factory,
       Reporter reporter,
@@ -38,7 +42,8 @@
     return new KotlinFileFacadeInfo(
         KotlinPackageInfo.create(
             kmFileFacade.toKmPackage(), clazz, factory, reporter, keepByteCode),
-        packageName);
+        packageName,
+        metadataVersion);
   }
 
   @Override
@@ -66,6 +71,11 @@
   }
 
   @Override
+  public int[] getMetadataVersion() {
+    return metadataVersion;
+  }
+
+  @Override
   public void trace(DexDefinitionSupplier definitionSupplier) {
     packageInfo.trace(definitionSupplier);
   }
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 5e11d43..ace8717 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java
@@ -27,6 +27,11 @@
 
 public class KotlinMetadataRewriter {
 
+  // Due to a bug with nested classes and the lookup of RequirementVersion, we bump all metadata
+  // versions to 1.4 if compiled with kotlin 1.3 (1.1.16). For more information, see b/161885097 for
+  // more information.
+  private static final int[] METADATA_VERSION_1_4 = new int[] {1, 4, 0};
+
   private static final class WriteMetadataFieldInfo {
     final boolean writeKind;
     final boolean writeMetadataVersion;
@@ -111,7 +116,10 @@
             KotlinClassHeader kotlinClassHeader = kotlinInfo.rewrite(clazz, appView, lens);
             DexAnnotation newMeta =
                 createKotlinMetadataAnnotation(
-                    kotlinClassHeader, kotlinInfo.getPackageName(), writeMetadataFieldInfo);
+                    kotlinClassHeader,
+                    kotlinInfo.getPackageName(),
+                    getMaxVersion(METADATA_VERSION_1_4, kotlinInfo.getMetadataVersion()),
+                    writeMetadataFieldInfo);
             clazz.setAnnotations(
                 clazz.annotations().rewrite(anno -> anno == oldMeta ? newMeta : anno));
           } catch (Throwable t) {
@@ -136,12 +144,15 @@
   }
 
   private DexAnnotation createKotlinMetadataAnnotation(
-      KotlinClassHeader header, String packageName, WriteMetadataFieldInfo writeMetadataFieldInfo) {
+      KotlinClassHeader header,
+      String packageName,
+      int[] metadataVersion,
+      WriteMetadataFieldInfo writeMetadataFieldInfo) {
     List<DexAnnotationElement> elements = new ArrayList<>();
     if (writeMetadataFieldInfo.writeMetadataVersion) {
       elements.add(
           new DexAnnotationElement(
-              kotlin.metadata.metadataVersion, createIntArray(header.getMetadataVersion())));
+              kotlin.metadata.metadataVersion, createIntArray(metadataVersion)));
     }
     if (writeMetadataFieldInfo.writeByteCodeVersion) {
       elements.add(
@@ -197,4 +208,23 @@
     }
     return new DexValueArray(values);
   }
+
+  // We are not sure that the format is <Major>-<Minor>-<Patch>, the format can be: <Major>-<Minor>.
+  private int[] getMaxVersion(int[] one, int[] other) {
+    assert one.length == 2 || one.length == 3;
+    assert other.length == 2 || other.length == 3;
+    if (one[0] != other[0]) {
+      return one[0] > other[0] ? one : other;
+    }
+    if (one[1] != other[1]) {
+      return one[1] > other[1] ? one : other;
+    }
+    int patchOne = one.length >= 3 ? one[2] : 0;
+    int patchOther = other.length >= 3 ? other[2] : 0;
+    if (patchOne != patchOther) {
+      return patchOne > patchOther ? one : other;
+    }
+    // They are equal up to patch, just return one.
+    return one;
+  }
 }
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 6ef7a0d..fad37c6 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataUtils.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataUtils.java
@@ -58,6 +58,11 @@
     }
 
     @Override
+    public int[] getMetadataVersion() {
+      throw new Unreachable("Should never be called");
+    }
+
+    @Override
     public boolean isNoKotlinInformation() {
       return true;
     }
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 34c5248..ec31d79 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassFacadeInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassFacadeInfo.java
@@ -23,20 +23,25 @@
 
   private final List<KotlinTypeReference> partClassNames;
   private final String packageName;
+  private final int[] metadataVersion;
 
   private KotlinMultiFileClassFacadeInfo(
-      List<KotlinTypeReference> partClassNames, String packageName) {
+      List<KotlinTypeReference> partClassNames, String packageName, int[] metadataVersion) {
     this.partClassNames = partClassNames;
     this.packageName = packageName;
+    this.metadataVersion = metadataVersion;
   }
 
   static KotlinMultiFileClassFacadeInfo create(
-      MultiFileClassFacade kmMultiFileClassFacade, String packageName, DexItemFactory factory) {
+      MultiFileClassFacade kmMultiFileClassFacade,
+      String packageName,
+      int[] metadataVersion,
+      DexItemFactory factory) {
     ImmutableList.Builder<KotlinTypeReference> builder = ImmutableList.builder();
     for (String partClassName : kmMultiFileClassFacade.getPartClassNames()) {
       builder.add(KotlinTypeReference.fromBinaryName(partClassName, factory));
     }
-    return new KotlinMultiFileClassFacadeInfo(builder.build(), packageName);
+    return new KotlinMultiFileClassFacadeInfo(builder.build(), packageName, metadataVersion);
   }
 
   @Override
@@ -69,6 +74,11 @@
   }
 
   @Override
+  public int[] getMetadataVersion() {
+    return metadataVersion;
+  }
+
+  @Override
   public void trace(DexDefinitionSupplier definitionSupplier) {
     forEachApply(partClassNames, type -> type::trace, definitionSupplier);
   }
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 ca97d0b..6b99d15 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassPartInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassPartInfo.java
@@ -24,17 +24,23 @@
   private final String facadeClassName;
   private final KotlinPackageInfo packageInfo;
   private final String packageName;
+  private final int[] metadataVersion;
 
   private KotlinMultiFileClassPartInfo(
-      String facadeClassName, KotlinPackageInfo packageInfo, String packageName) {
+      String facadeClassName,
+      KotlinPackageInfo packageInfo,
+      String packageName,
+      int[] metadataVersion) {
     this.facadeClassName = facadeClassName;
     this.packageInfo = packageInfo;
     this.packageName = packageName;
+    this.metadataVersion = metadataVersion;
   }
 
   static KotlinMultiFileClassPartInfo create(
       MultiFileClassPart classPart,
       String packageName,
+      int[] metadataVersion,
       DexClass clazz,
       DexItemFactory factory,
       Reporter reporter,
@@ -42,7 +48,8 @@
     return new KotlinMultiFileClassPartInfo(
         classPart.getFacadeClassName(),
         KotlinPackageInfo.create(classPart.toKmPackage(), clazz, factory, reporter, keepByteCode),
-        packageName);
+        packageName,
+        metadataVersion);
   }
 
   @Override
@@ -71,6 +78,11 @@
   }
 
   @Override
+  public int[] getMetadataVersion() {
+    return metadataVersion;
+  }
+
+  @Override
   public void trace(DexDefinitionSupplier definitionSupplier) {
     packageInfo.trace(definitionSupplier);
   }
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 79054f4..41147a5 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinSyntheticClassInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinSyntheticClassInfo.java
@@ -21,6 +21,7 @@
 
   private final KotlinLambdaInfo lambda;
   private final String packageName;
+  private final int[] metadataVersion;
 
   public enum Flavour {
     KotlinStyleLambda,
@@ -30,15 +31,18 @@
 
   private final Flavour flavour;
 
-  private KotlinSyntheticClassInfo(KotlinLambdaInfo lambda, Flavour flavour, String packageName) {
+  private KotlinSyntheticClassInfo(
+      KotlinLambdaInfo lambda, Flavour flavour, String packageName, int[] metadataVersion) {
     this.lambda = lambda;
     this.flavour = flavour;
     this.packageName = packageName;
+    this.metadataVersion = metadataVersion;
   }
 
   static KotlinSyntheticClassInfo create(
       SyntheticClass syntheticClass,
       String packageName,
+      int[] metadataVersion,
       DexClass clazz,
       Kotlin kotlin,
       DexItemFactory factory,
@@ -51,7 +55,8 @@
     return new KotlinSyntheticClassInfo(
         lambda != null ? KotlinLambdaInfo.create(clazz, lambda, factory, reporter) : null,
         getFlavour(syntheticClass, clazz, kotlin),
-        packageName);
+        packageName,
+        metadataVersion);
   }
 
   public boolean isLambda() {
@@ -100,6 +105,11 @@
     return packageName;
   }
 
+  @Override
+  public int[] getMetadataVersion() {
+    return metadataVersion;
+  }
+
   private static Flavour getFlavour(
       KotlinClassMetadata.SyntheticClass metadata, DexClass clazz, Kotlin kotlin) {
     // Returns KotlinStyleLambda if the given clazz is a Kotlin-style lambda: