Separate ArrayTypeSignature from ClassTypeSignature.

Bug: 129925954
Change-Id: Ia79049d018f4b795ed0347474c5bceb679163316
diff --git a/src/main/java/com/android/tools/r8/graph/GenericSignature.java b/src/main/java/com/android/tools/r8/graph/GenericSignature.java
index f948208..47763c5 100644
--- a/src/main/java/com/android/tools/r8/graph/GenericSignature.java
+++ b/src/main/java/com/android/tools/r8/graph/GenericSignature.java
@@ -173,9 +173,13 @@
       return null;
     }
 
-    public abstract TypeSignature toArrayTypeSignature(AppView<?> appView);
+    public TypeSignature toArrayTypeSignature(AppView<?> appView) {
+      return null;
+    }
 
-    public abstract TypeSignature toArrayElementTypeSignature(AppView<?> appView);
+    public TypeSignature toArrayElementTypeSignature(AppView<?> appView) {
+      return null;
+    }
   }
 
   // TODO(b/129925954): better structures for a circle of
@@ -200,6 +204,14 @@
       return null;
     }
 
+    public boolean isArrayTypeSignature() {
+      return false;
+    }
+
+    public ArrayTypeSignature asArrayTypeSignature() {
+      return null;
+    }
+
     public boolean isTypeVariableSignature() {
       return false;
     }
@@ -209,12 +221,10 @@
     }
   }
 
-  // TODO(b/129925954): separate ArrayTypeSignature or just reuse ClassTypeSignature?
   public static class ClassTypeSignature extends FieldTypeSignature {
     static final ClassTypeSignature UNKNOWN_CLASS_TYPE_SIGNATURE =
         new ClassTypeSignature(null, ImmutableList.of());
 
-    // This covers class type or array type, with or without type arguments.
     final DexType type;
     // E.g., for Map<K, V>, a signature will indicate what types are for K and V.
     // Note that this could be nested, e.g., Map<K, Consumer<V>>.
@@ -250,25 +260,8 @@
     }
 
     @Override
-    public ClassTypeSignature toArrayTypeSignature(AppView<?> appView) {
-      DexType arrayType = type.toArrayType(1, appView.dexItemFactory());
-      ClassTypeSignature result = new ClassTypeSignature(arrayType, typeArguments);
-      copyEnclosingRelations(result);
-      return result;
-    }
-
-    @Override
-    public ClassTypeSignature toArrayElementTypeSignature(AppView<?> appView) {
-      assert type.isArrayType();
-      DexType elementType = type.toArrayElementType( appView.dexItemFactory());
-      ClassTypeSignature result = new ClassTypeSignature(elementType, typeArguments);
-      copyEnclosingRelations(result);
-      return result;
-    }
-
-    private void copyEnclosingRelations(ClassTypeSignature cloned) {
-      cloned.enclosingTypeSignature = this.enclosingTypeSignature;
-      cloned.innerTypeSignature = this.innerTypeSignature;
+    public ArrayTypeSignature toArrayTypeSignature(AppView<?> appView) {
+      return new ArrayTypeSignature(this);
     }
 
     static void link(ClassTypeSignature outer, ClassTypeSignature inner) {
@@ -278,6 +271,38 @@
     }
   }
 
+  public static class ArrayTypeSignature extends FieldTypeSignature {
+    final TypeSignature elementSignature;
+
+    ArrayTypeSignature(TypeSignature elementSignature) {
+      this.elementSignature = elementSignature;
+    }
+
+    public TypeSignature elementSignature() {
+      return elementSignature;
+    }
+
+    @Override
+    public boolean isArrayTypeSignature() {
+      return true;
+    }
+
+    @Override
+    public ArrayTypeSignature asArrayTypeSignature() {
+      return this;
+    }
+
+    @Override
+    public TypeSignature toArrayTypeSignature(AppView<?> appView) {
+      return new ArrayTypeSignature(this);
+    }
+
+    @Override
+    public TypeSignature toArrayElementTypeSignature(AppView<?> appView) {
+      return elementSignature;
+    }
+  }
+
   public static class TypeVariableSignature extends FieldTypeSignature {
     final String typeVariable;
 
@@ -296,13 +321,8 @@
     }
 
     @Override
-    public TypeSignature toArrayTypeSignature(AppView<?> appView) {
-      throw new Unimplemented("TypeVariableSignature::toArrayTypeSignature");
-    }
-
-    @Override
-    public TypeSignature toArrayElementTypeSignature(AppView<?> appView) {
-      throw new Unimplemented("TypeVariableSignature::toArrayElementTypeSignature");
+    public ArrayTypeSignature toArrayTypeSignature(AppView<?> appView) {
+      return new ArrayTypeSignature(this);
     }
   }
 
