Extract CPP module pruning logic to a `DiscoveredModulesPruner` interface, replacing `NestedSetExpander`.

PiperOrigin-RevId: 399599280
diff --git a/src/main/java/com/google/devtools/build/lib/actions/ActionExecutionContext.java b/src/main/java/com/google/devtools/build/lib/actions/ActionExecutionContext.java
index 4aac1c1..9a39fc3 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/ActionExecutionContext.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/ActionExecutionContext.java
@@ -22,7 +22,6 @@
 import com.google.devtools.build.lib.bugreport.BugReporter;
 import com.google.devtools.build.lib.clock.Clock;
 import com.google.devtools.build.lib.cmdline.Label;
-import com.google.devtools.build.lib.collect.nestedset.NestedSetExpander;
 import com.google.devtools.build.lib.events.Event;
 import com.google.devtools.build.lib.events.EventKind;
 import com.google.devtools.build.lib.events.ExtendedEventHandler;
@@ -76,7 +75,7 @@
   @Nullable private ImmutableList<FilesetOutputSymlink> outputSymlinks;
 
   private final ArtifactPathResolver pathResolver;
-  private final NestedSetExpander nestedSetExpander;
+  private final DiscoveredModulesPruner discoveredModulesPruner;
   private final FilesystemCalls syscalls;
   private final ThreadStateReceiver threadStateReceiverForMetrics;
 
@@ -96,7 +95,7 @@
       @Nullable Environment env,
       @Nullable FileSystem actionFileSystem,
       @Nullable Object skyframeDepsResult,
-      NestedSetExpander nestedSetExpander,
+      DiscoveredModulesPruner discoveredModulesPruner,
       FilesystemCalls syscalls,
       ThreadStateReceiver threadStateReceiverForMetrics) {
     this.actionInputFileCache = actionInputFileCache;
@@ -118,7 +117,7 @@
     this.pathResolver = ArtifactPathResolver.createPathResolver(actionFileSystem,
         // executor is only ever null in testing.
         executor == null ? null : executor.getExecRoot());
-    this.nestedSetExpander = nestedSetExpander;
+    this.discoveredModulesPruner = discoveredModulesPruner;
     this.syscalls = syscalls;
   }
 
@@ -137,7 +136,7 @@
       ArtifactExpander artifactExpander,
       @Nullable FileSystem actionFileSystem,
       @Nullable Object skyframeDepsResult,
-      NestedSetExpander nestedSetExpander,
+      DiscoveredModulesPruner discoveredModulesPruner,
       FilesystemCalls syscalls,
       ThreadStateReceiver threadStateReceiverForMetrics) {
     this(
@@ -156,7 +155,7 @@
         /*env=*/ null,
         actionFileSystem,
         skyframeDepsResult,
-        nestedSetExpander,
+        discoveredModulesPruner,
         syscalls,
         threadStateReceiverForMetrics);
   }
@@ -174,7 +173,7 @@
       Map<String, String> clientEnv,
       Environment env,
       @Nullable FileSystem actionFileSystem,
-      NestedSetExpander nestedSetExpander,
+      DiscoveredModulesPruner discoveredModulesPruner,
       FilesystemCalls syscalls,
       ThreadStateReceiver threadStateReceiverForMetrics) {
     return new ActionExecutionContext(
@@ -193,7 +192,7 @@
         env,
         actionFileSystem,
         /*skyframeDepsResult=*/ null,
-        nestedSetExpander,
+        discoveredModulesPruner,
         syscalls,
         threadStateReceiverForMetrics);
   }
@@ -378,8 +377,8 @@
     return actionKeyContext;
   }
 
