Introduce ReturnType to separate V from BaseTypeSignature.

Bug: 129925954
Change-Id: I4ec940b7292cc05a082f582844fa6becb9e94615
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 743f406..049cb7a 100644
--- a/src/main/java/com/android/tools/r8/graph/GenericSignature.java
+++ b/src/main/java/com/android/tools/r8/graph/GenericSignature.java
@@ -133,6 +133,8 @@
     ClassSignature(
         ClassTypeSignature superClassSignature,
         List<ClassTypeSignature> superInterfaceSignatures) {
+      assert superClassSignature != null;
+      assert superInterfaceSignatures != null;
       this.superClassSignature = superClassSignature;
       this.superInterfaceSignatures = superInterfaceSignatures;
     }
@@ -223,7 +225,7 @@
 
   public static class ClassTypeSignature extends FieldTypeSignature {
     static final ClassTypeSignature UNKNOWN_CLASS_TYPE_SIGNATURE =
-        new ClassTypeSignature(null, ImmutableList.of());
+        new ClassTypeSignature(DexItemFactory.nullValueType, ImmutableList.of());
 
     final DexType type;
     // E.g., for Map<K, V>, a signature will indicate what types are for K and V.
@@ -237,6 +239,8 @@
     ClassTypeSignature innerTypeSignature;
 
     ClassTypeSignature(DexType type, List<FieldTypeSignature> typeArguments) {
+      assert type != null;
+      assert typeArguments != null;
       this.type = type;
       this.typeArguments = typeArguments;
     }
@@ -295,6 +299,7 @@
     final TypeSignature elementSignature;
 
     ArrayTypeSignature(TypeSignature elementSignature) {
+      assert elementSignature != null;
       this.elementSignature = elementSignature;
     }
 
@@ -327,6 +332,7 @@
     final String typeVariable;
 
     TypeVariableSignature(String typeVariable) {
+      assert typeVariable != null;
       this.typeVariable = typeVariable;
     }
 
@@ -351,8 +357,8 @@
     final DexType type;
 
     BaseTypeSignature(DexType type) {
-      assert type.isPrimitiveType() || type.isVoidType()
-          : type.toDescriptorString();
+      assert type != null;
+      assert type.isPrimitiveType() : type.toDescriptorString();
       this.type = type;
     }
 
@@ -373,22 +379,41 @@
     }
   }
 
