When desugaring to CF always set the CF version

Bug: 173198228
Change-Id: I5d6cbdc697a2c3003482c1455f89be84c5ef00ef
diff --git a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
index 58c9f2d..f41ccd1 100644
--- a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
@@ -255,6 +255,15 @@
         options.reporter, handler -> consumer.accept(ByteDataView.of(result), desc, handler));
   }
 
+  private CfVersion classFileVersionAfterDesugaring(CfVersion version) {
+    if (!appView.options().isDesugaring()) {
+      return version;
+    }
+    CfVersion maxVersionAfterDesugar =
+        options.canUseDefaultAndStaticInterfaceMethods() ? CfVersion.V1_8 : CfVersion.V1_7;
+    return Ordered.min(maxVersionAfterDesugar, version);
+  }
+
   private CfVersion getClassFileVersion(DexEncodedMethod method) {
     if (!method.hasClassFileVersion()) {
       // In this case bridges have been introduced for the Cf back-end,
@@ -282,7 +291,8 @@
     for (DexEncodedMethod method : clazz.virtualMethods()) {
       version = Ordered.max(version, getClassFileVersion(method));
     }
-    return version;
+    // Possibly downgrade class file version if code has been desugared.
+    return classFileVersionAfterDesugaring(version);
   }
 
   private DexValue getSystemAnnotationValue(DexAnnotationSet annotations, DexType type) {
diff --git a/src/test/java/com/android/tools/r8/TestBase.java b/src/test/java/com/android/tools/r8/TestBase.java
index a8b5af7..5669af0 100644
--- a/src/test/java/com/android/tools/r8/TestBase.java
+++ b/src/test/java/com/android/tools/r8/TestBase.java
@@ -17,6 +17,7 @@
 import com.android.tools.r8.ToolHelper.DexVm;
 import com.android.tools.r8.ToolHelper.KotlinTargetVersion;
 import com.android.tools.r8.ToolHelper.ProcessResult;
+import com.android.tools.r8.cf.CfVersion;
 import com.android.tools.r8.code.Instruction;
 import com.android.tools.r8.dex.ApplicationReader;
 import com.android.tools.r8.errors.Unreachable;
@@ -1724,4 +1725,35 @@
         .compile()
         .writeToZip();
   }
+
+  protected static CfVersion extractClassFileVersion(byte[] classFileBytes) {
+    class ClassFileVersionExtractor extends ClassVisitor {
+      private int version;
+
+      private ClassFileVersionExtractor() {
+        super(ASM_VERSION);
+      }
+
+      @Override
+      public void visit(
+          int version,
+          int access,
+          String name,
+          String signature,
+          String superName,
+          String[] interfaces) {
+        this.version = version;
+      }
+
+      CfVersion getClassFileVersion() {
+        return CfVersion.fromRaw(version);
+      }
+    }
+
+    ClassReader reader = new ClassReader(classFileBytes);
+    ClassFileVersionExtractor extractor = new ClassFileVersionExtractor();
+    reader.accept(
+        extractor, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
+    return extractor.getClassFileVersion();
+  }
 }
diff --git a/src/test/java/com/android/tools/r8/desugaring/DesugarCfVersion.java b/src/test/java/com/android/tools/r8/desugaring/DesugarCfVersion.java
new file mode 100644
index 0000000..493fe3d
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugaring/DesugarCfVersion.java
@@ -0,0 +1,256 @@
+// Copyright (c) 2020, 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.desugaring;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.cf.CfVersion;
+import com.android.tools.r8.utils.ZipUtils;
+import com.google.common.io.ByteStreams;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class DesugarCfVersion extends TestBase {
+
+  private final TestParameters parameters;
+
+  @Parameterized.Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withCfRuntimes().withAllApiLevelsAlsoForCf().build();
+  }
+
+  public DesugarCfVersion(TestParameters parameters) {
+    this.parameters = parameters;
+  }
+
+  @Test
+  public void test() throws Exception {
+    Path zip1 =
+        testForD8(parameters.getBackend())
+            .addProgramClassFileData(hide_1_8)
+            .setMinApi(parameters.getApiLevel())
+            .compile()
+            .writeToZip();
+
+    Path zip2 =
+        testForD8(parameters.getBackend())
+            .addProgramClassFileData(hide_1_7)
+            .setMinApi(parameters.getApiLevel())
+            .compile()
+            .writeToZip();
+
+    boolean canUseStaticAndDefaultInterfaceMethods =
+        parameters
+            .getApiLevel()
+            .isGreaterThanOrEqualTo(TestBase.apiLevelWithDefaultInterfaceMethodsSupport());
+    byte[] bytes1 = ByteStreams.toByteArray(Files.newInputStream(zip1));
+    byte[] bytes2 = ByteStreams.toByteArray(Files.newInputStream(zip2));
+    if (!canUseStaticAndDefaultInterfaceMethods) {
+      assertArrayEquals(bytes1, bytes2);
+    }
+
+    assertEquals(CfVersion.V1_8, extractClassFileVersion(hide_1_8));
+    assertEquals(CfVersion.V1_7, extractClassFileVersion(hide_1_7));
+    assertEquals(
+        canUseStaticAndDefaultInterfaceMethods ? CfVersion.V1_8 : CfVersion.V1_7,
+        extractClassFileVersion(
+            ZipUtils.readSingleEntry(zip1, "com/google/android/gms/common/internal/Hide.class")));
+    assertEquals(
+        CfVersion.V1_7,
+        extractClassFileVersion(
+            ZipUtils.readSingleEntry(zip2, "com/google/android/gms/common/internal/Hide.class")));
+  }
+
+  /*
+   Class file bytes for:
+
+   public interface com.google.android.gms.common.internal.Hide extends java.lang.annotation.Annotation
+     minor version: 0
+     major version: 52
+     flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+     this_class: #1                          // com/google/android/gms/common/internal/Hide
+     super_class: #2                         // java/lang/Object
+     interfaces: 1, fields: 0, methods: 0, attributes: 2
+   Constant pool:
+      #1 = Class              #19            // com/google/android/gms/common/internal/Hide
+      #2 = Class              #20            // java/lang/Object
+      #3 = Class              #21            // java/lang/annotation/Annotation
+      #4 = Utf8               SourceFile
+      #5 = Utf8               Hide.java
+      #6 = Utf8               RuntimeVisibleAnnotations
+      #7 = Utf8               Ljava/lang/annotation/Target;
+      #8 = Utf8               value
+      #9 = Utf8               Ljava/lang/annotation/ElementType;
+     #10 = Utf8               TYPE
+     #11 = Utf8               FIELD
+     #12 = Utf8               METHOD
+     #13 = Utf8               CONSTRUCTOR
+     #14 = Utf8               PACKAGE
+     #15 = Utf8               Ljava/lang/annotation/Retention;
+     #16 = Utf8               Ljava/lang/annotation/RetentionPolicy;
+     #17 = Utf8               CLASS
+     #18 = Utf8               Ljava/lang/annotation/Documented;
+     #19 = Utf8               com/google/android/gms/common/internal/Hide
+     #20 = Utf8               java/lang/Object
+     #21 = Utf8               java/lang/annotation/Annotation
+   {
+   }
+   SourceFile: "Hide.java"
+   RuntimeVisibleAnnotations:
+     0: #7(#8=[e#9.#10,e#9.#11,e#9.#12,e#9.#13,e#9.#14])
+       java.lang.annotation.Target(
+         value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR,Ljava/lang/annotation/ElementType;.PACKAGE]
+       )
+     1: #15(#8=e#16.#17)
+       java.lang.annotation.Retention(
+         value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+       )
+     2: #18()
+       java.lang.annotation.Documented
+
+  */
+
+  private static byte[] hide_1_8 =
+      new byte[] {
+        -54, -2, -70, -66, 0, 0, 0, 52, 0, 22, 7, 0, 19, 7, 0, 20,
+        7, 0, 21, 1, 0, 10, 83, 111, 117, 114, 99, 101, 70, 105, 108, 101,
+        1, 0, 9, 72, 105, 100, 101, 46, 106, 97, 118, 97, 1, 0, 25, 82,
+        117, 110, 116, 105, 109, 101, 86, 105, 115, 105, 98, 108, 101, 65, 110, 110,
+        111, 116, 97, 116, 105, 111, 110, 115, 1, 0, 29, 76, 106, 97, 118, 97,
+        47, 108, 97, 110, 103, 47, 97, 110, 110, 111, 116, 97, 116, 105, 111, 110,
+        47, 84, 97, 114, 103, 101, 116, 59, 1, 0, 5, 118, 97, 108, 117, 101,
+        1, 0, 34, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 97, 110,
+        110, 111, 116, 97, 116, 105, 111, 110, 47, 69, 108, 101, 109, 101, 110, 116,
+        84, 121, 112, 101, 59, 1, 0, 4, 84, 89, 80, 69, 1, 0, 5, 70,
+        73, 69, 76, 68, 1, 0, 6, 77, 69, 84, 72, 79, 68, 1, 0, 11,
+        67, 79, 78, 83, 84, 82, 85, 67, 84, 79, 82, 1, 0, 7, 80, 65,
+        67, 75, 65, 71, 69, 1, 0, 32, 76, 106, 97, 118, 97, 47, 108, 97,
+        110, 103, 47, 97, 110, 110, 111, 116, 97, 116, 105, 111, 110, 47, 82, 101,
+        116, 101, 110, 116, 105, 111, 110, 59, 1, 0, 38, 76, 106, 97, 118, 97,
+        47, 108, 97, 110, 103, 47, 97, 110, 110, 111, 116, 97, 116, 105, 111, 110,
+        47, 82, 101, 116, 101, 110, 116, 105, 111, 110, 80, 111, 108, 105, 99, 121,
+        59, 1, 0, 5, 67, 76, 65, 83, 83, 1, 0, 33, 76, 106, 97, 118,
+        97, 47, 108, 97, 110, 103, 47, 97, 110, 110, 111, 116, 97, 116, 105, 111,
+        110, 47, 68, 111, 99, 117, 109, 101, 110, 116, 101, 100, 59, 1, 0, 43,
+        99, 111, 109, 47, 103, 111, 111, 103, 108, 101, 47, 97, 110, 100, 114, 111,
+        105, 100, 47, 103, 109, 115, 47, 99, 111, 109, 109, 111, 110, 47, 105, 110,
+        116, 101, 114, 110, 97, 108, 47, 72, 105, 100, 101, 1, 0, 16, 106, 97,
+        118, 97, 47, 108, 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 1, 0,
+        31, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 97, 110, 110, 111, 116,
+        97, 116, 105, 111, 110, 47, 65, 110, 110, 111, 116, 97, 116, 105, 111, 110,
+        38, 1, 0, 1, 0, 2, 0, 1, 0, 3, 0, 0, 0, 0, 0, 2,
+        0, 4, 0, 0, 0, 2, 0, 5, 0, 6, 0, 0, 0, 51, 0, 3,
+        0, 7, 0, 1, 0, 8, 91, 0, 5, 101, 0, 9, 0, 10, 101, 0,
+        9, 0, 11, 101, 0, 9, 0, 12, 101, 0, 9, 0, 13, 101, 0, 9,
+        0, 14, 0, 15, 0, 1, 0, 8, 101, 0, 16, 0, 17, 0, 18, 0,
+        0
+      };
+
+  /*
+   Class file bytes for:
+
+   public interface com.google.android.gms.common.internal.Hide extends java.lang.annotation.Annotation
+     minor version: 0
+     major version: 51
+     flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+     this_class: #2                          // com/google/android/gms/common/internal/Hide
+     super_class: #4                         // java/lang/Object
+     interfaces: 1, fields: 0, methods: 0, attributes: 2
+   Constant pool:
+      #1 = Utf8               com/google/android/gms/common/internal/Hide
+      #2 = Class              #1             // com/google/android/gms/common/internal/Hide
+      #3 = Utf8               java/lang/Object
+      #4 = Class              #3             // java/lang/Object
+      #5 = Utf8               java/lang/annotation/Annotation
+      #6 = Class              #5             // java/lang/annotation/Annotation
+      #7 = Utf8               Hide.java
+      #8 = Utf8               Ljava/lang/annotation/Target;
+      #9 = Utf8               value
+     #10 = Utf8               Ljava/lang/annotation/ElementType;
+     #11 = Utf8               TYPE
+     #12 = Utf8               FIELD
+     #13 = Utf8               METHOD
+     #14 = Utf8               CONSTRUCTOR
+     #15 = Utf8               PACKAGE
+     #16 = Utf8               Ljava/lang/annotation/Retention;
+     #17 = Utf8               Ljava/lang/annotation/RetentionPolicy;
+     #18 = Utf8               CLASS
+     #19 = Utf8               Ljava/lang/annotation/Documented;
+     #20 = Utf8               SourceFile
+     #21 = Utf8               RuntimeVisibleAnnotations
+   {
+   }
+   SourceFile: "Hide.java"
+   RuntimeVisibleAnnotations:
+     0: #8(#9=[e#10.#11,e#10.#12,e#10.#13,e#10.#14,e#10.#15])
+       java.lang.annotation.Target(
+         value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR,Ljava/lang/annotation/ElementType;.PACKAGE]
+       )
+     1: #16(#9=e#17.#18)
+       java.lang.annotation.Retention(
+         value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+       )
+     2: #19()
+       java.lang.annotation.Documented
+
+  */
+  private static byte[] hide_1_7 =
+      new byte[] {
+        -54, -2, -70, -66, 0, 0, 0, 51, 0, 22, 1, 0, 43, 99, 111, 109,
+        47, 103, 111, 111, 103, 108, 101, 47, 97, 110, 100, 114, 111, 105, 100, 47,
+        103, 109, 115, 47, 99, 111, 109, 109, 111, 110, 47, 105, 110, 116, 101, 114,
+        110, 97, 108, 47, 72, 105, 100, 101, 7, 0, 1, 1, 0, 16, 106, 97,
+        118, 97, 47, 108, 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 7, 0,
+        3, 1, 0, 31, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 97, 110,
+        110, 111, 116, 97, 116, 105, 111, 110, 47, 65, 110, 110, 111, 116, 97, 116,
+        105, 111, 110, 7, 0, 5, 1, 0, 9, 72, 105, 100, 101, 46, 106, 97,
+        118, 97, 1, 0, 29, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47,
+        97, 110, 110, 111, 116, 97, 116, 105, 111, 110, 47, 84, 97, 114, 103, 101,
+        116, 59, 1, 0, 5, 118, 97, 108, 117, 101, 1, 0, 34, 76, 106, 97,
+        118, 97, 47, 108, 97, 110, 103, 47, 97, 110, 110, 111, 116, 97, 116, 105,
+        111, 110, 47, 69, 108, 101, 109, 101, 110, 116, 84, 121, 112, 101, 59, 1,
+        0, 4, 84, 89, 80, 69, 1, 0, 5, 70, 73, 69, 76, 68, 1, 0,
+        6, 77, 69, 84, 72, 79, 68, 1, 0, 11, 67, 79, 78, 83, 84, 82,
+        85, 67, 84, 79, 82, 1, 0, 7, 80, 65, 67, 75, 65, 71, 69, 1,
+        0, 32, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 97, 110, 110,
+        111, 116, 97, 116, 105, 111, 110, 47, 82, 101, 116, 101, 110, 116, 105, 111,
+        110, 59, 1, 0, 38, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47,
+        97, 110, 110, 111, 116, 97, 116, 105, 111, 110, 47, 82, 101, 116, 101, 110,
+        116, 105, 111, 110, 80, 111, 108, 105, 99, 121, 59, 1, 0, 5, 67, 76,
+        65, 83, 83, 1, 0, 33, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103,
+        47, 97, 110, 110, 111, 116, 97, 116, 105, 111, 110, 47, 68, 111, 99, 117,
+        109, 101, 110, 116, 101, 100, 59, 1, 0, 10, 83, 111, 117, 114, 99, 101,
+        70, 105, 108, 101, 1, 0, 25, 82, 117, 110, 116, 105, 109, 101, 86, 105,
+        115, 105, 98, 108, 101, 65, 110, 110, 111, 116, 97, 116, 105, 111, 110, 115,
+        38, 1, 0, 2, 0, 4, 0, 1, 0, 6, 0, 0, 0, 0, 0, 2,
+        0, 20, 0, 0, 0, 2, 0, 7, 0, 21, 0, 0, 0, 51, 0, 3,
+        0, 8, 0, 1, 0, 9, 91, 0, 5, 101, 0, 10, 0, 11, 101, 0,
+        10, 0, 12, 101, 0, 10, 0, 13, 101, 0, 10, 0, 14, 101, 0, 10,
+        0, 15, 0, 16, 0, 1, 0, 9, 101, 0, 17, 0, 18, 0, 19, 0,
+        0
+      };
+
+  // Code for generating the lists above.
+  public static void main(String[] args) throws IOException {
+    Path file = Paths.get(args[0]);
+    byte[] content = ByteStreams.toByteArray(Files.newInputStream(file));
+    final int bytesPerLine = 16;
+    for (int i = 0; i < content.length; i += bytesPerLine) {
+      for (int j = 0; j < bytesPerLine && i + j < content.length; j++) {
+        System.out.print(content[i + j] + ", ");
+      }
+      System.out.println();
+    }
+  }
+}