-  public NestedSetExpander getNestedSetExpander() {
-    return nestedSetExpander;
+  public DiscoveredModulesPruner getDiscoveredModulesPruner() {
+    return discoveredModulesPruner;
   }
 
   /**
@@ -428,7 +427,7 @@
         env,
         actionFileSystem,
         skyframeDepsResult,
-        nestedSetExpander,
+        discoveredModulesPruner,
         syscalls,
         threadStateReceiverForMetrics);
   }
@@ -451,7 +450,7 @@
         env,
         actionFileSystem,
         skyframeDepsResult,
-        nestedSetExpander,
+        discoveredModulesPruner,
         syscalls,
         threadStateReceiverForMetrics);
   }
diff --git a/src/main/java/com/google/devtools/build/lib/actions/DiscoveredModulesPruner.java b/src/main/java/com/google/devtools/build/lib/actions/DiscoveredModulesPruner.java
new file mode 100644
index 0000000..9868abb
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/actions/DiscoveredModulesPruner.java
@@ -0,0 +1,83 @@
+// Copyright 2021 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package com.google.devtools.build.lib.actions;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.devtools.build.lib.collect.nestedset.NestedSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Prunes discovered CPP modules by filtering out modules which are already accounted for
+ * transitively.
+ *
+ * <p>{@link #DEFAULT} should be used except when special handling is required for {@link NestedSet}
+ * data backed by remote storage.
+ */
+public interface DiscoveredModulesPruner {
+
+  /**
+   * Computes top-level only modules, i.e. used modules that aren't also dependencies of other used
+   * modules.
+   *
+   * <p>The returned set's iteration order should match that of {@code usedModules}.
+   *
+   * @param action the action requesting module pruning
+   * @param usedModules set of all modules used by {@code action}
+   * @param transitivelyUsedModules map from module to its transitive module dependencies
+   * @return a subset of {@code usedModules} without elements that are already accounted for via
+   *     transitive dependencies
+   * @throws InterruptedException if {@link NestedSet} data in {@code transitivelyUsedModules} is
+   *     backed by remote storage and an interruption occurs during retrieval
+   * @throws LostInputsActionExecutionException if {@link NestedSet} data in {@code
+   *     transitivelyUsedModules} is backed by remote storage and retrieval fails (e.g. due to
+   *     timeout)
+   */
+  Set<Artifact> computeTopLevelModules(
+      Action action,
+      Set<? extends Artifact> usedModules,
+      ImmutableMap<Artifact, NestedSet<Artifact>> transitivelyUsedModules)
+      throws InterruptedException, LostInputsActionExecutionException;
+
+  /** Default implementation of module pruning for in-memory {@link NestedSet} data. */
+  @SuppressWarnings("SetRemoveAll") // See comment on topLevel.remove().
+  DiscoveredModulesPruner DEFAULT =
+      (action, usedModules, transitivelyUsedModules) -> {
+        Set<Artifact> topLevel = new LinkedHashSet<>(usedModules);
+
+        // It is better to iterate over each nested set here instead of creating a joint one and
+        // iterating over it, as this makes use of NestedSet's memoization (each of them has likely
+        // been iterated over before).
+        for (Map.Entry<Artifact, NestedSet<Artifact>> entry : transitivelyUsedModules.entrySet()) {
+          Artifact directDep = entry.getKey();
+          if (!topLevel.contains(directDep)) {
+            // If this module was removed from topLevel because it is a dependency of another
+            // module, we can safely ignore it now as all of its dependants have also been removed.
+            continue;
+          }
+          List<Artifact> transitiveDeps = entry.getValue().toList();
+
+          // Don't use Set.removeAll() here as that iterates over the smaller set (topLevel, which
+          // would support efficient lookup) and looks up in the larger one (transitiveDeps, which
+          // is a linear scan).
+          for (Artifact module : transitiveDeps) {
+            topLevel.remove(module);
+          }
+        }
+
+        return topLevel;
+      };
+}
diff --git a/src/main/java/com/google/devtools/build/lib/collect/nestedset/BUILD b/src/main/java/com/google/devtools/build/lib/collect/nestedset/BUILD
index e538343..d7d4d29 100644
--- a/src/main/java/com/google/devtools/build/lib/collect/nestedset/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/collect/nestedset/BUILD
@@ -17,7 +17,6 @@
         "NestedSet.java",
         "NestedSetBuilder.java",
         "NestedSetCodecWithStore.java",
-        "NestedSetExpander.java",
         "NestedSetStore.java",
         "NestedSetVisitor.java",
         "Order.java",
diff --git a/src/main/java/com/google/devtools/build/lib/collect/nestedset/NestedSetExpander.java b/src/main/java/com/google/devtools/build/lib/collect/nestedset/NestedSetExpander.java
deleted file mode 100644
index 41d2a6e..0000000
--- a/src/main/java/com/google/devtools/build/lib/collect/nestedset/NestedSetExpander.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2020 The Bazel Authors. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//    http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-package com.google.devtools.build.lib.collect.nestedset;
-
-import com.google.common.collect.ImmutableList;
-import com.google.devtools.build.lib.collect.nestedset.NestedSetStore.MissingNestedSetException;
-import java.util.concurrent.TimeoutException;
-
-/**
- * Helper class to expand {@link NestedSet} instances.
- *
- * <p>Implementations besides {@link #DEFAULT} may wish to implement callbacks or timeouts for
- * dealing with expansions of sets from storage.
- */
-public interface NestedSetExpander {
-
-  <T> ImmutableList<T> toListInterruptibly(NestedSet<T> nestedSet)
-      throws InterruptedException, TimeoutException, MissingNestedSetException;
-
-  /** Simply delegates to {@link NestedSet#toListInterruptibly} without doing anything special. */
-  NestedSetExpander DEFAULT = NestedSet::toListInterruptibly;
-}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCompilationContext.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCompilationContext.java
index 45a3aa7..297402a 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCompilationContext.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCompilationContext.java
@@ -21,6 +21,7 @@
 import com.google.common.collect.Iterables;
 import com.google.devtools.build.lib.actions.ActionOwner;
 import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.Artifact.DerivedArtifact;
 import com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact;
 import com.google.devtools.build.lib.actions.MiddlemanFactory;
 import com.google.devtools.build.lib.analysis.AnalysisUtils;
@@ -490,11 +491,11 @@
    * Returns a list of all headers from {@code includes} that are properly declared as well as all
    * the modules that they are in.
    */
-  public Collection<Artifact.DerivedArtifact> computeUsedModules(
+  public Set<DerivedArtifact> computeUsedModules(
       boolean usePic, Set<Artifact> includes, boolean separate) {
-    CompactHashSet<Artifact.DerivedArtifact> modules = CompactHashSet.create();
+    CompactHashSet<DerivedArtifact> modules = CompactHashSet.create();
     for (HeaderInfo transitiveHeaderInfo : headerInfo.getTransitiveCollection()) {
-      Artifact.DerivedArtifact module = transitiveHeaderInfo.getModule(usePic);
+      DerivedArtifact module = transitiveHeaderInfo.getModule(usePic);
       if (module == null) {
         // If we don't have a main module, there is also not going to be a separate module. This is
         // verified when constructing HeaderInfo instances.
@@ -561,11 +562,11 @@
     return directModuleMaps;
   }
 
-  Artifact.DerivedArtifact getHeaderModule(boolean usePic) {
+  DerivedArtifact getHeaderModule(boolean usePic) {
     return headerInfo.getModule(usePic);
   }
 
-  Artifact.DerivedArtifact getSeparateHeaderModule(boolean usePic) {
+  DerivedArtifact getSeparateHeaderModule(boolean usePic) {
     return headerInfo.getSeparateModule(usePic);
   }
 
@@ -1032,8 +1033,8 @@
 
     public Builder setSeparateModuleHdrs(
         Collection<Artifact> headers,
-        Artifact.DerivedArtifact separateModule,
-        Artifact.DerivedArtifact separatePicModule) {
+        DerivedArtifact separateModule,
+        DerivedArtifact separatePicModule) {
       this.headerInfoBuilder.setSeparateModuleHdrs(headers, separateModule, separatePicModule);
       return this;
     }
@@ -1079,7 +1080,7 @@
      *
      * @param headerModule The .pcm file generated for this library.
      */
-    Builder setHeaderModule(Artifact.DerivedArtifact headerModule) {
+    Builder setHeaderModule(DerivedArtifact headerModule) {
       this.headerInfoBuilder.setHeaderModule(headerModule);
       return this;
     }
@@ -1089,7 +1090,7 @@
      *
      * @param picHeaderModule The .pic.pcm file generated for this library.
      */
-    Builder setPicHeaderModule(Artifact.DerivedArtifact picHeaderModule) {
+    Builder setPicHeaderModule(DerivedArtifact picHeaderModule) {
       this.headerInfoBuilder.setPicHeaderModule(picHeaderModule);
       return this;
     }
@@ -1261,9 +1262,9 @@
      * The modules built for this context. If null, then no module is being compiled for this
      * context.
      */
-    private final Artifact.DerivedArtifact headerModule;
+    private final DerivedArtifact headerModule;
 
-    private final Artifact.DerivedArtifact picHeaderModule;
+    private final DerivedArtifact picHeaderModule;
 
     /** All public header files that are compiled into this module. */
     private final ImmutableList<Artifact> modularPublicHeaders;
@@ -1280,8 +1281,8 @@
     /** Headers that can be compiled into a separate, smaller module for performance reasons. */
     private final ImmutableList<Artifact> separateModuleHeaders;
 
-    private final Artifact.DerivedArtifact separateModule;
-    private final Artifact.DerivedArtifact separatePicModule;
+    private final DerivedArtifact separateModule;
+    private final DerivedArtifact separatePicModule;
 
     /** HeaderInfos of direct dependencies of C++ target represented by this context. */
     private final ImmutableList<HeaderInfo> deps;
@@ -1290,14 +1291,14 @@
     private TransitiveHeaderCollection memo = null;
 
     HeaderInfo(
-        Artifact.DerivedArtifact headerModule,
-        Artifact.DerivedArtifact picHeaderModule,
+        DerivedArtifact headerModule,
+        DerivedArtifact picHeaderModule,
         ImmutableList<Artifact> modularPublicHeaders,
         ImmutableList<Artifact> modularPrivateHeaders,
         ImmutableList<Artifact> textualHeaders,
         ImmutableList<Artifact> separateModuleHeaders,
-        Artifact.DerivedArtifact separateModule,
-        Artifact.DerivedArtifact separatePicModule,
+        DerivedArtifact separateModule,
+        DerivedArtifact separatePicModule,
         ImmutableList<HeaderInfo> deps) {
       this.headerModule = headerModule;
       this.picHeaderModule = picHeaderModule;
@@ -1312,11 +1313,11 @@
       this.deps = deps;
     }
 
-    Artifact.DerivedArtifact getModule(boolean pic) {
+    DerivedArtifact getModule(boolean pic) {
       return pic ? picHeaderModule : headerModule;
     }
 
-    Artifact.DerivedArtifact getSeparateModule(boolean pic) {
+    DerivedArtifact getSeparateModule(boolean pic) {
       return pic ? separatePicModule : separateModule;
     }
 
@@ -1414,22 +1415,22 @@
 
     /** Builder class for {@link HeaderInfo}. */
     public static class Builder {
-      private Artifact.DerivedArtifact headerModule = null;
-      private Artifact.DerivedArtifact picHeaderModule = null;
+      private DerivedArtifact headerModule = null;
+      private DerivedArtifact picHeaderModule = null;
       private final Set<Artifact> modularPublicHeaders = new HashSet<>();
       private final Set<Artifact> modularPrivateHeaders = new HashSet<>();
       private final Set<Artifact> textualHeaders = new HashSet<>();
       private Collection<Artifact> separateModuleHeaders = ImmutableList.of();
-      private Artifact.DerivedArtifact separateModule = null;
-      private Artifact.DerivedArtifact separatePicModule = null;
+      private DerivedArtifact separateModule = null;
+      private DerivedArtifact separatePicModule = null;
       private final List<HeaderInfo> deps = new ArrayList<>();
 
-      Builder setHeaderModule(Artifact.DerivedArtifact headerModule) {
+      Builder setHeaderModule(DerivedArtifact headerModule) {
         this.headerModule = headerModule;
         return this;
       }
 
-      Builder setPicHeaderModule(Artifact.DerivedArtifact headerModule) {
+      Builder setPicHeaderModule(DerivedArtifact headerModule) {
         this.picHeaderModule = headerModule;
         return this;
       }
@@ -1472,8 +1473,8 @@
 
       public Builder setSeparateModuleHdrs(
           Collection<Artifact> headers,
-          Artifact.DerivedArtifact separateModule,
-          Artifact.DerivedArtifact separatePicModule) {
+          DerivedArtifact separateModule,
+          DerivedArtifact separatePicModule) {
         this.separateModuleHeaders = headers;
         this.separateModule = separateModule;
         this.separatePicModule = separatePicModule;
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java
index 89865a4..deef150 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java
@@ -21,6 +21,7 @@
 import com.google.common.base.Preconditions;
 import com.google.common.base.Supplier;
 import com.google.common.base.Suppliers;
+import com.google.common.collect.Collections2;
 import com.google.common.collect.ImmutableCollection;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
@@ -36,11 +37,11 @@
 import com.google.devtools.build.lib.actions.ActionExecutionContext;
 import com.google.devtools.build.lib.actions.ActionExecutionException;
 import com.google.devtools.build.lib.actions.ActionInput;
-import com.google.devtools.build.lib.actions.ActionInputDepOwnerMap;
 import com.google.devtools.build.lib.actions.ActionKeyContext;
 import com.google.devtools.build.lib.actions.ActionOwner;
 import com.google.devtools.build.lib.actions.ActionResult;
 import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.Artifact.DerivedArtifact;
 import com.google.devtools.build.lib.actions.ArtifactResolver;
 import com.google.devtools.build.lib.actions.CommandAction;
 import com.google.devtools.build.lib.actions.CommandLine;
@@ -50,7 +51,6 @@
 import com.google.devtools.build.lib.actions.EnvironmentalExecException;
 import com.google.devtools.build.lib.actions.ExecException;
 import com.google.devtools.build.lib.actions.ExecutionRequirements;
-import com.google.devtools.build.lib.actions.LostInputsActionExecutionException;
 import com.google.devtools.build.lib.actions.ParamFileInfo;
 import com.google.devtools.build.lib.actions.ParameterFile.ParameterFileType;
 import com.google.devtools.build.lib.actions.ResourceSet;
@@ -65,7 +65,6 @@
 import com.google.devtools.build.lib.cmdline.LabelConstants;
 import com.google.devtools.build.lib.collect.nestedset.NestedSet;
 import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
-import com.google.devtools.build.lib.collect.nestedset.NestedSetStore.MissingNestedSetException;
 import com.google.devtools.build.lib.collect.nestedset.Order;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadCompatible;
 import com.google.devtools.build.lib.exec.SpawnStrategyResolver;
@@ -105,12 +104,10 @@
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Iterator;
-import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
-import java.util.concurrent.TimeoutException;
 import java.util.function.Predicate;
 import javax.annotation.Nullable;
 import net.starlark.java.eval.EvalException;
@@ -187,7 +184,7 @@
    * Used only during input discovery, when input discovery requires other actions to be executed
    * first.
    */
-  private Collection<Artifact.DerivedArtifact> usedModules;
+  private Set<DerivedArtifact> usedModules;
 
   /**
    * This field is set only for C++ module compiles (compiling .cppmap files into .pcm files). It
@@ -541,61 +538,18 @@
       return additionalInputs;
     }
 
-    Map<Artifact, NestedSet<Artifact>> transitivelyUsedModules =
+    ImmutableMap<Artifact, NestedSet<Artifact>> transitivelyUsedModules =
         computeTransitivelyUsedModules(
             actionExecutionContext.getEnvironmentForDiscoveringInputs(), usedModules);
     if (transitivelyUsedModules == null) {
       return null;
     }
 
-    // Compute top-level modules, i.e. used modules that aren't also dependencies of other
-    // used modules. Combining the NestedSets of transitive deps of the top-level modules also
-    // gives us an effective way to compute and store discoveredModules.
-    Set<Artifact> topLevel = new LinkedHashSet<>(usedModules);
+    Set<Artifact> topLevel =
+        actionExecutionContext
+            .getDiscoveredModulesPruner()
+            .computeTopLevelModules(this, usedModules, transitivelyUsedModules);
 
-    Iterator<Map.Entry<Artifact, NestedSet<Artifact>>> iterator =
-        transitivelyUsedModules.entrySet().iterator();
-    while (iterator.hasNext()) {
-      // It is better to iterate over each nested set here instead of creating a joint one and
-      // iterating over it, as this makes use of NestedSet's memoization (each of them has likely
-      // been iterated over before). Don't use Set.removeAll() here as that iterates over the
-      // smaller set (topLevel, which would support efficient lookup) and looks up in the larger one
-      // (transitive, which is a linear scan).
-      // We get a collection view of the NestedSet in a way that can throw an InterruptedException
-      // because a NestedSet may contain a future.
-      Map.Entry<Artifact, NestedSet<Artifact>> entry = iterator.next();
-      Artifact dep = entry.getKey();
-      if (!topLevel.contains(dep)) {
-        // If this module was removed from topLevel because it is a dependency of another module,
-        // we can safely ignore it now as all of its dependants have also been removed.
-        continue;
-      }
-      NestedSet<Artifact> transitive = entry.getValue();
-
-      List<Artifact> modules;
-      try {
-        modules = actionExecutionContext.getNestedSetExpander().toListInterruptibly(transitive);
-      } catch (TimeoutException | MissingNestedSetException e) {
-        DetailedExitCode code =
-            e instanceof TimeoutException
-                ? createDetailedExitCode(
-                    "Timed out expanding modules for " + dep, Code.MODULE_EXPANSION_TIMEOUT)
-                : createDetailedExitCode(
-                    "Missing data while expanding modules for " + dep,
-                    Code.MODULE_EXPANSION_MISSING_DATA);
-        if (actionExecutionContext.isRewindingEnabled()) {
-          // If rewinding is enabled, this error is recoverable.
-          throw lostInputsExceptionForFailedNestedSetExpansion(dep, iterator, e, code);
-        }
-        actionExecutionContext.getBugReporter().sendBugReport(e);
-        throw new ActionExecutionException(
-            code.getFailureDetail().getMessage(), e, this, /*catastrophe=*/ false, code);
-      }
-
-      for (Artifact module : modules) {
-        topLevel.remove(module);
-      }
-    }
     NestedSetBuilder<Artifact> topLevelModulesBuilder = NestedSetBuilder.stableOrder();
     NestedSetBuilder<Artifact> discoveredModulesBuilder = NestedSetBuilder.stableOrder();
     for (Artifact module : topLevel) {
@@ -641,45 +595,6 @@
             || isDeclaredIn(cppConfiguration, actionExecutionContext, header, looseHdrDirs.get());
   }
 
-  /**
-   * Handles a failure (timeout or missing data) during expansion of transitively used modules.
-   *
-   * <p>A timeout may occur if a nested set of transitively used modules {@linkplain
-   * NestedSet#isFromStorage} but is not {@linkplain NestedSet#isReady ready}, while a {@link
-   * MissingNestedSetException} may occur if the data cannot be found.
-   *
-   * <p>Both cases are handled by throwing {@link LostInputsActionExecutionException} so that
-   * rewinding kicks in and rebuilds the nodes with the unavailable nested sets.
-   *
-   * <p>As soon as one failure is seen, any other nested sets of modules which are not ready are
-   * also treated as lost inputs.
-   *
-   * <p>Although the output {@link Artifact} (.pcm file) of dependent modules is not technically
-   * lost, it is treated as a lost input because rewinding will rebuild the corresponding action,
-   * thus reconstituting its nested set of transitively used modules. In lieu of an actual digest,
-   * we use the .pcm file's exec path since rewinding only uses the digest to detect multiple
-   * rewinds of the same input.
-   */
-  private LostInputsActionExecutionException lostInputsExceptionForFailedNestedSetExpansion(
-      Artifact timedOut,
-      Iterator<Map.Entry<Artifact, NestedSet<Artifact>>> remainingModules,
-      Exception e,
-      DetailedExitCode code) {
-    ImmutableMap.Builder<String, ActionInput> lostInputsBuilder = ImmutableMap.builder();
-    lostInputsBuilder.put(timedOut.getExecPathString(), timedOut);
-    remainingModules.forEachRemaining(
-        entry -> {
-          if (!entry.getValue().isReady()) {
-            Artifact alsoTimedOut = entry.getKey();
-            lostInputsBuilder.put(alsoTimedOut.getExecPathString(), alsoTimedOut);
-          }
-        });
-    ImmutableMap<String, ActionInput> lostInputs = lostInputsBuilder.build();
-    ActionInputDepOwnerMap owners = new ActionInputDepOwnerMap(lostInputs.values());
-    return new LostInputsActionExecutionException(
-        code.getFailureDetail().getMessage(), lostInputs, owners, this, e, code);
-  }
-
   @Override
   public Artifact getPrimaryInput() {
     return getSourceFile();
@@ -1816,22 +1731,20 @@
    */
   @Nullable
   private static ImmutableMap<Artifact, NestedSet<Artifact>> computeTransitivelyUsedModules(
-      SkyFunction.Environment env, Collection<Artifact.DerivedArtifact> usedModules)
-      throws InterruptedException {
+      SkyFunction.Environment env, Set<DerivedArtifact> usedModules) throws InterruptedException {
     // Because this env.getValues call does not specify any exceptions, it is impossible for input
     // discovery to recover from exceptions thrown by spurious module deps (for instance, if a
     // commented-out include references a header file with an error in it). However, we generally
     // don't try to recover from errors around spurious includes discovered in the current build.
     // TODO(janakr): Can errors be aggregated here at least?
     Map<SkyKey, SkyValue> actionExecutionValues =
-        env.getValues(
-            Iterables.transform(usedModules, Artifact.DerivedArtifact::getGeneratingActionKey));
+        env.getValues(Collections2.transform(usedModules, DerivedArtifact::getGeneratingActionKey));
     if (env.valuesMissing()) {
       return null;
     }
     ImmutableMap.Builder<Artifact, NestedSet<Artifact>> transitivelyUsedModules =
         ImmutableMap.builderWithExpectedSize(usedModules.size());
-    for (Artifact.DerivedArtifact module : usedModules) {
+    for (DerivedArtifact module : usedModules) {
       Preconditions.checkState(
           module.isFileType(CppFileTypes.CPP_MODULE), "Non-module? %s", module);
       ActionExecutionValue value =
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeActionExecutor.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeActionExecutor.java
index 52238cf..ab88a61 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeActionExecutor.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeActionExecutor.java
@@ -54,6 +54,7 @@
 import com.google.devtools.build.lib.actions.Artifact.SpecialArtifact;
 import com.google.devtools.build.lib.actions.ArtifactPathResolver;
 import com.google.devtools.build.lib.actions.CachedActionEvent;
+import com.google.devtools.build.lib.actions.DiscoveredModulesPruner;
 import com.google.devtools.build.lib.actions.EnvironmentalExecException;
 import com.google.devtools.build.lib.actions.Executor;
 import com.google.devtools.build.lib.actions.FileArtifactValue;
@@ -76,7 +77,6 @@
 import com.google.devtools.build.lib.buildtool.BuildRequestOptions;
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.collect.nestedset.NestedSet;
-import com.google.devtools.build.lib.collect.nestedset.NestedSetExpander;
 import com.google.devtools.build.lib.events.Event;
 import com.google.devtools.build.lib.events.EventHandler;
 import com.google.devtools.build.lib.events.ExtendedEventHandler;
@@ -214,7 +214,7 @@
   private boolean finalizeActions;
   private final Supplier<ImmutableList<Root>> sourceRootSupplier;
 
-  private NestedSetExpander nestedSetExpander;
+  private DiscoveredModulesPruner discoveredModulesPruner;
   private final PathFragment relativeOutputPath;
 
   SkyframeActionExecutor(
@@ -559,7 +559,7 @@
         artifactExpander,
         actionFileSystem,
         skyframeDepsResult,
-        nestedSetExpander,
+        discoveredModulesPruner,
         syscalls.get(),
         threadStateReceiverFactory.apply(actionLookupData));
   }
@@ -762,7 +762,7 @@
             clientEnv,
             env,
             actionFileSystem,
-            nestedSetExpander,
+            discoveredModulesPruner,
             syscalls.get(),
             threadStateReceiverFactory.apply(actionLookupData));
     if (actionFileSystem != null) {
@@ -859,10 +859,10 @@
   public void configure(
       MetadataProvider fileCache,
       ActionInputPrefetcher actionInputPrefetcher,
-      NestedSetExpander nestedSetExpander) {
+      DiscoveredModulesPruner discoveredModulesPruner) {
     this.perBuildFileCache = fileCache;
     this.actionInputPrefetcher = actionInputPrefetcher;
-    this.nestedSetExpander = nestedSetExpander;
+    this.discoveredModulesPruner = discoveredModulesPruner;
   }
 
   /**
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
index f3efe52..75c57df 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
@@ -58,6 +58,7 @@
 import com.google.devtools.build.lib.actions.ArtifactRoot;
 import com.google.devtools.build.lib.actions.CommandLineExpansionException;
 import com.google.devtools.build.lib.actions.CompletionContext.PathResolverFactory;
+import com.google.devtools.build.lib.actions.DiscoveredModulesPruner;
 import com.google.devtools.build.lib.actions.EnvironmentalExecException;
 import com.google.devtools.build.lib.actions.Executor;
 import com.google.devtools.build.lib.actions.FileStateType;
@@ -112,7 +113,6 @@
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.cmdline.PackageIdentifier;
 import com.google.devtools.build.lib.cmdline.TargetParsingException;
-import com.google.devtools.build.lib.collect.nestedset.NestedSetExpander;
 import com.google.devtools.build.lib.concurrent.ForkJoinQuiescingExecutor;
 import com.google.devtools.build.lib.concurrent.NamedForkJoinPool;
 import com.google.devtools.build.lib.concurrent.QuiescingExecutor;
@@ -722,7 +722,8 @@
 
   public void configureActionExecutor(
       MetadataProvider fileCache, ActionInputPrefetcher actionInputPrefetcher) {
-    skyframeActionExecutor.configure(fileCache, actionInputPrefetcher, NestedSetExpander.DEFAULT);
+    skyframeActionExecutor.configure(
+        fileCache, actionInputPrefetcher, DiscoveredModulesPruner.DEFAULT);
   }
 
   public void dump(boolean summarize, PrintStream out) {
diff --git a/src/test/java/com/google/devtools/build/lib/actions/ExecutableSymlinkActionTest.java b/src/test/java/com/google/devtools/build/lib/actions/ExecutableSymlinkActionTest.java
index 700afe0..3bd58f9 100644
--- a/src/test/java/com/google/devtools/build/lib/actions/ExecutableSymlinkActionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/actions/ExecutableSymlinkActionTest.java
@@ -24,7 +24,6 @@
 import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
 import com.google.devtools.build.lib.actions.util.DummyExecutor;
 import com.google.devtools.build.lib.analysis.actions.SymlinkAction;
-import com.google.devtools.build.lib.collect.nestedset.NestedSetExpander;
 import com.google.devtools.build.lib.exec.SingleBuildFileCache;
 import com.google.devtools.build.lib.skyframe.serialization.testutils.SerializationDepsUtils;
 import com.google.devtools.build.lib.skyframe.serialization.testutils.SerializationTester;
@@ -82,7 +81,7 @@
         /*artifactExpander=*/ null,
         /*actionFileSystem=*/ null,
         /*skyframeDepsResult=*/ null,
-        NestedSetExpander.DEFAULT,
+        DiscoveredModulesPruner.DEFAULT,
         UnixGlob.DEFAULT_SYSCALLS,
         ThreadStateReceiver.NULL_INSTANCE);
   }
diff --git a/src/test/java/com/google/devtools/build/lib/actions/util/ActionsTestUtil.java b/src/test/java/com/google/devtools/build/lib/actions/util/ActionsTestUtil.java
index f346c86..d4e5150 100644
--- a/src/test/java/com/google/devtools/build/lib/actions/util/ActionsTestUtil.java
+++ b/src/test/java/com/google/devtools/build/lib/actions/util/ActionsTestUtil.java
@@ -53,6 +53,7 @@
 import com.google.devtools.build.lib.actions.ArtifactRoot;
 import com.google.devtools.build.lib.actions.ArtifactRoot.RootType;
 import com.google.devtools.build.lib.actions.BuildConfigurationEvent;
+import com.google.devtools.build.lib.actions.DiscoveredModulesPruner;
 import com.google.devtools.build.lib.actions.Executor;
 import com.google.devtools.build.lib.actions.FileArtifactValue;
 import com.google.devtools.build.lib.actions.MiddlemanType;
@@ -71,7 +72,6 @@
 import com.google.devtools.build.lib.cmdline.RepositoryName;
 import com.google.devtools.build.lib.collect.nestedset.NestedSet;
 import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
-import com.google.devtools.build.lib.collect.nestedset.NestedSetExpander;
 import com.google.devtools.build.lib.collect.nestedset.Order;
 import com.google.devtools.build.lib.events.EventHandler;
 import com.google.devtools.build.lib.events.ExtendedEventHandler;
@@ -174,7 +174,7 @@
         (artifact, output) -> {},
         /*actionFileSystem=*/ null,
         /*skyframeDepsResult=*/ null,
-        NestedSetExpander.DEFAULT,
+        DiscoveredModulesPruner.DEFAULT,
         UnixGlob.DEFAULT_SYSCALLS,
         ThreadStateReceiver.NULL_INSTANCE);
   }
@@ -200,7 +200,7 @@
         (artifact, output) -> {},
         /*actionFileSystem=*/ null,
         /*skyframeDepsResult=*/ null,
-        NestedSetExpander.DEFAULT,
+        DiscoveredModulesPruner.DEFAULT,
         UnixGlob.DEFAULT_SYSCALLS,
         ThreadStateReceiver.NULL_INSTANCE);
   }
@@ -213,7 +213,7 @@
       Path execRoot,
       MetadataHandler metadataHandler,
       BuildDriver buildDriver,
-      NestedSetExpander nestedSetExpander) {
+      DiscoveredModulesPruner discoveredModulesPruner) {
     return ActionExecutionContext.forInputDiscovery(
         executor,
         new SingleBuildFileCache(execRoot.getPathString(), execRoot.getFileSystem()),
@@ -227,7 +227,7 @@
         ImmutableMap.of(),
         new BlockingSkyFunctionEnvironment(buildDriver, eventHandler),
         /*actionFileSystem=*/ null,
-        nestedSetExpander,
+        discoveredModulesPruner,
         UnixGlob.DEFAULT_SYSCALLS,
         ThreadStateReceiver.NULL_INSTANCE);
   }
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/actions/FileWriteActionTestCase.java b/src/test/java/com/google/devtools/build/lib/analysis/actions/FileWriteActionTestCase.java
index b41421f..7cc761b 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/actions/FileWriteActionTestCase.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/actions/FileWriteActionTestCase.java
@@ -26,11 +26,11 @@
 import com.google.devtools.build.lib.actions.ActionOwner;
 import com.google.devtools.build.lib.actions.ActionResult;
 import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.DiscoveredModulesPruner;
 import com.google.devtools.build.lib.actions.Executor;
 import com.google.devtools.build.lib.actions.ThreadStateReceiver;
 import com.google.devtools.build.lib.analysis.util.ActionTester;
 import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
-import com.google.devtools.build.lib.collect.nestedset.NestedSetExpander;
 import com.google.devtools.build.lib.events.StoredEventHandler;
 import com.google.devtools.build.lib.exec.BinTools;
 import com.google.devtools.build.lib.exec.util.TestExecutorBuilder;
@@ -81,7 +81,7 @@
             /*artifactExpander=*/ null,
             /*actionFileSystem=*/ null,
             /*skyframeDepsResult=*/ null,
-            NestedSetExpander.DEFAULT,
+            DiscoveredModulesPruner.DEFAULT,
             UnixGlob.DEFAULT_SYSCALLS,
             ThreadStateReceiver.NULL_INSTANCE);
   }
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/actions/ParamFileWriteActionTest.java b/src/test/java/com/google/devtools/build/lib/analysis/actions/ParamFileWriteActionTest.java
index 1d4d3da..cfcb632 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/actions/ParamFileWriteActionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/actions/ParamFileWriteActionTest.java
@@ -29,6 +29,7 @@
 import com.google.devtools.build.lib.actions.ArtifactRoot;
 import com.google.devtools.build.lib.actions.ArtifactRoot.RootType;
 import com.google.devtools.build.lib.actions.CommandLine;
+import com.google.devtools.build.lib.actions.DiscoveredModulesPruner;
 import com.google.devtools.build.lib.actions.Executor;
 import com.google.devtools.build.lib.actions.ParameterFile.ParameterFileType;
 import com.google.devtools.build.lib.actions.ThreadStateReceiver;
@@ -37,7 +38,6 @@
 import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
 import com.google.devtools.build.lib.collect.nestedset.NestedSet;
 import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
-import com.google.devtools.build.lib.collect.nestedset.NestedSetExpander;
 import com.google.devtools.build.lib.collect.nestedset.Order;
 import com.google.devtools.build.lib.events.StoredEventHandler;
 import com.google.devtools.build.lib.exec.BinTools;
@@ -205,7 +205,7 @@
         artifactExpander,
         /*actionFileSystem=*/ null,
         /*skyframeDepsResult=*/ null,
-        NestedSetExpander.DEFAULT,
+        DiscoveredModulesPruner.DEFAULT,
         UnixGlob.DEFAULT_SYSCALLS,
         ThreadStateReceiver.NULL_INSTANCE);
   }
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/actions/SymlinkActionTest.java b/src/test/java/com/google/devtools/build/lib/analysis/actions/SymlinkActionTest.java
index 4144c78..a9e5aac 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/actions/SymlinkActionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/actions/SymlinkActionTest.java
@@ -22,11 +22,11 @@
 import com.google.devtools.build.lib.actions.ActionInputPrefetcher;
 import com.google.devtools.build.lib.actions.ActionResult;
 import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.DiscoveredModulesPruner;
 import com.google.devtools.build.lib.actions.Executor;
 import com.google.devtools.build.lib.actions.ThreadStateReceiver;
 import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
 import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
-import com.google.devtools.build.lib.collect.nestedset.NestedSetExpander;
 import com.google.devtools.build.lib.events.StoredEventHandler;
 import com.google.devtools.build.lib.exec.util.TestExecutorBuilder;
 import com.google.devtools.build.lib.skyframe.serialization.testutils.SerializationDepsUtils;
@@ -102,7 +102,7 @@
                 /*artifactExpander=*/ null,
                 /*actionFileSystem=*/ null,
                 /*skyframeDepsResult=*/ null,
-                NestedSetExpander.DEFAULT,
+                DiscoveredModulesPruner.DEFAULT,
                 UnixGlob.DEFAULT_SYSCALLS,
                 ThreadStateReceiver.NULL_INSTANCE));
     assertThat(actionResult.spawnResults()).isEmpty();
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/actions/TemplateExpansionActionTest.java b/src/test/java/com/google/devtools/build/lib/analysis/actions/TemplateExpansionActionTest.java
index cfdf49b..190bc6a 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/actions/TemplateExpansionActionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/actions/TemplateExpansionActionTest.java
@@ -27,12 +27,12 @@
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.actions.ArtifactRoot;
 import com.google.devtools.build.lib.actions.ArtifactRoot.RootType;
+import com.google.devtools.build.lib.actions.DiscoveredModulesPruner;
 import com.google.devtools.build.lib.actions.Executor;
 import com.google.devtools.build.lib.actions.ThreadStateReceiver;
 import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
 import com.google.devtools.build.lib.analysis.BlazeDirectories;
 import com.google.devtools.build.lib.analysis.ServerDirectories;
-import com.google.devtools.build.lib.collect.nestedset.NestedSetExpander;
 import com.google.devtools.build.lib.events.StoredEventHandler;
 import com.google.devtools.build.lib.exec.BinTools;
 import com.google.devtools.build.lib.exec.util.TestExecutorBuilder;
@@ -208,7 +208,7 @@
         /*artifactExpander=*/ null,
         /*actionFileSystem=*/ null,
         /*skyframeDepsResult=*/ null,
-        NestedSetExpander.DEFAULT,
+        DiscoveredModulesPruner.DEFAULT,
         UnixGlob.DEFAULT_SYSCALLS,
         ThreadStateReceiver.NULL_INSTANCE);
   }
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewTestCase.java b/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewTestCase.java
index d97f843..51d4af5 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewTestCase.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewTestCase.java
@@ -53,6 +53,7 @@
 import com.google.devtools.build.lib.actions.CommandLineExpansionException;
 import com.google.devtools.build.lib.actions.CommandLines;
 import com.google.devtools.build.lib.actions.CommandLines.CommandLineAndParamFileInfo;
