Version 2.1.46

Cherry-pick: Add reproduction of b/159441805
CL: https://r8-review.googlesource.com/c/r8/+/52341/

Cherry-pick: Add library desugaring support for java.util.TimeZone
CL: https://r8-review.googlesource.com/c/r8/+/52340

Bug: 159441805
Bug: 159275214
Change-Id: If05f3cee337646c2915340d9c59aaa80c8d2d4f7
diff --git a/src/library_desugar/desugar_jdk_libs.json b/src/library_desugar/desugar_jdk_libs.json
index 5bdc91e..049699a 100644
--- a/src/library_desugar/desugar_jdk_libs.json
+++ b/src/library_desugar/desugar_jdk_libs.json
@@ -2,7 +2,7 @@
   "configuration_format_version": 3,
   "group_id" : "com.tools.android",
   "artifact_id" : "desugar_jdk_libs",
-  "version": "1.0.9",
+  "version": "1.0.10",
   "required_compilation_api_level": 26,
   "synthesized_library_classes_package_prefix": "j$.",
   "common_flags": [
@@ -84,7 +84,8 @@
       },
       "retarget_lib_member": {
         "java.util.Date#toInstant": "java.util.DesugarDate",
-        "java.util.GregorianCalendar#toZonedDateTime": "java.util.DesugarGregorianCalendar"
+        "java.util.GregorianCalendar#toZonedDateTime": "java.util.DesugarGregorianCalendar",
+        "java.util.TimeZone#toZoneId": "java.util.DesugarTimeZone"
       },
       "custom_conversion": {
         "java.time.ZonedDateTime": "java.time.TimeConversions",
@@ -163,7 +164,9 @@
         "java.util.Date#from": "java.util.DesugarDate",
         "java.util.Date#toInstant": "java.util.DesugarDate",
         "java.util.GregorianCalendar#from": "java.util.DesugarGregorianCalendar",
-        "java.util.GregorianCalendar#toZonedDateTime": "java.util.DesugarGregorianCalendar"
+        "java.util.GregorianCalendar#toZonedDateTime": "java.util.DesugarGregorianCalendar",
+        "java.util.TimeZone#getTimeZone": "java.util.DesugarTimeZone",
+        "java.util.TimeZone#toZoneId": "java.util.DesugarTimeZone"
       },
       "custom_conversion": {
         "java.time.ZonedDateTime": "java.time.TimeConversions",
diff --git a/src/main/java/com/android/tools/r8/Version.java b/src/main/java/com/android/tools/r8/Version.java
index d2eebf1..5a52f49 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.45";
+  public static final String LABEL = "2.1.46";
 
   private Version() {
   }
diff --git a/src/test/java/com/android/tools/r8/MarkersTest.java b/src/test/java/com/android/tools/r8/MarkersTest.java
index 4fa3dd6..cc7b81e 100644
--- a/src/test/java/com/android/tools/r8/MarkersTest.java
+++ b/src/test/java/com/android/tools/r8/MarkersTest.java
@@ -69,7 +69,7 @@
         allOf(
             markerTool(Tool.L8),
             markerCompilationMode(compilationMode),
-            markerDesugaredLibraryIdentifier("com.tools.android:desugar_jdk_libs:1.0.9"),
+            markerDesugaredLibraryIdentifier("com.tools.android:desugar_jdk_libs:1.0.10"),
             markerHasChecksums(false));
     Matcher<Marker> d8Matcher =
         allOf(
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaTimeTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaTimeTest.java
index 23d3658..6414d4b 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaTimeTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaTimeTest.java
@@ -37,7 +37,13 @@
   private final TestParameters parameters;
   private final boolean shrinkDesugaredLibrary;
   private static final String expectedOutput =
-      StringUtils.lines("Caught java.time.format.DateTimeParseException", "true", "Hello, world");
+      StringUtils.lines(
+          "Caught java.time.format.DateTimeParseException",
+          "true",
+          "1970-01-02T10:17:36.789Z",
+          "GMT",
+          "GMT",
+          "Hello, world");
 
   @Parameters(name = "{1}, shrinkDesugaredLibrary: {0}")
   public static List<Object[]> data() {
@@ -62,13 +68,15 @@
     String expectedInstanceOfTypes;
     if (parameters.getApiLevel().getLevel() >= 26) {
       expectedInvokeHolders =
-          ImmutableSet.of("java.time.Clock", "java.time.LocalDate", "java.time.ZoneOffset");
+          ImmutableSet.of(
+              "java.time.Clock", "java.time.LocalDate", "java.time.ZoneOffset", "java.time.ZoneId");
       expectedCatchGuards = ImmutableSet.of("java.time.format.DateTimeParseException");
       expectedCheckCastType = ImmutableSet.of("java.time.ZoneId");
       expectedInstanceOfTypes = "java.time.ZoneOffset";
     } else {
       expectedInvokeHolders =
-          ImmutableSet.of("j$.time.Clock", "j$.time.LocalDate", "j$.time.ZoneOffset");
+          ImmutableSet.of(
+              "j$.time.Clock", "j$.time.LocalDate", "j$.time.ZoneOffset", "j$.time.ZoneId");
       expectedCatchGuards = ImmutableSet.of("j$.time.format.DateTimeParseException");
       expectedCheckCastType = ImmutableSet.of("j$.time.ZoneId");
       expectedInstanceOfTypes = "j$.time.ZoneOffset";
@@ -166,6 +174,14 @@
         System.out.println("NOT!");
       }
       System.out.println(java.time.ZoneOffset.getAvailableZoneIds().size() > 0);
+
+      System.out.println(
+          java.util.Date.from(new java.util.Date(123456789).toInstant()).toInstant());
+
+      java.util.TimeZone timeZone = java.util.TimeZone.getTimeZone(java.time.ZoneId.of("GMT"));
+      System.out.println(timeZone.getID());
+      System.out.println(timeZone.toZoneId().getId());
+
       System.out.println("Hello, world");
     }
   }
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RetargetOverrideTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RetargetOverrideTest.java
index 04a7258..32bbe65 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RetargetOverrideTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RetargetOverrideTest.java
@@ -122,6 +122,26 @@
       System.out.println("43");
       System.out.println(myAtomicInteger.updateAndGet(x -> x + 100));
       System.out.println("145");
+
+      try {
+        MyDateNoOverride.from(myCal.toInstant());
+        System.out.println("b/159441805 fixed");
+      } catch (NoSuchMethodError e) {
+        // TODO(b/159441805): Should not throw.
+      }
+
+      try {
+        MyDateOverride.from(myCal.toInstant());
+        System.out.println("b/159441805 fixed");
+      } catch (NoSuchMethodError e) {
+        // TODO(b/159441805): Should not throw.
+      }
+
+      System.out.println(MyDateDoubleOverride.from(myCal.toInstant()).toInstant());
+      System.out.println("1970-01-02T10:17:36.788Z");
+
+      System.out.println(MyDateTrippleOverride.from(myCal.toInstant()).toInstant());
+      System.out.println("1970-01-02T10:17:36.788Z");
     }
 
     public static void polyTypes() {
@@ -212,6 +232,22 @@
     public Instant toInstant() {
       return super.toInstant().plusSeconds(3);
     }
+
+    public static Date from(Instant instant) {
+      return new Date(123456788);
+    }
+  }
+
+  static class MyDateTrippleOverride extends MyDateDoubleOverride {
+
+    public MyDateTrippleOverride(long date) {
+      super(date);
+    }
+
+    @Override
+    public Instant toInstant() {
+      return super.toInstant().plusSeconds(6);
+    }
   }
 
   static class MyDateNoOverride extends Date {
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/BasicTimeConversionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/BasicTimeConversionTest.java
deleted file mode 100644
index bb728fb..0000000
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/BasicTimeConversionTest.java
+++ /dev/null
@@ -1,158 +0,0 @@
-// Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-package com.android.tools.r8.desugar.desugaredlibrary.conversiontests;
-
-import static junit.framework.TestCase.assertTrue;
-
-import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
-import com.android.tools.r8.utils.AndroidApiLevel;
-import com.android.tools.r8.utils.BooleanUtils;
-import com.android.tools.r8.utils.StringUtils;
-import com.android.tools.r8.utils.codeinspector.CodeInspector;
-import com.android.tools.r8.utils.codeinspector.MethodSubject;
-import java.time.ZoneId;
-import java.util.List;
-import java.util.TimeZone;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class BasicTimeConversionTest extends DesugaredLibraryTestBase {
-
-  private final TestParameters parameters;
-  private final boolean shrinkDesugaredLibrary;
-  private static final String GMT = StringUtils.lines("GMT");
-
-  @Parameters(name = "{0}, shrinkDesugaredLibrary: {1}")
-  public static List<Object[]> data() {
-    return buildParameters(
-        getConversionParametersUpToExcluding(AndroidApiLevel.O), BooleanUtils.values());
-  }
-
-  public BasicTimeConversionTest(TestParameters parameters, boolean shrinkDesugaredLibrary) {
-    this.shrinkDesugaredLibrary = shrinkDesugaredLibrary;
-    this.parameters = parameters;
-  }
-
-  @Test
-  public void testRewrittenAPICallsD8() throws Exception {
-    KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
-    testForD8()
-        .setMinApi(parameters.getApiLevel())
-        .addInnerClasses(BasicTimeConversionTest.class)
-        .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
-        .compile()
-        .addDesugaredCoreLibraryRunClassPath(
-            this::buildDesugaredLibrary,
-            parameters.getApiLevel(),
-            keepRuleConsumer.get(),
-            shrinkDesugaredLibrary)
-        .inspect(this::checkAPIRewritten)
-        .run(parameters.getRuntime(), Executor.class)
-        .assertSuccessWithOutput(GMT);
-    if (shrinkDesugaredLibrary) {
-      checkKeepRules(keepRuleConsumer.get());
-    }
-  }
-
-  private void checkKeepRules(String keepRules) {
-    assertTrue(keepRules.contains("TimeConversion"));
-  }
-
-  @Test
-  public void testRewrittenAPICallsR8() throws Exception {
-    KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
-    testForR8(parameters.getBackend())
-        .setMinApi(parameters.getApiLevel())
-        .addKeepMainRule(Executor.class)
-        .addInnerClasses(BasicTimeConversionTest.class)
-        .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
-        .compile()
-        .addDesugaredCoreLibraryRunClassPath(
-            this::buildDesugaredLibrary,
-            parameters.getApiLevel(),
-            keepRuleConsumer.get(),
-            shrinkDesugaredLibrary)
-        .run(parameters.getRuntime(), Executor.class)
-        .assertSuccessWithOutput(GMT);
-    if (shrinkDesugaredLibrary) {
-      checkKeepRules(keepRuleConsumer.get());
-    }
-  }
-
-  private void checkAPIRewritten(CodeInspector inspector) {
-    MethodSubject mainMethod = inspector.clazz(Executor.class).uniqueMethodWithName("main");
-    // Check the API calls are not using j$ types.
-    assertTrue(
-        mainMethod
-            .streamInstructions()
-            .anyMatch(
-                instr ->
-                    instr.isInvokeStatic()
-                        && instr.getMethod().name.toString().equals("getTimeZone")
-                        && instr
-                            .getMethod()
-                            .proto
-                            .parameters
-                            .values[0]
-                            .toString()
-                            .equals("java.time.ZoneId")));
-    assertTrue(
-        mainMethod
-            .streamInstructions()
-            .anyMatch(
-                instr ->
-                    instr.isInvokeVirtual()
-                        && instr.getMethod().name.toString().equals("toZoneId")
-                        && instr
-                            .getMethod()
-                            .proto
-                            .returnType
-                            .toString()
-                            .equals("java.time.ZoneId")));
-    // Check the conversion instructions are present.
-    assertTrue(
-        mainMethod
-            .streamInstructions()
-            .anyMatch(
-                instr ->
-                    instr.isInvokeStatic()
-                        && instr.getMethod().name.toString().equals("convert")
-                        && instr
-                            .getMethod()
-                            .proto
-                            .parameters
-                            .values[0]
-                            .toString()
-                            .equals("j$.time.ZoneId")));
-    assertTrue(
-        mainMethod
-            .streamInstructions()
-            .anyMatch(
-                instr ->
-                    instr.isInvokeStatic()
-                        && instr.getMethod().name.toString().equals("convert")
-                        && instr
-                            .getMethod()
-                            .proto
-                            .parameters
-                            .values[0]
-                            .toString()
-                            .equals("java.time.ZoneId")));
-  }
-
-  static class Executor {
-    public static void main(String[] args) {
-      ZoneId zoneId = ZoneId.systemDefault();
-      // Following is a call where java.time.ZoneId is a parameter type (getTimeZone()).
-      TimeZone timeZone = TimeZone.getTimeZone(zoneId);
-      // Following is a call where java.time.ZoneId is a return type (toZoneId()).
-      System.out.println(timeZone.toZoneId().getId());
-    }
-  }
-}