[Retrace] Add api call for retracing an entire stack trace

This CL also introduce the notion of a RetraceStackTraceContext that
is needed for retracing frames.

Change-Id: I45872d2c9ce61bd647665173dd998a1264be460a
diff --git a/src/main/java/com/android/tools/r8/retrace/Retrace.java b/src/main/java/com/android/tools/r8/retrace/Retrace.java
index 62c04bb..11dcc13 100644
--- a/src/main/java/com/android/tools/r8/retrace/Retrace.java
+++ b/src/main/java/com/android/tools/r8/retrace/Retrace.java
@@ -18,6 +18,7 @@
 import com.android.tools.r8.utils.ListUtils;
 import com.android.tools.r8.utils.OptionsParsing;
 import com.android.tools.r8.utils.OptionsParsing.ParseContext;
+import com.android.tools.r8.utils.Pair;
 import com.android.tools.r8.utils.StringDiagnostic;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.Timing;
@@ -36,7 +37,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Scanner;
-import java.util.function.Consumer;
 import java.util.stream.Collectors;
 
 /**
@@ -139,7 +139,7 @@
   private final StackTraceLineParser<T, ST> stackTraceLineParser;
   private final StackTraceElementProxyRetracer<T, ST> proxyRetracer;
   private final DiagnosticsHandler diagnosticsHandler;
-  private final boolean isVerbose;
+  protected final boolean isVerbose;
 
   Retrace(
       StackTraceLineParser<T, ST> stackTraceLineParser,
@@ -153,12 +153,12 @@
   }
 
   /**
-   * Retraces a stack frame and calls the consumer for each retraced line
+   * Retraces a complete stack frame and returns a list of retraced stack traces.
    *
    * @param stackTrace the stack trace to be retrace
-   * @param retracedFrameConsumer the consumer to accept the retraced stack trace.
+   * @return list of potentially ambiguous stack traces.
    */