+import com.google.devtools.build.lib.actions.DiscoveredModulesPruner;
 import com.google.devtools.build.lib.actions.Executor;
 import com.google.devtools.build.lib.actions.MapBasedActionGraph;
 import com.google.devtools.build.lib.actions.MetadataProvider;
@@ -113,7 +114,6 @@
 import com.google.devtools.build.lib.cmdline.RepositoryName;
 import com.google.devtools.build.lib.collect.nestedset.NestedSet;
 import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
-import com.google.devtools.build.lib.collect.nestedset.NestedSetExpander;
 import com.google.devtools.build.lib.collect.nestedset.Order;
 import com.google.devtools.build.lib.events.Event;
 import com.google.devtools.build.lib.events.ExtendedEventHandler;
@@ -2473,7 +2473,7 @@
           artifactExpander,
           /*actionFileSystem=*/ null,
           /*skyframeDepsResult*/ null,
-          NestedSetExpander.DEFAULT,
+          DiscoveredModulesPruner.DEFAULT,
           UnixGlob.DEFAULT_SYSCALLS,
           ThreadStateReceiver.NULL_INSTANCE);
     }
diff --git a/src/test/java/com/google/devtools/build/lib/exec/StandaloneTestStrategyTest.java b/src/test/java/com/google/devtools/build/lib/exec/StandaloneTestStrategyTest.java
index d293698..0b5c36e 100644
--- a/src/test/java/com/google/devtools/build/lib/exec/StandaloneTestStrategyTest.java
+++ b/src/test/java/com/google/devtools/build/lib/exec/StandaloneTestStrategyTest.java
@@ -32,6 +32,7 @@
 import com.google.devtools.build.lib.actions.ActionInputPrefetcher;
 import com.google.devtools.build.lib.actions.ActionKeyContext;
 import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.DiscoveredModulesPruner;
 import com.google.devtools.build.lib.actions.Spawn;
 import com.google.devtools.build.lib.actions.SpawnContinuation;
 import com.google.devtools.build.lib.actions.SpawnResult;
