Add GenericSignatureTypeRewriter and use it for rewriting

The CL adds GenericSignatureTypeRewriter and adds the new
GenericSignature for parsing and type-rewriting.

Bug: 170915828
Bug: 154793333
Change-Id: I7c4ba9e8bf5752abf2a19e261804b7895de11f34
diff --git a/src/main/java/com/android/tools/r8/graph/DexClass.java b/src/main/java/com/android/tools/r8/graph/DexClass.java
index 2b75c58..24a99a0 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClass.java
@@ -341,7 +341,7 @@
             appView.options().reporter);
       }
     }
-    return ClassSignature.NO_CLASS_SIGNATURE;
+    return ClassSignature.noSignature();
   }
 
   private boolean verifyCorrectnessOfFieldHolder(DexEncodedField field) {
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 9c34474..a92dc75 100644
--- a/src/main/java/com/android/tools/r8/graph/GenericSignature.java
+++ b/src/main/java/com/android/tools/r8/graph/GenericSignature.java
@@ -174,7 +174,7 @@
 
   public static class ClassSignature implements DexDefinitionSignature<DexClass> {
 
-    public static final ClassSignature NO_CLASS_SIGNATURE =
+    private static final ClassSignature NO_CLASS_SIGNATURE =
         new ClassSignature(EMPTY_TYPE_PARAMS, NO_FIELD_TYPE_SIGNATURE, EMPTY_SUPER_INTERFACES);
 
     final List<FormalTypeParameter> formalTypeParameters;
diff --git a/src/main/java/com/android/tools/r8/graph/GenericSignatureTypeRewriter.java b/src/main/java/com/android/tools/r8/graph/GenericSignatureTypeRewriter.java
new file mode 100644
index 0000000..c95ce02
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/GenericSignatureTypeRewriter.java
@@ -0,0 +1,326 @@
+// Copyright (c) 2020, 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.graph;
+
+import static com.android.tools.r8.graph.GenericSignature.EMPTY_SUPER_INTERFACES;
+import static com.android.tools.r8.graph.GenericSignature.EMPTY_TYPE_ARGUMENTS;
+import static com.android.tools.r8.graph.GenericSignature.EMPTY_TYPE_PARAMS;
+import static com.android.tools.r8.graph.GenericSignature.EMPTY_TYPE_SIGNATURES;
+import static com.android.tools.r8.graph.GenericSignature.FieldTypeSignature.noSignature;
+import static com.android.tools.r8.graph.GenericSignature.StarFieldTypeSignature.STAR_FIELD_TYPE_SIGNATURE;
+
+import com.android.tools.r8.graph.GenericSignature.ArrayTypeSignature;
+import com.android.tools.r8.graph.GenericSignature.ClassSignature;
+import com.android.tools.r8.graph.GenericSignature.ClassTypeSignature;
+import com.android.tools.r8.graph.GenericSignature.FieldTypeSignature;
+import com.android.tools.r8.graph.GenericSignature.FormalTypeParameter;
+import com.android.tools.r8.graph.GenericSignature.MethodTypeSignature;
+import com.android.tools.r8.graph.GenericSignature.ReturnType;
+import com.android.tools.r8.graph.GenericSignature.TypeSignature;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import java.util.ArrayList;
+import java.util.List;
+
+public class GenericSignatureTypeRewriter {
+
+  private final AppView<?> appView;
+  private final DexProgramClass context;
+
+  private final FieldTypeSignature objectTypeSignature;
+
+  public GenericSignatureTypeRewriter(AppView<?> appView, DexProgramClass context) {
+    this.appView = appView;
+    this.context = context;
+    objectTypeSignature =
+        new ClassTypeSignature(appView.dexItemFactory().objectType, EMPTY_TYPE_ARGUMENTS);
+  }
+
+  public ClassSignature rewrite(ClassSignature classSignature) {
+    if (classSignature.hasNoSignature()) {
+      return classSignature;
+    }
+    return new ClassSignatureRewriter().run(classSignature);
+  }
+
+  public FieldTypeSignature rewrite(FieldTypeSignature fieldTypeSignature) {
+    if (fieldTypeSignature.hasNoSignature()) {
+      return fieldTypeSignature;
+    }
+    return new TypeSignatureRewriter().run(fieldTypeSignature);
+  }
+
+  public MethodTypeSignature rewrite(MethodTypeSignature methodTypeSignature) {
+    if (methodTypeSignature.hasNoSignature()) {
+      return methodTypeSignature;
+    }
+    return new MethodTypeSignatureRewriter().run(methodTypeSignature);
+  }
+
+  private class ClassSignatureRewriter implements GenericSignatureVisitor {
+
+    private final List<FormalTypeParameter> rewrittenTypeParameters = new ArrayList<>();
+    private ClassTypeSignature rewrittenSuperClass;
+    private final List<ClassTypeSignature> rewrittenSuperInterfaces = new ArrayList<>();
+
+    @Override
+    public void visitClassSignature(ClassSignature classSignature) {
+      classSignature.visit(this);
+    }
+
+    @Override
+    public void visitFormalTypeParameters(List<FormalTypeParameter> formalTypeParameters) {
+      for (FormalTypeParameter formalTypeParameter : formalTypeParameters) {
+        rewrittenTypeParameters.add(new FormalTypeParameterRewriter().run(formalTypeParameter));
+      }
+    }
+
+    @Override
+    public void visitSuperClass(ClassTypeSignature classTypeSignature) {
+      rewrittenSuperClass = new ClassTypeSignatureRewriter(true).run(classTypeSignature);
+      if (rewrittenSuperClass == null) {
+        rewrittenSuperClass =
+            new ClassTypeSignature(appView.dexItemFactory().objectType, EMPTY_TYPE_ARGUMENTS);
+      }
+    }
+
+    @Override
+    public void visitSuperInterface(ClassTypeSignature classTypeSignature) {
+      ClassTypeSignature superInterface =
+          new ClassTypeSignatureRewriter(true).run(classTypeSignature);
+      if (superInterface != null) {
+        rewrittenSuperInterfaces.add(superInterface);
+      }
+    }
+
+    private ClassSignature run(ClassSignature classSignature) {
+      classSignature.visit(this);
+      if (rewrittenTypeParameters.isEmpty()
+          && rewrittenSuperInterfaces.isEmpty()
+          && rewrittenSuperClass.isNoSignature()
+          && rewrittenSuperClass.type == appView.dexItemFactory().objectType) {
+        return ClassSignature.noSignature();
+      }
+      return new ClassSignature(
+          rewrittenTypeParameters.isEmpty() ? EMPTY_TYPE_PARAMS : rewrittenTypeParameters,
+          rewrittenSuperClass,
+          rewrittenSuperInterfaces.isEmpty() ? EMPTY_SUPER_INTERFACES : rewrittenSuperInterfaces);
+    }
+  }
+
+  private class MethodTypeSignatureRewriter implements GenericSignatureVisitor {
+
+    private final List<FormalTypeParameter> rewrittenTypeParameters = new ArrayList<>();
+    private final List<TypeSignature> rewrittenTypeSignatures = new ArrayList<>();
+
+    ReturnType rewrittenReturnType = null;
+    private final List<TypeSignature> rewrittenThrowsSignatures = new ArrayList<>();
+
+    @Override
+    public void visitFormalTypeParameters(List<FormalTypeParameter> formalTypeParameters) {
+      for (FormalTypeParameter formalTypeParameter : formalTypeParameters) {
+        rewrittenTypeParameters.add(new FormalTypeParameterRewriter().run(formalTypeParameter));
+      }
+    }
+
+    @Override
+    public void visitMethodTypeSignatures(List<TypeSignature> typeSignatures) {
+      for (TypeSignature typeSignature : typeSignatures) {
+        TypeSignature rewrittenType = new TypeSignatureRewriter().run(typeSignature);
+        rewrittenTypeSignatures.add(rewrittenType == null ? objectTypeSignature : rewrittenType);
+      }
+    }
+
+    @Override
+    public void visitReturnType(ReturnType returnType) {
+      if (returnType.isVoidDescriptor()) {
+        rewrittenReturnType = ReturnType.VOID;
+      } else {
+        TypeSignature originalType = returnType.typeSignature();
+        TypeSignature rewrittenType = new TypeSignatureRewriter().run(originalType);
+        if (rewrittenType == null) {
+          rewrittenReturnType = ReturnType.VOID;
+        } else if (rewrittenType == originalType) {
+          rewrittenReturnType = returnType;
+        } else {
+          rewrittenReturnType = new ReturnType(rewrittenType);
+        }
+      }
+    }
+
+    @Override
+    public void visitThrowsSignatures(List<TypeSignature> typeSignatures) {
+      for (TypeSignature typeSignature : typeSignatures) {
+        TypeSignature rewrittenType = new TypeSignatureRewriter().run(typeSignature);
+        // If a throwing type is no longer found we remove it from the signature.
+        if (rewrittenType != null) {
+          rewrittenThrowsSignatures.add(rewrittenType);
+        }
+      }
+    }
+
+    private MethodTypeSignature run(MethodTypeSignature methodTypeSignature) {
+      methodTypeSignature.visit(this);
+      assert rewrittenReturnType != null;
+      if (rewrittenTypeParameters.isEmpty()
+          && rewrittenTypeSignatures.isEmpty()
+          && rewrittenReturnType.isVoidDescriptor()
+          && rewrittenThrowsSignatures.isEmpty()) {
+        return MethodTypeSignature.noSignature();
+      }
+      return new MethodTypeSignature(
+          rewrittenTypeParameters.isEmpty() ? EMPTY_TYPE_PARAMS : rewrittenTypeParameters,
+          rewrittenTypeSignatures.isEmpty() ? EMPTY_TYPE_SIGNATURES : rewrittenTypeSignatures,
+          rewrittenReturnType,
+          rewrittenThrowsSignatures.isEmpty() ? EMPTY_TYPE_SIGNATURES : rewrittenThrowsSignatures);
+    }
+  }
+
+  private class FormalTypeParameterRewriter implements GenericSignatureVisitor {
+
+    private FieldTypeSignature rewrittenClassBound = noSignature();
+    private final List<FieldTypeSignature> rewrittenInterfaceBounds = new ArrayList<>();
+
+    @Override
+    public void visitClassBound(FieldTypeSignature fieldSignature) {
+      rewrittenClassBound = new TypeSignatureRewriter().run(fieldSignature);
+    }
+
+    @Override
+    public void visitInterfaceBound(FieldTypeSignature fieldSignature) {
+      FieldTypeSignature interfaceBound = new TypeSignatureRewriter().run(fieldSignature);
+      if (interfaceBound != null) {
+        rewrittenInterfaceBounds.add(interfaceBound);
+      }
+    }
+
+    private FormalTypeParameter run(FormalTypeParameter formalTypeParameter) {
+      formalTypeParameter.visit(this);
+      // Guard against the case where we have <T::...> that is, no class or interfaces bounds.
+      if (rewrittenInterfaceBounds.isEmpty()
+          && (rewrittenClassBound == null || !rewrittenClassBound.hasSignature())) {
+        rewrittenClassBound = objectTypeSignature;
+      }
+      return new FormalTypeParameter(
+          formalTypeParameter.name,
+          rewrittenClassBound == null ? noSignature() : rewrittenClassBound,
+          rewrittenInterfaceBounds.isEmpty() ? EMPTY_TYPE_ARGUMENTS : rewrittenInterfaceBounds);
+    }
+  }
+
+  private class TypeSignatureRewriter implements GenericSignatureVisitor {
+
+    private TypeSignature run(TypeSignature typeSignature) {
+      if (typeSignature.isBaseTypeSignature()) {
+        return typeSignature;
+      }
+      assert typeSignature.isFieldTypeSignature();
+      return run(typeSignature.asFieldTypeSignature());
+    }
+
+    private FieldTypeSignature run(FieldTypeSignature fieldTypeSignature) {
+      if (fieldTypeSignature.isStar()) {
+        return fieldTypeSignature;
+      }
+      if (fieldTypeSignature.isTypeVariableSignature()) {
+        return fieldTypeSignature;
+      }
+      if (fieldTypeSignature.isArrayTypeSignature()) {
+        ArrayTypeSignature arrayTypeSignature = fieldTypeSignature.asArrayTypeSignature();
+        TypeSignature rewrittenElement = run(arrayTypeSignature.elementSignature);
+        if (rewrittenElement == null) {
+          return new ArrayTypeSignature(objectTypeSignature);
+        }
+        return rewrittenElement.toArrayTypeSignature();
+      }
+      assert fieldTypeSignature.isClassTypeSignature();
+      ClassTypeSignature classTypeSignature = fieldTypeSignature.asClassTypeSignature();
+      if (classTypeSignature.isNoSignature()) {
+        return classTypeSignature;
+      }
+      return new ClassTypeSignatureRewriter(false).run(classTypeSignature);
+    }
+  }
+
+  private class ClassTypeSignatureRewriter implements GenericSignatureVisitor {
+
+    private final AppInfoWithLiveness appInfoWithLiveness;
+    private final boolean isSuperClassOrInterface;
+
+    // These fields are updated when iterating the modeled structure.
+    private DexType currentType;
+
+    // The following references are used to have a head and tail pointer to the classTypeSignature
+    // link we are building. The topClassSignature will have a reference to the top-most package
+    // and class-name. The parentClassSignature is a pointer pointing to the tail always and will
+    // be linked and updated when calling ClassTypeSignature.link.
+    private ClassTypeSignature topClassSignature;
+    private ClassTypeSignature parentClassSignature;
+
+    private ClassTypeSignatureRewriter(boolean isSuperClassOrInterface) {
+      appInfoWithLiveness =
+          appView.appInfo().hasLiveness() ? appView.appInfo().withLiveness() : null;
+      this.isSuperClassOrInterface = isSuperClassOrInterface;
+    }
+
+    @Override
+    public void visitSimpleClass(ClassTypeSignature classTypeSignature) {
+      currentType = getTarget(classTypeSignature.type);
+      if (currentType == null) {
+        return;
+      }
+      classTypeSignature.visit(this);
+    }
+
+    @Override
+    public void visitTypeArguments(List<FieldTypeSignature> typeArguments) {
+      ClassTypeSignature newClassTypeSignature;
+      if (typeArguments.isEmpty()) {
+        newClassTypeSignature = new ClassTypeSignature(currentType, EMPTY_TYPE_ARGUMENTS);
+      } else {
+        List<FieldTypeSignature> rewrittenTypeArguments = new ArrayList<>(typeArguments.size());
+        for (FieldTypeSignature typeArgument : typeArguments) {
+          if (typeArgument.isStar()) {
+            rewrittenTypeArguments.add(typeArgument);
+            continue;
+          }
+          FieldTypeSignature rewritten = new TypeSignatureRewriter().run(typeArgument);
+          if (rewritten != null) {
+            rewrittenTypeArguments.add(rewritten.asArgument(typeArgument.getWildcardIndicator()));
+          } else {
+            rewrittenTypeArguments.add(STAR_FIELD_TYPE_SIGNATURE);
+          }
+        }
+        newClassTypeSignature = new ClassTypeSignature(currentType, rewrittenTypeArguments);
+      }
+      if (topClassSignature == null) {
+        topClassSignature = newClassTypeSignature;
+        parentClassSignature = newClassTypeSignature;
+      } else {
+        ClassTypeSignature.link(parentClassSignature, newClassTypeSignature);
+        parentClassSignature = newClassTypeSignature;
+      }
+    }
+
+    private ClassTypeSignature run(ClassTypeSignature classTypeSignature) {
+      currentType = getTarget(classTypeSignature.type);
+      if (currentType == null) {
+        return null;
+      }
+      classTypeSignature.visit(this);
+      return topClassSignature;
+    }
+
+    private DexType getTarget(DexType type) {
+      DexType rewrittenType = appView.graphLense().lookupType(type);
+      if (appInfoWithLiveness != null && appInfoWithLiveness.wasPruned(rewrittenType)) {
+        return null;
+      }
+      if (isSuperClassOrInterface && context.type == rewrittenType) {
+        return null;
+      }
+      return rewrittenType;
+    }
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureRewriter.java b/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureRewriter.java
index 1f66108..fd5dc11 100644
--- a/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureRewriter.java
+++ b/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureRewriter.java
@@ -4,28 +4,25 @@
 
 package com.android.tools.r8.naming.signature;
 
-import static com.android.tools.r8.utils.DescriptorUtils.getClassBinaryNameFromDescriptor;
-import static com.android.tools.r8.utils.DescriptorUtils.getDescriptorFromClassBinaryName;
-
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexAnnotation;
 import com.android.tools.r8.graph.DexAnnotationSet;
 import com.android.tools.r8.graph.DexProgramClass;
-import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GenericSignature;
+import com.android.tools.r8.graph.GenericSignature.ClassSignature;
+import com.android.tools.r8.graph.GenericSignature.FieldTypeSignature;
+import com.android.tools.r8.graph.GenericSignature.MethodTypeSignature;
+import com.android.tools.r8.graph.GenericSignatureTypeRewriter;
 import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.utils.DescriptorUtils;
 import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.PredicateUtils;
 import com.android.tools.r8.utils.Reporter;
-import com.android.tools.r8.utils.StringDiagnostic;
 import com.android.tools.r8.utils.ThreadUtils;
-import java.lang.reflect.GenericSignatureFormatError;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
-import java.util.function.BiConsumer;
-import java.util.function.Consumer;
+import java.util.function.Function;
 import java.util.function.Predicate;
-import java.util.function.Supplier;
 
 // TODO(b/129925954): Reimplement this by using the internal encoding and transformation logic.
 public class GenericSignatureRewriter {
@@ -34,12 +31,14 @@
   private final NamingLens namingLens;
   private final InternalOptions options;
   private final Reporter reporter;
+  private final Predicate<DexType> isTypeMissing;
 
   public GenericSignatureRewriter(AppView<?> appView, NamingLens namingLens) {
     this.appView = appView;
     this.namingLens = namingLens;
     this.options = appView.options();
     this.reporter = options.reporter;
+    isTypeMissing = PredicateUtils.isNull(appView.appInfo()::definitionForWithoutExistenceAssert);
   }
 
   public void run(Iterable<? extends DexProgramClass> classes, ExecutorService executorService)
@@ -56,51 +55,77 @@
     ThreadUtils.processItems(
         classes,
         clazz -> {
-          GenericSignatureCollector genericSignatureCollector =
-              new GenericSignatureCollector(clazz);
-          GenericSignatureParser<DexType> genericSignatureParser =
-              new GenericSignatureParser<>(genericSignatureCollector);
+          GenericSignatureTypeRewriter typeRewriter =
+              new GenericSignatureTypeRewriter(appView, clazz);
           clazz.setAnnotations(
               rewriteGenericSignatures(
                   clazz.annotations(),
-                  genericSignatureParser::parseClassSignature,
-                  genericSignatureCollector::getRenamedSignature,
-                  (signature, e) ->
-                      options.warningInvalidSignature(clazz, clazz.getOrigin(), signature, e)));
+                  signature -> {
+                    ClassSignature classSignature =
+                        GenericSignature.parseClassSignature(
+                            clazz.toSourceString(),
+                            signature,
+                            clazz.origin,
+                            appView.dexItemFactory(),
+                            options.reporter);
+                    if (classSignature.hasNoSignature()) {
+                      return null;
+                    }
+                    return typeRewriter
+                        .rewrite(classSignature)
+                        .toRenamedString(namingLens, isTypeMissing);
+                  }));
           clazz.forEachField(
               field ->
                   field.setAnnotations(
                       rewriteGenericSignatures(
                           field.annotations(),
-                          genericSignatureParser::parseFieldSignature,
-                          genericSignatureCollector::getRenamedSignature,
-                          (signature, e) ->
-                              options.warningInvalidSignature(
-                                  field, clazz.getOrigin(), signature, e))));
+                          signature -> {
+                            FieldTypeSignature fieldSignature =
+                                GenericSignature.parseFieldTypeSignature(
+                                    field.toSourceString(),
+                                    signature,
+                                    clazz.origin,
+                                    appView.dexItemFactory(),
+                                    options.reporter);
+                            if (fieldSignature.hasNoSignature()) {
+                              return null;
+                            }
+                            return typeRewriter
+                                .rewrite(fieldSignature)
+                                .toRenamedString(namingLens, isTypeMissing);
+                          })));
           clazz.forEachMethod(
               method ->
                   method.setAnnotations(
                       rewriteGenericSignatures(
                           method.annotations(),
-                          genericSignatureParser::parseMethodSignature,
-                          genericSignatureCollector::getRenamedSignature,
-                          (signature, e) ->
-                              options.warningInvalidSignature(
-                                  method, clazz.getOrigin(), signature, e))));
+                          signature -> {
+                            MethodTypeSignature methodSignature =
+                                GenericSignature.parseMethodSignature(
+                                    method.toSourceString(),
+                                    signature,
+                                    clazz.origin,
+                                    appView.dexItemFactory(),
+                                    options.reporter);
+                            if (methodSignature.hasNoSignature()) {
+                              return null;
+                            }
+                            return typeRewriter
+                                .rewrite(methodSignature)
+                                .toRenamedString(namingLens, isTypeMissing);
+                          })));
         },
         executorService);
   }
 
   private DexAnnotationSet rewriteGenericSignatures(
-      DexAnnotationSet annotations,
-      Consumer<String> parser,
-      Supplier<String> collector,
-      BiConsumer<String, GenericSignatureFormatError> parseError) {
+      DexAnnotationSet annotations, Function<String, String> rewrite) {
     // There can be no more than one signature annotation in an annotation set.
     final int VALID = -1;
-    int invalid = VALID;
+    int invalidOrPrunedIndex = VALID;
     DexAnnotation[] rewrittenAnnotations = null;
-    for (int i = 0; i < annotations.annotations.length && invalid == VALID; i++) {
+    for (int i = 0; i < annotations.annotations.length && invalidOrPrunedIndex == VALID; i++) {
       DexAnnotation annotation = annotations.annotations[i];
       if (DexAnnotation.isSignatureAnnotation(annotation, appView.dexItemFactory())) {
         if (rewrittenAnnotations == null) {
@@ -108,16 +133,12 @@
           System.arraycopy(annotations.annotations, 0, rewrittenAnnotations, 0, i);
         }
         String signature = DexAnnotation.getSignature(annotation);
-        try {
-          parser.accept(signature);
-          String renamedSignature = collector.get();
-          assert verifyConsistentRenaming(parser, collector, renamedSignature);
-          DexAnnotation signatureAnnotation =
-              DexAnnotation.createSignatureAnnotation(renamedSignature, appView.dexItemFactory());
-          rewrittenAnnotations[i] = signatureAnnotation;
-        } catch (GenericSignatureFormatError e) {
-          parseError.accept(signature, e);
-          invalid = i;
+        String rewrittenSignature = rewrite.apply(signature);
+        if (rewrittenSignature != null) {
+          rewrittenAnnotations[i] =
+              DexAnnotation.createSignatureAnnotation(rewrittenSignature, appView.dexItemFactory());
+        } else {
+          invalidOrPrunedIndex = i;
         }
       } else if (rewrittenAnnotations != null) {
         rewrittenAnnotations[i] = annotation;
@@ -125,7 +146,7 @@
     }
 
     // Return the rewritten signatures if it was valid and could be rewritten.
-    if (invalid == VALID) {
+    if (invalidOrPrunedIndex == VALID) {
       return rewrittenAnnotations != null
           ? new DexAnnotationSet(rewrittenAnnotations)
           : annotations;
@@ -135,156 +156,11 @@
         new DexAnnotation[annotations.annotations.length - 1];
     int dest = 0;
     for (int i = 0; i < annotations.annotations.length; i++) {
-      if (i != invalid) {
+      if (i != invalidOrPrunedIndex) {
         prunedAnnotations[dest++] = annotations.annotations[i];
       }
     }
     assert dest == prunedAnnotations.length;
     return new DexAnnotationSet(prunedAnnotations);
   }
-
-  /**
-   * Calling this method will clobber the parsed signature in the collector - ideally with the same
-   * string. Only use this after the original result has been collected.
-   */
-  private boolean verifyConsistentRenaming(
-      Consumer<String> parser, Supplier<String> collector, String renamedSignature) {
-    if (!options.testing.assertConsistentRenamingOfSignature) {
-      return true;
-    }
-    parser.accept(renamedSignature);
-    String reRenamedSignature = collector.get();
-    assert renamedSignature.equals(reRenamedSignature);
-    return true;
-  }
-
-  private class GenericSignatureCollector implements GenericSignatureAction<DexType> {
-    private StringBuilder renamedSignature;
-    private final DexProgramClass currentClassContext;
-    private DexType lastWrittenType = null;
-
-    GenericSignatureCollector(DexProgramClass clazz) {
-      this.currentClassContext = clazz;
-    }
-
-    String getRenamedSignature() {
-      return renamedSignature.toString();
-    }
-
-    @Override
-    public void parsedSymbol(char symbol) {
-      if (symbol == ';' && lastWrittenType == null) {
-        // The type was never written (maybe because it was merged with it's subtype).
-        return;
-      }
-      // If the super-class or interface has been merged, we will stop writing out type
-      // arguments, resulting in a signature on the form '<>' if we do not remove it.
-      if (symbol == '>' && removeWrittenCharacter(c -> c == '<')) {
-        return;
-      }
-      renamedSignature.append(symbol);
-    }
-
-    @Override
-    public void parsedIdentifier(String identifier) {
-      renamedSignature.append(identifier);
-    }
-
-    @Override
-    public DexType parsedTypeName(String name, ParserPosition parserPosition) {
-      if (parserPosition == ParserPosition.ENCLOSING_INNER_OR_TYPE_ANNOTATION
-          && lastWrittenType == null) {
-        // We are writing type-arguments for a merged class.
-        removeWrittenClassCharacter();
-        return null;
-      }
-      String originalDescriptor = getDescriptorFromClassBinaryName(name);
-      DexType type =
-          appView.graphLense().lookupType(appView.dexItemFactory().createType(originalDescriptor));
-      if (appView.appInfo().hasLiveness() && appView.withLiveness().appInfo().wasPruned(type)) {
-        type = appView.dexItemFactory().objectType;
-      }
-      DexString renamedDescriptor = namingLens.lookupDescriptor(type);
-      if (parserPosition == ParserPosition.CLASS_SUPER_OR_INTERFACE_ANNOTATION
-          && currentClassContext != null) {
-        // We may have merged the type down to the current class type.
-        DexString classDescriptor = currentClassContext.type.descriptor;
-        if (!originalDescriptor.equals(classDescriptor.toString())
-            && renamedDescriptor.equals(classDescriptor)) {
-          lastWrittenType = null;
-          removeWrittenClassCharacter();
-          return type;
-        }
-      }
-      renamedSignature.append(getClassBinaryNameFromDescriptor(renamedDescriptor.toString()));
-      lastWrittenType = type;
-      return type;
-    }
-
-    private boolean removeWrittenCharacter(Predicate<Character> removeIf) {
-      int index = renamedSignature.length() - 1;
-      if (index < 0 || !removeIf.test(renamedSignature.charAt(index))) {
-        return false;
-      }
-      renamedSignature.deleteCharAt(index);
-      return true;
-    }
-
-    private void removeWrittenClassCharacter() {
-      removeWrittenCharacter(c -> c == 'L');
-    }
-
-    @Override
-    public DexType parsedInnerTypeName(DexType enclosingType, String name) {
-      if (enclosingType == null) {
-        // We are writing inner type names
-        removeWrittenClassCharacter();
-        return null;
-      }
-      assert enclosingType.isClassType();
-      String enclosingDescriptor = enclosingType.toDescriptorString();
-      DexType type =
-          appView
-              .dexItemFactory()
-              .createType(
-                  getDescriptorFromClassBinaryName(
-                      getClassBinaryNameFromDescriptor(enclosingDescriptor)
-                          + DescriptorUtils.INNER_CLASS_SEPARATOR
-                          + name));
-      type = appView.graphLense().lookupType(type);
-      String renamedDescriptor = namingLens.lookupDescriptor(type).toString();
-      if (!renamedDescriptor.equals(type.toDescriptorString())) {
-        // TODO(b/147504070): If this is a merged class equal to the class context, do not add.
-        // Pick the renamed inner class from the fully renamed binary name.
-        String fullRenamedBinaryName = getClassBinaryNameFromDescriptor(renamedDescriptor);
-        String enclosingRenamedBinaryName =
-            getClassBinaryNameFromDescriptor(namingLens.lookupDescriptor(enclosingType).toString());
-        int innerClassPos = enclosingRenamedBinaryName.length() + 1;
-        if (innerClassPos < fullRenamedBinaryName.length()) {
-          renamedSignature.append(fullRenamedBinaryName.substring(innerClassPos));
-        } else if (appView.options().keepInnerClassStructure()) {
-          reporter.warning(
-              new StringDiagnostic(
-                  "Should have retained InnerClasses attribute of " + type + ".",
-                  appView.appInfo().originFor(type)));
-          renamedSignature.append(name);
-        }
-      } else {
-        // Did not find the class - keep the inner class name as is.
-        // TODO(b/110085899): Warn about missing classes in signatures?
-        renamedSignature.append(name);
-      }
-      return type;
-    }
-
-    @Override
-    public void start() {
-      renamedSignature = new StringBuilder();
-    }
-
-    @Override
-    public void stop() {
-      // nothing to do
-    }
-  }
 }
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index af62b23..14788ba 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -28,7 +28,6 @@
 import com.android.tools.r8.features.FeatureSplitConfiguration;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexClass;
-import com.android.tools.r8.graph.DexDefinition;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexItem;
 import com.android.tools.r8.graph.DexItemFactory;
@@ -57,7 +56,6 @@
 import com.google.common.collect.Sets;
 import java.io.IOException;
 import java.io.PrintStream;
-import java.lang.reflect.GenericSignatureFormatError;
 import java.nio.file.Files;
 import java.nio.file.InvalidPathException;
 import java.nio.file.Path;
@@ -911,31 +909,6 @@
     }
   }
 
-  public void warningInvalidSignature(
-      DexDefinition item, Origin origin, String signature, GenericSignatureFormatError e) {
-    StringBuilder message = new StringBuilder("Invalid signature '");
-    message.append(signature);
-    message.append("' for ");
-    if (item.isDexClass()) {
-      message.append("class ");
-      message.append((item.asDexClass()).getType().toSourceString());
-    } else if (item.isDexEncodedField()) {
-      message.append("field ");
-      message.append(item.toSourceString());
-    } else {
-      assert item.isDexEncodedMethod();
-      message.append("method ");
-      message.append(item.toSourceString());
-    }
-    message.append(".");
-    message.append(System.lineSeparator());
-    message.append("Signature is ignored and will not be present in the output.");
-    message.append(System.lineSeparator());
-    message.append("Parser error: ");
-    message.append(e.getMessage());
-    reporter.warning(new StringDiagnostic(message.toString(), origin));
-  }
-
   public boolean printWarnings() {
     boolean printed = false;
     boolean printOutdatedToolchain = false;
diff --git a/src/main/java/com/android/tools/r8/utils/PredicateUtils.java b/src/main/java/com/android/tools/r8/utils/PredicateUtils.java
index 880da5e..f219259 100644
--- a/src/main/java/com/android/tools/r8/utils/PredicateUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/PredicateUtils.java
@@ -4,6 +4,7 @@
 
 package com.android.tools.r8.utils;
 
+import java.util.function.Function;
 import java.util.function.Predicate;
 
 public class PredicateUtils {
@@ -20,4 +21,8 @@
   public static <T> Predicate<T> not(Predicate<T> predicate) {
     return t -> !predicate.test(t);
   }
+
+  public static <T, R> Predicate<T> isNull(Function<T, R> func) {
+    return t -> func.apply(t) == null;
+  }
 }
diff --git a/src/test/java/com/android/tools/r8/graph/genericsignature/ClassSignatureTest.java b/src/test/java/com/android/tools/r8/graph/genericsignature/ClassSignatureTest.java
index cd057d2..eb76047 100644
--- a/src/test/java/com/android/tools/r8/graph/genericsignature/ClassSignatureTest.java
+++ b/src/test/java/com/android/tools/r8/graph/genericsignature/ClassSignatureTest.java
@@ -5,7 +5,6 @@
 package com.android.tools.r8.graph.genericsignature;
 
 import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage;
-import static com.android.tools.r8.graph.GenericSignature.ClassSignature.NO_CLASS_SIGNATURE;
 import static org.hamcrest.CoreMatchers.containsString;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertThrows;
@@ -171,7 +170,7 @@
             Origin.unknown(),
             new DexItemFactory(),
             new Reporter(testDiagnosticMessages));
-    assertEquals(NO_CLASS_SIGNATURE, parsed);
+    assertEquals(ClassSignature.noSignature(), parsed);
     return testDiagnosticMessages;
   }
 }
diff --git a/src/test/java/com/android/tools/r8/naming/b126592786/B126592786.java b/src/test/java/com/android/tools/r8/naming/b126592786/B126592786.java
index 2f909be..20e13bf 100644
--- a/src/test/java/com/android/tools/r8/naming/b126592786/B126592786.java
+++ b/src/test/java/com/android/tools/r8/naming/b126592786/B126592786.java
@@ -55,19 +55,20 @@
             "}",
             "-keepattributes InnerClasses,EnclosingMethod,Signature ")
         .compile()
