Add support for backporting List.of(E...)
Test: tools/test.py --no-internal -v *ListBackportJava9Test*
Change-Id: I2cc66c3f299f86694118f2426c60d4f245354d92
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
index aeb1dd5..b47dced 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
@@ -925,18 +925,17 @@
method = factory.createMethod(type, proto, name);
addProvider(new MethodGenerator(method, ObjectsMethods::new));
- // List of
+ // List<E> List.of(<args>) for 0 to 10 arguments and List.of(E[])
type = factory.listType;
name = factory.createString("of");
-
- // From 0 to 10 arguments.
- ArrayList<DexType> parameters = new ArrayList<>();
for (int i = 0; i <= 10; i++) {
- proto = factory.createProto(factory.listType, parameters);
+ proto = factory.createProto(factory.listType, Collections.nCopies(i, factory.objectType));
method = factory.createMethod(type, proto, name);
addProvider(new MethodGenerator(method, ListMethods::new));
- parameters.add(factory.objectType);
}
+ proto = factory.createProto(factory.listType, factory.objectArrayType);
+ method = factory.createMethod(type, proto, name);
+ addProvider(new MethodGenerator(method, ListMethods::new, "ofArray"));
}
private void initializeJava11MethodProviders(DexItemFactory factory) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/backports/ListMethods.java b/src/main/java/com/android/tools/r8/ir/desugar/backports/ListMethods.java
index 9aec5f0..736a476 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/backports/ListMethods.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/backports/ListMethods.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.ir.synthetic.TemplateMethodCode;
import com.android.tools.r8.utils.InternalOptions;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -140,4 +141,14 @@
Objects.requireNonNull(e9),
Objects.requireNonNull(e10)));
}
+
+ public static <E> List<E> ofArray(E[] elements) {
+ // TODO(140709356): The other overloads should call into this method to ensure consistent
+ // behavior, but we cannot link against List.of(E[]) because it's only available in Java 9.
+ ArrayList<E> list = new ArrayList<>(elements.length);
+ for (E element : elements) {
+ list.add(Objects.requireNonNull(element));
+ }
+ return Collections.unmodifiableList(list);
+ }
}
diff --git a/src/test/examplesJava9/backport/ListBackportJava9Main.java b/src/test/examplesJava9/backport/ListBackportJava9Main.java
index 88d20ab..4c8ae88 100644
--- a/src/test/examplesJava9/backport/ListBackportJava9Main.java
+++ b/src/test/examplesJava9/backport/ListBackportJava9Main.java
@@ -13,6 +13,7 @@
testOf1();
testOf2();
testOf10();
+ testOfVarargs();
}
private static void testOf0() {
@@ -103,6 +104,45 @@
}
}
+ private static void testOfVarargs() {
+ Object anObject0 = new Object();
+ Object anObject6 = new Object();
+ Object anObject10 = new Object();
+ List<Object> ofObject =
+ List.of(anObject0, new Object(), new Object(), new Object(), new Object(), new Object(),
+ anObject6, new Object(), new Object(), new Object(), anObject10);
+ assertEquals(11, ofObject.size());
+ assertSame(anObject0, ofObject.get(0));
+ assertSame(anObject6, ofObject.get(6));
+ assertSame(anObject10, ofObject.get(10));
+ assertMutationNotAllowed(ofObject);
+
+ List<Integer> ofInteger = List.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+ assertEquals(11, ofInteger.size());
+ assertEquals(0, ofInteger.get(0));
+ assertEquals(6, ofInteger.get(6));
+ assertEquals(10, ofInteger.get(10));
+
+ List<Object> ofMixed = List.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, anObject10);
+ assertEquals(11, ofMixed.size());
+ assertEquals(0, ofMixed.get(0));
+ assertEquals(6, ofMixed.get(6));
+ assertSame(anObject10, ofMixed.get(10));
+ assertMutationNotAllowed(ofMixed);
+
+ // Ensure the supplied mutable array is not used directly since it is mutable.
+ Object[] mutableArray = { anObject0 };
+ List<Object> ofMutableArray = List.of(mutableArray);
+ mutableArray[0] = anObject10;
+ assertSame(anObject0, ofMutableArray.get(0));
+
+ try {
+ List.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, null);
+ throw new AssertionError();
+ } catch (NullPointerException expected) {
+ }
+ }
+
private static void assertMutationNotAllowed(List<Object> ofObject) {
try {
ofObject.add(new Object());