@@ -54,7 +55,6 @@
 import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.TestStatus;
 import com.google.devtools.build.lib.clock.BlazeClock;
 import com.google.devtools.build.lib.clock.Clock;
-import com.google.devtools.build.lib.collect.nestedset.NestedSetExpander;
 import com.google.devtools.build.lib.events.Event;
 import com.google.devtools.build.lib.events.EventKind;
 import com.google.devtools.build.lib.events.ExtendedEventHandler;
@@ -153,7 +153,7 @@
           /*artifactExpander=*/ null,
           /*actionFileSystem=*/ null,
           /*skyframeDepsResult=*/ null,
-          NestedSetExpander.DEFAULT,
+          DiscoveredModulesPruner.DEFAULT,
           UnixGlob.DEFAULT_SYSCALLS,
           ThreadStateReceiver.NULL_INSTANCE);
       this.actionContextRegistry = actionContextRegistry;
diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/CreateIncSymlinkActionTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/CreateIncSymlinkActionTest.java
index ca32999..75a3af4 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/cpp/CreateIncSymlinkActionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/CreateIncSymlinkActionTest.java
@@ -27,10 +27,10 @@
 import com.google.devtools.build.lib.actions.ArtifactPathResolver;
 import com.google.devtools.build.lib.actions.ArtifactRoot;
 import com.google.devtools.build.lib.actions.ArtifactRoot.RootType;