-        .inspect(inspector -> {
-            String genericTypeDescriptor = "Ljava/lang/Object;";
-            if (genericTypeLive) {
-              ClassSubject genericType = inspector.clazz(GenericType.class);
-              assertThat(genericType, isRenamed(minify));
-              genericTypeDescriptor = genericType.getFinalDescriptor();
-            }
-            String expectedSignature = "Ljava/util/List<" + genericTypeDescriptor + ">;";
-            FieldSubject list = inspector.clazz(A.class).uniqueFieldWithName("list");
-            assertThat(list, isPresent());
-            assertThat(list.getSignatureAnnotation(), isPresent());
-            assertEquals(expectedSignature, list.getSignatureAnnotationValue());
-        })
+        .inspect(
+            inspector -> {
+              String genericTypeDescriptor = "*";
+              if (genericTypeLive) {
+                ClassSubject genericType = inspector.clazz(GenericType.class);
+                assertThat(genericType, isRenamed(minify));
+                genericTypeDescriptor = genericType.getFinalDescriptor();
+              }
+              String expectedSignature = "Ljava/util/List<" + genericTypeDescriptor + ">;";
+              FieldSubject list = inspector.clazz(A.class).uniqueFieldWithName("list");
+              assertThat(list, isPresent());
+              assertThat(list.getSignatureAnnotation(), isPresent());
+              assertEquals(expectedSignature, list.getSignatureAnnotationValue());
+            })
         .run(mainClass)
         .assertSuccess();
   }