+  public static class ReturnType {
+    static final ReturnType VOID = new ReturnType(null);
+
+    // `null` indicates that it's `void`.
+    final TypeSignature typeSignature;
+
+    ReturnType(TypeSignature typeSignature) {
+      this.typeSignature = typeSignature;
+    }
+
+    public boolean isVoidDescriptor() {
+      return typeSignature == null;
+    }
+
+    public TypeSignature typeSignature() {
+      return typeSignature;
+    }
+  }
+
   public static class MethodTypeSignature implements DexDefinitionSignature<DexEncodedMethod> {
     static final MethodTypeSignature UNKNOWN_METHOD_TYPE_SIGNATURE =
-        new MethodTypeSignature(
-            ImmutableList.of(),
-            ClassTypeSignature.UNKNOWN_CLASS_TYPE_SIGNATURE,
-            ImmutableList.of());
+        new MethodTypeSignature(ImmutableList.of(), ReturnType.VOID, ImmutableList.of());
 
     // TODO(b/129925954): encoding formal type parameters
     final List<TypeSignature> typeSignatures;
-    final TypeSignature returnType;
+    final ReturnType returnType;
     final List<TypeSignature> throwsSignatures;
 
     MethodTypeSignature(
         List<TypeSignature> typeSignatures,
-        TypeSignature returnType,
+        ReturnType returnType,
         List<TypeSignature> throwsSignatures) {
+      assert typeSignatures != null;
+      assert returnType != null;
+      assert throwsSignatures != null;
       this.typeSignatures = typeSignatures;
       this.returnType = returnType;
       this.throwsSignatures = throwsSignatures;
@@ -401,7 +426,7 @@
       return typeSignatures.get(i);
     }
 
-    public TypeSignature returnType() {
+    public ReturnType returnType() {
       return returnType;
     }
 
@@ -848,7 +873,7 @@
 
       expect(')');
 
-      TypeSignature returnType = updateReturnType();
+      ReturnType returnType = updateReturnType();
 
       ImmutableList.Builder<TypeSignature> throwsSignatureBuilder = ImmutableList.builder();
       if (symbol == '^') {
@@ -868,13 +893,13 @@
           parameterSignatureBuilder.build(), returnType, throwsSignatureBuilder.build());
     }
 
-    private TypeSignature updateReturnType() {
+    private ReturnType updateReturnType() {
       // ReturnType ::= TypeSignature | "V".
       if (symbol != 'V') {
-        return updateTypeSignature(ParserPosition.MEMBER_ANNOTATION);
+        return new ReturnType(updateTypeSignature(ParserPosition.MEMBER_ANNOTATION));
       } else {
         scanSymbol();
-        return new BaseTypeSignature(appView.dexItemFactory().voidType);
+        return ReturnType.VOID;
       }
     }
 
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataSynthesizer.java b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataSynthesizer.java
index 88a1d8c..ecef010 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataSynthesizer.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataSynthesizer.java
@@ -250,23 +250,23 @@
 
     DexProto proto = method.method.proto;
     DexType returnType = proto.returnType;
-    TypeSignature returnSignature = signature.returnType();
-    KmType kmReturnType = toRenamedKmType(returnType, returnSignature, appView, lens);
+    TypeSignature returnSignature = signature.returnType().typeSignature();
+    KmType kmReturnType = setRenamedKmType(
+        returnType, returnSignature, appView, lens, kmFunction::setReturnType);
     if (kmReturnType == null) {
       return null;
     }
-    kmFunction.setReturnType(kmReturnType);
 
     if (method.isKotlinExtensionFunction()) {
       assert proto.parameters.values.length > 0
           : method.method.toSourceString();
       DexType receiverType = proto.parameters.values[0];
       TypeSignature receiverSignature = signature.getParameterTypeSignature(0);
-      KmType kmReceiverType = toRenamedKmType(receiverType, receiverSignature, appView, lens);
+      KmType kmReceiverType = setRenamedKmType(
+          receiverType, receiverSignature, appView, lens, kmFunction::setReceiverParameterType);
       if (kmReceiverType == null) {
         return null;
       }
-      kmFunction.setReceiverParameterType(kmReceiverType);
     }
 
     List<KmValueParameter> parameters = kmFunction.getValueParameters();
@@ -514,7 +514,7 @@
         }
 
         DexType returnType = getter.method.proto.returnType;
-        TypeSignature returnSignature = signature.returnType();
+        TypeSignature returnSignature = signature.returnType().typeSignature();
         if (kmPropertyType == null) {
           // The property type is not set yet.
           kmPropertyType = setRenamedKmType(
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 3bf1f61..775f030 100644
--- a/src/test/java/com/android/tools/r8/graph/GenericSignatureTest.java
+++ b/src/test/java/com/android/tools/r8/graph/GenericSignatureTest.java
@@ -6,6 +6,7 @@
 import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
@@ -15,6 +16,7 @@
 import com.android.tools.r8.graph.GenericSignature.FieldTypeSignature;
 import com.android.tools.r8.graph.GenericSignature.MethodTypeSignature;
 import com.android.tools.r8.graph.GenericSignature.Parser;
+import com.android.tools.r8.graph.GenericSignature.ReturnType;
 import com.android.tools.r8.graph.GenericSignature.TypeSignature;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.android.tools.r8.utils.AndroidApp;
@@ -57,6 +59,8 @@
     ClassSubject cyy = inspector.clazz(CYY.class);
     assertThat(cyy, isPresent());
 
+    DexEncodedMethod method;
+
     ClassSignature classSignature;
     ClassTypeSignature classTypeSignature;
     FieldTypeSignature fieldTypeSignature;
@@ -65,6 +69,8 @@
     FieldTypeSignature typeArgument;
     TypeSignature parameterSignature;
     TypeSignature elementSignature;
+    ReturnType returnType;
+    TypeSignature returnTypeSignature;
 
     //
     // Testing ClassSignature
@@ -110,17 +116,19 @@
     // A$Y$YY newYY([B<T>)
     MethodSubject newYY = zz.uniqueMethodWithName("newYY");
     assertThat(newYY, isPresent());
-    DexEncodedMethod method = newYY.getMethod();
+    method = newYY.getMethod();
     assertNotNull(method);
 
     methodTypeSignature = Parser.toMethodTypeSignature(method, appView);
     assertNotNull(methodTypeSignature);
 
     // 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());
+    returnType = methodTypeSignature.returnType();
+    assertFalse(returnType.isVoidDescriptor());
+    returnTypeSignature = returnType.typeSignature();
+    assertTrue(returnTypeSignature.isFieldTypeSignature());
+    assertTrue(returnTypeSignature.asFieldTypeSignature().isClassTypeSignature());
+    check_A_Y_YY(a, y, yy, returnTypeSignature.asFieldTypeSignature().asClassTypeSignature());
 
     // type of 1st argument: [B<T>
     assertEquals(1, methodTypeSignature.typeSignatures.size());
@@ -146,9 +154,11 @@
 
     // return type: Function<A$Y$ZZ<TT>, A$Y$YY>
     returnType = methodTypeSignature.returnType();
-    assertTrue(returnType.isFieldTypeSignature());
-    assertTrue(returnType.asFieldTypeSignature().isClassTypeSignature());
-    classTypeSignature = returnType.asFieldTypeSignature().asClassTypeSignature();
+    assertFalse(returnType.isVoidDescriptor());
+    returnTypeSignature = returnType.typeSignature();
+    assertTrue(returnTypeSignature.isFieldTypeSignature());
+    assertTrue(returnTypeSignature.asFieldTypeSignature().isClassTypeSignature());
+    classTypeSignature = returnTypeSignature.asFieldTypeSignature().asClassTypeSignature();
     DexType functionType =
         factory.createType(DescriptorUtils.javaTypeToDescriptor(Function.class.getTypeName()));
     assertEquals(functionType, classTypeSignature.type);
@@ -167,18 +177,24 @@
     // type of 1st argument: Supplier<A$Y$ZZ<TT>>
     assertEquals(1, methodTypeSignature.typeSignatures.size());
     parameterSignature = methodTypeSignature.getParameterTypeSignature(0);
-    assertNotNull(parameterSignature);
-    assertTrue(parameterSignature.isFieldTypeSignature());
-    assertTrue(parameterSignature.asFieldTypeSignature().isClassTypeSignature());
-    classTypeSignature = parameterSignature.asFieldTypeSignature().asClassTypeSignature();
-    DexType supplierType =
-        factory.createType(DescriptorUtils.javaTypeToDescriptor(Supplier.class.getTypeName()));
-    assertEquals(supplierType, classTypeSignature.type);
-    typeArguments = classTypeSignature.typeArguments;
-    assertEquals(1, typeArguments.size());
-    typeArgument = typeArguments.get(0);
-    assertTrue(typeArgument.isClassTypeSignature());
-    check_A_Y_ZZ(a, y, zz, typeArgument.asClassTypeSignature());
+    check_supplier(factory, a, y, zz, parameterSignature);
+
+    // void boo(Supplier<A$Y$ZZ<TT>>)
+    MethodSubject boo = zz.uniqueMethodWithName("boo");
+    assertThat(boo, isPresent());
+    method = boo.getMethod();
+    assertNotNull(method);
+
+    // return type: void
+    methodTypeSignature = Parser.toMethodTypeSignature(method, appView);
+    assertNotNull(methodTypeSignature);
+    returnType = methodTypeSignature.returnType();
+    assertTrue(returnType.isVoidDescriptor());
+
+    // type of 1st argument: Supplier<A$Y$ZZ<TT>>
+    assertEquals(1, methodTypeSignature.typeSignatures.size());
+    parameterSignature = methodTypeSignature.getParameterTypeSignature(0);
+    check_supplier(factory, a, y, zz, parameterSignature);
   }
 
   private void check_A_Y(ClassSubject a, ClassSubject y, ClassTypeSignature signature) {
@@ -208,6 +224,26 @@
     assertTrue(typeArgument.isTypeVariableSignature());
     assertEquals("TT", typeArgument.asTypeVariableSignature().typeVariable);
   }
+
+  private void check_supplier(
+      DexItemFactory factory,
+      ClassSubject a,
+      ClassSubject y,
+      ClassSubject zz,
+      TypeSignature signature) {
+    assertNotNull(signature);
+    assertTrue(signature.isFieldTypeSignature());
+    assertTrue(signature.asFieldTypeSignature().isClassTypeSignature());
+    ClassTypeSignature classTypeSignature = signature.asFieldTypeSignature().asClassTypeSignature();
+    DexType supplierType =
+        factory.createType(DescriptorUtils.javaTypeToDescriptor(Supplier.class.getTypeName()));
+    assertEquals(supplierType, classTypeSignature.type);
+    List<FieldTypeSignature> typeArguments = classTypeSignature.typeArguments;
+    assertEquals(1, typeArguments.size());
+    FieldTypeSignature typeArgument = typeArguments.get(0);
+    assertTrue(typeArgument.isClassTypeSignature());
+    check_A_Y_ZZ(a, y, zz, typeArgument.asClassTypeSignature());
+  }
 }
 
 //
@@ -237,6 +273,10 @@
           }
         };
       }
+
+      void boo(Supplier<ZZ<TT>> zzSupplier) {
+        convertToYY(zzSupplier).apply(this);
+      }
     }
 
     ZZ<T> zz() {