+import com.google.devtools.build.lib.actions.DiscoveredModulesPruner;
 import com.google.devtools.build.lib.actions.ThreadStateReceiver;
 import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
 import com.google.devtools.build.lib.actions.util.DummyExecutor;
-import com.google.devtools.build.lib.collect.nestedset.NestedSetExpander;
 import com.google.devtools.build.lib.events.StoredEventHandler;
 import com.google.devtools.build.lib.testutil.FoundationTestCase;
 import com.google.devtools.build.lib.util.Fingerprint;
@@ -143,7 +143,7 @@
         /*artifactExpander=*/ null,
         /*actionFileSystem=*/ null,
         /*skyframeDepsResult=*/ null,
-        NestedSetExpander.DEFAULT,
+        DiscoveredModulesPruner.DEFAULT,
         UnixGlob.DEFAULT_SYSCALLS,
         ThreadStateReceiver.NULL_INSTANCE);
   }
diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/LtoBackendActionTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/LtoBackendActionTest.java
index 27943fe..deeef6b 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/cpp/LtoBackendActionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/LtoBackendActionTest.java
@@ -25,6 +25,7 @@
 import com.google.devtools.build.lib.actions.ActionExecutionException;
 import com.google.devtools.build.lib.actions.ActionInputPrefetcher;
 import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.DiscoveredModulesPruner;
 import com.google.devtools.build.lib.actions.Executor;
 import com.google.devtools.build.lib.actions.ThreadStateReceiver;
 import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
