[Metadata] Keep special kotlin types for reflect and kotlinc
Bug: 196179629
Change-Id: I1b09d5b1f0f809cfe556e2771a11cc03e84b1671
diff --git a/src/main/java/com/android/tools/r8/kotlin/Kotlin.java b/src/main/java/com/android/tools/r8/kotlin/Kotlin.java
index 2bbd2b3..9470367 100644
--- a/src/main/java/com/android/tools/r8/kotlin/Kotlin.java
+++ b/src/main/java/com/android/tools/r8/kotlin/Kotlin.java
@@ -9,8 +9,10 @@
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
+import com.google.common.collect.ImmutableSet;
import it.unimi.dsi.fastutil.objects.Object2IntArrayMap;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
+import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@@ -33,8 +35,59 @@
public static final class ClassClassifiers {
public static final String arrayBinaryName = NAME + "/Array";
+ public static final String arrayDescriptor = PACKAGE_PREFIX + "Array;";
public static final String anyDescriptor = PACKAGE_PREFIX + "Any;";
+ public static final String unitDescriptor = PACKAGE_PREFIX + "Unit;";
+ public static final String booleanDescriptor = PACKAGE_PREFIX + "Boolean";
+ public static final String charDescriptor = PACKAGE_PREFIX + "Char";
+ public static final String byteDescriptor = PACKAGE_PREFIX + "Byte";
+ public static final String uByteDescriptor = PACKAGE_PREFIX + "UByte";
+ public static final String shortDescriptor = PACKAGE_PREFIX + "Short;";
+ public static final String uShortDescriptor = PACKAGE_PREFIX + "UShort;";
+ public static final String intDescriptor = PACKAGE_PREFIX + "Int;";
+ public static final String uIntDescriptor = PACKAGE_PREFIX + "UInt;";
+ public static final String floatDescriptor = PACKAGE_PREFIX + "Float;";
+ public static final String longDescriptor = PACKAGE_PREFIX + "Long;";
+ public static final String uLongDescriptor = PACKAGE_PREFIX + "ULong;";
+ public static final String doubleDescriptor = PACKAGE_PREFIX + "Double;";
+ public static final String functionDescriptor = PACKAGE_PREFIX + "Function;";
+ public static final String kFunctionDescriptor = PACKAGE_PREFIX + "KFunction;";
public static final String anyName = NAME + "/Any";
+
+ public static final Set<String> kotlinPrimitivesDescriptors =
+ ImmutableSet.<String>builder()
+ .add(booleanDescriptor)
+ .add(charDescriptor)
+ .add(byteDescriptor)
+ .add(uByteDescriptor)
+ .add(shortDescriptor)
+ .add(uShortDescriptor)
+ .add(intDescriptor)
+ .add(uIntDescriptor)
+ .add(floatDescriptor)
+ .add(longDescriptor)
+ .add(uLongDescriptor)
+ .add(doubleDescriptor)
+ .build();
+
+ // Kotlin static known types is a possible not complete collection of descriptors that kotlinc
+ // and kotlin reflect know and expect the existence of.
+ public static final Set<String> kotlinStaticallyKnownTypes;
+
+ static {
+ ImmutableSet.Builder<String> builder = ImmutableSet.builder();
+ kotlinPrimitivesDescriptors.forEach(
+ primitive -> {
+ builder.add(primitive);
+ builder.add(primitive.substring(0, primitive.length() - 1) + "Array;");
+ });
+ builder.add(unitDescriptor);
+ builder.add(anyDescriptor);
+ builder.add(arrayDescriptor);
+ builder.add(functionDescriptor);
+ builder.add(kFunctionDescriptor);
+ kotlinStaticallyKnownTypes = builder.build();
+ }
}
public Kotlin(DexItemFactory factory) {
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeReference.java b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeReference.java
index 8cea528..4fd93a0 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeReference.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeReference.java
@@ -11,6 +11,7 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens;
+import com.android.tools.r8.kotlin.Kotlin.ClassClassifiers;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.shaking.EnqueuerMetadataTraceable;
import com.android.tools.r8.utils.DescriptorUtils;
@@ -79,8 +80,16 @@
}
DexType rewrittenType = toRewrittenTypeOrNull(appView, known);
if (rewrittenType == null) {
- rewrittenConsumer.accept(defaultValue);
- return true;
+ String knownDescriptor = known.toDescriptorString();
+ // Static known kotlin types can be pruned without rewriting to Any since the types are known
+ // by kotlinc and kotlin reflect.
+ if (ClassClassifiers.kotlinStaticallyKnownTypes.contains(knownDescriptor)) {
+ rewrittenConsumer.accept(knownDescriptor);
+ return false;
+ } else {
+ rewrittenConsumer.accept(defaultValue);
+ return true;
+ }
}
String renamedString = namingLens.lookupDescriptor(rewrittenType).toString();
rewrittenConsumer.accept(renamedString);
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteUnitPrimitiveTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteUnitPrimitiveTest.java
index 66760d1..fafb083 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteUnitPrimitiveTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteUnitPrimitiveTest.java
@@ -10,7 +10,6 @@
import static com.android.tools.r8.ToolHelper.getKotlinReflectJar;
import static com.android.tools.r8.ToolHelper.getKotlinStdlibJar;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertNull;
@@ -18,6 +17,7 @@
import com.android.tools.r8.KotlinTestParameters;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.kotlin.KotlinMetadataWriter;
import com.android.tools.r8.shaking.ProguardKeepAttributes;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.StringUtils;
@@ -128,9 +128,7 @@
getKotlinStdlibJar(kotlinc), ToolHelper.getKotlinReflectJar(kotlinc), libJar)
.addClasspath(main)
.run(parameters.getRuntime(), PKG_APP + ".MainKt")
- // TODO(b/196179629): Should not fail.
- .assertFailureWithErrorThatMatches(
- containsString("Could not compute caller for function: public final fun testUnit()"));
+ .assertSuccessWithOutput(EXPECTED);
}
private void inspect(CodeInspector inspector) throws IOException {
@@ -150,10 +148,11 @@
KotlinClassHeader rewrittenHeader = rewrittenMetadata.getHeader();
TestCase.assertEquals(originalHeader.getKind(), rewrittenHeader.getKind());
TestCase.assertEquals(originalHeader.getPackageName(), rewrittenHeader.getPackageName());
- // TODO(b/196179629): There should not be any rewriting of the data since the return type
- // should not change. Therefore we should be able to assert everything to be equal.
- Assert.assertNotEquals(originalHeader.getData1(), rewrittenHeader.getData1());
- Assert.assertNotEquals(originalHeader.getData2(), rewrittenHeader.getData2());
+ Assert.assertArrayEquals(originalHeader.getData1(), rewrittenHeader.getData1());
+ Assert.assertArrayEquals(originalHeader.getData2(), rewrittenHeader.getData2());
+ String expected = KotlinMetadataWriter.kotlinMetadataToString("", originalMetadata);
+ String actual = KotlinMetadataWriter.kotlinMetadataToString("", rewrittenMetadata);
+ TestCase.assertEquals(expected, actual);
}
}
}