Version 1.4.70
Cherry pick: Stopgap of NPE when searching for the definition of synthesized class.
CL: https://r8-review.googlesource.com/c/r8/+/33961
Cherry pick (partial): Use up-to-date AppInfo in IRConverter.
CL: https://r8-review.googlesource.com/c/r8/+/35363
Bug: 127762980
Change-Id: I0752d6d32bf31407a495dd9f080216433dc32e95
diff --git a/src/main/java/com/android/tools/r8/Version.java b/src/main/java/com/android/tools/r8/Version.java
index bfadd2c..30d9b3b 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 = "1.4.69";
+ public static final String LABEL = "1.4.70";
private Version() {
}
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfo.java b/src/main/java/com/android/tools/r8/graph/AppInfo.java
index db83f6a..d3548c8 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfo.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfo.java
@@ -25,7 +25,7 @@
new ConcurrentHashMap<>();
// For some optimizations, e.g. optimizing synthetic classes, we may need to resolve the current
// class being optimized.
- private ConcurrentHashMap<DexType, DexProgramClass> synthesizedClasses =
+ private final ConcurrentHashMap<DexType, DexProgramClass> synthesizedClasses =
new ConcurrentHashMap<>();
public AppInfo(DexApplication application) {
@@ -37,6 +37,7 @@
this.app = previous.app;
this.dexItemFactory = app.dexItemFactory;
this.definitions.putAll(previous.definitions);
+ this.synthesizedClasses.putAll(previous.synthesizedClasses);
}
protected AppInfo(DirectMappedDexApplication application, GraphLense lense) {
diff --git a/src/main/java/com/android/tools/r8/graph/DexType.java b/src/main/java/com/android/tools/r8/graph/DexType.java
index 1a880f6..9368a79 100644
--- a/src/main/java/com/android/tools/r8/graph/DexType.java
+++ b/src/main/java/com/android/tools/r8/graph/DexType.java
@@ -12,11 +12,12 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.ir.desugar.Java8MethodRewriter;
import com.android.tools.r8.ir.desugar.TwrCloseResourceRewriter;
+import com.android.tools.r8.logging.Log;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.InternalOptions.OutlineOptions;
-import com.google.common.collect.ImmutableList;
import com.google.common.base.Predicates;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
@@ -169,6 +170,13 @@
}
public boolean isStrictSubtypeOf(DexType other, AppInfo appInfo) {
+ // For all erroneous cases, saying `no`---not a strict subtype---is conservative.
+ return isStrictSubtypeOf(other, appInfo, false);
+ }
+
+ // Depending on optimizations, conservative answer of subtype relation may vary.
+ // Pass different `orElse` in that case.
+ public boolean isStrictSubtypeOf(DexType other, AppInfo appInfo, boolean orElse) {
if (this == other) {
return false;
}
@@ -187,7 +195,7 @@
return other.directSubtypes.stream().anyMatch(subtype -> this.isSubtypeOf(subtype,
appInfo));
}
- return isSubtypeOfClass(other, appInfo);
+ return isSubtypeOfClass(other, appInfo, orElse);
}
private boolean isInterfaceSubtypeOf(DexType candidate, DexType other, AppInfo appInfo) {
@@ -207,15 +215,22 @@
return false;
}
- private boolean isSubtypeOfClass(DexType other, AppInfo appInfo) {
+ private boolean isSubtypeOfClass(DexType other, AppInfo appInfo, boolean orElse) {
DexType self = this;
if (other.hierarchyLevel == UNKNOWN_LEVEL) {
- // We have no definition for this class, hence it is not part of the
- // hierarchy.
- return false;
+ // We have no definition for this class, hence it is not part of the hierarchy.
+ return orElse;
}
while (other.hierarchyLevel < self.hierarchyLevel) {
DexClass holder = appInfo.definitionFor(self);
+ // TODO(b/113374256): even synthesized class should be available ATM.
+ if (holder == null) {
+ assert self.isD8R8SynthesizedClassType();
+ if (Log.ENABLED) {
+ Log.debug(getClass(), "%s is not in AppInfo yet.", self.toSourceString());
+ }
+ return orElse;
+ }
assert holder != null && !holder.isInterface();
self = holder.superType;
}
diff --git a/src/test/java/com/android/tools/r8/kotlin/KotlinLambdaMergingWithReprocessingTest.java b/src/test/java/com/android/tools/r8/kotlin/KotlinLambdaMergingWithReprocessingTest.java
new file mode 100644
index 0000000..25cb8f94
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/KotlinLambdaMergingWithReprocessingTest.java
@@ -0,0 +1,26 @@
+// 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.kotlin;
+
+import com.android.tools.r8.utils.InternalOptions;
+import java.util.function.Consumer;
+import org.junit.Test;
+
+public class KotlinLambdaMergingWithReprocessingTest extends AbstractR8KotlinTestBase {
+
+ private Consumer<InternalOptions> optionsModifier =
+ o -> {
+ o.enableTreeShaking = true;
+ o.enableMinification = false;
+ o.enableInlining = true;
+ o.enableClassInlining = true;
+ o.enableLambdaMerging = true;
+ };
+
+ @Test
+ public void testMergingKStyleLambdasAndReprocessing() throws Exception {
+ final String mainClassName = "reprocess_merged_lambdas_kstyle.MainKt";
+ runTest("reprocess_merged_lambdas_kstyle", mainClassName, optionsModifier, null);
+ }
+}