@@ -36,7 +37,6 @@
 import com.google.devtools.build.lib.analysis.util.AnalysisTestUtil;
 import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
 import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
-import com.google.devtools.build.lib.collect.nestedset.NestedSetExpander;
 import com.google.devtools.build.lib.collect.nestedset.Order;
 import com.google.devtools.build.lib.events.StoredEventHandler;
 import com.google.devtools.build.lib.exec.BinTools;
@@ -105,7 +105,7 @@
             /*artifactExpander=*/ null,
             /*actionFileSystem=*/ null,
             /*skyframeDepsResult=*/ null,
-            NestedSetExpander.DEFAULT,
+            DiscoveredModulesPruner.DEFAULT,
             UnixGlob.DEFAULT_SYSCALLS,
             ThreadStateReceiver.NULL_INSTANCE);
   }
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/BazelJ2ObjcLibraryTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/BazelJ2ObjcLibraryTest.java
index 75d6abc..8a2b18c 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/objc/BazelJ2ObjcLibraryTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/BazelJ2ObjcLibraryTest.java
@@ -34,6 +34,7 @@
 import com.google.devtools.build.lib.actions.Artifact.SpecialArtifact;
 import com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact;
 import com.google.devtools.build.lib.actions.CommandAction;
+import com.google.devtools.build.lib.actions.DiscoveredModulesPruner;
 import com.google.devtools.build.lib.actions.ThreadStateReceiver;
 import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
 import com.google.devtools.build.lib.analysis.ConfiguredTarget;
