Change Spawn.get{Tool,Input}Files to NestedSet

I think this should basically be a no-op. In a few places, it delays
flattening of the nested set, and could potentially reduce peak memory
use / reduce the time we're holding onto a flattened copy of the inputs.

PiperOrigin-RevId: 288673175
diff --git a/src/main/java/com/google/devtools/build/lib/actions/BaseSpawn.java b/src/main/java/com/google/devtools/build/lib/actions/BaseSpawn.java
index 0be3e7a..8115ff7 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/BaseSpawn.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/BaseSpawn.java
@@ -18,6 +18,7 @@
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 import com.google.devtools.build.lib.analysis.platform.PlatformInfo;
+import com.google.devtools.build.lib.collect.nestedset.NestedSet;
 import com.google.devtools.build.lib.vfs.PathFragment;
 import java.util.Collection;
 import java.util.List;
@@ -102,12 +103,12 @@
   }
 
   @Override
-  public Iterable<? extends ActionInput> getToolFiles() {
+  public NestedSet<? extends ActionInput> getToolFiles() {
     return action.getTools();
   }
 
   @Override
-  public Iterable<? extends ActionInput> getInputFiles() {
+  public NestedSet<? extends ActionInput> getInputFiles() {
     return action.getInputs();
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/actions/DelegateSpawn.java b/src/main/java/com/google/devtools/build/lib/actions/DelegateSpawn.java
index ca45bfb..651a747 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/DelegateSpawn.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/DelegateSpawn.java
@@ -17,6 +17,7 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.devtools.build.lib.analysis.platform.PlatformInfo;
+import com.google.devtools.build.lib.collect.nestedset.NestedSet;
 import java.util.Collection;
 import javax.annotation.Nullable;
 
@@ -58,12 +59,12 @@
   }
 
   @Override
-  public Iterable<? extends ActionInput> getToolFiles() {
+  public NestedSet<? extends ActionInput> getToolFiles() {
     return spawn.getToolFiles();
   }
 
   @Override
-  public Iterable<? extends ActionInput> getInputFiles() {
+  public NestedSet<? extends ActionInput> getInputFiles() {
     return spawn.getInputFiles();
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/actions/SimpleSpawn.java b/src/main/java/com/google/devtools/build/lib/actions/SimpleSpawn.java
index 536cb31..9144cde 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/SimpleSpawn.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/SimpleSpawn.java
@@ -17,7 +17,11 @@
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
 import com.google.devtools.build.lib.analysis.platform.PlatformInfo;
+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.Order;
 import java.util.Map;
 import javax.annotation.Nullable;
 import javax.annotation.concurrent.Immutable;
@@ -32,8 +36,8 @@
   private final ImmutableList<String> arguments;
   private final ImmutableMap<String, String> environment;
   private final ImmutableMap<String, String> executionInfo;
-  private final ImmutableList<? extends ActionInput> inputs;
-  private final ImmutableList<? extends ActionInput> tools;
+  private final NestedSet<? extends ActionInput> inputs;
+  private final NestedSet<? extends ActionInput> tools;
   private final RunfilesSupplier runfilesSupplier;
   private final Map<Artifact, ImmutableList<FilesetOutputSymlink>> filesetMappings;
   private final ImmutableList<? extends ActionInput> outputs;
@@ -46,9 +50,9 @@
       ImmutableMap<String, String> executionInfo,
       RunfilesSupplier runfilesSupplier,
       Map<Artifact, ImmutableList<FilesetOutputSymlink>> filesetMappings,
-      ImmutableList<? extends ActionInput> inputs,
-      ImmutableList<? extends ActionInput> tools,
-      ImmutableList<? extends ActionInput> outputs,
+      NestedSet<? extends ActionInput> inputs,
+      NestedSet<? extends ActionInput> tools,
+      ImmutableSet<? extends ActionInput> outputs,
       ResourceSet localResources) {
     this.owner = Preconditions.checkNotNull(owner);
     this.arguments = Preconditions.checkNotNull(arguments);
@@ -59,7 +63,7 @@
     this.runfilesSupplier =
         runfilesSupplier == null ? EmptyRunfilesSupplier.INSTANCE : runfilesSupplier;
     this.filesetMappings = filesetMappings;
-    this.outputs = Preconditions.checkNotNull(outputs);
+    this.outputs = Preconditions.checkNotNull(outputs).asList();
     this.localResources = Preconditions.checkNotNull(localResources);
   }
 
@@ -68,8 +72,8 @@
       ImmutableList<String> arguments,
       ImmutableMap<String, String> environment,
       ImmutableMap<String, String> executionInfo,
-      ImmutableList<? extends ActionInput> inputs,
-      ImmutableList<? extends ActionInput> outputs,
+      NestedSet<? extends ActionInput> inputs,
+      ImmutableSet<? extends ActionInput> outputs,
       ResourceSet localResources) {
     this(
         owner,
@@ -79,7 +83,7 @@
         null,
         ImmutableMap.of(),
         inputs,
-        ImmutableList.<Artifact>of(),
+        NestedSetBuilder.emptySet(Order.STABLE_ORDER),
         outputs,
         localResources);
   }
@@ -110,12 +114,12 @@
   }
 
   @Override
-  public ImmutableList<? extends ActionInput> getInputFiles() {
+  public NestedSet<? extends ActionInput> getInputFiles() {
     return inputs;
   }
 
   @Override
-  public ImmutableList<? extends ActionInput> getToolFiles() {
+  public NestedSet<? extends ActionInput> getToolFiles() {
     return tools;
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/actions/Spawn.java b/src/main/java/com/google/devtools/build/lib/actions/Spawn.java
index 6ed2abf..9d95e7d 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/Spawn.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/Spawn.java
@@ -17,6 +17,7 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.devtools.build.lib.analysis.platform.PlatformInfo;
+import com.google.devtools.build.lib.collect.nestedset.NestedSet;
 import java.util.Collection;
 import javax.annotation.Nullable;
 
@@ -65,26 +66,26 @@
    *
    * <p>The returned set of files is a subset of what getInputFiles() returns.
    *
-   * <p>This method explicitly does not expand middleman artifacts. Pass the result
-   * to an appropriate utility method on {@link com.google.devtools.build.lib.actions.Artifact} to
-   * expand the middlemen.
+   * <p>This method explicitly does not expand middleman artifacts. Pass the result to an
+   * appropriate utility method on {@link com.google.devtools.build.lib.actions.Artifact} to expand
+   * the middlemen.
    *
-   * <p>This is for use with persistent workers, so we can restart workers when their binaries
-   * have changed.
+   * <p>This is for use with persistent workers, so we can restart workers when their binaries have
+   * changed.
    */
-  Iterable<? extends ActionInput> getToolFiles();
+  NestedSet<? extends ActionInput> getToolFiles();
 
   /**
    * Returns the list of files that this command may read.
    *
-   * <p>This method explicitly does not expand middleman artifacts. Pass the result
-   * to an appropriate utility method on {@link com.google.devtools.build.lib.actions.Artifact} to
-   * expand the middlemen.
+   * <p>This method explicitly does not expand middleman artifacts. Pass the result to an
+   * appropriate utility method on {@link com.google.devtools.build.lib.actions.Artifact} to expand
+   * the middlemen.
    *
-   * <p>This is for use with remote execution, so we can ship inputs before starting the
-   * command. Order stability across multiple calls should be upheld for performance reasons.
+   * <p>This is for use with remote execution, so we can ship inputs before starting the command.
+   * Order stability across multiple calls should be upheld for performance reasons.
    */
-  Iterable<? extends ActionInput> getInputFiles();
+  NestedSet<? extends ActionInput> getInputFiles();
 
   /**
    * Returns the collection of files that this command must write.  Callers should not mutate
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/actions/SpawnAction.java b/src/main/java/com/google/devtools/build/lib/analysis/actions/SpawnAction.java
index a294bfa..970329d 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/actions/SpawnAction.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/actions/SpawnAction.java
@@ -383,7 +383,7 @@
     return getSpawn(getInputs());
   }
 
-  final Spawn getSpawn(Iterable<Artifact> inputs) throws CommandLineExpansionException {
+  final Spawn getSpawn(NestedSet<Artifact> inputs) throws CommandLineExpansionException {
     return new ActionSpawn(
         commandLines.allArguments(),
         ImmutableMap.of(),
@@ -547,8 +547,7 @@
 
   /** A spawn instance that is tied to a specific SpawnAction. */
   private class ActionSpawn extends BaseSpawn {
-
-    private final ImmutableList<ActionInput> inputs;
+    private final NestedSet<ActionInput> inputs;
     private final Map<Artifact, ImmutableList<FilesetOutputSymlink>> filesetMappings;
     private final ImmutableMap<String, String> effectiveEnvironment;
 
@@ -561,7 +560,7 @@
     private ActionSpawn(
         ImmutableList<String> arguments,
         Map<String, String> clientEnv,
-        Iterable<Artifact> inputs,
+        NestedSet<Artifact> inputs,
         Iterable<? extends ActionInput> additionalInputs,
         Map<Artifact, ImmutableList<FilesetOutputSymlink>> filesetMappings) {
       super(
@@ -571,7 +570,7 @@
           SpawnAction.this.getRunfilesSupplier(),
           SpawnAction.this,
           resourceSet);
-      ImmutableList.Builder<ActionInput> inputsBuilder = ImmutableList.builder();
+      NestedSetBuilder<ActionInput> inputsBuilder = NestedSetBuilder.stableOrder();
       ImmutableList<Artifact> manifests = getRunfilesSupplier().getManifests();
       for (Artifact input : inputs) {
         if (!input.isFileset() && !manifests.contains(input)) {
@@ -597,7 +596,7 @@
     }
 
     @Override
-    public Iterable<? extends ActionInput> getInputFiles() {
+    public NestedSet<? extends ActionInput> getInputFiles() {
       return inputs;
     }
   }
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/actions/StarlarkAction.java b/src/main/java/com/google/devtools/build/lib/analysis/actions/StarlarkAction.java
index 9b02b95..0a4e682 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/actions/StarlarkAction.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/actions/StarlarkAction.java
@@ -206,8 +206,7 @@
 
   @Override
   public Iterable<Artifact> getInputFilesForExtraAction(
-      ActionExecutionContext actionExecutionContext)
-      throws ActionExecutionException, InterruptedException {
+      ActionExecutionContext actionExecutionContext) {
     return allInputs;
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/collect/nestedset/NestedSetBuilder.java b/src/main/java/com/google/devtools/build/lib/collect/nestedset/NestedSetBuilder.java
index d2d0ece..d8292cf 100644
--- a/src/main/java/com/google/devtools/build/lib/collect/nestedset/NestedSetBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/collect/nestedset/NestedSetBuilder.java
@@ -274,7 +274,7 @@
     return new NestedSetBuilder<>(Order.NAIVE_LINK_ORDER);
   }
 
-  public static <E> NestedSetBuilder<E> fromNestedSet(NestedSet<E> set) {
+  public static <E> NestedSetBuilder<E> fromNestedSet(NestedSet<? extends E> set) {
     return new NestedSetBuilder<E>(set.getOrder()).addTransitive(set);
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/exec/StandaloneTestStrategy.java b/src/main/java/com/google/devtools/build/lib/exec/StandaloneTestStrategy.java
index c266278..e0cf8d0 100644
--- a/src/main/java/com/google/devtools/build/lib/exec/StandaloneTestStrategy.java
+++ b/src/main/java/com/google/devtools/build/lib/exec/StandaloneTestStrategy.java
@@ -17,12 +17,12 @@
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Lists;
 import com.google.common.io.ByteStreams;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.devtools.build.lib.actions.ActionExecutionContext;
 import com.google.devtools.build.lib.actions.ActionInputHelper;
-import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.actions.ArtifactPathResolver;
 import com.google.devtools.build.lib.actions.EnvironmentalExecException;
 import com.google.devtools.build.lib.actions.ExecException;
@@ -43,6 +43,8 @@
 import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos;
 import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.TestResult.ExecutionInfo;
 import com.google.devtools.build.lib.buildeventstream.TestFileNameConstants;
+import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
+import com.google.devtools.build.lib.collect.nestedset.Order;
 import com.google.devtools.build.lib.events.Reporter;
 import com.google.devtools.build.lib.util.OS;
 import com.google.devtools.build.lib.util.Pair;
@@ -132,9 +134,9 @@
             ImmutableMap.copyOf(executionInfo),
             action.getRunfilesSupplier(),
             ImmutableMap.of(),
-            /*inputs=*/ action.getInputs().toList(),
-            /*tools=*/ ImmutableList.<Artifact>of(),
-            ImmutableList.copyOf(action.getSpawnOutputs()),
+            /*inputs=*/ action.getInputs(),
+            /*tools=*/ NestedSetBuilder.emptySet(Order.STABLE_ORDER),
+            ImmutableSet.copyOf(action.getSpawnOutputs()),
             localResourceUsage);
     return new StandaloneTestRunnerSpawn(
         action, actionExecutionContext, spawn, tmpDir, workingDirectory, execRoot);
@@ -398,9 +400,10 @@
         ImmutableMap.copyOf(action.getExecutionInfo()),
         null,
         ImmutableMap.of(),
-        /*inputs=*/ ImmutableList.of(action.getTestXmlGeneratorScript(), action.getTestLog()),
-        /*tools=*/ ImmutableList.<Artifact>of(),
-        /*outputs=*/ ImmutableList.of(ActionInputHelper.fromPath(action.getXmlOutputPath())),
+        /*inputs=*/ NestedSetBuilder.create(
+            Order.STABLE_ORDER, action.getTestXmlGeneratorScript(), action.getTestLog()),
+        /*tools=*/ NestedSetBuilder.emptySet(Order.STABLE_ORDER),
+        /*outputs=*/ ImmutableSet.of(ActionInputHelper.fromPath(action.getXmlOutputPath())),
         SpawnAction.DEFAULT_RESOURCE_SET);
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/includescanning/SpawnIncludeScanner.java b/src/main/java/com/google/devtools/build/lib/includescanning/SpawnIncludeScanner.java
index b94e840..3d122a5 100644
--- a/src/main/java/com/google/devtools/build/lib/includescanning/SpawnIncludeScanner.java
+++ b/src/main/java/com/google/devtools/build/lib/includescanning/SpawnIncludeScanner.java
@@ -44,6 +44,8 @@
 import com.google.devtools.build.lib.actions.SpawnResult;
 import com.google.devtools.build.lib.analysis.platform.PlatformInfo;
 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.Order;
 import com.google.devtools.build.lib.includescanning.IncludeParser.GrepIncludesFileType;
 import com.google.devtools.build.lib.includescanning.IncludeParser.Inclusion;
 import com.google.devtools.build.lib.util.io.FileOutErr;
@@ -340,8 +342,9 @@
       GrepIncludesFileType fileType)
       throws ExecException, InterruptedException {
     ActionInput output = ActionInputHelper.fromPath(outputExecPath);
-    ImmutableList<? extends ActionInput> inputs = ImmutableList.of(grepIncludes, input);
-    ImmutableList<ActionInput> outputs = ImmutableList.of(output);
+    NestedSet<? extends ActionInput> inputs =
+        NestedSetBuilder.create(Order.STABLE_ORDER, grepIncludes, input);
+    ImmutableSet<ActionInput> outputs = ImmutableSet.of(output);
     ImmutableList<String> command =
         ImmutableList.of(
             grepIncludes.getExecPathString(),
@@ -459,8 +462,9 @@
       Artifact grepIncludes,
       GrepIncludesFileType fileType) {
     ActionInput output = ActionInputHelper.fromPath(outputExecPath);
-    ImmutableList<? extends ActionInput> inputs = ImmutableList.of(grepIncludes, input);
-    ImmutableList<ActionInput> outputs = ImmutableList.of(output);
+    NestedSet<? extends ActionInput> inputs =
+        NestedSetBuilder.create(Order.STABLE_ORDER, grepIncludes, input);
+    ImmutableSet<ActionInput> outputs = ImmutableSet.of(output);
     ImmutableList<String> command =
         ImmutableList.of(
             grepIncludes.getExecPathString(),
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 0b3b4ab..72da2b2 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
@@ -380,7 +380,7 @@
    * {@link #discoverInputs(ActionExecutionContext)} must be called before this method is called on
    * each action execution.
    */
-  public Iterable<Artifact> getAdditionalInputs() {
+  public NestedSet<Artifact> getAdditionalInputs() {
     return Preconditions.checkNotNull(additionalInputs);
   }
 
@@ -1420,19 +1420,16 @@
   protected Spawn createSpawn(Map<String, String> clientEnv) throws ActionExecutionException {
     // Intentionally not adding {@link CppCompileAction#inputsForInvalidation}, those are not needed
     // for execution.
-    ImmutableList.Builder<ActionInput> inputsBuilder =
-        new ImmutableList.Builder<ActionInput>()
-            .addAll(getMandatoryInputs())
-            .addAll(getAdditionalInputs());
+    NestedSetBuilder<ActionInput> inputsBuilder =
+        NestedSetBuilder.<ActionInput>stableOrder()
+            .addTransitive(getMandatoryInputs())
+            .addTransitive(getAdditionalInputs());
     if (getParamFileActionInput() != null) {
       inputsBuilder.add(getParamFileActionInput());
     }
-    ImmutableList<ActionInput> inputs = inputsBuilder.build();
+    NestedSet<ActionInput> inputs = inputsBuilder.build();
 
     ImmutableMap<String, String> executionInfo = getExecutionInfo();
-    ImmutableList.Builder<ActionInput> outputs =
-        ImmutableList.builderWithExpectedSize(getOutputs().size() + 1);
-    outputs.addAll(getOutputs());
     if (getDotdFile() != null && useInMemoryDotdFiles()) {
       /*
        * CppCompileAction does dotd file scanning locally inside the Bazel process and thus
@@ -1458,7 +1455,7 @@
           getEnvironment(clientEnv),
           executionInfo,
           inputs,
-          outputs.build(),
+          getOutputs(),
           estimateResourceConsumptionLocal());
     } catch (CommandLineExpansionException e) {
       throw new ActionExecutionException(
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkAction.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkAction.java
index 9ccf38b..b1904fd 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkAction.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkAction.java
@@ -329,8 +329,8 @@
           ImmutableList.copyOf(getCommandLine(actionExecutionContext.getArtifactExpander())),
           getEnvironment(actionExecutionContext.getClientEnv()),
           getExecutionInfo(),
-          ImmutableList.copyOf(getInputs()),
-          getOutputs().asList(),
+          getInputs(),
+          getOutputs(),
           estimateResourceConsumptionLocal());
     } catch (CommandLineExpansionException e) {
       throw new ActionExecutionException(
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompileAction.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompileAction.java
index e94bf23..d96e948 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompileAction.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompileAction.java
@@ -439,13 +439,13 @@
   }
 
   private final class JavaSpawn extends BaseSpawn {
-    final Iterable<ActionInput> inputs;
+    final NestedSet<ActionInput> inputs;
 
     public JavaSpawn(
         CommandLines.ExpandedCommandLines expandedCommandLines,
         Map<String, String> environment,
         Map<String, String> executionInfo,
-        Iterable<Artifact> inputs) {
+        NestedSet<Artifact> inputs) {
       super(
           ImmutableList.copyOf(expandedCommandLines.arguments()),
           environment,
@@ -453,11 +453,14 @@
           EmptyRunfilesSupplier.INSTANCE,
           JavaCompileAction.this,
           LOCAL_RESOURCES);
-      this.inputs = Iterables.concat(inputs, expandedCommandLines.getParamFiles());
+      this.inputs =
+          NestedSetBuilder.<ActionInput>fromNestedSet(inputs)
+              .addAll(expandedCommandLines.getParamFiles())
+              .build();
     }
 
     @Override
-    public Iterable<? extends ActionInput> getInputFiles() {
+    public NestedSet<? extends ActionInput> getInputFiles() {
       return inputs;
     }
   }
diff --git a/src/test/java/com/google/devtools/build/lib/BUILD b/src/test/java/com/google/devtools/build/lib/BUILD
index 706db4f..fe8ec3a 100644
--- a/src/test/java/com/google/devtools/build/lib/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/BUILD
@@ -1315,6 +1315,7 @@
         "//src/main/java/com/google/devtools/build/lib/actions",
         "//src/main/java/com/google/devtools/build/lib/actions:localhost_capacity",
         "//src/main/java/com/google/devtools/build/lib/clock",
+        "//src/main/java/com/google/devtools/build/lib/collect/nestedset",
         "//src/main/java/com/google/devtools/build/lib/exec/local",
         "//src/main/java/com/google/devtools/build/lib/exec/local:options",
         "//src/main/java/com/google/devtools/build/lib/rules/apple",
diff --git a/src/test/java/com/google/devtools/build/lib/exec/util/SpawnBuilder.java b/src/test/java/com/google/devtools/build/lib/exec/util/SpawnBuilder.java
index 88ddf2c..cce2e41 100644
--- a/src/test/java/com/google/devtools/build/lib/exec/util/SpawnBuilder.java
+++ b/src/test/java/com/google/devtools/build/lib/exec/util/SpawnBuilder.java
@@ -16,6 +16,7 @@
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
 import com.google.devtools.build.lib.actions.ActionExecutionMetadata;
 import com.google.devtools.build.lib.actions.ActionInput;
 import com.google.devtools.build.lib.actions.ActionInputHelper;
@@ -27,6 +28,8 @@
 import com.google.devtools.build.lib.actions.SimpleSpawn;
 import com.google.devtools.build.lib.actions.Spawn;
 import com.google.devtools.build.lib.analysis.platform.PlatformInfo;
+import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
+import com.google.devtools.build.lib.collect.nestedset.Order;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -45,7 +48,7 @@
   private final Map<String, String> environment = new HashMap<>();
   private final Map<String, String> executionInfo = new HashMap<>();
   private ImmutableMap<String, String> execProperties = ImmutableMap.of();
-  private final List<ActionInput> inputs = new ArrayList<>();
+  private final NestedSetBuilder<ActionInput> inputs = NestedSetBuilder.stableOrder();
   private final List<ActionInput> outputs = new ArrayList<>();
   private final Map<Artifact, ImmutableList<FilesetOutputSymlink>> filesetMappings =
       new HashMap<>();
@@ -66,9 +69,9 @@
         ImmutableMap.copyOf(executionInfo),
         runfilesSupplier,
         ImmutableMap.copyOf(filesetMappings),
-        ImmutableList.copyOf(inputs),
-        /*tools=*/ ImmutableList.<Artifact>of(),
-        ImmutableList.copyOf(outputs),
+        inputs.build(),
+        /*tools=*/ NestedSetBuilder.emptySet(Order.STABLE_ORDER),
+        ImmutableSet.copyOf(outputs),
         ResourceSet.ZERO);
   }
 
diff --git a/src/test/java/com/google/devtools/build/lib/remote/BUILD b/src/test/java/com/google/devtools/build/lib/remote/BUILD
index 7421605..02c3d79 100644
--- a/src/test/java/com/google/devtools/build/lib/remote/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/remote/BUILD
@@ -50,6 +50,7 @@
         "//src/main/java/com/google/devtools/build/lib/authandtls",
         "//src/main/java/com/google/devtools/build/lib/buildeventstream",
         "//src/main/java/com/google/devtools/build/lib/clock",
+        "//src/main/java/com/google/devtools/build/lib/collect/nestedset",
         "//src/main/java/com/google/devtools/build/lib/remote",
         "//src/main/java/com/google/devtools/build/lib/remote/common",
         "//src/main/java/com/google/devtools/build/lib/remote/disk",
diff --git a/src/test/java/com/google/devtools/build/lib/remote/GrpcRemoteExecutionClientTest.java b/src/test/java/com/google/devtools/build/lib/remote/GrpcRemoteExecutionClientTest.java
index c498b47..90fc834 100644
--- a/src/test/java/com/google/devtools/build/lib/remote/GrpcRemoteExecutionClientTest.java
+++ b/src/test/java/com/google/devtools/build/lib/remote/GrpcRemoteExecutionClientTest.java
@@ -58,6 +58,8 @@
 import com.google.devtools.build.lib.authandtls.AuthAndTLSOptions;
 import com.google.devtools.build.lib.authandtls.GoogleAuthUtils;
 import com.google.devtools.build.lib.clock.JavaClock;
+import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
+import com.google.devtools.build.lib.collect.nestedset.Order;
 import com.google.devtools.build.lib.exec.ExecutionOptions;
 import com.google.devtools.build.lib.exec.util.FakeOwner;
 import com.google.devtools.build.lib.remote.RemoteRetrier.ExponentialBackoff;
@@ -167,8 +169,9 @@
             ImmutableList.of("/bin/echo", "Hi!"),
             ImmutableMap.of("VARIABLE", "value"),
             /*executionInfo=*/ ImmutableMap.<String, String>of(),
-            /*inputs=*/ ImmutableList.of(ActionInputHelper.fromPath("input")),
-            /*outputs=*/ ImmutableList.<ActionInput>of(
+            /*inputs=*/ NestedSetBuilder.create(
+                Order.STABLE_ORDER, ActionInputHelper.fromPath("input")),
+            /*outputs=*/ ImmutableSet.<ActionInput>of(
                 new ActionInput() {
                   @Override
                   public String getExecPathString() {
@@ -259,7 +262,8 @@
             logDir,
             /* filesToDownload= */ ImmutableSet.of());
 
-    inputDigest = fakeFileCache.createScratchInput(simpleSpawn.getInputFiles().get(0), "xyz");
+    inputDigest =
+        fakeFileCache.createScratchInput(simpleSpawn.getInputFiles().getSingleton(), "xyz");
     command =
         Command.newBuilder()
             .addAllArguments(ImmutableList.of("/bin/echo", "Hi!"))
diff --git a/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnCacheTest.java b/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnCacheTest.java
index 5c93a05..eca1c7e 100644
--- a/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnCacheTest.java
+++ b/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnCacheTest.java
@@ -48,6 +48,8 @@
 import com.google.devtools.build.lib.actions.SpawnResult.Status;
 import com.google.devtools.build.lib.actions.cache.MetadataInjector;
 import com.google.devtools.build.lib.clock.JavaClock;
+import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
+import com.google.devtools.build.lib.collect.nestedset.Order;
 import com.google.devtools.build.lib.events.Event;
 import com.google.devtools.build.lib.events.EventKind;
 import com.google.devtools.build.lib.events.Reporter;
@@ -216,8 +218,9 @@
         ImmutableList.of("/bin/echo", "Hi!"),
         ImmutableMap.of("VARIABLE", "value"),
         executionInfo,
-        /* inputs= */ ImmutableList.of(ActionInputHelper.fromPath("input")),
-        /* outputs= */ ImmutableList.of(ActionInputHelper.fromPath("/random/file")),
+        /* inputs= */ NestedSetBuilder.create(
+            Order.STABLE_ORDER, ActionInputHelper.fromPath("input")),
+        /* outputs= */ ImmutableSet.of(ActionInputHelper.fromPath("/random/file")),
         ResourceSet.ZERO);
   }
 
@@ -254,7 +257,7 @@
     reporter.addHandler(eventHandler);
     cache = remoteSpawnCacheWithOptions(options);
 
-    fakeFileCache.createScratchInput(simpleSpawn.getInputFiles().get(0), "xyz");
+    fakeFileCache.createScratchInput(simpleSpawn.getInputFiles().getSingleton(), "xyz");
   }
 
   @SuppressWarnings("unchecked")
diff --git a/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnRunnerTest.java b/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnRunnerTest.java
index cc2d9e1..44b12d2 100644
--- a/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnRunnerTest.java
+++ b/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnRunnerTest.java
@@ -55,6 +55,8 @@
 import com.google.devtools.build.lib.actions.SpawnResult.Status;
 import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
 import com.google.devtools.build.lib.clock.JavaClock;
+import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
+import com.google.devtools.build.lib.collect.nestedset.Order;
 import com.google.devtools.build.lib.events.Event;
 import com.google.devtools.build.lib.events.EventKind;
 import com.google.devtools.build.lib.events.Reporter;
@@ -836,8 +838,8 @@
             /*arguments=*/ ImmutableList.of(),
             /*environment=*/ ImmutableMap.of(),
             /*executionInfo=*/ ImmutableMap.of(),
-            /*inputs=*/ ImmutableList.of(input),
-            /*outputs=*/ ImmutableList.<ActionInput>of(),
+            /*inputs=*/ NestedSetBuilder.create(Order.STABLE_ORDER, input),
+            /*outputs=*/ ImmutableSet.<ActionInput>of(),
             ResourceSet.ZERO);
     SpawnExecutionContext policy =
         new FakeSpawnExecutionContext(spawn, fakeFileCache, execRoot, outErr);
@@ -973,8 +975,8 @@
         /*arguments=*/ ImmutableList.of(),
         /*environment=*/ ImmutableMap.of(),
         /*executionInfo=*/ executionInfo,
-        /*inputs=*/ ImmutableList.of(),
-        /*outputs=*/ ImmutableList.copyOf(outputs),
+        /*inputs=*/ NestedSetBuilder.emptySet(Order.STABLE_ORDER),
+        /*outputs=*/ ImmutableSet.copyOf(outputs),
         ResourceSet.ZERO);
   }
 
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 1a0ce10..f9c7b96 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
@@ -19,6 +19,7 @@
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Sets;
 import com.google.common.eventbus.EventBus;
 import com.google.devtools.build.lib.actions.ActionExecutionContext;
@@ -38,6 +39,8 @@
 import com.google.devtools.build.lib.analysis.BlazeDirectories;
 import com.google.devtools.build.lib.analysis.ServerDirectories;
 import com.google.devtools.build.lib.clock.BlazeClock;
+import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
+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;
 import com.google.devtools.build.lib.exec.BinTools;
@@ -158,8 +161,8 @@
         ImmutableList.copyOf(arguments),
         /*environment=*/ ImmutableMap.of(),
         /*executionInfo=*/ ImmutableMap.of(),
-        /*inputs=*/ ImmutableList.of(),
-        /*outputs=*/ ImmutableList.of(),
+        /*inputs=*/ NestedSetBuilder.emptySet(Order.STABLE_ORDER),
+        /*outputs=*/ ImmutableSet.of(),
         ResourceSet.ZERO);
   }
 
@@ -240,14 +243,15 @@
       // down where that env var is coming from.
       return;
     }
-    Spawn spawn = new SimpleSpawn(
-        new ActionsTestUtil.NullAction(),
-        ImmutableList.of("/usr/bin/env"),
-        /*environment=*/ ImmutableMap.of("foo", "bar", "baz", "boo"),
-        /*executionInfo=*/ ImmutableMap.of(),
-        /*inputs=*/ ImmutableList.of(),
-        /*outputs=*/ ImmutableList.of(),
-        ResourceSet.ZERO);
+    Spawn spawn =
+        new SimpleSpawn(
+            new ActionsTestUtil.NullAction(),
+            ImmutableList.of("/usr/bin/env"),
+            /*environment=*/ ImmutableMap.of("foo", "bar", "baz", "boo"),
+            /*executionInfo=*/ ImmutableMap.of(),
+            /*inputs=*/ NestedSetBuilder.emptySet(Order.STABLE_ORDER),
+            /*outputs=*/ ImmutableSet.of(),
+            ResourceSet.ZERO);
     run(spawn);
     assertThat(Sets.newHashSet(out().split("\n"))).isEqualTo(Sets.newHashSet("foo=bar", "baz=boo"));
   }