Merge "Add settings.gradle if not present in app folder"
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 4d79275..065ad10 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -628,9 +628,7 @@
       NamingLens namingLens;
       if (options.enableMinification) {
         timing.begin("Minification");
-        namingLens =
-            new Minifier(appView.appInfo().withLiveness(), rootSet, desugaredCallSites, options)
-                .run(timing);
+        namingLens = new Minifier(appView.withLiveness(), rootSet, desugaredCallSites).run(timing);
         timing.end();
       } else {
         namingLens = NamingLens.getIdentityLens();
diff --git a/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java b/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
index bc81538..b59b79b 100644
--- a/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
@@ -9,6 +9,7 @@
 import static com.android.tools.r8.utils.DescriptorUtils.getDescriptorFromClassBinaryName;
 import static com.android.tools.r8.utils.DescriptorUtils.getPackageBinaryNameFromJavaType;
 
+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.DexClass;
@@ -50,6 +51,7 @@
 
 class ClassNameMinifier {
 
+  private final AppView<AppInfoWithLiveness> appView;
   private final AppInfoWithLiveness appInfo;
   private final Reporter reporter;
   private final PackageObfuscationMode packageObfuscationMode;
@@ -74,11 +76,10 @@
   private final GenericSignatureParser<DexType> genericSignatureParser =
       new GenericSignatureParser<>(genericSignatureRewriter);
 
-  ClassNameMinifier(
-      AppInfoWithLiveness appInfo,
-      RootSet rootSet,
-      InternalOptions options) {
-    this.appInfo = appInfo;
+  ClassNameMinifier(AppView<AppInfoWithLiveness> appView, RootSet rootSet) {
+    this.appView = appView;
+    this.appInfo = appView.appInfo();
+    InternalOptions options = appView.options();
     this.reporter = options.reporter;
     this.packageObfuscationMode = options.getProguardConfiguration().getPackageObfuscationMode();
     this.isAccessModificationAllowed =
@@ -546,6 +547,7 @@
     @Override
     public DexType parsedTypeName(String name) {
       DexType type = appInfo.dexItemFactory.createType(getDescriptorFromClassBinaryName(name));
+      type = appView.graphLense().lookupType(type);
       DexString renamedDescriptor = renaming.getOrDefault(type, type.descriptor);
       renamedSignature.append(getClassBinaryNameFromDescriptor(renamedDescriptor.toString()));
       return type;
@@ -564,6 +566,7 @@
       String enclosingRenamedBinaryName =
           getClassBinaryNameFromDescriptor(
               renaming.getOrDefault(enclosingType, enclosingType.descriptor).toString());
+      type = appView.graphLense().lookupType(type);
       DexString renamedDescriptor = renaming.get(type);
       if (renamedDescriptor != null) {
         // Pick the renamed inner class from the fully renamed binary name.
diff --git a/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java b/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
index be339b6..e2127dd 100644
--- a/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.naming;
 
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexEncodedField;
 import com.android.tools.r8.graph.DexField;
@@ -10,7 +11,6 @@
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 import com.android.tools.r8.shaking.RootSetBuilder.RootSet;
-import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.Timing;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Sets;
@@ -19,8 +19,8 @@
 
 class FieldNameMinifier extends MemberNameMinifier<DexField, DexType> {
 
-  FieldNameMinifier(AppInfoWithLiveness appInfo, RootSet rootSet, InternalOptions options) {
-    super(appInfo, rootSet, options);
+  FieldNameMinifier(AppView<AppInfoWithLiveness> appView, RootSet rootSet) {
+    super(appView, rootSet);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/naming/MemberNameMinifier.java b/src/main/java/com/android/tools/r8/naming/MemberNameMinifier.java
index 419bfbb..53957e4 100644
--- a/src/main/java/com/android/tools/r8/naming/MemberNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/MemberNameMinifier.java
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.naming;
 
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.CachedHashValueDexItem;
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexType;
@@ -18,6 +19,7 @@
 
 abstract class MemberNameMinifier<MemberType, StateType extends CachedHashValueDexItem> {
 
+  protected final AppView<AppInfoWithLiveness> appView;
   protected final AppInfoWithLiveness appInfo;
   protected final RootSet rootSet;
   protected final InternalOptions options;
@@ -34,10 +36,11 @@
   // which is useful for debugging.
   private final BiMap<DexType, NamingState<StateType, ?>> states = HashBiMap.create();
 
-  MemberNameMinifier(AppInfoWithLiveness appInfo, RootSet rootSet, InternalOptions options) {
-    this.appInfo = appInfo;
+  MemberNameMinifier(AppView<AppInfoWithLiveness> appView, RootSet rootSet) {
+    this.appView = appView;
+    this.appInfo = appView.appInfo();
     this.rootSet = rootSet;
-    this.options = options;
+    this.options = appView.options();
     this.dictionary = options.getProguardConfiguration().getObfuscationDictionary();
     this.useUniqueMemberNames = options.getProguardConfiguration().isUseUniqueClassMemberNames();
     this.overloadAggressively =
diff --git a/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java b/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
index 8864271..2cd8712 100644
--- a/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.naming;
 
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexCallSite;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexEncodedMethod;
@@ -91,11 +92,8 @@
 
   private final FrontierState frontierState = new FrontierState();
 
-  MethodNameMinifier(
-      AppInfoWithLiveness appInfo,
-      RootSet rootSet,
-      InternalOptions options) {
-    super(appInfo, rootSet, options);
+  MethodNameMinifier(AppView<AppInfoWithLiveness> appView, RootSet rootSet) {
+    super(appView, rootSet);
     equivalence =
         overloadAggressively
             ? MethodSignatureEquivalence.get()
diff --git a/src/main/java/com/android/tools/r8/naming/Minifier.java b/src/main/java/com/android/tools/r8/naming/Minifier.java
index 5333125..7f389a4 100644
--- a/src/main/java/com/android/tools/r8/naming/Minifier.java
+++ b/src/main/java/com/android/tools/r8/naming/Minifier.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.naming;
 
 import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexCallSite;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexEncodedMethod;
@@ -24,6 +25,7 @@
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.Timing;
 import com.google.common.collect.ImmutableMap;
+import java.util.HashMap;
 import java.util.IdentityHashMap;
 import java.util.Map;
 import java.util.Set;
@@ -35,26 +37,27 @@
 
   static final char INNER_CLASS_SEPARATOR = '$';
 
+  private final AppView<AppInfoWithLiveness> appView;
   private final AppInfoWithLiveness appInfo;
   private final RootSet rootSet;
   private final Set<DexCallSite> desugaredCallSites;
   private final InternalOptions options;
 
   public Minifier(
-      AppInfoWithLiveness appInfo,
+      AppView<AppInfoWithLiveness> appView,
       RootSet rootSet,
-      Set<DexCallSite> desugaredCallSites,
-      InternalOptions options) {
-    this.appInfo = appInfo;
+      Set<DexCallSite> desugaredCallSites) {
+    this.appView = appView;
+    this.appInfo = appView.appInfo();
     this.rootSet = rootSet;
     this.desugaredCallSites = desugaredCallSites;
-    this.options = options;
+    this.options = appView.options();
   }
 
   public NamingLens run(Timing timing) {
     assert options.enableMinification;
     timing.begin("MinifyClasses");
-    ClassNameMinifier classNameMinifier = new ClassNameMinifier(appInfo, rootSet, options);
+    ClassNameMinifier classNameMinifier = new ClassNameMinifier(appView, rootSet);
     ClassRenaming classRenaming = classNameMinifier.computeRenaming(timing);
     timing.end();
 
@@ -64,16 +67,14 @@
 
     timing.begin("MinifyMethods");
     MethodRenaming methodRenaming =
-        new MethodNameMinifier(appInfo, rootSet, options)
-            .computeRenaming(desugaredCallSites, timing);
+        new MethodNameMinifier(appView, rootSet).computeRenaming(desugaredCallSites, timing);
     timing.end();
 
     assert new MinifiedRenaming(classRenaming, methodRenaming, FieldRenaming.empty(), appInfo)
         .verifyNoCollisions(appInfo.classes(), appInfo.dexItemFactory);
 
     timing.begin("MinifyFields");
-    FieldRenaming fieldRenaming =
-        new FieldNameMinifier(appInfo, rootSet, options).computeRenaming(timing);
+    FieldRenaming fieldRenaming = new FieldNameMinifier(appView, rootSet).computeRenaming(timing);
     timing.end();
 
     NamingLens lens = new MinifiedRenaming(classRenaming, methodRenaming, fieldRenaming, appInfo);
@@ -86,11 +87,13 @@
     return lens;
   }
 
-  private static class MinifiedRenaming extends NamingLens {
+  static class MinifiedRenaming extends NamingLens {
 
     private final AppInfo appInfo;
     private final Map<String, String> packageRenaming;
     private final Map<DexItem, DexString> renaming = new IdentityHashMap<>();
+    // This set is only used for asserting no duplicated names.
+    private final Map<DexString, DexType> renamedTypesForVerification;
 
     private MinifiedRenaming(
         ClassRenaming classRenaming,
@@ -103,6 +106,10 @@
       renaming.putAll(methodRenaming.renaming);
       renaming.putAll(methodRenaming.callSiteRenaming);
       renaming.putAll(fieldRenaming.renaming);
+      renamedTypesForVerification = new HashMap<>();
+      for (Map.Entry<DexType, DexString> entry : classRenaming.classRenaming.entrySet()) {
+        renamedTypesForVerification.put(entry.getValue(), entry.getKey());
+      }
     }
 
     @Override
@@ -112,7 +119,18 @@
 
     @Override
     public DexString lookupDescriptor(DexType type) {
-      return renaming.getOrDefault(type, type.descriptor);
+      DexString dexString = renaming.get(type);
+      if (dexString != null) {
+        return dexString;
+      }
+      assert type.isPrimitiveType()
+              || type.isVoidType()
+              || !renamedTypesForVerification.containsKey(type.descriptor)
+          : "Duplicate minified type '"
+              + type.descriptor
+              + "' already mapped for: "
+              + renamedTypesForVerification.get(type.descriptor);
+      return type.descriptor;
     }
 
     @Override
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardTypeMatcher.java b/src/main/java/com/android/tools/r8/shaking/ProguardTypeMatcher.java
index dc8925a..a59a08c 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardTypeMatcher.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardTypeMatcher.java
@@ -386,24 +386,43 @@
             wildcard = wildcards.get(wildcardIndex);
             assert wildcard.isPattern();
             wildcardPattern = wildcard.asPattern();
+
             boolean includeSeparators = pattern.length() > (i + 1) && pattern.charAt(i + 1) == '*';
-            int nextPatternIndex = i + (includeSeparators ? 2 : 1);
-            // Fast cases for the common case where a pattern ends with '**' or '*'.
+            boolean includeAll = pattern.length() > (i + 2) && pattern.charAt(i + 2) == '*';
+            int nextPatternIndex = i + 1;
+            if (includeAll) {
+              nextPatternIndex += 2;
+            } else if (includeSeparators) {
+              nextPatternIndex += 1;
+            }
+
+            // Fast cases for the common case where a pattern ends with  '*', '**', or '***'.
             if (nextPatternIndex == pattern.length()) {
-              wildcardPattern.setCaptured(name.substring(nameIndex, name.length()));
+              wildcardPattern.setCaptured(name.substring(nameIndex));
+              if (includeAll) {
+                return true;
+              }
               if (includeSeparators) {
                 return kind == ClassOrType.CLASS || !isArrayType(name);
               }
               boolean hasSeparators = containsSeparatorsStartingAt(name, nameIndex);
               return !hasSeparators && (kind == ClassOrType.CLASS || !isArrayType(name));
             }
+
             // Match the rest of the pattern against the (non-empty) rest of the class name.
             for (int nextNameIndex = nameIndex; nextNameIndex < name.length(); nextNameIndex++) {
               wildcardPattern.setCaptured(name.substring(nameIndex, nextNameIndex));
-              if (!includeSeparators && name.charAt(nextNameIndex) == '.') {
-                return matchClassOrTypeNameImpl(
-                    pattern, nextPatternIndex, name, nextNameIndex, wildcards, wildcardIndex + 1,
-                    kind);
+              if (!includeSeparators) {
+                if (name.charAt(nextNameIndex) == '.') {
+                  return matchClassOrTypeNameImpl(
+                      pattern,
+                      nextPatternIndex,
+                      name,
+                      nextNameIndex,
+                      wildcards,
+                      wildcardIndex + 1,
+                      kind);
+                }
               }
               if (kind == ClassOrType.TYPE && name.charAt(nextNameIndex) == '[') {
                 return matchClassOrTypeNameImpl(
@@ -416,11 +435,12 @@
                 return true;
               }
             }
-            // Finally, check the case where the '*' or '**' eats all of the class name.
-            wildcardPattern.setCaptured(name.substring(nameIndex, name.length()));
+
+            // Finally, check the case where the '*', '**', or '***' eats all of the class name.
+            wildcardPattern.setCaptured(name.substring(nameIndex));
             return matchClassOrTypeNameImpl(
-                pattern, nextPatternIndex, name, name.length(), wildcards, wildcardIndex + 1,
-                kind);
+                pattern, nextPatternIndex, name, name.length(), wildcards, wildcardIndex + 1, kind);
+
           case '?':
             wildcard = wildcards.get(wildcardIndex);
             assert wildcard.isPattern();
@@ -432,6 +452,7 @@
             nameIndex++;
             wildcardIndex++;
             break;
+
           case '<':
             wildcard = wildcards.get(wildcardIndex);
             assert wildcard.isBackReference();
@@ -446,6 +467,7 @@
             wildcardIndex++;
             i = pattern.indexOf(">", i);
             break;
+
           default:
             if (nameIndex == name.length() || patternChar != name.charAt(nameIndex++)) {
               return false;
diff --git a/src/test/java/com/android/tools/r8/naming/MinifierTest.java b/src/test/java/com/android/tools/r8/naming/MinifierTest.java
index 473ca53..adf74ce 100644
--- a/src/test/java/com/android/tools/r8/naming/MinifierTest.java
+++ b/src/test/java/com/android/tools/r8/naming/MinifierTest.java
@@ -3,13 +3,16 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.naming;
 
+import static junit.framework.TestCase.assertTrue;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.fail;
 
 import com.android.tools.r8.graph.DexField;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.naming.Minifier.MinifiedRenaming;
 import com.android.tools.r8.utils.ListUtils;
 import com.android.tools.r8.utils.Timing;
 import java.nio.file.Paths;
@@ -40,6 +43,25 @@
     inspection.accept(dexItemFactory, naming);
   }
 
+  @Test
+  public void ensureClassesAddedToRenamingOrNoClashTest() throws Exception {
+    MinifiedRenaming naming =
+        (MinifiedRenaming) runMinifier(ListUtils.map(keepRulesFiles, Paths::get));
+    // Create a type that exists.
+    String existingType = "La/c;";
+    DexType d = dexItemFactory.createType(existingType);
+    try {
+      naming.lookupDescriptor(d);
+    } catch (AssertionError ae) {
+      assertTrue(
+          ae.getMessage()
+              .startsWith(
+                  "Duplicate minified type '" + existingType + "' already mapped for: naming001."));
+      return;
+    }
+    fail("Should have thrown an error.");
+  }
+
   @Parameters(name = "test: {0} keep: {1}")
   public static Collection<Object[]> data() {
     List<String> tests = Arrays.asList("naming001");
diff --git a/src/test/java/com/android/tools/r8/naming/NamingTestBase.java b/src/test/java/com/android/tools/r8/naming/NamingTestBase.java
index 7b6052a..4dcb52f 100644
--- a/src/test/java/com/android/tools/r8/naming/NamingTestBase.java
+++ b/src/test/java/com/android/tools/r8/naming/NamingTestBase.java
@@ -10,6 +10,7 @@
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.GraphLense;
 import com.android.tools.r8.shaking.Enqueuer;
+import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 import com.android.tools.r8.shaking.ProguardConfiguration;
 import com.android.tools.r8.shaking.RootSetBuilder;
 import com.android.tools.r8.shaking.RootSetBuilder.RootSet;
@@ -74,9 +75,12 @@
         new RootSetBuilder(appView, program, configuration.getRules(), options).run(executor);
 
     Enqueuer enqueuer = new Enqueuer(appView, options, null, options.forceProguardCompatibility);
-    AppInfoWithSubtyping appInfo =
+    AppInfoWithLiveness appInfo =
         enqueuer.traceApplication(rootSet, configuration.getDontWarnPatterns(), executor, timing);
-    return new Minifier(appInfo.withLiveness(), rootSet, Collections.emptySet(), options)
+    return new Minifier(
+        new AppView<>(appInfo, GraphLense.getIdentityLense(), options),
+        rootSet,
+        Collections.emptySet())
         .run(timing);
   }
 
diff --git a/src/test/java/com/android/tools/r8/naming/b124357885/B124357885Test.java b/src/test/java/com/android/tools/r8/naming/b124357885/B124357885Test.java
index 32e8e4d..659a8fc 100644
--- a/src/test/java/com/android/tools/r8/naming/b124357885/B124357885Test.java
+++ b/src/test/java/com/android/tools/r8/naming/b124357885/B124357885Test.java
@@ -7,20 +7,21 @@
 import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
 import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed;
 import static org.hamcrest.CoreMatchers.allOf;
-import static org.hamcrest.CoreMatchers.anyOf;
-import static org.hamcrest.CoreMatchers.containsString;
 import static org.hamcrest.CoreMatchers.not;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 
+import com.android.tools.r8.R8TestCompileResult;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.graph.DexAnnotationElement;
 import com.android.tools.r8.graph.DexValue;
 import com.android.tools.r8.graph.DexValue.DexValueArray;
 import com.android.tools.r8.graph.DexValue.DexValueString;
 import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.AnnotationSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.MethodSubject;
 import java.lang.reflect.Method;
 import java.lang.reflect.ParameterizedType;
@@ -28,7 +29,7 @@
 
 public class B124357885Test extends TestBase {
 
-  private void checkSignatureAnnotation(AnnotationSubject signature) {
+  private void checkSignatureAnnotation(CodeInspector inspector, AnnotationSubject signature) {
     DexAnnotationElement[] elements = signature.getAnnotation().elements;
     assertEquals(1, elements.length);
     assertEquals("value", elements[0].name.toString());
@@ -39,20 +40,22 @@
       assertTrue(value instanceof DexValueString);
       builder.append(((DexValueString) value).value);
     }
-    // TODO(124357885): This should be the minified name for FooImpl instead of Foo.
-    String fooDescriptor = DescriptorUtils.javaTypeToDescriptor(Foo.class.getTypeName());
+    String fooImplFinalDescriptor =
+        DescriptorUtils.javaTypeToDescriptor(inspector.clazz(FooImpl.class).getFinalName());
     StringBuilder expected =
         new StringBuilder()
             .append("()")
-            .append(fooDescriptor.substring(0, fooDescriptor.length() - 1))  // Remove the ;.
+            // Remove the final ; from the descriptor to add the generic type.
+            .append(fooImplFinalDescriptor.substring(0, fooImplFinalDescriptor.length() - 1))
             .append("<Ljava/lang/String;>")
-            .append(";");  // Add the ; here.
+            // Add the ; after the generic type.
+            .append(";");
     assertEquals(expected.toString(), builder.toString());
   }
 
   @Test
   public void test() throws Exception {
-    testForR8(Backend.DEX)
+    R8TestCompileResult compileResult = testForR8(Backend.DEX)
         .addProgramClasses(Main.class, Service.class, Foo.class, FooImpl.class)
         .addKeepMainRule(Main.class)
         .addKeepRules("-keepattributes Signature,InnerClasses,EnclosingMethod")
@@ -66,17 +69,14 @@
           assertEquals(1, inspector.clazz(Service.class).allMethods().size());
           MethodSubject fooList = inspector.clazz(Service.class).allMethods().get(0);
           AnnotationSubject signature = fooList.annotation("dalvik.annotation.Signature");
-          checkSignatureAnnotation(signature);
-        })
-        .run(Main.class)
-        .assertFailureWithErrorThatMatches(
-            anyOf(
-                containsString(
-                    "java.lang.ClassNotFoundException: "
-                        + "Didn't find class \"com.android.tools.r8.naming.b124357885.Foo\""),
-                containsString(
-                    "java.lang.NoClassDefFoundError: "
-                        + "com/android/tools/r8/naming/b124357885/Foo")));
+          checkSignatureAnnotation(inspector, signature);
+        });
+
+        String fooImplFinalName = compileResult.inspector().clazz(FooImpl.class).getFinalName();
+
+        compileResult
+            .run(Main.class)
+            .assertSuccessWithOutput(StringUtils.lines(fooImplFinalName, fooImplFinalName));
   }
 }
 
@@ -89,7 +89,7 @@
 
     // Convince R8 we only use subtypes to get class merging of Foo into FooImpl.
     Foo<String> foo = new FooImpl<>();
-    System.out.println(foo);
+    System.out.println(foo.getClass().getTypeName());
   }
 }
 
diff --git a/src/test/java/com/android/tools/r8/proguard/rules/ProguardMatchAllRuleWithPrefixTest.java b/src/test/java/com/android/tools/r8/proguard/rules/ProguardMatchAllRuleWithPrefixTest.java
new file mode 100644
index 0000000..d5f456b
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/proguard/rules/ProguardMatchAllRuleWithPrefixTest.java
@@ -0,0 +1,59 @@
+// Copyright (c) 2019, 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.proguard.rules;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.junit.Assert.assertThat;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import org.junit.Test;
+
+/** Regression test for b/124584385. */
+public class ProguardMatchAllRuleWithPrefixTest extends TestBase {
+
+  @Test
+  public void test() throws Exception {
+    CodeInspector inspector =
+        testForR8(Backend.DEX)
+            .addProgramClasses(TestClass.class)
+            .addKeepRules(
+                "-keep,allowobfuscation class com.android.tools.r8.*** {",
+                "  com.android.tools.r8.*** methodA();",
+                "  com.android.tools.r8.***Class methodB();",
+                "  com.android.tools.r8.***[] methodC();",
+                "  com.android.tools.r8.***Class[] methodD();",
+                "}")
+            .compile()
+            .inspector();
+
+    ClassSubject classSubject = inspector.clazz(TestClass.class);
+    assertThat(classSubject, isPresent());
+    assertThat(classSubject.uniqueMethodWithName("methodA"), isPresent());
+    assertThat(classSubject.uniqueMethodWithName("methodB"), isPresent());
+    assertThat(classSubject.uniqueMethodWithName("methodC"), isPresent());
+    assertThat(classSubject.uniqueMethodWithName("methodD"), isPresent());
+  }
+
+  static class TestClass {
+
+    TestClass methodA() {
+      return new TestClass();
+    }
+
+    TestClass methodB() {
+      return new TestClass();
+    }
+
+    TestClass[] methodC() {
+      return new TestClass[0];
+    }
+
+    TestClass[] methodD() {
+      return new TestClass[0];
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
index aa083da..f585226 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
@@ -321,6 +321,14 @@
     return obfuscatedTypeName != null ? obfuscatedTypeName : originalTypeName;
   }
 
+  String getOriginalTypeName(String minifiedTypeName) {
+    String originalTypeName = null;
+    if (mapping != null) {
+      originalTypeName = mapType(obfuscatedToOriginalMapping, minifiedTypeName);
+    }
+    return originalTypeName != null ? originalTypeName : minifiedTypeName;
+  }
+
   InstructionSubject createInstructionSubject(Instruction instruction) {
     DexInstructionSubject dexInst = new DexInstructionSubject(instruction);
     if (dexInst.isInvoke()) {
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java
index 6581a47..dd7cd85 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java
@@ -143,18 +143,14 @@
     //     X method(X) -> a
     //
     // whereas the final signature is for X.a is "a (a)"
-    String[] OriginalParameters = new String[signature.parameters.length];
-    for (int i = 0; i < OriginalParameters.length; i++) {
-      String obfuscated = signature.parameters[i];
-      String original = codeInspector.obfuscatedToOriginalMapping.get(obfuscated);
-      OriginalParameters[i] = original != null ? original : obfuscated;
+    String[] originalParameters = new String[signature.parameters.length];
+    for (int i = 0; i < originalParameters.length; i++) {
+      originalParameters[i] = codeInspector.getOriginalTypeName(signature.parameters[i]);
     }
-    String obfuscatedReturnType = signature.type;
-    String originalReturnType = codeInspector.obfuscatedToOriginalMapping.get(obfuscatedReturnType);
-    String returnType = originalReturnType != null ? originalReturnType : obfuscatedReturnType;
+    String returnType = codeInspector.getOriginalTypeName(signature.type);
 
     MethodSignature lookupSignature =
-        new MethodSignature(signature.name, returnType, OriginalParameters);
+        new MethodSignature(signature.name, returnType, originalParameters);
 
     MemberNaming memberNaming = clazz.naming.lookup(lookupSignature);
     return memberNaming != null ? (MethodSignature) memberNaming.getOriginalSignature() : signature;