@@ -41,7 +42,6 @@
 import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.cmdline.RepositoryName;
-import com.google.devtools.build.lib.collect.nestedset.NestedSetExpander;
 import com.google.devtools.build.lib.packages.NativeAspectClass;
 import com.google.devtools.build.lib.packages.util.MockObjcSupport;
 import com.google.devtools.build.lib.rules.apple.ApplePlatform.PlatformType;
@@ -807,7 +807,7 @@
             DUMMY_ARTIFACT_EXPANDER,
             /*actionFileSystem=*/ null,
             /*skyframeDepsResult=*/ null,
-            NestedSetExpander.DEFAULT,
+            DiscoveredModulesPruner.DEFAULT,
             UnixGlob.DEFAULT_SYSCALLS,
             ThreadStateReceiver.NULL_INSTANCE);
     ByteArrayOutputStream moduleMapStream = new ByteArrayOutputStream();
@@ -867,7 +867,7 @@
             DUMMY_ARTIFACT_EXPANDER,
             /*actionFileSystem=*/ null,
             /*skyframeDepsResult=*/ null,
-            NestedSetExpander.DEFAULT,
+            DiscoveredModulesPruner.DEFAULT,
             UnixGlob.DEFAULT_SYSCALLS,
             ThreadStateReceiver.NULL_INSTANCE);
 
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/TimestampBuilderTestCase.java b/src/test/java/com/google/devtools/build/lib/skyframe/TimestampBuilderTestCase.java
index 453de08..88e3072 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/TimestampBuilderTestCase.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/TimestampBuilderTestCase.java
@@ -44,6 +44,7 @@
 import com.google.devtools.build.lib.actions.ArtifactRoot.RootType;
 import com.google.devtools.build.lib.actions.BasicActionLookupValue;
 import com.google.devtools.build.lib.actions.BuildFailedException;