-  public void retraceStackTrace(List<T> stackTrace, Consumer<List<List<T>>> retracedFrameConsumer) {
+  public List<List<T>> retraceStackTrace(List<T> stackTrace) {
     ListUtils.forEachWithIndex(
         stackTrace,
         (line, lineNumber) -> {
@@ -168,7 +168,57 @@
             throw new RetraceAbortException();
           }
         });
-    stackTrace.forEach(line -> retracedFrameConsumer.accept(retraceFrame(line)));
+    List<Pair<List<T>, RetraceStackTraceContext>> retracedStackTraces = new ArrayList<>();
+    retracedStackTraces.add(
+        new Pair<>(new ArrayList<>(), RetraceStackTraceContext.getInitialContext()));
+    retracedStackTraces =
+        ListUtils.fold(
+            stackTrace,
+            retracedStackTraces,
+            (acc, stackTraceLine) -> {
+              ST parsedLine = stackTraceLineParser.parse(stackTraceLine);
+              List<Pair<List<T>, RetraceStackTraceContext>> newRetracedStackTraces =
+                  new ArrayList<>();
+              for (Pair<List<T>, RetraceStackTraceContext> retracedStackTrace : acc) {
+                Map<
+                        RetraceStackTraceElementProxy<T, ST>,
+                        List<RetraceStackTraceElementProxy<T, ST>>>
+                    ambiguousBlocks = new HashMap<>();
+                List<RetraceStackTraceElementProxy<T, ST>> ambiguousKeys = new ArrayList<>();
+                proxyRetracer
+                    .retrace(parsedLine, retracedStackTrace.getSecond())
+                    .forEach(
+                        retracedElement -> {
+                          if (retracedElement.isTopFrame() || !retracedElement.hasRetracedClass()) {
+                            ambiguousKeys.add(retracedElement);
+                            ambiguousBlocks.put(retracedElement, new ArrayList<>());
+                          }
+                          ambiguousBlocks.get(ListUtils.last(ambiguousKeys)).add(retracedElement);
+                        });
+                if (ambiguousKeys.isEmpty()) {
+                  // This happens when there is nothing to report.
+                  newRetracedStackTraces.add(
+                      new Pair<>(
+                          retracedStackTrace.getFirst(),
+                          RetraceStackTraceContext.getInitialContext()));
+                  continue;
+                }
+                Collections.sort(ambiguousKeys);
+                ambiguousKeys.forEach(
+                    key -> {
+                      List<T> resultList = new ArrayList<>();
+                      resultList.addAll(retracedStackTrace.getFirst());
+                      resultList.addAll(
+                          ListUtils.map(
+                              ambiguousBlocks.get(key),
+                              retracedElement ->
+                                  parsedLine.toRetracedItem(retracedElement, isVerbose)));
+                      newRetracedStackTraces.add(new Pair<>(resultList, key.getContext()));
+                    });
+              }
+              return newRetracedStackTraces;
+            });
+    return ListUtils.map(retracedStackTraces, Pair::getFirst);
   }
 
   /**
@@ -178,11 +228,11 @@
    * @return A collection of retraced frame where each entry in the outer list is ambiguous
    */
   public List<List<T>> retraceFrame(T stackTraceFrame) {
-    Map<RetraceStackTraceProxy<T, ST>, List<T>> ambiguousBlocks = new HashMap<>();
-    List<RetraceStackTraceProxy<T, ST>> ambiguousKeys = new ArrayList<>();
+    Map<RetraceStackTraceElementProxy<T, ST>, List<T>> ambiguousBlocks = new HashMap<>();
+    List<RetraceStackTraceElementProxy<T, ST>> ambiguousKeys = new ArrayList<>();
     ST parsedLine = stackTraceLineParser.parse(stackTraceFrame);
     proxyRetracer
-        .retrace(parsedLine)
+        .retrace(parsedLine, RetraceStackTraceContext.getInitialContext())
         .forEach(
             retracedElement -> {
               if (retracedElement.isTopFrame() || !retracedElement.hasRetracedClass()) {
@@ -209,7 +259,7 @@
   public List<T> retraceLine(T stackTraceLine) {
     ST parsedLine = stackTraceLineParser.parse(stackTraceLine);
     return proxyRetracer
-        .retrace(parsedLine)
+        .retrace(parsedLine, RetraceStackTraceContext.getInitialContext())
         .map(
             retraceFrame -> {
               retraceFrame.getOriginalItem().toRetracedItem(retraceFrame, isVerbose);
diff --git a/src/main/java/com/android/tools/r8/retrace/RetraceClassResult.java b/src/main/java/com/android/tools/r8/retrace/RetraceClassResult.java
index 29f4703..138e686 100644
--- a/src/main/java/com/android/tools/r8/retrace/RetraceClassResult.java
+++ b/src/main/java/com/android/tools/r8/retrace/RetraceClassResult.java
@@ -22,11 +22,14 @@
   RetraceMethodResult lookupMethod(
       String methodName, List<TypeReference> formalTypes, TypeReference returnType);
 
-  RetraceFrameResult lookupFrame(String methodName);
+  RetraceFrameResult lookupFrame(RetraceStackTraceContext context, String methodName);
 
-  RetraceFrameResult lookupFrame(String methodName, int position);
+  RetraceFrameResult lookupFrame(RetraceStackTraceContext context, String methodName, int position);
 
   RetraceFrameResult lookupFrame(
-      String methodName, int position, List<TypeReference> formalTypes, TypeReference returnType);
-
+      RetraceStackTraceContext context,
+      String methodName,
+      int position,
+      List<TypeReference> formalTypes,
+      TypeReference returnType);
 }
diff --git a/src/main/java/com/android/tools/r8/retrace/RetraceElement.java b/src/main/java/com/android/tools/r8/retrace/RetraceElement.java
index 55de558..63d40db 100644
--- a/src/main/java/com/android/tools/r8/retrace/RetraceElement.java
+++ b/src/main/java/com/android/tools/r8/retrace/RetraceElement.java
@@ -16,4 +16,6 @@
   R getRetraceResultContext();
 
   boolean isCompilerSynthesized();
+
+  RetraceStackTraceContext getContext();
 }
diff --git a/src/main/java/com/android/tools/r8/retrace/RetraceStackTraceContext.java b/src/main/java/com/android/tools/r8/retrace/RetraceStackTraceContext.java
new file mode 100644
index 0000000..9004cc1
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/retrace/RetraceStackTraceContext.java
@@ -0,0 +1,16 @@
+// Copyright (c) 2021, 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.retrace;
+
+import com.android.tools.r8.Keep;
+import com.android.tools.r8.retrace.internal.RetraceStackTraceContextImpl;
+
+@Keep
+public interface RetraceStackTraceContext {
+
+  static RetraceStackTraceContext getInitialContext() {
+    return new RetraceStackTraceContextImpl();
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/retrace/RetraceStackTraceProxy.java b/src/main/java/com/android/tools/r8/retrace/RetraceStackTraceElementProxy.java
similarity index 82%
rename from src/main/java/com/android/tools/r8/retrace/RetraceStackTraceProxy.java
rename to src/main/java/com/android/tools/r8/retrace/RetraceStackTraceElementProxy.java
index d326609d..c148bc0 100644
--- a/src/main/java/com/android/tools/r8/retrace/RetraceStackTraceProxy.java
+++ b/src/main/java/com/android/tools/r8/retrace/RetraceStackTraceElementProxy.java
@@ -8,8 +8,8 @@
 import java.util.List;
 
 @Keep
-public interface RetraceStackTraceProxy<T, ST extends StackTraceElementProxy<T, ST>>
-    extends Comparable<RetraceStackTraceProxy<T, ST>> {
+public interface RetraceStackTraceElementProxy<T, ST extends StackTraceElementProxy<T, ST>>
+    extends Comparable<RetraceStackTraceElementProxy<T, ST>> {
 
   boolean isAmbiguous();
 
@@ -44,4 +44,6 @@
   String getSourceFile();
 
   int getLineNumber();
+
+  RetraceStackTraceContext getContext();
 }
diff --git a/src/main/java/com/android/tools/r8/retrace/Retracer.java b/src/main/java/com/android/tools/r8/retrace/Retracer.java
index b99f20c..c609e44 100644
--- a/src/main/java/com/android/tools/r8/retrace/Retracer.java
+++ b/src/main/java/com/android/tools/r8/retrace/Retracer.java
@@ -22,6 +22,9 @@
 
   RetraceFrameResult retraceFrame(MethodReference methodReference, int position);
 
+  RetraceFrameResult retraceFrame(
+      MethodReference methodReference, int position, RetraceStackTraceContext context);
+
   RetraceFieldResult retraceField(FieldReference fieldReference);
 
   RetraceTypeResult retraceType(TypeReference typeReference);
diff --git a/src/main/java/com/android/tools/r8/retrace/StackTraceElementProxy.java b/src/main/java/com/android/tools/r8/retrace/StackTraceElementProxy.java
index 25150d2..46c7eff 100644
--- a/src/main/java/com/android/tools/r8/retrace/StackTraceElementProxy.java
+++ b/src/main/java/com/android/tools/r8/retrace/StackTraceElementProxy.java
@@ -38,5 +38,6 @@
 
   public abstract String getMethodArguments();
 
-  public abstract T toRetracedItem(RetraceStackTraceProxy<T, ST> retracedProxy, boolean verbose);
+  public abstract T toRetracedItem(
+      RetraceStackTraceElementProxy<T, ST> retracedProxy, boolean verbose);
 }
diff --git a/src/main/java/com/android/tools/r8/retrace/StackTraceElementProxyRetracer.java b/src/main/java/com/android/tools/r8/retrace/StackTraceElementProxyRetracer.java
index 2795942..851bbc2 100644
--- a/src/main/java/com/android/tools/r8/retrace/StackTraceElementProxyRetracer.java
+++ b/src/main/java/com/android/tools/r8/retrace/StackTraceElementProxyRetracer.java
@@ -11,7 +11,8 @@
 @Keep
 public interface StackTraceElementProxyRetracer<T, ST extends StackTraceElementProxy<T, ST>> {
 
-  Stream<? extends RetraceStackTraceProxy<T, ST>> retrace(ST element);
+  Stream<? extends RetraceStackTraceElementProxy<T, ST>> retrace(
+      ST element, RetraceStackTraceContext context);
 
   static <T, ST extends StackTraceElementProxy<T, ST>>
       StackTraceElementProxyRetracer<T, ST> createDefault(Retracer retracer) {
diff --git a/src/main/java/com/android/tools/r8/retrace/StringRetrace.java b/src/main/java/com/android/tools/r8/retrace/StringRetrace.java
index 4bdb42c..0296d71 100644
--- a/src/main/java/com/android/tools/r8/retrace/StringRetrace.java
+++ b/src/main/java/com/android/tools/r8/retrace/StringRetrace.java
@@ -76,10 +76,42 @@
    */
   public List<String> retrace(List<String> stackTrace) {
     List<String> retracedStrings = new ArrayList<>();
-    retraceStackTrace(stackTrace, result -> joinAmbiguousLines(result, retracedStrings::add));
+    List<List<String>> retracedStackTraces =
+        removeDuplicateStackTraces(retraceStackTrace(stackTrace));
+    if (retracedStackTraces.size() > 1) {
+      retracedStrings.add(
+          "There are "
+              + retracedStackTraces.size()
+              + " ambiguous stack traces."
+              + (isVerbose ? "" : " Use --verbose to have all listed."));
+    }
+    for (int i = 0; i < retracedStackTraces.size(); i++) {
+      if (i > 0) {
+        retracedStrings.add("< OR >");
+      }
+      retracedStrings.addAll(retracedStackTraces.get(i));
+      if (!isVerbose) {
+        break;
+      }
+    }
     return retracedStrings;
   }
 
+  private List<List<String>> removeDuplicateStackTraces(List<List<String>> stackTraces) {
+    if (stackTraces.size() == 1) {
+      return stackTraces;
+    }
+    Set<List<String>> seenStackTraces = new HashSet<>();
+    List<List<String>> nonDuplicateStackTraces = new ArrayList<>();
+    stackTraces.forEach(
+        stackTrace -> {
+          if (seenStackTraces.add(stackTrace)) {
+            nonDuplicateStackTraces.add(stackTrace);
+          }
+        });
+    return nonDuplicateStackTraces;
+  }
+
   /**
    * Retraces a single stack trace line and returns the potential list of original frames
    *
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/RetraceClassResultImpl.java b/src/main/java/com/android/tools/r8/retrace/internal/RetraceClassResultImpl.java
index 9117006..d2eee25 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/RetraceClassResultImpl.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/RetraceClassResultImpl.java
@@ -16,6 +16,7 @@
 import com.android.tools.r8.retrace.RetraceClassElement;
 import com.android.tools.r8.retrace.RetraceClassResult;
 import com.android.tools.r8.retrace.RetraceFrameResult;
+import com.android.tools.r8.retrace.RetraceStackTraceContext;
 import com.android.tools.r8.retrace.RetraceUnknownJsonMappingInformationResult;
 import com.android.tools.r8.retrace.RetracedSourceFile;
 import com.android.tools.r8.retrace.Retracer;
@@ -121,18 +122,23 @@
   }
 
   @Override
-  public RetraceFrameResultImpl lookupFrame(String methodName) {
+  public RetraceFrameResultImpl lookupFrame(RetraceStackTraceContext context, String methodName) {
     return lookupFrame(MethodDefinition.create(obfuscatedReference, methodName), -1);
   }
 
   @Override
-  public RetraceFrameResultImpl lookupFrame(String methodName, int position) {
+  public RetraceFrameResultImpl lookupFrame(
+      RetraceStackTraceContext context, String methodName, int position) {
     return lookupFrame(MethodDefinition.create(obfuscatedReference, methodName), position);
   }
 
   @Override
   public RetraceFrameResultImpl lookupFrame(
-      String methodName, int position, List<TypeReference> formalTypes, TypeReference returnType) {
+      RetraceStackTraceContext context,
+      String methodName,
+      int position,
+      List<TypeReference> formalTypes,
+      TypeReference returnType) {
     return lookupFrame(
         MethodDefinition.create(
             Reference.method(obfuscatedReference, methodName, formalTypes, returnType)),
@@ -269,6 +275,12 @@
     }
 
     @Override
+    public RetraceStackTraceContext getContext() {
+      // TODO(b/197936862): Extend the context to enable tracking information.
+      return RetraceStackTraceContext.getInitialContext();
+    }
+
+    @Override
     public RetraceFieldResultImpl lookupField(String fieldName) {
       return lookupField(FieldDefinition.create(classReference.getClassReference(), fieldName));
     }
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/RetraceFieldResultImpl.java b/src/main/java/com/android/tools/r8/retrace/internal/RetraceFieldResultImpl.java
index 38667c4..b536bea 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/RetraceFieldResultImpl.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/RetraceFieldResultImpl.java
@@ -10,6 +10,7 @@
 import com.android.tools.r8.references.Reference;
 import com.android.tools.r8.retrace.RetraceFieldElement;
 import com.android.tools.r8.retrace.RetraceFieldResult;
+import com.android.tools.r8.retrace.RetraceStackTraceContext;
 import com.android.tools.r8.retrace.RetracedSourceFile;
 import com.android.tools.r8.retrace.Retracer;
 import com.android.tools.r8.retrace.internal.RetraceClassResultImpl.RetraceClassElementImpl;
@@ -113,6 +114,11 @@
     }
 
     @Override
+    public RetraceStackTraceContext getContext() {
+      return RetraceStackTraceContext.getInitialContext();
+    }
+
+    @Override
     public boolean isUnknown() {
       return fieldReference.isUnknown();
     }
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/RetraceFrameResultImpl.java b/src/main/java/com/android/tools/r8/retrace/internal/RetraceFrameResultImpl.java
index 5d0f836..8ca0828 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/RetraceFrameResultImpl.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/RetraceFrameResultImpl.java
@@ -11,6 +11,7 @@
 import com.android.tools.r8.references.MethodReference;
 import com.android.tools.r8.retrace.RetraceFrameElement;
 import com.android.tools.r8.retrace.RetraceFrameResult;
+import com.android.tools.r8.retrace.RetraceStackTraceContext;
 import com.android.tools.r8.retrace.RetracedClassMemberReference;
 import com.android.tools.r8.retrace.RetracedMethodReference;
 import com.android.tools.r8.retrace.RetracedSourceFile;
@@ -179,6 +180,11 @@
     }
 
     @Override
+    public RetraceStackTraceContext getContext() {
+      return RetraceStackTraceContext.getInitialContext();
+    }
+
+    @Override
     public RetraceFrameResult getRetraceResultContext() {
       return retraceFrameResult;
     }
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/RetraceMethodResultImpl.java b/src/main/java/com/android/tools/r8/retrace/internal/RetraceMethodResultImpl.java
index c6ac407..ab18153 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/RetraceMethodResultImpl.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/RetraceMethodResultImpl.java
@@ -10,6 +10,7 @@
 import com.android.tools.r8.references.MethodReference;
 import com.android.tools.r8.retrace.RetraceMethodElement;
 import com.android.tools.r8.retrace.RetraceMethodResult;
+import com.android.tools.r8.retrace.RetraceStackTraceContext;
 import com.android.tools.r8.retrace.RetracedMethodReference;
 import com.android.tools.r8.retrace.RetracedSourceFile;
 import com.android.tools.r8.retrace.Retracer;
@@ -147,6 +148,11 @@
     }
 
     @Override
+    public RetraceStackTraceContext getContext() {
+      return RetraceStackTraceContext.getInitialContext();
+    }
+
+    @Override
     public boolean isUnknown() {
       return methodReference.isUnknown();
     }
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/RetraceStackTraceContextImpl.java b/src/main/java/com/android/tools/r8/retrace/internal/RetraceStackTraceContextImpl.java
new file mode 100644
index 0000000..b33e06d
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/retrace/internal/RetraceStackTraceContextImpl.java
@@ -0,0 +1,9 @@
+// Copyright (c) 2021, 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.retrace.internal;
+
+import com.android.tools.r8.retrace.RetraceStackTraceContext;
+
+public class RetraceStackTraceContextImpl implements RetraceStackTraceContext {}
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/RetracerImpl.java b/src/main/java/com/android/tools/r8/retrace/internal/RetracerImpl.java
index d1c5874..0758be3 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/RetracerImpl.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/RetracerImpl.java
@@ -12,6 +12,8 @@
 import com.android.tools.r8.references.TypeReference;
 import com.android.tools.r8.retrace.InvalidMappingFileException;
 import com.android.tools.r8.retrace.ProguardMapProducer;
+import com.android.tools.r8.retrace.RetraceFrameResult;
+import com.android.tools.r8.retrace.RetraceStackTraceContext;
 import com.android.tools.r8.retrace.Retracer;
 import java.io.BufferedReader;
 
@@ -53,7 +55,13 @@
   }
 
   @Override
-  public RetraceFrameResultImpl retraceFrame(MethodReference methodReference, int position) {
+  public RetraceFrameResult retraceFrame(MethodReference methodReference, int position) {
+    return retraceFrame(methodReference, position, RetraceStackTraceContext.getInitialContext());
+  }
+
+  @Override
+  public RetraceFrameResult retraceFrame(
+      MethodReference methodReference, int position, RetraceStackTraceContext context) {
     return retraceClass(methodReference.getHolderClass())
         .lookupMethod(methodReference.getMethodName())
         .narrowByPosition(position);
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/StackTraceElementProxyRetracerImpl.java b/src/main/java/com/android/tools/r8/retrace/internal/StackTraceElementProxyRetracerImpl.java
index 0f29acd..136d755 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/StackTraceElementProxyRetracerImpl.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/StackTraceElementProxyRetracerImpl.java
@@ -9,7 +9,8 @@
 import com.android.tools.r8.retrace.RetraceClassResult;
 import com.android.tools.r8.retrace.RetraceFieldResult;
 import com.android.tools.r8.retrace.RetraceFrameResult;
-import com.android.tools.r8.retrace.RetraceStackTraceProxy;
+import com.android.tools.r8.retrace.RetraceStackTraceContext;
+import com.android.tools.r8.retrace.RetraceStackTraceElementProxy;
 import com.android.tools.r8.retrace.RetraceTypeResult;
 import com.android.tools.r8.retrace.RetraceTypeResult.Element;
 import com.android.tools.r8.retrace.RetracedClassReference;
@@ -37,9 +38,10 @@
   }
 
   @Override
-  public Stream<? extends RetraceStackTraceProxy<T, ST>> retrace(ST element) {
-    Stream<RetraceStackTraceProxyImpl<T, ST>> currentResults =
-        Stream.of(RetraceStackTraceProxyImpl.create(element));
+  public Stream<? extends RetraceStackTraceElementProxy<T, ST>> retrace(
+      ST element, RetraceStackTraceContext context) {
+    Stream<RetraceStackTraceElementProxyImpl<T, ST>> currentResults =
+        Stream.of(RetraceStackTraceElementProxyImpl.create(element, context));
     if (!element.hasClassName()
         && !element.hasFieldOrReturnType()
         && !element.hasMethodArguments()) {
@@ -60,8 +62,8 @@
     return currentResults;
   }
 
-  private Stream<RetraceStackTraceProxyImpl<T, ST>> retraceClassOrType(
-      Stream<RetraceStackTraceProxyImpl<T, ST>> currentResults,
+  private Stream<RetraceStackTraceElementProxyImpl<T, ST>> retraceClassOrType(
+      Stream<RetraceStackTraceElementProxyImpl<T, ST>> currentResults,
       ST element,
       RetraceClassResult classResult) {
     return currentResults.flatMap(
@@ -69,57 +71,61 @@
             classResult.stream()
                 .map(
                     classElement -> {
-                      RetraceStackTraceProxyImpl.Builder<T, ST> proxyBuilder =
+                      RetraceStackTraceElementProxyImpl.Builder<T, ST> newProxyBuilder =
                           proxy
                               .builder()
                               .setRetracedClass(classElement.getRetracedClass())
                               .joinAmbiguous(classResult.isAmbiguous())
-                              .setTopFrame(true);
+                              .setTopFrame(true)
+                              .setContext(classElement.getContext());
                       if (element.hasSourceFile()) {
-                        RetracedSourceFile sourceFileResult = classElement.getSourceFile();
-                        proxyBuilder.setSourceFile(
-                            sourceFileResult.hasRetraceResult()
-                                ? sourceFileResult.getSourceFile()
+                        RetracedSourceFile sourceFile = classElement.getSourceFile();
+                        newProxyBuilder.setSourceFile(
+                            sourceFile.hasRetraceResult()
+                                ? sourceFile.getSourceFile()
                                 : RetraceUtils.inferSourceFile(
                                     classElement.getRetracedClass().getTypeName(),
                                     element.getSourceFile(),
                                     classResult.hasRetraceResult()));
                       }
-                      return proxyBuilder.build();
+                      return newProxyBuilder.build();
                     }));
   }
 
-  private Stream<RetraceStackTraceProxyImpl<T, ST>> retraceMethod(
-      Stream<RetraceStackTraceProxyImpl<T, ST>> currentResults,
+  private Stream<RetraceStackTraceElementProxyImpl<T, ST>> retraceMethod(
+      Stream<RetraceStackTraceElementProxyImpl<T, ST>> currentResults,
       ST element,
       RetraceClassResult classResult) {
     return currentResults.flatMap(
         proxy -> {
           RetraceFrameResult frameResult =
               element.hasLineNumber()
-                  ? classResult.lookupFrame(element.getMethodName(), element.getLineNumber())
-                  : classResult.lookupFrame(element.getMethodName());
+                  ? classResult.lookupFrame(
+                      proxy.context, element.getMethodName(), element.getLineNumber())
+                  : classResult.lookupFrame(proxy.context, element.getMethodName());
           return frameResult.stream()
               .flatMap(
                   frameElement -> {
-                    List<RetraceStackTraceProxyImpl<T, ST>> retracedProxies = new ArrayList<>();
+                    List<RetraceStackTraceElementProxyImpl<T, ST>> retracedProxies =
+                        new ArrayList<>();
                     frameElement.visitNonCompilerSynthesizedFrames(
                         (frame, position) -> {
                           boolean isTopFrame = position == 0;
-                          RetraceStackTraceProxyImpl.Builder<T, ST> proxyBuilder =
+                          RetraceStackTraceElementProxyImpl.Builder<T, ST> newProxyBuilder =
                               proxy
                                   .builder()
                                   .setRetracedClass(frame.getHolderClass())
                                   .setRetracedMethod(frame)
                                   .joinAmbiguous(frameResult.isAmbiguous() && isTopFrame)
-                                  .setTopFrame(isTopFrame);
+                                  .setTopFrame(isTopFrame)
+                                  .setContext(frameElement.getContext());
                           if (element.hasLineNumber()) {
-                            proxyBuilder.setLineNumber(
+                            newProxyBuilder.setLineNumber(
                                 frame.getOriginalPositionOrDefault(element.getLineNumber()));
                           }
                           if (element.hasSourceFile()) {
                             RetracedSourceFile sourceFileResult = frameElement.getSourceFile(frame);
-                            proxyBuilder.setSourceFile(
+                            newProxyBuilder.setSourceFile(
                                 sourceFileResult.hasRetraceResult()
                                     ? sourceFileResult.getSourceFile()
                                     : RetraceUtils.inferSourceFile(
@@ -127,15 +133,15 @@
                                         element.getSourceFile(),
                                         classResult.hasRetraceResult()));
                           }
-                          retracedProxies.add(proxyBuilder.build());
+                          retracedProxies.add(newProxyBuilder.build());
                         });
                     return retracedProxies.stream();
                   });
         });
   }
 
-  private Stream<RetraceStackTraceProxyImpl<T, ST>> retraceField(
-      Stream<RetraceStackTraceProxyImpl<T, ST>> currentResults,
+  private Stream<RetraceStackTraceElementProxyImpl<T, ST>> retraceField(
+      Stream<RetraceStackTraceElementProxyImpl<T, ST>> currentResults,
       ST element,
       RetraceClassResult classResult) {
     return currentResults.flatMap(
@@ -144,30 +150,31 @@
           return retraceFieldResult.stream()
               .map(
                   fieldElement -> {
-                    RetraceStackTraceProxyImpl.Builder<T, ST> proxyBuilder =
+                    RetraceStackTraceElementProxyImpl.Builder<T, ST> newProxyBuilder =
                         proxy
                             .builder()
                             .setRetracedClass(fieldElement.getField().getHolderClass())
                             .setRetracedField(fieldElement.getField())
                             .joinAmbiguous(retraceFieldResult.isAmbiguous())
-                            .setTopFrame(true);
+                            .setTopFrame(true)
+                            .setContext(fieldElement.getContext());
                     if (element.hasSourceFile()) {
-                      RetracedSourceFile sourceFileResult = fieldElement.getSourceFile();
-                      proxyBuilder.setSourceFile(
-                          sourceFileResult.hasRetraceResult()
-                              ? sourceFileResult.getSourceFile()
+                      RetracedSourceFile sourceFile = fieldElement.getSourceFile();
+                      newProxyBuilder.setSourceFile(
+                          sourceFile.hasRetraceResult()
+                              ? sourceFile.getSourceFile()
                               : RetraceUtils.inferSourceFile(
                                   fieldElement.getField().getHolderClass().getTypeName(),
                                   element.getSourceFile(),
                                   classResult.hasRetraceResult()));
                     }
-                    return proxyBuilder.build();
+                    return newProxyBuilder.build();
                   });
         });
   }
 
-  private Stream<RetraceStackTraceProxyImpl<T, ST>> retraceFieldOrReturnType(
-      Stream<RetraceStackTraceProxyImpl<T, ST>> currentResults, ST element) {
+  private Stream<RetraceStackTraceElementProxyImpl<T, ST>> retraceFieldOrReturnType(
+      Stream<RetraceStackTraceElementProxyImpl<T, ST>> currentResults, ST element) {
     if (!element.hasFieldOrReturnType()) {
       return currentResults;
     }
@@ -196,8 +203,8 @@
     }
   }
 
-  private Stream<RetraceStackTraceProxyImpl<T, ST>> retracedMethodArguments(
-      Stream<RetraceStackTraceProxyImpl<T, ST>> currentResults, ST element) {
+  private Stream<RetraceStackTraceElementProxyImpl<T, ST>> retracedMethodArguments(
+      Stream<RetraceStackTraceElementProxyImpl<T, ST>> currentResults, ST element) {
     if (!element.hasMethodArguments()) {
       return currentResults;
     }
@@ -236,8 +243,8 @@
                             .build()));
   }
 
-  public static class RetraceStackTraceProxyImpl<T, ST extends StackTraceElementProxy<T, ST>>
-      implements RetraceStackTraceProxy<T, ST> {
+  public static class RetraceStackTraceElementProxyImpl<T, ST extends StackTraceElementProxy<T, ST>>
+      implements RetraceStackTraceElementProxy<T, ST> {
 
     private final ST originalItem;
     private final RetracedClassReference retracedClass;
@@ -249,8 +256,9 @@
     private final int lineNumber;
     private final boolean isAmbiguous;
     private final boolean isTopFrame;
+    private final RetraceStackTraceContext context;
 
-    private RetraceStackTraceProxyImpl(
+    private RetraceStackTraceElementProxyImpl(
         ST originalItem,
         RetracedClassReference retracedClass,
         RetracedMethodReference retracedMethod,
@@ -260,7 +268,8 @@
         String sourceFile,
         int lineNumber,
         boolean isAmbiguous,
-        boolean isTopFrame) {
+        boolean isTopFrame,
+        RetraceStackTraceContext context) {
       assert originalItem != null;
       this.originalItem = originalItem;
       this.retracedClass = retracedClass;
@@ -272,6 +281,7 @@
       this.lineNumber = lineNumber;
       this.isAmbiguous = isAmbiguous;
       this.isTopFrame = isTopFrame;
+      this.context = context;
     }
 
     @Override
@@ -355,9 +365,10 @@
     }
 
     private static <T, ST extends StackTraceElementProxy<T, ST>>
-        RetraceStackTraceProxyImpl<T, ST> create(ST originalItem) {
-      return new RetraceStackTraceProxyImpl<T, ST>(
-          originalItem, null, null, null, null, null, null, -1, false, false);
+        RetraceStackTraceElementProxyImpl<T, ST> create(
+            ST originalItem, RetraceStackTraceContext context) {
+      return new RetraceStackTraceElementProxyImpl<T, ST>(
+          originalItem, null, null, null, null, null, null, -1, false, false, context);
     }
 
     private Builder<T, ST> builder() {
@@ -371,6 +382,7 @@
       builder.lineNumber = lineNumber;
       builder.isAmbiguous = isAmbiguous;
       builder.isTopFrame = isTopFrame;
+      builder.context = context;
       return builder;
     }
 
@@ -380,7 +392,12 @@
     }
 
     @Override
-    public int compareTo(RetraceStackTraceProxy<T, ST> other) {
+    public RetraceStackTraceContext getContext() {
+      return context;
+    }
+
+    @Override
+    public int compareTo(RetraceStackTraceElementProxy<T, ST> other) {
       int classCompare = Boolean.compare(hasRetracedClass(), other.hasRetracedClass());
       if (classCompare != 0) {
         return classCompare;
@@ -434,6 +451,7 @@
       private int lineNumber = -1;
       private boolean isAmbiguous;
       private boolean isTopFrame;
+      private RetraceStackTraceContext context;
 
       private Builder(ST originalElement) {
         this.originalElement = originalElement;
@@ -484,12 +502,17 @@
         return this;
       }
 
-      private RetraceStackTraceProxyImpl<T, ST> build() {
+      private Builder<T, ST> setContext(RetraceStackTraceContext context) {
+        this.context = context;
+        return this;
+      }
+
+      private RetraceStackTraceElementProxyImpl<T, ST> build() {
         RetracedClassReference retracedClass = classContext;
         if (methodContext != null) {
           retracedClass = methodContext.getHolderClass();
         }
-        return new RetraceStackTraceProxyImpl<>(
+        return new RetraceStackTraceElementProxyImpl<>(
             originalElement,
             retracedClass,
             methodContext,
@@ -499,7 +522,8 @@
             sourceFile,
             lineNumber,
             isAmbiguous,
-            isTopFrame);
+            isTopFrame,
+            context);
       }
     }
   }
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/StackTraceElementStringProxy.java b/src/main/java/com/android/tools/r8/retrace/internal/StackTraceElementStringProxy.java
index 0b22dae..7afc10b 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/StackTraceElementStringProxy.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/StackTraceElementStringProxy.java
@@ -10,7 +10,7 @@
 
 import com.android.tools.r8.references.ClassReference;
 import com.android.tools.r8.references.Reference;
-import com.android.tools.r8.retrace.RetraceStackTraceProxy;
+import com.android.tools.r8.retrace.RetraceStackTraceElementProxy;
 import com.android.tools.r8.retrace.RetracedClassReference;
 import com.android.tools.r8.retrace.RetracedFieldReference;
 import com.android.tools.r8.retrace.RetracedTypeReference;
@@ -141,7 +141,8 @@
 
   @Override
   public String toRetracedItem(
-      RetraceStackTraceProxy<String, StackTraceElementStringProxy> retracedProxy, boolean verbose) {
+      RetraceStackTraceElementProxy<String, StackTraceElementStringProxy> retracedProxy,
+      boolean verbose) {
     StringBuilder sb = new StringBuilder();
     int lastSeenIndex = 0;
     for (StringIndex index : orderedIndices) {
@@ -333,14 +334,17 @@
     protected final int startIndex;
     protected final int endIndex;
     private final TriFunction<
-            RetraceStackTraceProxy<String, ?>, StackTraceElementStringProxy, Boolean, String>
+            RetraceStackTraceElementProxy<String, ?>, StackTraceElementStringProxy, Boolean, String>
         retracedString;
 
     private StringIndex(
         int startIndex,
         int endIndex,
         TriFunction<
-                RetraceStackTraceProxy<String, ?>, StackTraceElementStringProxy, Boolean, String>
+                RetraceStackTraceElementProxy<String, ?>,
+                StackTraceElementStringProxy,
+                Boolean,
+                String>
             retracedString) {
       this.startIndex = startIndex;
       this.endIndex = endIndex;
@@ -363,7 +367,10 @@
         int startIndex,
         int endIndex,
         TriFunction<
-                RetraceStackTraceProxy<String, ?>, StackTraceElementStringProxy, Boolean, String>
+                RetraceStackTraceElementProxy<String, ?>,
+                StackTraceElementStringProxy,
+                Boolean,
+                String>
             retracedString,
         ClassNameType classNameType) {
       super(startIndex, endIndex, retracedString);
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousMethodVerboseStackTrace.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousMethodVerboseStackTrace.java
index 017a6b8..5ce9e89 100644
--- a/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousMethodVerboseStackTrace.java
+++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousMethodVerboseStackTrace.java
@@ -40,14 +40,19 @@
   @Override
   public List<String> retraceVerboseStackTrace() {
     return Arrays.asList(
+        "There are 2 ambiguous stack traces.",
         "Exception in thread \"main\" java.lang.NullPointerException",
         "\tat com.android.tools.r8.naming.retrace.Main.c(Main.java)",
-        "\tat com.android.tools.r8.naming.retrace.Main.com.android.Foo main("
-            + "java.lang.String[])(Main.java)",
-        "\t<OR #1> at com.android.tools.r8.naming.retrace.Main.void main("
-            + "com.android.Bar)(Main.java)",
-        "\tat com.android.tools.r8.naming.retrace.Main.com.android.Foo main("
-            + "java.lang.String[],com.android.Bar)(Main.java)");
+        "\tat com.android.tools.r8.naming.retrace.Main.com.android.Foo"
+            + " main(java.lang.String[])(Main.java)",
+        "\tat com.android.tools.r8.naming.retrace.Main.com.android.Foo"
+            + " main(java.lang.String[],com.android.Bar)(Main.java)",
+        "< OR >",
+        "Exception in thread \"main\" java.lang.NullPointerException",
+        "\tat com.android.tools.r8.naming.retrace.Main.c(Main.java)",
+        "\tat com.android.tools.r8.naming.retrace.Main.void main(com.android.Bar)(Main.java)",
+        "\tat com.android.tools.r8.naming.retrace.Main.com.android.Foo"
+            + " main(java.lang.String[],com.android.Bar)(Main.java)");
   }
 
   @Override
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousMissingLineStackTrace.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousMissingLineStackTrace.java
index e3cab8a..3442711 100644
--- a/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousMissingLineStackTrace.java
+++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousMissingLineStackTrace.java
@@ -25,30 +25,82 @@
   @Override
   public List<String> retracedStackTrace() {
     return Arrays.asList(
+        "There are 8 ambiguous stack traces. Use --verbose to have all listed.",
         "com.android.tools.r8.CompilationException: foo[parens](Source:3)",
         "    at com.android.tools.r8.R8.bar(R8.java:7)",
-        "    <OR #1> at com.android.tools.r8.R8.foo(R8.java:7)",
         "    at com.android.tools.r8.R8.bar(R8.java:8)",
-        "    <OR #1> at com.android.tools.r8.R8.foo(R8.java:8)",
         "    at com.android.tools.r8.R8.main(Unknown Source)",
         "Caused by: com.android.tools.r8.CompilationException: foo[parens](Source:3)",
         "    at com.android.tools.r8.R8.bar(R8.java:9)",
-        "    <OR #1> at com.android.tools.r8.R8.foo(R8.java:9)",
         "    ... 42 more");
   }
 
   @Override
   public List<String> retraceVerboseStackTrace() {
     return Arrays.asList(
+        "There are 8 ambiguous stack traces.",
         "com.android.tools.r8.CompilationException: foo[parens](Source:3)",
         "    at com.android.tools.r8.R8.void bar(int,int)(R8.java:7)",
-        "    <OR #1> at com.android.tools.r8.R8.void foo(int)(R8.java:7)",
         "    at com.android.tools.r8.R8.void bar(int,int)(R8.java:8)",
-        "    <OR #1> at com.android.tools.r8.R8.void foo(int)(R8.java:8)",
         "    at com.android.tools.r8.R8.main(Unknown Source)",
         "Caused by: com.android.tools.r8.CompilationException: foo[parens](Source:3)",
         "    at com.android.tools.r8.R8.void bar(int,int)(R8.java:9)",
-        "    <OR #1> at com.android.tools.r8.R8.void foo(int)(R8.java:9)",
+        "    ... 42 more",
+        "< OR >",
+        "com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void bar(int,int)(R8.java:7)",
+        "    at com.android.tools.r8.R8.void bar(int,int)(R8.java:8)",
+        "    at com.android.tools.r8.R8.main(Unknown Source)",
+        "Caused by: com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java:9)",
+        "    ... 42 more",
+        "< OR >",
+        "com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void bar(int,int)(R8.java:7)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java:8)",
+        "    at com.android.tools.r8.R8.main(Unknown Source)",
+        "Caused by: com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void bar(int,int)(R8.java:9)",
+        "    ... 42 more",
+        "< OR >",
+        "com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void bar(int,int)(R8.java:7)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java:8)",
+        "    at com.android.tools.r8.R8.main(Unknown Source)",
+        "Caused by: com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java:9)",
+        "    ... 42 more",
+        "< OR >",
+        "com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java:7)",
+        "    at com.android.tools.r8.R8.void bar(int,int)(R8.java:8)",
+        "    at com.android.tools.r8.R8.main(Unknown Source)",
+        "Caused by: com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void bar(int,int)(R8.java:9)",
+        "    ... 42 more",
+        "< OR >",
+        "com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java:7)",
+        "    at com.android.tools.r8.R8.void bar(int,int)(R8.java:8)",
+        "    at com.android.tools.r8.R8.main(Unknown Source)",
+        "Caused by: com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java:9)",
+        "    ... 42 more",
+        "< OR >",
+        "com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java:7)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java:8)",
+        "    at com.android.tools.r8.R8.main(Unknown Source)",
+        "Caused by: com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void bar(int,int)(R8.java:9)",
+        "    ... 42 more",
+        "< OR >",
+        "com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java:7)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java:8)",
+        "    at com.android.tools.r8.R8.main(Unknown Source)",
+        "Caused by: com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java:9)",
         "    ... 42 more");
   }
 
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousStackTrace.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousStackTrace.java
index 9692fa2..989868f 100644
--- a/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousStackTrace.java
+++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousStackTrace.java
@@ -24,58 +24,83 @@
 
   @Override
   public List<String> retracedStackTrace() {
-    // ProGuard version shows ambiguous traces differently:
-    //
-    // Proguard Retrace:
-    // com.android.tools.r8.CompilationException: foo[parens](Source:3)
-    //   at com.android.tools.r8.R8.foo(R8.java)
-    //                              bar(R8.java)
-    //   at com.android.tools.r8.R8.foo(R8.java)
-    //                              bar(R8.java)
-    //   at com.android.tools.r8.R8.main(r8.java)
-    // Caused by: com.android.tools.r8.CompilationException: foo[parens](Source:3)
-    //   at com.android.tools.r8.R8.foo(R8.java)
-    //                              bar(R8.java)
-    //   ... 42 more
-    //
-    // Other Retrace:
-    // com.android.tools.r8.CompilationException: foo[parens](Source:3)
-    //   at com.android.tools.r8.R8.foo(R8.java)
-    //   at <OR> com.android.tools.r8.R8.bar(R8.java)
-    //   at com.android.tools.r8.R8.foo(R8.java)
-    //   at <OR> com.android.tools.r8.R8.bar(R8.java)
-    //   at com.android.tools.r8.R8.main(r8.java)
-    // Caused by: com.android.tools.r8.CompilationException: foo[parens](Source:3)
-    //   at <OR> com.android.tools.r8.R8.bar(R8.java)
-    //   at com.android.tools.r8.R8(r8.java)
-    //   ... 42 more
-    //
-    // We have decided on the format below.
     return Arrays.asList(
+        "There are 8 ambiguous stack traces. Use --verbose to have all listed.",
         "com.android.tools.r8.CompilationException: foo[parens](Source:3)",
         "    at com.android.tools.r8.R8.bar(R8.java)",
-        "    <OR #1> at com.android.tools.r8.R8.foo(R8.java)",
         "    at com.android.tools.r8.R8.bar(R8.java)",
-        "    <OR #1> at com.android.tools.r8.R8.foo(R8.java)",
         "    at com.android.tools.r8.R8.main(Unknown Source)",
         "Caused by: com.android.tools.r8.CompilationException: foo[parens](Source:3)",
         "    at com.android.tools.r8.R8.bar(R8.java)",
-        "    <OR #1> at com.android.tools.r8.R8.foo(R8.java)",
         "    ... 42 more");
   }
 
   @Override
   public List<String> retraceVerboseStackTrace() {
     return Arrays.asList(
+        "There are 8 ambiguous stack traces.",
         "com.android.tools.r8.CompilationException: foo[parens](Source:3)",
         "    at com.android.tools.r8.R8.void bar(int,int)(R8.java)",
-        "    <OR #1> at com.android.tools.r8.R8.void foo(int)(R8.java)",
         "    at com.android.tools.r8.R8.void bar(int,int)(R8.java)",
-        "    <OR #1> at com.android.tools.r8.R8.void foo(int)(R8.java)",
         "    at com.android.tools.r8.R8.main(Unknown Source)",
         "Caused by: com.android.tools.r8.CompilationException: foo[parens](Source:3)",
         "    at com.android.tools.r8.R8.void bar(int,int)(R8.java)",
-        "    <OR #1> at com.android.tools.r8.R8.void foo(int)(R8.java)",
+        "    ... 42 more",
+        "< OR >",
+        "com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void bar(int,int)(R8.java)",
+        "    at com.android.tools.r8.R8.void bar(int,int)(R8.java)",
+        "    at com.android.tools.r8.R8.main(Unknown Source)",
+        "Caused by: com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java)",
+        "    ... 42 more",
+        "< OR >",
+        "com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void bar(int,int)(R8.java)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java)",
+        "    at com.android.tools.r8.R8.main(Unknown Source)",
+        "Caused by: com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void bar(int,int)(R8.java)",
+        "    ... 42 more",
+        "< OR >",
+        "com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void bar(int,int)(R8.java)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java)",
+        "    at com.android.tools.r8.R8.main(Unknown Source)",
+        "Caused by: com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java)",
+        "    ... 42 more",
+        "< OR >",
+        "com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java)",
+        "    at com.android.tools.r8.R8.void bar(int,int)(R8.java)",
+        "    at com.android.tools.r8.R8.main(Unknown Source)",
+        "Caused by: com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void bar(int,int)(R8.java)",
+        "    ... 42 more",
+        "< OR >",
+        "com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java)",
+        "    at com.android.tools.r8.R8.void bar(int,int)(R8.java)",
+        "    at com.android.tools.r8.R8.main(Unknown Source)",
+        "Caused by: com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java)",
+        "    ... 42 more",
+        "< OR >",
+        "com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java)",
+        "    at com.android.tools.r8.R8.main(Unknown Source)",
+        "Caused by: com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void bar(int,int)(R8.java)",
+        "    ... 42 more",
+        "< OR >",
+        "com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java)",
+        "    at com.android.tools.r8.R8.main(Unknown Source)",
+        "Caused by: com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java)",
         "    ... 42 more");
   }
 
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousWithSignatureNonVerboseStackTrace.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousWithSignatureNonVerboseStackTrace.java
index dbfe5f8..97f2162 100644
--- a/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousWithSignatureNonVerboseStackTrace.java
+++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousWithSignatureNonVerboseStackTrace.java
@@ -39,12 +39,22 @@
   @Override
   public List<String> retraceVerboseStackTrace() {
     return Arrays.asList(
+        "There are 4 ambiguous stack traces.",
         "java.lang.IndexOutOfBoundsException",
         "\tat java.util.ArrayList.get(ArrayList.java:411)",
         "\tat com.android.tools.r8.Internal.boolean foo(int,int)(Internal.java)",
-        "\t<OR #1> at com.android.tools.r8.Internal.void foo(int)(Internal.java)",
-        "\t<OR #2> at com.android.tools.r8.Internal.void foo(int,boolean)(Internal.java)",
-        "\t<OR #3> at com.android.tools.r8.Internal.void foo(int,int)(Internal.java)");
+        "< OR >",
+        "java.lang.IndexOutOfBoundsException",
+        "\tat java.util.ArrayList.get(ArrayList.java:411)",
+        "\tat com.android.tools.r8.Internal.void foo(int)(Internal.java)",
+        "< OR >",
+        "java.lang.IndexOutOfBoundsException",
+        "\tat java.util.ArrayList.get(ArrayList.java:411)",
+        "\tat com.android.tools.r8.Internal.void foo(int,boolean)(Internal.java)",
+        "< OR >",
+        "java.lang.IndexOutOfBoundsException",
+        "\tat java.util.ArrayList.get(ArrayList.java:411)",
+        "\tat com.android.tools.r8.Internal.void foo(int,int)(Internal.java)");
   }
 
   @Override
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousWithSignatureVerboseStackTrace.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousWithSignatureVerboseStackTrace.java
index 4c39bf2..23991fb 100644
--- a/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousWithSignatureVerboseStackTrace.java
+++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousWithSignatureVerboseStackTrace.java
@@ -39,12 +39,22 @@
   @Override
   public List<String> retraceVerboseStackTrace() {
     return Arrays.asList(
+        "There are 4 ambiguous stack traces.",
         "java.lang.IndexOutOfBoundsException",
         "\tat java.util.ArrayList.get(ArrayList.java:411)",
         "\tat com.android.tools.r8.Internal.boolean foo(int,int)(Internal.java)",
-        "\t<OR #1> at com.android.tools.r8.Internal.void foo(int)(Internal.java)",
-        "\t<OR #2> at com.android.tools.r8.Internal.void foo(int,boolean)(Internal.java)",
-        "\t<OR #3> at com.android.tools.r8.Internal.void foo(int,int)(Internal.java)");
+        "< OR >",
+        "java.lang.IndexOutOfBoundsException",
+        "\tat java.util.ArrayList.get(ArrayList.java:411)",
+        "\tat com.android.tools.r8.Internal.void foo(int)(Internal.java)",
+        "< OR >",
+        "java.lang.IndexOutOfBoundsException",
+        "\tat java.util.ArrayList.get(ArrayList.java:411)",
+        "\tat com.android.tools.r8.Internal.void foo(int,boolean)(Internal.java)",
+        "< OR >",
+        "java.lang.IndexOutOfBoundsException",
+        "\tat java.util.ArrayList.get(ArrayList.java:411)",
+        "\tat com.android.tools.r8.Internal.void foo(int,int)(Internal.java)");
   }
 
   @Override
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/MultipleLinesNoLineNumberStackTrace.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/MultipleLinesNoLineNumberStackTrace.java
index 5638f88..004b7d5 100644
--- a/src/test/java/com/android/tools/r8/retrace/stacktraces/MultipleLinesNoLineNumberStackTrace.java
+++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/MultipleLinesNoLineNumberStackTrace.java
@@ -29,21 +29,21 @@
   @Override
   public List<String> retracedStackTrace() {
     return Arrays.asList(
+        "There are 2 ambiguous stack traces. Use --verbose to have all listed.",
         "Exception in thread \"main\" java.lang.NullPointerException",
-        "\tat com.android.tools.r8.naming.retrace.Main.main(Main.java)",
-        "\t<OR #1> at com.android.tools.r8.naming.retrace.Main.method1(Main.java)",
-        "\t<OR #1> at com.android.tools.r8.naming.retrace.Main.main(Main.java)");
+        "\tat com.android.tools.r8.naming.retrace.Main.main(Main.java)");
   }
 
   @Override
   public List<String> retraceVerboseStackTrace() {
     return Arrays.asList(
+        "There are 2 ambiguous stack traces.",
         "Exception in thread \"main\" java.lang.NullPointerException",
         "\tat com.android.tools.r8.naming.retrace.Main.void main(java.lang.String[])(Main.java)",
-        "\t<OR #1> at com.android.tools.r8.naming.retrace.Main."
-            + "void method1(java.lang.String)(Main.java)",
-        "\t<OR #1> at com.android.tools.r8.naming.retrace.Main."
-            + "void main(java.lang.String[])(Main.java)");
+        "< OR >",
+        "Exception in thread \"main\" java.lang.NullPointerException",
+        "\tat com.android.tools.r8.naming.retrace.Main.void method1(java.lang.String)(Main.java)",
+        "\tat com.android.tools.r8.naming.retrace.Main.void main(java.lang.String[])(Main.java)");
   }
 
   @Override
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/NoObfuscatedLineNumberWithOverrideTest.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/NoObfuscatedLineNumberWithOverrideTest.java
index b8c106b..858c06b 100644
--- a/src/test/java/com/android/tools/r8/retrace/stacktraces/NoObfuscatedLineNumberWithOverrideTest.java
+++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/NoObfuscatedLineNumberWithOverrideTest.java
@@ -35,28 +35,49 @@
   @Override
   public List<String> retracedStackTrace() {
     return Arrays.asList(
+        "There are 4 ambiguous stack traces. Use --verbose to have all listed.",
         "Exception in thread \"main\" java.lang.NullPointerException",
         "\tat com.android.tools.r8.naming.retrace.Main.main(Main.java:3)",
         "\tat com.android.tools.r8.naming.retrace.Main.overload1(Main.java:7)",
-        "\t<OR #1> at com.android.tools.r8.naming.retrace.Main.overload2(Main.java:11)",
         "\tat com.android.tools.r8.naming.retrace.Main.definedOverload(Main.java:7)",
-        "\t<OR #1> at com.android.tools.r8.naming.retrace.Main.definedOverload(Main.java:11)",
         "\tat com.android.tools.r8.naming.retrace.Main.mainPC(Main.java:42)");
   }
 
   @Override
   public List<String> retraceVerboseStackTrace() {
     return Arrays.asList(
+        "There are 4 ambiguous stack traces.",
         "Exception in thread \"main\" java.lang.NullPointerException",
         "\tat com.android.tools.r8.naming.retrace.Main.void main(java.lang.String)(Main.java:3)",
         "\tat com.android.tools.r8.naming.retrace.Main.void overload1()(Main.java:7)",
-        "\t<OR #1> at com.android.tools.r8.naming.retrace.Main."
-            + "void overload2(java.lang.String)(Main.java:11)",
         "\tat com.android.tools.r8.naming.retrace.Main.void definedOverload()(Main.java:7)",
-        "\t<OR #1> at com.android.tools.r8.naming.retrace.Main."
-            + "void definedOverload(java.lang.String)(Main.java:11)",
-        "\tat com.android.tools.r8.naming.retrace.Main."
-            + "void mainPC(java.lang.String[])(Main.java:42)");
+        "\tat com.android.tools.r8.naming.retrace.Main.void"
+            + " mainPC(java.lang.String[])(Main.java:42)",
+        "< OR >",
+        "Exception in thread \"main\" java.lang.NullPointerException",
+        "\tat com.android.tools.r8.naming.retrace.Main.void main(java.lang.String)(Main.java:3)",
+        "\tat com.android.tools.r8.naming.retrace.Main.void overload1()(Main.java:7)",
+        "\tat com.android.tools.r8.naming.retrace.Main.void"
+            + " definedOverload(java.lang.String)(Main.java:11)",
+        "\tat com.android.tools.r8.naming.retrace.Main.void"
+            + " mainPC(java.lang.String[])(Main.java:42)",
+        "< OR >",
+        "Exception in thread \"main\" java.lang.NullPointerException",
+        "\tat com.android.tools.r8.naming.retrace.Main.void main(java.lang.String)(Main.java:3)",
+        "\tat com.android.tools.r8.naming.retrace.Main.void"
+            + " overload2(java.lang.String)(Main.java:11)",
+        "\tat com.android.tools.r8.naming.retrace.Main.void definedOverload()(Main.java:7)",
+        "\tat com.android.tools.r8.naming.retrace.Main.void"
+            + " mainPC(java.lang.String[])(Main.java:42)",
+        "< OR >",
+        "Exception in thread \"main\" java.lang.NullPointerException",
+        "\tat com.android.tools.r8.naming.retrace.Main.void main(java.lang.String)(Main.java:3)",
+        "\tat com.android.tools.r8.naming.retrace.Main.void"
+            + " overload2(java.lang.String)(Main.java:11)",
+        "\tat com.android.tools.r8.naming.retrace.Main.void"
+            + " definedOverload(java.lang.String)(Main.java:11)",
+        "\tat com.android.tools.r8.naming.retrace.Main.void"
+            + " mainPC(java.lang.String[])(Main.java:42)");
   }
 
   @Override
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/OverloadSameLineTest.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/OverloadSameLineTest.java
index ccd73f3..c5fe164 100644
--- a/src/test/java/com/android/tools/r8/retrace/stacktraces/OverloadSameLineTest.java
+++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/OverloadSameLineTest.java
@@ -29,20 +29,24 @@
   @Override
   public List<String> retracedStackTrace() {
     return Arrays.asList(
+        "There are 3 ambiguous stack traces. Use --verbose to have all listed.",
         "Exception in thread \"main\" java.lang.NullPointerException",
-        "\tat com.android.tools.r8.naming.retrace.Main.overload(Main.java:7)",
-        "\t<OR #1> at com.android.tools.r8.naming.retrace.Main.overload(Main.java:15)",
-        "\t<OR #2> at com.android.tools.r8.naming.retrace.Main.overload(Main.java:13)");
+        "\tat com.android.tools.r8.naming.retrace.Main.overload(Main.java:7)");
   }
 
   @Override
   public List<String> retraceVerboseStackTrace() {
     return Arrays.asList(
+        "There are 3 ambiguous stack traces.",
         "Exception in thread \"main\" java.lang.NullPointerException",
         "\tat com.android.tools.r8.naming.retrace.Main.void overload()(Main.java:7)",
-        "\t<OR #1> at com.android.tools.r8.naming.retrace.Main.void overload(int)(Main.java:15)",
-        "\t<OR #2> at com.android.tools.r8.naming.retrace.Main."
-            + "void overload(java.lang.String)(Main.java:13)");
+        "< OR >",
+        "Exception in thread \"main\" java.lang.NullPointerException",
+        "\tat com.android.tools.r8.naming.retrace.Main.void overload(int)(Main.java:15)",
+        "< OR >",
+        "Exception in thread \"main\" java.lang.NullPointerException",
+        "\tat com.android.tools.r8.naming.retrace.Main.void"
+            + " overload(java.lang.String)(Main.java:13)");
   }
 
   @Override
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/SingleLineNoLineNumberStackTrace.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/SingleLineNoLineNumberStackTrace.java
index 770b2f8..120cd8e 100644
--- a/src/test/java/com/android/tools/r8/retrace/stacktraces/SingleLineNoLineNumberStackTrace.java
+++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/SingleLineNoLineNumberStackTrace.java
@@ -36,33 +36,45 @@
   @Override
   public List<String> retracedStackTrace() {
     return Arrays.asList(
+        "There are 2 ambiguous stack traces. Use --verbose to have all listed.",
         "Exception in thread \"main\" java.lang.NullPointerException",
         "\tat com.android.tools.r8.naming.retrace.Main.method1(Main.java:42)",
         "\tat com.android.tools.r8.naming.retrace.Main.main(Main.java:28)",
         "\tat com.android.tools.r8.naming.retrace.Main.method2(Main.java:42)",
         "\tat com.android.tools.r8.naming.retrace.Main.main2(Main.java:29)",
         "\tat com.android.tools.r8.naming.retrace.Main.main3(Main.java:30)",
-        "\t<OR #1> at com.android.tools.r8.naming.retrace.Main.method3(Main.java:72)",
         "\tat com.android.tools.r8.naming.retrace.Main.main4(Main.java:153)");
   }
 
   @Override
   public List<String> retraceVerboseStackTrace() {
     return Arrays.asList(
+        "There are 2 ambiguous stack traces.",
         "Exception in thread \"main\" java.lang.NullPointerException",
-        "\tat com.android.tools.r8.naming.retrace.Main."
-            + "void method1(java.lang.String)(Main.java:42)",
+        "\tat com.android.tools.r8.naming.retrace.Main.void"
+            + " method1(java.lang.String)(Main.java:42)",
         "\tat com.android.tools.r8.naming.retrace.Main.void main(java.lang.String[])(Main.java:28)",
-        "\tat com.android.tools.r8.naming.retrace.Main."
-            + "void method2(java.lang.String)(Main.java:42)",
-        "\tat com.android.tools.r8.naming.retrace.Main."
-            + "void main2(java.lang.String[])(Main.java:29)",
-        "\tat com.android.tools.r8.naming.retrace.Main."
-            + "void main3(java.lang.String[])(Main.java:30)",
-        "\t<OR #1> at com.android.tools.r8.naming.retrace.Main."
-            + "void method3(java.lang.String)(Main.java:72)",
-        "\tat com.android.tools.r8.naming.retrace.Main."
-            + "void main4(java.lang.String[])(Main.java:153)");
+        "\tat com.android.tools.r8.naming.retrace.Main.void"
+            + " method2(java.lang.String)(Main.java:42)",
+        "\tat com.android.tools.r8.naming.retrace.Main.void"
+            + " main2(java.lang.String[])(Main.java:29)",
+        "\tat com.android.tools.r8.naming.retrace.Main.void"
+            + " main3(java.lang.String[])(Main.java:30)",
+        "\tat com.android.tools.r8.naming.retrace.Main.void"
+            + " main4(java.lang.String[])(Main.java:153)",
+        "< OR >",
+        "Exception in thread \"main\" java.lang.NullPointerException",
+        "\tat com.android.tools.r8.naming.retrace.Main.void"
+            + " method1(java.lang.String)(Main.java:42)",
+        "\tat com.android.tools.r8.naming.retrace.Main.void main(java.lang.String[])(Main.java:28)",
+        "\tat com.android.tools.r8.naming.retrace.Main.void"
+            + " method2(java.lang.String)(Main.java:42)",
+        "\tat com.android.tools.r8.naming.retrace.Main.void"
+            + " main2(java.lang.String[])(Main.java:29)",
+        "\tat com.android.tools.r8.naming.retrace.Main.void"
+            + " method3(java.lang.String)(Main.java:72)",
+        "\tat com.android.tools.r8.naming.retrace.Main.void"
+            + " main4(java.lang.String[])(Main.java:153)");
   }
 
   @Override
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/UnknownSourceStackTrace.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/UnknownSourceStackTrace.java
index e6481ac..2f946f8 100644
--- a/src/test/java/com/android/tools/r8/retrace/stacktraces/UnknownSourceStackTrace.java
+++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/UnknownSourceStackTrace.java
@@ -25,30 +25,82 @@
   @Override
   public List<String> retracedStackTrace() {
     return Arrays.asList(
+        "There are 8 ambiguous stack traces. Use --verbose to have all listed.",
         "com.android.tools.r8.CompilationException: foo[parens](Source:3)",
         "    at com.android.tools.r8.R8.bar(R8.java)",
-        "    <OR #1> at com.android.tools.r8.R8.foo(R8.java)",
         "    at com.android.tools.r8.R8.bar(R8.java)",
-        "    <OR #1> at com.android.tools.r8.R8.foo(R8.java)",
         "    at com.android.tools.r8.R8.main(Unknown Source)",
         "Caused by: com.android.tools.r8.CompilationException: foo[parens](Source:3)",
         "    at com.android.tools.r8.R8.bar(R8.java)",
-        "    <OR #1> at com.android.tools.r8.R8.foo(R8.java)",
         "    ... 42 more");
   }
 
   @Override
   public List<String> retraceVerboseStackTrace() {
     return Arrays.asList(
+        "There are 8 ambiguous stack traces.",
         "com.android.tools.r8.CompilationException: foo[parens](Source:3)",
         "    at com.android.tools.r8.R8.void bar(int,int)(R8.java)",
-        "    <OR #1> at com.android.tools.r8.R8.void foo(int)(R8.java)",
         "    at com.android.tools.r8.R8.void bar(int,int)(R8.java)",
-        "    <OR #1> at com.android.tools.r8.R8.void foo(int)(R8.java)",
         "    at com.android.tools.r8.R8.main(Unknown Source)",
         "Caused by: com.android.tools.r8.CompilationException: foo[parens](Source:3)",
         "    at com.android.tools.r8.R8.void bar(int,int)(R8.java)",
-        "    <OR #1> at com.android.tools.r8.R8.void foo(int)(R8.java)",
+        "    ... 42 more",
+        "< OR >",
+        "com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void bar(int,int)(R8.java)",
+        "    at com.android.tools.r8.R8.void bar(int,int)(R8.java)",
+        "    at com.android.tools.r8.R8.main(Unknown Source)",
+        "Caused by: com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java)",
+        "    ... 42 more",
+        "< OR >",
+        "com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void bar(int,int)(R8.java)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java)",
+        "    at com.android.tools.r8.R8.main(Unknown Source)",
+        "Caused by: com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void bar(int,int)(R8.java)",
+        "    ... 42 more",
+        "< OR >",
+        "com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void bar(int,int)(R8.java)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java)",
+        "    at com.android.tools.r8.R8.main(Unknown Source)",
+        "Caused by: com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java)",
+        "    ... 42 more",
+        "< OR >",
+        "com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java)",
+        "    at com.android.tools.r8.R8.void bar(int,int)(R8.java)",
+        "    at com.android.tools.r8.R8.main(Unknown Source)",
+        "Caused by: com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void bar(int,int)(R8.java)",
+        "    ... 42 more",
+        "< OR >",
+        "com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java)",
+        "    at com.android.tools.r8.R8.void bar(int,int)(R8.java)",
+        "    at com.android.tools.r8.R8.main(Unknown Source)",
+        "Caused by: com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java)",
+        "    ... 42 more",
+        "< OR >",
+        "com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java)",
+        "    at com.android.tools.r8.R8.main(Unknown Source)",
+        "Caused by: com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void bar(int,int)(R8.java)",
+        "    ... 42 more",
+        "< OR >",
+        "com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java)",
+        "    at com.android.tools.r8.R8.main(Unknown Source)",
+        "Caused by: com.android.tools.r8.CompilationException: foo[parens](Source:3)",
+        "    at com.android.tools.r8.R8.void foo(int)(R8.java)",
         "    ... 42 more");
   }