Extend TraversalContinuation$Continue with result value

Change-Id: I8217d0dced17bab0de58b425087fd7ef2ad5e170
diff --git a/src/main/java/com/android/tools/r8/androidapi/AndroidApiClass.java b/src/main/java/com/android/tools/r8/androidapi/AndroidApiClass.java
index 977a836..2477240 100644
--- a/src/main/java/com/android/tools/r8/androidapi/AndroidApiClass.java
+++ b/src/main/java/com/android/tools/r8/androidapi/AndroidApiClass.java
@@ -30,28 +30,28 @@
 
   public abstract int getMemberCount();
 
-  public TraversalContinuation<?> visitFields(
-      BiFunction<FieldReference, AndroidApiLevel, TraversalContinuation<?>> visitor) {
+  public TraversalContinuation<?, ?> visitFields(
+      BiFunction<FieldReference, AndroidApiLevel, TraversalContinuation<?, ?>> visitor) {
     return visitFields(visitor, classReference, 1);
   }
 
-  public TraversalContinuation<?> visitMethods(
-      BiFunction<MethodReference, AndroidApiLevel, TraversalContinuation<?>> visitor) {
+  public TraversalContinuation<?, ?> visitMethods(
+      BiFunction<MethodReference, AndroidApiLevel, TraversalContinuation<?, ?>> visitor) {
     return visitMethods(visitor, classReference, 1);
   }
 
-  protected abstract TraversalContinuation<?> visitFields(
-      BiFunction<FieldReference, AndroidApiLevel, TraversalContinuation<?>> visitor,
+  protected abstract TraversalContinuation<?, ?> visitFields(
+      BiFunction<FieldReference, AndroidApiLevel, TraversalContinuation<?, ?>> visitor,
       ClassReference holder,
       int minApiClass);
 
-  protected abstract TraversalContinuation<?> visitMethods(
-      BiFunction<MethodReference, AndroidApiLevel, TraversalContinuation<?>> visitor,
+  protected abstract TraversalContinuation<?, ?> visitMethods(
+      BiFunction<MethodReference, AndroidApiLevel, TraversalContinuation<?, ?>> visitor,
       ClassReference holder,
       int minApiClass);
 
-  protected TraversalContinuation<?> visitField(
-      BiFunction<FieldReference, AndroidApiLevel, TraversalContinuation<?>> visitor,
+  protected TraversalContinuation<?, ?> visitField(
+      BiFunction<FieldReference, AndroidApiLevel, TraversalContinuation<?, ?>> visitor,
       ClassReference holder,
       int minApiClass,
       int minApiField,
@@ -62,8 +62,8 @@
         getAndroidApiLevel(Integer.max(minApiClass, minApiField)));
   }
 
-  protected TraversalContinuation<?> visitMethod(
-      BiFunction<MethodReference, AndroidApiLevel, TraversalContinuation<?>> visitor,
+  protected TraversalContinuation<?, ?> visitMethod(
+      BiFunction<MethodReference, AndroidApiLevel, TraversalContinuation<?, ?>> visitor,
       ClassReference holder,
       int minApiClass,
       int minApiMethod,
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java b/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java
index f5cb1a3..4c28ff0 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java
@@ -148,12 +148,12 @@
   }
 
   /** Primitive traversal over all (non-interface) superclasses of a given type. */
-  public <T> TraversalContinuation<T> traverseSuperClasses(
-      DexClass clazz, TriFunction<DexType, DexClass, DexClass, TraversalContinuation<T>> fn) {
+  public <B> TraversalContinuation<B, ?> traverseSuperClasses(
+      DexClass clazz, TriFunction<DexType, DexClass, DexClass, TraversalContinuation<B, ?>> fn) {
     DexClass currentClass = clazz;
     while (currentClass != null && currentClass.getSuperType() != null) {
       DexClass superclass = definitionFor(currentClass.getSuperType());
-      TraversalContinuation<T> stepResult =
+      TraversalContinuation<B, ?> stepResult =
           fn.apply(currentClass.getSuperType(), superclass, currentClass);
       if (stepResult.shouldBreak()) {
         return stepResult;
@@ -170,8 +170,9 @@
    * given type is *not* visited. The function indicates if traversal should continue or break. The
    * result of the traversal is BREAK iff the function returned BREAK.
    */
-  public TraversalContinuation<?> traverseSuperTypes(
-      final DexClass clazz, TriFunction<DexType, DexClass, Boolean, TraversalContinuation<?>> fn) {
+  public TraversalContinuation<?, ?> traverseSuperTypes(
+      final DexClass clazz,
+      TriFunction<DexType, DexClass, Boolean, TraversalContinuation<?, ?>> fn) {
     // We do an initial zero-allocation pass over the class super chain as it does not require a
     // worklist/seen-set. Only if the traversal is not aborted and there actually are interfaces,
     // do we continue traversal over the interface types. This is assuming that the second pass
@@ -184,7 +185,8 @@
         if (currentClass.superType == null) {
           break;
         }
-        TraversalContinuation<?> stepResult = fn.apply(currentClass.superType, currentClass, false);
+        TraversalContinuation<?, ?> stepResult =
+            fn.apply(currentClass.superType, currentClass, false);
         if (stepResult.shouldBreak()) {
           return stepResult;
         }
@@ -203,7 +205,7 @@
       while (currentClass != null) {
         for (DexType iface : currentClass.interfaces.values) {
           if (seen.add(iface)) {
-            TraversalContinuation<?> stepResult = fn.apply(iface, currentClass, true);
+            TraversalContinuation<?, ?> stepResult = fn.apply(iface, currentClass, true);
             if (stepResult.shouldBreak()) {
               return stepResult;
             }
@@ -223,7 +225,7 @@
       if (definition != null) {
         for (DexType iface : definition.interfaces.values) {
           if (seen.add(iface)) {
-            TraversalContinuation<?> stepResult = fn.apply(iface, definition, true);
+            TraversalContinuation<?, ?> stepResult = fn.apply(iface, definition, true);
             if (stepResult.shouldBreak()) {
               return stepResult;
             }
@@ -317,7 +319,7 @@
     if (superclass.getType() == dexItemFactory().objectType) {
       return true;
     }
-    TraversalContinuation<Boolean> result =
+    TraversalContinuation<Boolean, ?> result =
         traverseSuperClasses(
             subclass,
             (currentType, currentClass, immediateSubclass) -> {
diff --git a/src/main/java/com/android/tools/r8/graph/DexClass.java b/src/main/java/com/android/tools/r8/graph/DexClass.java
index e320709..4fac278 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClass.java
@@ -356,8 +356,8 @@
     staticFields(predicate).forEach(consumer);
   }
 
-  public TraversalContinuation<?> traverseFields(
-      Function<DexEncodedField, TraversalContinuation<?>> fn) {
+  public TraversalContinuation<?, ?> traverseFields(
+      Function<DexEncodedField, TraversalContinuation<?, ?>> fn) {
     for (DexEncodedField field : fields()) {
       if (fn.apply(field).shouldBreak()) {
         return TraversalContinuation.doBreak();
diff --git a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
index 354cc52..5e30d52 100644
--- a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
@@ -353,32 +353,33 @@
     return null;
   }
 
-  public TraversalContinuation<?> traverseProgramMembers(
-      Function<ProgramMember<?, ?>, TraversalContinuation<?>> fn) {
-    TraversalContinuation<?> continuation = traverseProgramFields(fn);
+  public TraversalContinuation<?, ?> traverseProgramMembers(
+      Function<ProgramMember<?, ?>, TraversalContinuation<?, ?>> fn) {
+    TraversalContinuation<?, ?> continuation = traverseProgramFields(fn);
     if (continuation.shouldContinue()) {
       return traverseProgramMethods(fn);
     }
     return TraversalContinuation.doBreak();
   }
 
-  public TraversalContinuation<?> traverseProgramFields(
-      Function<? super ProgramField, TraversalContinuation<?>> fn) {
+  public TraversalContinuation<?, ?> traverseProgramFields(
+      Function<? super ProgramField, TraversalContinuation<?, ?>> fn) {
     return traverseFields(field -> fn.apply(new ProgramField(this, field)));
   }
 
-  public TraversalContinuation<?> traverseProgramMethods(
-      Function<? super ProgramMethod, TraversalContinuation<?>> fn) {
+  public TraversalContinuation<?, ?> traverseProgramMethods(
+      Function<? super ProgramMethod, TraversalContinuation<?, ?>> fn) {
     return getMethodCollection().traverse(method -> fn.apply(new ProgramMethod(this, method)));
   }
 
-  public TraversalContinuation<?> traverseProgramInstanceInitializers(
-      Function<ProgramMethod, TraversalContinuation<?>> fn) {
+  public TraversalContinuation<?, ?> traverseProgramInstanceInitializers(
+      Function<ProgramMethod, TraversalContinuation<?, ?>> fn) {
     return traverseProgramMethods(fn, DexEncodedMethod::isInstanceInitializer);
   }
 
-  public TraversalContinuation<?> traverseProgramMethods(
-      Function<ProgramMethod, TraversalContinuation<?>> fn, Predicate<DexEncodedMethod> predicate) {
+  public TraversalContinuation<?, ?> traverseProgramMethods(
+      Function<ProgramMethod, TraversalContinuation<?, ?>> fn,
+      Predicate<DexEncodedMethod> predicate) {
     return getMethodCollection()
         .traverse(
             method ->
diff --git a/src/main/java/com/android/tools/r8/graph/MethodArrayBacking.java b/src/main/java/com/android/tools/r8/graph/MethodArrayBacking.java
index d00dca3..24c8b0a 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodArrayBacking.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodArrayBacking.java
@@ -71,15 +71,15 @@
   }
 
   @Override
-  TraversalContinuation<?> traverse(Function<DexEncodedMethod, TraversalContinuation<?>> fn) {
+  TraversalContinuation<?, ?> traverse(Function<DexEncodedMethod, TraversalContinuation<?, ?>> fn) {
     for (DexEncodedMethod method : directMethods) {
-      TraversalContinuation<?> stepResult = fn.apply(method);
+      TraversalContinuation<?, ?> stepResult = fn.apply(method);
       if (stepResult.shouldBreak()) {
         return stepResult;
       }
     }
     for (DexEncodedMethod method : virtualMethods) {
-      TraversalContinuation<?> stepResult = fn.apply(method);
+      TraversalContinuation<?, ?> stepResult = fn.apply(method);
       if (stepResult.shouldBreak()) {
         return stepResult;
       }
diff --git a/src/main/java/com/android/tools/r8/graph/MethodCollection.java b/src/main/java/com/android/tools/r8/graph/MethodCollection.java
index 1cb7d71..a31e669 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodCollection.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodCollection.java
@@ -117,8 +117,8 @@
     return backing.size();
   }
 
-  public TraversalContinuation<?> traverse(
-      Function<DexEncodedMethod, TraversalContinuation<?>> fn) {
+  public TraversalContinuation<?, ?> traverse(
+      Function<DexEncodedMethod, TraversalContinuation<?, ?>> fn) {
     return backing.traverse(fn);
   }
 
diff --git a/src/main/java/com/android/tools/r8/graph/MethodCollectionBacking.java b/src/main/java/com/android/tools/r8/graph/MethodCollectionBacking.java
index 8eacebe..b270516 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodCollectionBacking.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodCollectionBacking.java
@@ -38,8 +38,8 @@
 
   // Traversal methods.
 
-  abstract TraversalContinuation<?> traverse(
-      Function<DexEncodedMethod, TraversalContinuation<?>> fn);
+  abstract TraversalContinuation<?, ?> traverse(
+      Function<DexEncodedMethod, TraversalContinuation<?, ?>> fn);
 
   /**
    * Return a new backing mapped by the given function.
diff --git a/src/main/java/com/android/tools/r8/graph/MethodCollectionConcurrencyChecked.java b/src/main/java/com/android/tools/r8/graph/MethodCollectionConcurrencyChecked.java
index 17bbae3..0889c63 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodCollectionConcurrencyChecked.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodCollectionConcurrencyChecked.java
@@ -84,10 +84,10 @@
   }
 
   @Override
-  public TraversalContinuation<?> traverse(
-      Function<DexEncodedMethod, TraversalContinuation<?>> fn) {
+  public TraversalContinuation<?, ?> traverse(
+      Function<DexEncodedMethod, TraversalContinuation<?, ?>> fn) {
     assert assertReadEntry();
-    TraversalContinuation<?> result = super.traverse(fn);
+    TraversalContinuation<?, ?> result = super.traverse(fn);
     assert assertReadExit();
     return result;
   }
diff --git a/src/main/java/com/android/tools/r8/graph/MethodMapBacking.java b/src/main/java/com/android/tools/r8/graph/MethodMapBacking.java
index eb5b9be..0e838b9 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodMapBacking.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodMapBacking.java
@@ -100,9 +100,9 @@
   }
 
   @Override
-  TraversalContinuation<?> traverse(Function<DexEncodedMethod, TraversalContinuation<?>> fn) {
+  TraversalContinuation<?, ?> traverse(Function<DexEncodedMethod, TraversalContinuation<?, ?>> fn) {
     for (Entry<DexMethodSignature, DexEncodedMethod> entry : methodMap.entrySet()) {
-      TraversalContinuation<?> result = fn.apply(entry.getValue());
+      TraversalContinuation<?, ?> result = fn.apply(entry.getValue());
       if (result.shouldBreak()) {
         return result;
       }
diff --git a/src/main/java/com/android/tools/r8/graph/ObjectAllocationInfoCollection.java b/src/main/java/com/android/tools/r8/graph/ObjectAllocationInfoCollection.java
index ef1de89..300bca7 100644
--- a/src/main/java/com/android/tools/r8/graph/ObjectAllocationInfoCollection.java
+++ b/src/main/java/com/android/tools/r8/graph/ObjectAllocationInfoCollection.java
@@ -34,10 +34,10 @@
 
   void forEachInstantiatedLambdaInterfaces(Consumer<DexType> consumer);
 
-  TraversalContinuation<?> traverseInstantiatedSubtypes(
+  TraversalContinuation<?, ?> traverseInstantiatedSubtypes(
       DexType type,
-      Function<DexProgramClass, TraversalContinuation<?>> onClass,
-      Function<LambdaDescriptor, TraversalContinuation<?>> onLambda,
+      Function<DexProgramClass, TraversalContinuation<?, ?>> onClass,
+      Function<LambdaDescriptor, TraversalContinuation<?, ?>> onLambda,
       AppInfo appInfo);
 
   ObjectAllocationInfoCollection rewrittenWithLens(
diff --git a/src/main/java/com/android/tools/r8/graph/ObjectAllocationInfoCollectionImpl.java b/src/main/java/com/android/tools/r8/graph/ObjectAllocationInfoCollectionImpl.java
index 6b31147..1aa8117 100644
--- a/src/main/java/com/android/tools/r8/graph/ObjectAllocationInfoCollectionImpl.java
+++ b/src/main/java/com/android/tools/r8/graph/ObjectAllocationInfoCollectionImpl.java
@@ -184,10 +184,10 @@
   }
 
   @Override
-  public TraversalContinuation<?> traverseInstantiatedSubtypes(
+  public TraversalContinuation<?, ?> traverseInstantiatedSubtypes(
       DexType type,
-      Function<DexProgramClass, TraversalContinuation<?>> onClass,
-      Function<LambdaDescriptor, TraversalContinuation<?>> onLambda,
+      Function<DexProgramClass, TraversalContinuation<?, ?>> onClass,
+      Function<LambdaDescriptor, TraversalContinuation<?, ?>> onLambda,
       AppInfo appInfo) {
     WorkList<DexClass> worklist = WorkList.newIdentityWorkList();
     if (type == appInfo.dexItemFactory().objectType) {
diff --git a/src/main/java/com/android/tools/r8/graph/UseRegistry.java b/src/main/java/com/android/tools/r8/graph/UseRegistry.java
index 919d940..6e08e6c 100644
--- a/src/main/java/com/android/tools/r8/graph/UseRegistry.java
+++ b/src/main/java/com/android/tools/r8/graph/UseRegistry.java
@@ -15,7 +15,7 @@
   private final AppView<?> appView;
   private final T context;
 
-  private TraversalContinuation<?> continuation = TraversalContinuation.doContinue();
+  private TraversalContinuation<?, ?> continuation = TraversalContinuation.doContinue();
 
   public enum MethodHandleUse {
     ARGUMENT_TO_LAMBDA_METAFACTORY,
@@ -54,7 +54,7 @@
     return context.asMethod();
   }
 
-  public TraversalContinuation<?> getTraversalContinuation() {
+  public TraversalContinuation<?, ?> getTraversalContinuation() {
     return continuation;
   }
 
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/RespectPackageBoundaries.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/RespectPackageBoundaries.java
index 1573dde..5bc0f58 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/RespectPackageBoundaries.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/RespectPackageBoundaries.java
@@ -65,7 +65,7 @@
     // Check that all accesses from [clazz] to classes or members from the current package of
     // [clazz] will continue to work. This is guaranteed if the methods of [clazz] do not access
     // any private or protected classes or members from the current package of [clazz].
-    TraversalContinuation<?> result =
+    TraversalContinuation<?, ?> result =
         clazz.traverseProgramMethods(
             method -> {
               boolean foundIllegalAccess =
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/apimodel/ApiInvokeOutlinerDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/apimodel/ApiInvokeOutlinerDesugaring.java
index 06fadd9..0ef825c 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/apimodel/ApiInvokeOutlinerDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/apimodel/ApiInvokeOutlinerDesugaring.java
@@ -127,7 +127,7 @@
     if (result != null) {
       return result;
     }
-    TraversalContinuation<DexEncodedMethod> traversalResult =
+    TraversalContinuation<DexEncodedMethod, ?> traversalResult =
         appView
             .appInfoForDesugaring()
             .traverseSuperClasses(
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/SimpleDominatingEffectAnalysis.java b/src/main/java/com/android/tools/r8/ir/optimize/SimpleDominatingEffectAnalysis.java
index 572b153..75e94fb 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/SimpleDominatingEffectAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/SimpleDominatingEffectAnalysis.java
@@ -249,7 +249,7 @@
     new StatefulDepthFirstSearchWorkList<BasicBlock, ResultStateWithPartialBlocks>() {
 
       @Override
-      protected TraversalContinuation<?> process(
+      protected TraversalContinuation<?, ?> process(
           DFSNodeWithState<BasicBlock, ResultStateWithPartialBlocks> node,
           Function<BasicBlock, DFSNodeWithState<BasicBlock, ResultStateWithPartialBlocks>>
               childNodeConsumer) {
@@ -285,7 +285,7 @@
       }
 
       @Override
-      protected TraversalContinuation<?> joiner(
+      protected TraversalContinuation<?, ?> joiner(
           DFSNodeWithState<BasicBlock, ResultStateWithPartialBlocks> node,
           List<DFSNodeWithState<BasicBlock, ResultStateWithPartialBlocks>> childNodes) {
         ResultStateWithPartialBlocks resultState = node.getState();
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardClassNameList.java b/src/main/java/com/android/tools/r8/shaking/ProguardClassNameList.java
index ffc2149..cc5d00b 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardClassNameList.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardClassNameList.java
@@ -114,11 +114,11 @@
         });
   }
 
-  public abstract TraversalContinuation<?> traverseTypeMatchers(
-      Function<ProguardTypeMatcher, TraversalContinuation<?>> fn);
+  public abstract TraversalContinuation<?, ?> traverseTypeMatchers(
+      Function<ProguardTypeMatcher, TraversalContinuation<?, ?>> fn);
 
-  public final TraversalContinuation<?> traverseTypeMatchers(
-      Function<ProguardTypeMatcher, TraversalContinuation<?>> fn,
+  public final TraversalContinuation<?, ?> traverseTypeMatchers(
+      Function<ProguardTypeMatcher, TraversalContinuation<?, ?>> fn,
       Predicate<ProguardTypeMatcher> predicate) {
     return traverseTypeMatchers(
         matcher -> {
@@ -168,8 +168,8 @@
     }
 
     @Override
-    public TraversalContinuation<?> traverseTypeMatchers(
-        Function<ProguardTypeMatcher, TraversalContinuation<?>> fn) {
+    public TraversalContinuation<?, ?> traverseTypeMatchers(
+        Function<ProguardTypeMatcher, TraversalContinuation<?, ?>> fn) {
       return TraversalContinuation.doContinue();
     }
   }
@@ -236,8 +236,8 @@
     }
 
     @Override
-    public TraversalContinuation<?> traverseTypeMatchers(
-        Function<ProguardTypeMatcher, TraversalContinuation<?>> fn) {
+    public TraversalContinuation<?, ?> traverseTypeMatchers(
+        Function<ProguardTypeMatcher, TraversalContinuation<?, ?>> fn) {
       return fn.apply(className);
     }
   }
@@ -320,8 +320,8 @@
     }
 
     @Override
-    public TraversalContinuation<?> traverseTypeMatchers(
-        Function<ProguardTypeMatcher, TraversalContinuation<?>> fn) {
+    public TraversalContinuation<?, ?> traverseTypeMatchers(
+        Function<ProguardTypeMatcher, TraversalContinuation<?, ?>> fn) {
       for (ProguardTypeMatcher matcher : classNames) {
         if (fn.apply(matcher).shouldBreak()) {
           return TraversalContinuation.doBreak();
@@ -416,8 +416,8 @@
     }
 
     @Override
-    public TraversalContinuation<?> traverseTypeMatchers(
-        Function<ProguardTypeMatcher, TraversalContinuation<?>> fn) {
+    public TraversalContinuation<?, ?> traverseTypeMatchers(
+        Function<ProguardTypeMatcher, TraversalContinuation<?, ?>> fn) {
       for (ProguardTypeMatcher matcher : classNames.keySet()) {
         if (fn.apply(matcher).shouldBreak()) {
           return TraversalContinuation.doBreak();
diff --git a/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java b/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
index b10e649..484cd3a 100644
--- a/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
+++ b/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
@@ -1403,7 +1403,7 @@
           dependentMinimumKeepInfo.getUnconditionalMinimumKeepInfoOrDefault(
               MinimumKeepInfoCollection.empty());
       for (DexProgramClass clazz : classesWithCheckDiscardedMembers) {
-        TraversalContinuation<?> continueIfAllMembersMarkedAsCheckDiscarded =
+        TraversalContinuation<?, ?> continueIfAllMembersMarkedAsCheckDiscarded =
             clazz.traverseProgramMembers(
                 member ->
                     TraversalContinuation.continueIf(
diff --git a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
index 6cc5f84..9797f72 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
@@ -417,7 +417,7 @@
     // If there is a constructor in the target, make sure that all source constructors can be
     // inlined.
     if (!Iterables.isEmpty(targetClass.programInstanceInitializers())) {
-      TraversalContinuation<?> result =
+      TraversalContinuation<?, ?> result =
           sourceClass.traverseProgramInstanceInitializers(
               method -> {
                 AbortReason reason = disallowInlining(method, targetClass);
@@ -454,7 +454,7 @@
     // If there is an invoke-special to a default interface method and we are not merging into an
     // interface, then abort, since invoke-special to a virtual class method requires desugaring.
     if (sourceClass.isInterface() && !targetClass.isInterface()) {
-      TraversalContinuation<?> result =
+      TraversalContinuation<?, ?> result =
           sourceClass.traverseProgramMethods(
               method -> {
                 boolean foundInvokeSpecialToDefaultLibraryMethod =
@@ -586,7 +586,7 @@
     // Check that all accesses from [source] to classes or members from the current package of
     // [source] will continue to work. This is guaranteed if the methods of [source] do not access
     // any private or protected classes or members from the current package of [source].
-    TraversalContinuation<?> result =
+    TraversalContinuation<?, ?> result =
         source.traverseProgramMethods(
             method -> {
               boolean foundIllegalAccess =
diff --git a/src/main/java/com/android/tools/r8/utils/DepthFirstSearchWorkListBase.java b/src/main/java/com/android/tools/r8/utils/DepthFirstSearchWorkListBase.java
index 6b5df9b..c9a56da 100644
--- a/src/main/java/com/android/tools/r8/utils/DepthFirstSearchWorkListBase.java
+++ b/src/main/java/com/android/tools/r8/utils/DepthFirstSearchWorkListBase.java
@@ -107,10 +107,10 @@
   abstract T createDfsNode(N node);
 
   /** The initial processing of a node during forward search */
-  abstract TraversalContinuation<?> internalOnVisit(T node);
+  abstract TraversalContinuation<?, ?> internalOnVisit(T node);
 
   /** The joining of state during backtracking of the algorithm. */
-  abstract TraversalContinuation<?> internalOnJoin(T node);
+  abstract TraversalContinuation<?, ?> internalOnJoin(T node);
 
   final T internalEnqueueNode(N value) {
     T dfsNode = createDfsNode(value);
@@ -121,13 +121,13 @@
   }
 
   @SafeVarargs
-  public final TraversalContinuation<?> run(N... roots) {
+  public final TraversalContinuation<?, ?> run(N... roots) {
     return run(Arrays.asList(roots));
   }
 
-  public final TraversalContinuation<?> run(Collection<N> roots) {
+  public final TraversalContinuation<?, ?> run(Collection<N> roots) {
     roots.forEach(this::internalEnqueueNode);
-    TraversalContinuation<?> continuation = TraversalContinuation.doContinue();
+    TraversalContinuation<?, ?> continuation = TraversalContinuation.doContinue();
     while (!workList.isEmpty()) {
       T node = workList.removeLast();
       if (node.isFinished()) {
@@ -161,7 +161,7 @@
      *     before but not finished there is a cycle.
      * @return A value describing if the DFS algorithm should continue to run.
      */
-    protected abstract TraversalContinuation<?> process(
+    protected abstract TraversalContinuation<?, ?> process(
         DFSNode<N> node, Function<N, DFSNode<N>> childNodeConsumer);
 
     @Override
@@ -170,12 +170,12 @@
     }
 
     @Override
-    TraversalContinuation<?> internalOnVisit(DFSNodeImpl<N> node) {
+    TraversalContinuation<?, ?> internalOnVisit(DFSNodeImpl<N> node) {
       return process(node, this::internalEnqueueNode);
     }
 
     @Override
-    protected TraversalContinuation<?> internalOnJoin(DFSNodeImpl<N> node) {
+    protected TraversalContinuation<?, ?> internalOnJoin(DFSNodeImpl<N> node) {
       return TraversalContinuation.doContinue();
     }
   }
@@ -195,7 +195,7 @@
      *     before but not finished there is a cycle.
      * @return A value describing if the DFS algorithm should continue to run.
      */
-    protected abstract TraversalContinuation<?> process(
+    protected abstract TraversalContinuation<?, ?> process(
         DFSNodeWithState<N, S> node, Function<N, DFSNodeWithState<N, S>> childNodeConsumer);
 
     /**
@@ -205,7 +205,7 @@
      * @param childStates The already computed child states.
      * @return A value describing if the DFS algorithm should continue to run.
      */
-    protected abstract TraversalContinuation<?> joiner(
+    protected abstract TraversalContinuation<?, ?> joiner(
         DFSNodeWithState<N, S> node, List<DFSNodeWithState<N, S>> childStates);
 
     @Override
@@ -214,7 +214,7 @@
     }
 
     @Override
-    TraversalContinuation<?> internalOnVisit(DFSNodeWithStateImpl<N, S> node) {
+    TraversalContinuation<?, ?> internalOnVisit(DFSNodeWithStateImpl<N, S> node) {
       List<DFSNodeWithState<N, S>> childStates = new ArrayList<>();
       List<DFSNodeWithState<N, S>> removedChildStates = childStateMap.put(node, childStates);
       assert removedChildStates == null;
@@ -228,7 +228,7 @@
     }
 
     @Override
-    protected TraversalContinuation<?> internalOnJoin(DFSNodeWithStateImpl<N, S> node) {
+    protected TraversalContinuation<?, ?> internalOnJoin(DFSNodeWithStateImpl<N, S> node) {
       return joiner(
           node,
           childStateMap.computeIfAbsent(
diff --git a/src/main/java/com/android/tools/r8/utils/TraversalContinuation.java b/src/main/java/com/android/tools/r8/utils/TraversalContinuation.java
index 5bd242f..19f89d8 100644
--- a/src/main/java/com/android/tools/r8/utils/TraversalContinuation.java
+++ b/src/main/java/com/android/tools/r8/utils/TraversalContinuation.java
@@ -7,34 +7,58 @@
 
 /** Two value continuation value to indicate the continuation of a loop/traversal. */
 /* This class is used for building up api class member traversals. */
-public abstract class TraversalContinuation<T> {
+public abstract class TraversalContinuation<TB, TC> {
 
   public boolean isBreak() {
-    return !isContinue();
+    return false;
+  }
+
+  public Break<TB, TC> asBreak() {
+    return null;
   }
 
   public boolean isContinue() {
     return false;
   }
 
-  public Break<T> asBreak() {
+  public Continue<TB, TC> asContinue() {
     return null;
   }
 
-  public static final class Continue<T> extends TraversalContinuation<T> {
-    private static final TraversalContinuation<?> CONTINUE = new Continue<Object>();
+  public static class Continue<TB, TC> extends TraversalContinuation<TB, TC> {
+    private static final TraversalContinuation<?, ?> CONTINUE_NO_VALUE =
+        new Continue<Object, Object>(null) {
+          @Override
+          public Object getValue() {
+            return new Unreachable(
+                "Invalid attempt at getting a value from a no-value continue state.");
+          }
+        };
 
-    private Continue() {}
+    private final TC value;
+
+    private Continue(TC value) {
+      this.value = value;
+    }
+
+    public TC getValue() {
+      return value;
+    }
 
     @Override
     public boolean isContinue() {
       return true;
     }
+
+    @Override
+    public Continue<TB, TC> asContinue() {
+      return this;
+    }
   }
 
-  public static class Break<T> extends TraversalContinuation<T> {
-    private static final TraversalContinuation<?> BREAK_NO_VALUE =
-        new Break<Object>(null) {
+  public static class Break<TB, TC> extends TraversalContinuation<TB, TC> {
+    private static final TraversalContinuation<?, ?> BREAK_NO_VALUE =
+        new Break<Object, Object>(null) {
           @Override
           public Object getValue() {
             return new Unreachable(
@@ -42,40 +66,50 @@
           }
         };
 
-    private final T value;
+    private final TB value;
 
-    private Break(T value) {
+    private Break(TB value) {
       this.value = value;
     }
 
-    public T getValue() {
+    public TB getValue() {
       return value;
     }
 
     @Override
-    public Break<T> asBreak() {
+    public boolean isBreak() {
+      return true;
+    }
+
+    @Override
+    public Break<TB, TC> asBreak() {
       return this;
     }
   }
 
-  public static TraversalContinuation<?> breakIf(boolean condition) {
+  public static TraversalContinuation<?, ?> breakIf(boolean condition) {
     return continueIf(!condition);
   }
 
-  public static TraversalContinuation<?> continueIf(boolean condition) {
+  public static TraversalContinuation<?, ?> continueIf(boolean condition) {
     return condition ? doContinue() : doBreak();
   }
 
   @SuppressWarnings("unchecked")
-  public static <T> TraversalContinuation<T> doContinue() {
-    return (TraversalContinuation<T>) Continue.CONTINUE;
+  public static <TB, TC> TraversalContinuation<TB, TC> doContinue() {
+    return (TraversalContinuation<TB, TC>) Continue.CONTINUE_NO_VALUE;
   }
 
-  public static TraversalContinuation<?> doBreak() {
-    return Break.BREAK_NO_VALUE;
+  public static <TB, TC> TraversalContinuation<TB, TC> doContinue(TC value) {
+    return new Continue<>(value);
   }
 
-  public static <T> TraversalContinuation<T> doBreak(T value) {
+  @SuppressWarnings("unchecked")
+  public static <TB, TC> TraversalContinuation<TB, TC> doBreak() {
+    return (TraversalContinuation<TB, TC>) Break.BREAK_NO_VALUE;
+  }
+
+  public static <TB, TC> TraversalContinuation<TB, TC> doBreak(TB value) {
     return new Break<>(value);
   }