+import com.google.devtools.build.lib.actions.DiscoveredModulesPruner;
 import com.google.devtools.build.lib.actions.Executor;
 import com.google.devtools.build.lib.actions.FileStateValue;
 import com.google.devtools.build.lib.actions.FileValue;
@@ -70,7 +71,6 @@
 import com.google.devtools.build.lib.clock.Clock;
 import com.google.devtools.build.lib.collect.nestedset.NestedSet;
 import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
-import com.google.devtools.build.lib.collect.nestedset.NestedSetExpander;
 import com.google.devtools.build.lib.collect.nestedset.Order;
 import com.google.devtools.build.lib.events.Reporter;
 import com.google.devtools.build.lib.events.StoredEventHandler;
@@ -257,7 +257,8 @@
 
     MetadataProvider cache =
         new SingleBuildFileCache(rootDirectory.getPathString(), scratch.getFileSystem());
-    skyframeActionExecutor.configure(cache, ActionInputPrefetcher.NONE, NestedSetExpander.DEFAULT);
+    skyframeActionExecutor.configure(
+        cache, ActionInputPrefetcher.NONE, DiscoveredModulesPruner.DEFAULT);
 
     final InMemoryMemoizingEvaluator evaluator =
         new InMemoryMemoizingEvaluator(
diff --git a/src/test/java/com/google/devtools/build/lib/standalone/StandaloneSpawnStrategyTest.java b/src/test/java/com/google/devtools/build/lib/standalone/StandaloneSpawnStrategyTest.java
index 95cf263..a94299c 100644
--- a/src/test/java/com/google/devtools/build/lib/standalone/StandaloneSpawnStrategyTest.java
+++ b/src/test/java/com/google/devtools/build/lib/standalone/StandaloneSpawnStrategyTest.java
@@ -29,6 +29,7 @@
 import com.google.devtools.build.lib.actions.ActionKeyContext;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.actions.Artifact.ArtifactExpander;
+import com.google.devtools.build.lib.actions.DiscoveredModulesPruner;
 import com.google.devtools.build.lib.actions.ExecException;
 import com.google.devtools.build.lib.actions.ResourceManager;
 import com.google.devtools.build.lib.actions.ResourceSet;
@@ -41,7 +42,6 @@
 import com.google.devtools.build.lib.analysis.BlazeDirectories;
 import com.google.devtools.build.lib.analysis.ServerDirectories;
 import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
-import com.google.devtools.build.lib.collect.nestedset.NestedSetExpander;
 import com.google.devtools.build.lib.collect.nestedset.Order;
 import com.google.devtools.build.lib.events.PrintingEventHandler;
 import com.google.devtools.build.lib.events.Reporter;
@@ -216,7 +216,7 @@
         SIMPLE_ARTIFACT_EXPANDER,
         /*actionFileSystem=*/ null,
         /*skyframeDepsResult=*/ null,
-        NestedSetExpander.DEFAULT,
+        DiscoveredModulesPruner.DEFAULT,
         UnixGlob.DEFAULT_SYSCALLS,
         ThreadStateReceiver.NULL_INSTANCE);
   }
diff --git a/src/test/java/com/google/devtools/build/lib/starlark/StarlarkActionWithShadowedActionTest.java b/src/test/java/com/google/devtools/build/lib/starlark/StarlarkActionWithShadowedActionTest.java
index 04724e1..ff1d778 100644
--- a/src/test/java/com/google/devtools/build/lib/starlark/StarlarkActionWithShadowedActionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/starlark/StarlarkActionWithShadowedActionTest.java
@@ -27,6 +27,7 @@
 import com.google.devtools.build.lib.actions.ActionExecutionContext.LostInputsCheck;
 import com.google.devtools.build.lib.actions.ActionInputPrefetcher;
 import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.DiscoveredModulesPruner;
 import com.google.devtools.build.lib.actions.Executor;
 import com.google.devtools.build.lib.actions.ThreadStateReceiver;
 import com.google.devtools.build.lib.analysis.actions.StarlarkAction;
@@ -34,7 +35,6 @@
 import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
 import com.google.devtools.build.lib.collect.nestedset.NestedSet;
 import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
-import com.google.devtools.build.lib.collect.nestedset.NestedSetExpander;
 import com.google.devtools.build.lib.collect.nestedset.Order;
 import com.google.devtools.build.lib.exec.BinTools;
 import com.google.devtools.build.lib.exec.util.TestExecutorBuilder;
@@ -120,7 +120,7 @@
             /*artifactExpander=*/ null,
             /*actionFileSystem=*/ null,
             /*skyframeDepsResult=*/ null,
-            NestedSetExpander.DEFAULT,
+            DiscoveredModulesPruner.DEFAULT,
             UnixGlob.DEFAULT_SYSCALLS,
             ThreadStateReceiver.NULL_INSTANCE);
   }