Version 2.0.32
Backport fix for classinlining static roots with instance fields. The
diff is part of the CL below which fixes the issue.
CL: https://r8-review.googlesource.com/47320/
Bug: 149781762
Change-Id: I0bd7afef5e70380fff379adc5a53d27ec8b3a6f5
diff --git a/src/main/java/com/android/tools/r8/Version.java b/src/main/java/com/android/tools/r8/Version.java
index d38eb99..7944c37 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.0.32";
+ public static final String LABEL = "2.0.33";
private Version() {
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java
index 5683361..f78ba2c 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java
@@ -306,10 +306,24 @@
indirectUsers.addAll(alias.uniqueUsers());
continue;
}
- // Field read/write.
- if (user.isInstanceGet()
- || (user.isInstancePut()
- && receivers.addIllegalReceiverAlias(user.asInstancePut().value()))) {
+
+ if (user.isInstanceGet()) {
+ if (root.isStaticGet()) {
+ // We don't have a replacement for this field read.
+ return user; // Not eligible.
+ }
+ DexEncodedField field =
+ appView.appInfo().resolveField(user.asFieldInstruction().getField());
+ if (field == null || field.isStatic()) {
+ return user; // Not eligible.
+ }
+ continue;
+ }
+
+ if (user.isInstancePut()) {
+ if (!receivers.addIllegalReceiverAlias(user.asInstancePut().value())) {
+ return user; // Not eligible.
+ }
DexEncodedField field =
appView.appInfo().resolveField(user.asFieldInstruction().getField());
if (field == null || field.isStatic()) {
diff --git a/src/test/java/com/android/tools/r8/kotlin/sealed/SealedClassTest.java b/src/test/java/com/android/tools/r8/kotlin/sealed/SealedClassTest.java
new file mode 100644
index 0000000..0d809d2
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/sealed/SealedClassTest.java
@@ -0,0 +1,78 @@
+// 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.kotlin.sealed;
+
+import static com.android.tools.r8.KotlinCompilerTool.KOTLINC;
+import static com.android.tools.r8.ToolHelper.getFilesInTestFolderRelativeToClass;
+
+import com.android.tools.r8.CompilationFailedException;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestRuntime;
+import com.android.tools.r8.TestRuntime.CfRuntime;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.KotlinTargetVersion;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.function.BiFunction;
+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 SealedClassTest extends TestBase {
+
+ private static final String MAIN = "com.android.tools.r8.kotlin.sealed.kt.FormatKt";
+ private static final String[] EXPECTED = new String[] {"ZIP"};
+
+ private final TestParameters parameters;
+ private final KotlinTargetVersion targetVersion;
+
+ @Parameters(name = "{0}")
+ public static List<Object[]> data() {
+ return buildParameters(
+ getTestParameters().withAllRuntimesAndApiLevels().build(), KotlinTargetVersion.values());
+ }
+
+ public SealedClassTest(TestParameters parameters, KotlinTargetVersion targetVersion) {
+ this.parameters = parameters;
+ this.targetVersion = targetVersion;
+ }
+
+ private static BiFunction<TestRuntime, KotlinTargetVersion, Path> compilationResults =
+ memoizeBiFunction(SealedClassTest::compileKotlinCode);
+
+ private static Path compileKotlinCode(TestRuntime runtime, KotlinTargetVersion targetVersion)
+ throws IOException {
+ CfRuntime cfRuntime = runtime.isCf() ? runtime.asCf() : TestRuntime.getCheckedInJdk9();
+ return kotlinc(cfRuntime, getStaticTemp(), KOTLINC, targetVersion)
+ .addSourceFiles(getFilesInTestFolderRelativeToClass(SealedClassTest.class, "kt", ".kt"))
+ .compile();
+ }
+
+ @Test
+ public void testRuntime() throws ExecutionException, CompilationFailedException, IOException {
+ testForRuntime(parameters)
+ .addProgramFiles(compilationResults.apply(parameters.getRuntime(), targetVersion))
+ .addRunClasspathFiles(buildOnDexRuntime(parameters, ToolHelper.getKotlinStdlibJar()))
+ .run(parameters.getRuntime(), MAIN)
+ .assertSuccessWithOutputLines(EXPECTED);
+ }
+
+ @Test
+ public void testR8() throws ExecutionException, CompilationFailedException, IOException {
+ testForR8(parameters.getBackend())
+ .addProgramFiles(compilationResults.apply(parameters.getRuntime(), targetVersion))
+ .addProgramFiles(buildOnDexRuntime(parameters, ToolHelper.getKotlinStdlibJar()))
+ .setMinApi(parameters.getApiLevel())
+ .allowAccessModification()
+ .addKeepMainRule(MAIN)
+ .run(parameters.getRuntime(), MAIN)
+ .assertSuccessWithOutputLines(EXPECTED);
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/kotlin/sealed/kt/Format.kt b/src/test/java/com/android/tools/r8/kotlin/sealed/kt/Format.kt
new file mode 100644
index 0000000..2c1e189
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/sealed/kt/Format.kt
@@ -0,0 +1,20 @@
+// 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.kotlin.sealed.kt
+
+public sealed class Format(val name: String) {
+ object Zip : Format("ZIP")
+ object Directory : Format("DIRECTORY")
+}
+
+fun main() {
+ val value = when ("ZIP") {
+ Format.Zip.name -> Format.Zip
+ Format.Directory.name -> Format.Directory
+ else -> throw IllegalArgumentException(
+ "Valid formats: ${Format.Zip.name} or ${Format.Directory.name}.")
+ }
+ println(value.name)
+}
\ No newline at end of file