@@ -311,8 +331,7 @@
     final DexType type;
 
     BaseTypeSignature(DexType type) {
-      assert type.isPrimitiveType() || type.isPrimitiveArrayType()
-              || type.isVoidType()
+      assert type.isPrimitiveType() || type.isVoidType()
           : type.toDescriptorString();
       this.type = type;
     }
@@ -328,17 +347,9 @@
     }
 
     @Override
-    public BaseTypeSignature toArrayTypeSignature(AppView<?> appView) {
+    public ArrayTypeSignature toArrayTypeSignature(AppView<?> appView) {
       assert !type.isVoidType();
-      DexType arrayType = type.toArrayType(1, appView.dexItemFactory());
-      return new BaseTypeSignature(arrayType);
-    }
-
-    @Override
-    public BaseTypeSignature toArrayElementTypeSignature(AppView<?> appView) {
-      assert type.isPrimitiveArrayType();
-      DexType elementType = type.toArrayElementType(appView.dexItemFactory());
-      return new BaseTypeSignature(elementType);
+      return new ArrayTypeSignature(this);
     }
   }
 
diff --git a/src/test/java/com/android/tools/r8/graph/GenericSignatureTest.java b/src/test/java/com/android/tools/r8/graph/GenericSignatureTest.java
index 710e8da..3bf1f61 100644
--- a/src/test/java/com/android/tools/r8/graph/GenericSignatureTest.java
+++ b/src/test/java/com/android/tools/r8/graph/GenericSignatureTest.java
@@ -50,6 +50,8 @@
     assertThat(yy, isPresent());
     ClassSubject zz = inspector.clazz(A.Y.ZZ.class);
     assertThat(zz, isPresent());
+    ClassSubject b = inspector.clazz(B.class);
+    assertThat(b, isPresent());
     ClassSubject cy = inspector.clazz(CY.class);
     assertThat(cy, isPresent());
     ClassSubject cyy = inspector.clazz(CYY.class);
@@ -61,6 +63,8 @@
     MethodTypeSignature methodTypeSignature;
     List<FieldTypeSignature> typeArguments;
     FieldTypeSignature typeArgument;
+    TypeSignature parameterSignature;
+    TypeSignature elementSignature;
 
     //
     // Testing ClassSignature
@@ -103,7 +107,7 @@
     // Testing MethodTypeSignature
     //
 
-    // A$Y$YY newYY()
+    // A$Y$YY newYY([B<T>)
     MethodSubject newYY = zz.uniqueMethodWithName("newYY");
     assertThat(newYY, isPresent());
     DexEncodedMethod method = newYY.getMethod();
@@ -112,14 +116,25 @@
     methodTypeSignature = Parser.toMethodTypeSignature(method, appView);
     assertNotNull(methodTypeSignature);
 
-    assertTrue(methodTypeSignature.typeSignatures.isEmpty());
-
     // return type: A$Y$YY
     TypeSignature returnType = methodTypeSignature.returnType();
     assertTrue(returnType.isFieldTypeSignature());
     assertTrue(returnType.asFieldTypeSignature().isClassTypeSignature());
     check_A_Y_YY(a, y, yy, returnType.asFieldTypeSignature().asClassTypeSignature());
 
+    // type of 1st argument: [B<T>
+    assertEquals(1, methodTypeSignature.typeSignatures.size());
+    parameterSignature = methodTypeSignature.getParameterTypeSignature(0);
+    assertNotNull(parameterSignature);
+    assertTrue(parameterSignature.isFieldTypeSignature());
+    assertTrue(parameterSignature.asFieldTypeSignature().isArrayTypeSignature());
+    elementSignature =
+        parameterSignature.asFieldTypeSignature().asArrayTypeSignature().elementSignature;
+    assertTrue(elementSignature.isFieldTypeSignature());
+    assertTrue(elementSignature.asFieldTypeSignature().isClassTypeSignature());
+    classTypeSignature = elementSignature.asFieldTypeSignature().asClassTypeSignature();
+    assertEquals(b.getDexClass().type, classTypeSignature.type);
+
     // Function<A$Y$ZZ<TT>, A$Y$YY> convertToYY(Supplier<A$Y$ZZ<TT>>
     MethodSubject convertToYY = zz.uniqueMethodWithName("convertToYY");
     assertThat(convertToYY, isPresent());
@@ -151,7 +166,7 @@
 
     // type of 1st argument: Supplier<A$Y$ZZ<TT>>
     assertEquals(1, methodTypeSignature.typeSignatures.size());
-    TypeSignature parameterSignature = methodTypeSignature.getParameterTypeSignature(0);
+    parameterSignature = methodTypeSignature.getParameterTypeSignature(0);
     assertNotNull(parameterSignature);
     assertTrue(parameterSignature.isFieldTypeSignature());
     assertTrue(parameterSignature.asFieldTypeSignature().isClassTypeSignature());
@@ -209,7 +224,7 @@
     class ZZ<TT> extends YY {
       public YY yy;
 
-      YY newYY() {
+      YY newYY(B... bs) {
         return new YY();
       }