diff --git a/src/test/java/com/android/tools/r8/naming/signature/GenericSignatureRenamingTest.java b/src/test/java/com/android/tools/r8/naming/signature/GenericSignatureRenamingTest.java
index adf7ba7..e945182 100644
--- a/src/test/java/com/android/tools/r8/naming/signature/GenericSignatureRenamingTest.java
+++ b/src/test/java/com/android/tools/r8/naming/signature/GenericSignatureRenamingTest.java
@@ -4,7 +4,6 @@
 
 package com.android.tools.r8.naming.signature;
 
-import static org.junit.Assert.assertThrows;
 import static org.junit.Assume.assumeTrue;
 
 import com.android.tools.r8.CompilationMode;
@@ -71,18 +70,13 @@
   }
 
   @Test
-  public void testR8WithAssertEnabled() {
-    // TODO(b/154793333): Enable assertions always when resolved.
-    assertThrows(
-        AssertionError.class,
-        () -> {
-          test(
-              testForR8(parameters.getBackend())
-                  .addKeepRules("-dontobfuscate")
-                  .addOptionsModification(
-                      internalOptions ->
-                          internalOptions.testing.assertConsistentRenamingOfSignature = true));
-        });
+  public void testR8WithAssertEnabled() throws Exception {
+    test(
+        testForR8(parameters.getBackend())
+            .addKeepRules("-dontobfuscate")
+            .addOptionsModification(
+                internalOptions ->
+                    internalOptions.testing.assertConsistentRenamingOfSignature = true));
   }
 
   private void test(R8TestBuilder<?> builder) throws Exception {