Rename Root to ArtifactRoot.

This is slightly more descriptive, and we will potentially want to use the name Root for a broader concept shared between ArtifactRoot and RootedPath.

PiperOrigin-RevId: 182082367
diff --git a/src/main/java/com/google/devtools/build/lib/actions/Artifact.java b/src/main/java/com/google/devtools/build/lib/actions/Artifact.java
index 7468de1..a72c77d 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/Artifact.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/Artifact.java
@@ -164,7 +164,7 @@
 
   private final int hashCode;
   private final Path path;
-  private final Root root;
+  private final ArtifactRoot root;
   private final PathFragment execPath;
   private final PathFragment rootRelativePath;
   private final ArtifactOwner owner;
@@ -176,18 +176,20 @@
    *
    * <p>In a source Artifact, the path tail after the root will be identical to the execPath, but
    * the root will be orthogonal to execRoot.
+   *
    * <pre>
    *  [path] == [/root/][execPath]
    * </pre>
    *
    * <p>In a derived Artifact, the execPath will overlap with part of the root, which in turn will
    * be below the execRoot.
+   *
    * <pre>
    *  [path] == [/root][pathTail] == [/execRoot][execPath] == [/execRoot][rootPrefix][pathTail]
    * </pre>
    */
   @VisibleForTesting
-  public Artifact(Path path, Root root, PathFragment execPath, ArtifactOwner owner) {
+  public Artifact(Path path, ArtifactRoot root, PathFragment execPath, ArtifactOwner owner) {
     if (root == null || !path.startsWith(root.getPath())) {
       throw new IllegalArgumentException(root + ": illegal root for " + path
           + " (execPath: " + execPath + ")");
@@ -233,7 +235,7 @@
    * <pre>
    */
   @VisibleForTesting
-  public Artifact(Path path, Root root, PathFragment execPath) {
+  public Artifact(Path path, ArtifactRoot root, PathFragment execPath) {
     this(path, root, execPath, ArtifactOwner.NULL_OWNER);
   }
 
@@ -241,17 +243,15 @@
    * Constructs a source or derived Artifact for the specified path and specified root. The root
    * must be an ancestor of the path.
    */
-  @VisibleForTesting  // Only exists for testing.
-  public Artifact(Path path, Root root) {
+  @VisibleForTesting // Only exists for testing.
+  public Artifact(Path path, ArtifactRoot root) {
     this(path, root, root.getExecPath().getRelative(path.relativeTo(root.getPath())),
         ArtifactOwner.NULL_OWNER);
   }
 
-  /**
-   * Constructs a source or derived Artifact for the specified root-relative path and root.
-   */
-  @VisibleForTesting  // Only exists for testing.
-  public Artifact(PathFragment rootRelativePath, Root root) {
+  /** Constructs a source or derived Artifact for the specified root-relative path and root. */
+  @VisibleForTesting // Only exists for testing.
+  public Artifact(PathFragment rootRelativePath, ArtifactRoot root) {
     this(root.getPath().getRelative(rootRelativePath), root,
         root.getExecPath().getRelative(rootRelativePath), ArtifactOwner.NULL_OWNER);
   }
@@ -347,13 +347,15 @@
 
   /**
    * Returns the root beneath which this Artifact resides, if any. This may be one of the
-   * package-path entries (for source Artifacts), or one of the bin, genfiles or includes dirs
-   * (for derived Artifacts). It will always be an ancestor of getPath().
+   * package-path entries (for source Artifacts), or one of the bin, genfiles or includes dirs (for
+   * derived Artifacts). It will always be an ancestor of getPath().
    */
-  @SkylarkCallable(name = "root", structField = true,
-      doc = "The root beneath which this file resides."
+  @SkylarkCallable(
+    name = "root",
+    structField = true,
+    doc = "The root beneath which this file resides."
   )
-  public final Root getRoot() {
+  public final ArtifactRoot getRoot() {
     return root;
   }
 
@@ -443,7 +445,11 @@
     private final SpecialArtifactType type;
 
     @VisibleForTesting
-    public SpecialArtifact(Path path, Root root, PathFragment execPath, ArtifactOwner owner,
+    public SpecialArtifact(
+        Path path,
+        ArtifactRoot root,
+        PathFragment execPath,
+        ArtifactOwner owner,
         SpecialArtifactType type) {
       super(path, root, execPath, owner);
       this.type = type;
diff --git a/src/main/java/com/google/devtools/build/lib/actions/ArtifactFactory.java b/src/main/java/com/google/devtools/build/lib/actions/ArtifactFactory.java
index 37bd6f4..26d97f7 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/ArtifactFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/ArtifactFactory.java
@@ -145,7 +145,7 @@
   }
 
   @Override
-  public Artifact getSourceArtifact(PathFragment execPath, Root root, ArtifactOwner owner) {
+  public Artifact getSourceArtifact(PathFragment execPath, ArtifactRoot root, ArtifactOwner owner) {
     Preconditions.checkArgument(!execPath.isAbsolute(), "%s %s %s", execPath, root, owner);
     Preconditions.checkNotNull(owner, "%s %s", execPath, root);
     execPath = execPath.normalize();
@@ -153,11 +153,11 @@
   }
 
   @Override
-  public Artifact getSourceArtifact(PathFragment execPath, Root root) {
+  public Artifact getSourceArtifact(PathFragment execPath, ArtifactRoot root) {
     return getSourceArtifact(execPath, root, ArtifactOwner.NULL_OWNER);
   }
 
-  private void validatePath(PathFragment rootRelativePath, Root root) {
+  private void validatePath(PathFragment rootRelativePath, ArtifactRoot root) {
     Preconditions.checkArgument(!root.isSourceRoot());
     Preconditions.checkArgument(!rootRelativePath.isAbsolute(), rootRelativePath);
     Preconditions.checkArgument(rootRelativePath.isNormalized(), rootRelativePath);
@@ -177,8 +177,8 @@
    * computed as {@code root.getRelative(rootRelativePath).relativeTo(root.execRoot)}.
    */
   // TODO(bazel-team): Don't allow root == execRootParent.
-  public Artifact getDerivedArtifact(PathFragment rootRelativePath, Root root,
-      ArtifactOwner owner) {
+  public Artifact getDerivedArtifact(
+      PathFragment rootRelativePath, ArtifactRoot root, ArtifactOwner owner) {
     validatePath(rootRelativePath, root);
     Path path = root.getPath().getRelative(rootRelativePath);
     return getArtifact(path, root, path.relativeTo(root.getExecRoot()), owner, null);
@@ -192,8 +192,8 @@
    * <p>The root must be below the execRootParent, and the execPath of the resulting Artifact is
    * computed as {@code root.getRelative(rootRelativePath).relativeTo(root.execRoot)}.
    */
-  public Artifact getFilesetArtifact(PathFragment rootRelativePath, Root root,
-      ArtifactOwner owner) {
+  public Artifact getFilesetArtifact(
+      PathFragment rootRelativePath, ArtifactRoot root, ArtifactOwner owner) {
     validatePath(rootRelativePath, root);
     Path path = root.getPath().getRelative(rootRelativePath);
     return getArtifact(
@@ -201,22 +201,22 @@
   }
 
   /**
-   * Returns an artifact that represents a TreeArtifact; that is, a directory containing some
-   * tree of ArtifactFiles unknown at analysis time.
+   * Returns an artifact that represents a TreeArtifact; that is, a directory containing some tree
+   * of ArtifactFiles unknown at analysis time.
    *
    * <p>The root must be below the execRootParent, and the execPath of the resulting Artifact is
    * computed as {@code root.getRelative(rootRelativePath).relativeTo(root.execRoot)}.
    */
-  public Artifact getTreeArtifact(PathFragment rootRelativePath, Root root,
-      ArtifactOwner owner) {
+  public Artifact getTreeArtifact(
+      PathFragment rootRelativePath, ArtifactRoot root, ArtifactOwner owner) {
     validatePath(rootRelativePath, root);
     Path path = root.getPath().getRelative(rootRelativePath);
     return getArtifact(
         path, root, path.relativeTo(root.getExecRoot()), owner, SpecialArtifactType.TREE);
   }
 
-  public Artifact getConstantMetadataArtifact(PathFragment rootRelativePath, Root root,
-      ArtifactOwner owner) {
+  public Artifact getConstantMetadataArtifact(
+      PathFragment rootRelativePath, ArtifactRoot root, ArtifactOwner owner) {
     validatePath(rootRelativePath, root);
     Path path = root.getPath().getRelative(rootRelativePath);
     return getArtifact(
@@ -225,12 +225,15 @@
   }
 
   /**
-   * Returns the Artifact for the specified path, creating one if not found and
-   * setting the <code>root</code> and <code>execPath</code> to the
-   * specified values.
+   * Returns the Artifact for the specified path, creating one if not found and setting the <code>
+   * root</code> and <code>execPath</code> to the specified values.
    */
-  private synchronized Artifact getArtifact(Path path, Root root, PathFragment execPath,
-      ArtifactOwner owner, @Nullable SpecialArtifactType type) {
+  private synchronized Artifact getArtifact(
+      Path path,
+      ArtifactRoot root,
+      PathFragment execPath,
+      ArtifactOwner owner,
+      @Nullable SpecialArtifactType type) {
     Preconditions.checkNotNull(root);
     Preconditions.checkNotNull(execPath);
 
@@ -250,7 +253,11 @@
     return artifact;
   }
 
-  private Artifact createArtifact(Path path, Root root, PathFragment execPath, ArtifactOwner owner,
+  private Artifact createArtifact(
+      Path path,
+      ArtifactRoot root,
+      PathFragment execPath,
+      ArtifactOwner owner,
       @Nullable SpecialArtifactType type) {
     Preconditions.checkNotNull(owner, path);
     if (type == null) {
@@ -261,13 +268,15 @@
   }
 
   /**
-   * Returns an {@link Artifact} with exec path formed by composing {@code baseExecPath} and
-   * {@code relativePath} (via {@code baseExecPath.getRelative(relativePath)} if baseExecPath is
-   * not null). That Artifact will have root determined by the package roots of this factory if it
-   * lives in a subpackage distinct from that of baseExecPath, and {@code baseRoot} otherwise.
+   * Returns an {@link Artifact} with exec path formed by composing {@code baseExecPath} and {@code
+   * relativePath} (via {@code baseExecPath.getRelative(relativePath)} if baseExecPath is not null).
+   * That Artifact will have root determined by the package roots of this factory if it lives in a
+   * subpackage distinct from that of baseExecPath, and {@code baseRoot} otherwise.
    */
   public synchronized Artifact resolveSourceArtifactWithAncestor(
-      PathFragment relativePath, PathFragment baseExecPath, Root baseRoot,
+      PathFragment relativePath,
+      PathFragment baseExecPath,
+      ArtifactRoot baseRoot,
       RepositoryName repositoryName) {
     Preconditions.checkState(
         (baseExecPath == null) == (baseRoot == null),
@@ -288,10 +297,10 @@
     if (isDerivedArtifact(execPath)) {
       return null;
     }
-    Root sourceRoot = findSourceRoot(execPath, baseExecPath, baseRoot, repositoryName);
+    ArtifactRoot sourceRoot = findSourceRoot(execPath, baseExecPath, baseRoot, repositoryName);
     Artifact artifact = sourceArtifactCache.getArtifactIfValid(execPath);
     if (artifact != null) {
-      Root artifactRoot = artifact.getRoot();
+      ArtifactRoot artifactRoot = artifact.getRoot();
       Preconditions.checkState(
           sourceRoot == null || sourceRoot.equals(artifactRoot),
           "roots mismatch: %s %s %s",
@@ -308,8 +317,10 @@
    * root directory if our execPath doesn't start with baseExecPath due to uplevel references.
    */
   @Nullable
-  private Root findSourceRoot(
-      PathFragment execPath, @Nullable PathFragment baseExecPath, @Nullable Root baseRoot,
+  private ArtifactRoot findSourceRoot(
+      PathFragment execPath,
+      @Nullable PathFragment baseExecPath,
+      @Nullable ArtifactRoot baseRoot,
       RepositoryName repositoryName) {
     PathFragment dir = execPath.getParentDirectory();
     if (dir == null) {
@@ -323,7 +334,7 @@
     }
 
     while (dir != null && !dir.equals(baseExecPath)) {
-      Root sourceRoot =
+      ArtifactRoot sourceRoot =
           packageRoots.getRootForPackage(PackageIdentifier.create(repositoryName, dir));
       if (sourceRoot != null) {
         return sourceRoot;
@@ -365,7 +376,8 @@
         unresolvedPaths.add(execPath);
       }
     }
-    Map<PathFragment, Root> sourceRoots = resolver.findPackageRootsForFiles(unresolvedPaths);
+    Map<PathFragment, ArtifactRoot> sourceRoots =
+        resolver.findPackageRootsForFiles(unresolvedPaths);
     // We are missing some dependencies. We need to rerun this method later.
     if (sourceRoots == null) {
       return null;
@@ -380,7 +392,7 @@
   public Path getPathFromSourceExecPath(PathFragment execPath) {
     Preconditions.checkState(
         !execPath.startsWith(derivedPathPrefix), "%s is derived: %s", execPath, derivedPathPrefix);
-    Root sourceRoot =
+    ArtifactRoot sourceRoot =
         packageRoots.getRootForPackage(PackageIdentifier.create(RepositoryName.MAIN, execPath));
     if (sourceRoot != null) {
       return sourceRoot.getPath().getRelative(execPath);
@@ -388,7 +400,7 @@
     return execRoot.getRelative(execPath);
   }
 
-  private Artifact createArtifactIfNotValid(Root sourceRoot, PathFragment execPath) {
+  private Artifact createArtifactIfNotValid(ArtifactRoot sourceRoot, PathFragment execPath) {
     if (sourceRoot == null) {
       return null;  // not a path that we can find...
     }
diff --git a/src/main/java/com/google/devtools/build/lib/actions/ArtifactResolver.java b/src/main/java/com/google/devtools/build/lib/actions/ArtifactResolver.java
index 7542118..2b543d2 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/ArtifactResolver.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/ArtifactResolver.java
@@ -34,15 +34,15 @@
    * @param owner the artifact owner.
    * @return the canonical source artifact for the given path
    */
-  Artifact getSourceArtifact(PathFragment execPath, Root root, ArtifactOwner owner);
+  Artifact getSourceArtifact(PathFragment execPath, ArtifactRoot root, ArtifactOwner owner);
 
   /**
    * Returns the source Artifact for the specified path, creating it if not found and setting its
    * root and execPath.
    *
-   * @see #getSourceArtifact(PathFragment, Root, ArtifactOwner)
+   * @see #getSourceArtifact(PathFragment, ArtifactRoot, ArtifactOwner)
    */
-  Artifact getSourceArtifact(PathFragment execPath, Root root);
+  Artifact getSourceArtifact(PathFragment execPath, ArtifactRoot root);
 
   /**
    * Resolves a source Artifact given an execRoot-relative path.
diff --git a/src/main/java/com/google/devtools/build/lib/actions/Root.java b/src/main/java/com/google/devtools/build/lib/actions/ArtifactRoot.java
similarity index 83%
rename from src/main/java/com/google/devtools/build/lib/actions/Root.java
rename to src/main/java/com/google/devtools/build/lib/actions/ArtifactRoot.java
index 27c6898..47b3c5e 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/Root.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/ArtifactRoot.java
@@ -44,16 +44,19 @@
  * <p>The derived roots must have paths that point inside the exec root, i.e. below the directory
  * that is the root of the merged directory tree.
  */
-@SkylarkModule(name = "root",
-    category = SkylarkModuleCategory.BUILTIN,
-    doc = "A root for files. The roots are the directories containing files, and they are mapped "
-        + "together into a single directory tree to form the execution environment.")
+@SkylarkModule(
+  name = "root",
+  category = SkylarkModuleCategory.BUILTIN,
+  doc =
+      "A root for files. The roots are the directories containing files, and they are mapped "
+          + "together into a single directory tree to form the execution environment."
+)
 @Immutable
-public final class Root implements Comparable<Root>, Serializable, SkylarkValue {
+public final class ArtifactRoot implements Comparable<ArtifactRoot>, Serializable, SkylarkValue {
 
   // This must always be consistent with Package.getSourceRoot; otherwise computing source roots
   // from exec paths does not work, which can break the action cache for input-discovering actions.
-  public static Root computeSourceRoot(Path packageRoot, RepositoryName repository) {
+  public static ArtifactRoot computeSourceRoot(Path packageRoot, RepositoryName repository) {
     if (repository.isMain()) {
       return asSourceRoot(packageRoot);
     } else {
@@ -66,8 +69,8 @@
   }
 
   /** Returns the given path as a source root. The path may not be {@code null}. */
-  public static Root asSourceRoot(Path path) {
-    return new Root(null, path);
+  public static ArtifactRoot asSourceRoot(Path path) {
+    return new ArtifactRoot(null, path);
   }
 
   /**
@@ -77,17 +80,17 @@
    * <p>Be careful with this method - all derived roots must be registered with the artifact factory
    * before the analysis phase.
    */
-  public static Root asDerivedRoot(Path execRoot, Path root) {
+  public static ArtifactRoot asDerivedRoot(Path execRoot, Path root) {
     Preconditions.checkArgument(root.startsWith(execRoot));
     Preconditions.checkArgument(!root.equals(execRoot));
-    return new Root(execRoot, root);
+    return new ArtifactRoot(execRoot, root);
   }
 
-  public static Root middlemanRoot(Path execRoot, Path outputDir) {
+  public static ArtifactRoot middlemanRoot(Path execRoot, Path outputDir) {
     Path root = outputDir.getRelative("internal");
     Preconditions.checkArgument(root.startsWith(execRoot));
     Preconditions.checkArgument(!root.equals(execRoot));
-    return new Root(execRoot, root, true);
+    return new ArtifactRoot(execRoot, root, true);
   }
 
   @Nullable private final Path execRoot;
@@ -95,14 +98,14 @@
   private final boolean isMiddlemanRoot;
   private final PathFragment execPath;
 
-  private Root(@Nullable Path execRoot, Path path, boolean isMiddlemanRoot) {
+  private ArtifactRoot(@Nullable Path execRoot, Path path, boolean isMiddlemanRoot) {
     this.execRoot = execRoot;
     this.path = Preconditions.checkNotNull(path);
     this.isMiddlemanRoot = isMiddlemanRoot;
     this.execPath = isSourceRoot() ? PathFragment.EMPTY_FRAGMENT : path.relativeTo(execRoot);
   }
 
-  private Root(@Nullable Path execRoot, Path path) {
+  private ArtifactRoot(@Nullable Path execRoot, Path path) {
     this(execRoot, path, false);
   }
 
@@ -138,7 +141,7 @@
   }
 
   @Override
-  public int compareTo(Root o) {
+  public int compareTo(ArtifactRoot o) {
     return path.compareTo(o.path);
   }
 
@@ -152,10 +155,10 @@
     if (o == this) {
       return true;
     }
-    if (!(o instanceof Root)) {
+    if (!(o instanceof ArtifactRoot)) {
       return false;
     }
-    Root r = (Root) o;
+    ArtifactRoot r = (ArtifactRoot) o;
     return path.equals(r.path) && Objects.equals(execRoot, r.execRoot);
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/actions/MiddlemanFactory.java b/src/main/java/com/google/devtools/build/lib/actions/MiddlemanFactory.java
index fbbc100..43a9e37 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/MiddlemanFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/MiddlemanFactory.java
@@ -45,15 +45,15 @@
    *
    * @param owner the owner of the action that will be created; must not be null
    * @param purpose the purpose for which this middleman is created. This should be a string which
-   *        is suitable for use as a filename. A single rule may have many middlemen with distinct
-   *        purposes.
+   *     is suitable for use as a filename. A single rule may have many middlemen with distinct
+   *     purposes.
    * @param inputs the set of artifacts for which the created artifact is to be the middleman.
    * @param middlemanDir the directory in which to place the middleman.
    * @return null iff {@code inputs} is empty; the single element of {@code inputs} if there's only
-   *         one; a new aggregating middleman for the {@code inputs} otherwise
+   *     one; a new aggregating middleman for the {@code inputs} otherwise
    */
   public Artifact createAggregatingMiddleman(
-      ActionOwner owner, String purpose, Iterable<Artifact> inputs, Root middlemanDir) {
+      ActionOwner owner, String purpose, Iterable<Artifact> inputs, ArtifactRoot middlemanDir) {
     if (hasExactlyOneInput(inputs)) { // Optimization: No middleman for just one input.
       return Iterables.getOnlyElement(inputs);
     }
@@ -64,28 +64,26 @@
   }
 
   /**
-   * Returns <code>null</code> iff inputs is empty. Returns the sole element
-   * of inputs iff <code>inputs.size()==1</code>. Otherwise, returns a
-   * middleman artifact and creates a middleman action that generates that
-   * artifact.
+   * Returns <code>null</code> iff inputs is empty. Returns the sole element of inputs iff <code>
+   * inputs.size()==1</code>. Otherwise, returns a middleman artifact and creates a middleman action
+   * that generates that artifact.
    *
    * @param owner the owner of the action that will be created.
-   * @param owningArtifact the artifact of the file for which the runfiles
-   *        should be created. There may be at most one set of runfiles for
-   *        an owning artifact, unless the owning artifact is null. There
-   *        may be at most one set of runfiles per owner with a null
-   *        owning artifact.
-   *        Further, if the owning Artifact is non-null, the owning Artifacts'
-   *        root-relative path must be unique and the artifact must be part
-   *        of the runfiles tree for which this middleman is created. Usually
-   *        this artifact will be an executable program.
-   * @param inputs the set of artifacts for which the created artifact is to be
-   *        the middleman.
+   * @param owningArtifact the artifact of the file for which the runfiles should be created. There
+   *     may be at most one set of runfiles for an owning artifact, unless the owning artifact is
+   *     null. There may be at most one set of runfiles per owner with a null owning artifact.
+   *     Further, if the owning Artifact is non-null, the owning Artifacts' root-relative path must
+   *     be unique and the artifact must be part of the runfiles tree for which this middleman is
+   *     created. Usually this artifact will be an executable program.
+   * @param inputs the set of artifacts for which the created artifact is to be the middleman.
    * @param middlemanDir the directory in which to place the middleman.
    */
   public Artifact createRunfilesMiddleman(
-      ActionOwner owner, @Nullable Artifact owningArtifact, Iterable<Artifact> inputs,
-      Root middlemanDir, String tag) {
+      ActionOwner owner,
+      @Nullable Artifact owningArtifact,
+      Iterable<Artifact> inputs,
+      ArtifactRoot middlemanDir,
+      String tag) {
     Preconditions.checkArgument(middlemanDir.isMiddlemanRoot());
     if (hasExactlyOneInput(inputs)) { // Optimization: No middleman for just one input.
       return Iterables.getOnlyElement(inputs);
@@ -114,19 +112,23 @@
    *
    * @param owner the owner of the action that will be created. May not be null.
    * @param middlemanName a unique file name for the middleman artifact in the {@code middlemanDir};
-   *        in practice this is usually the owning rule's label (so it gets escaped as such)
+   *     in practice this is usually the owning rule's label (so it gets escaped as such)
    * @param purpose the purpose for which this middleman is created. This should be a string which
-   *        is suitable for use as a filename. A single rule may have many middlemen with distinct
-   *        purposes.
+   *     is suitable for use as a filename. A single rule may have many middlemen with distinct
+   *     purposes.
    * @param inputs the set of artifacts for which the created artifact is to be the middleman; must
-   *        not be null or empty
+   *     not be null or empty
    * @param middlemanDir the directory in which to place the middleman.
    * @return a middleman that enforces scheduling order (just like a scheduling middleman) and
-   *         propagates errors, but is ignored by the dependency checker
+   *     propagates errors, but is ignored by the dependency checker
    * @throws IllegalArgumentException if {@code inputs} is null or empty
    */
-  public Artifact createErrorPropagatingMiddleman(ActionOwner owner, String middlemanName,
-      String purpose, Iterable<Artifact> inputs, Root middlemanDir) {
+  public Artifact createErrorPropagatingMiddleman(
+      ActionOwner owner,
+      String middlemanName,
+      String purpose,
+      Iterable<Artifact> inputs,
+      ArtifactRoot middlemanDir) {
     Preconditions.checkArgument(inputs != null);
     Preconditions.checkArgument(!Iterables.isEmpty(inputs));
     // We must always create this middleman even if there is only one input.
@@ -135,11 +137,11 @@
   }
 
   /**
-   * Returns the same artifact as {@code createErrorPropagatingMiddleman} would return,
-   * but doesn't create any action.
+   * Returns the same artifact as {@code createErrorPropagatingMiddleman} would return, but doesn't
+   * create any action.
    */
-  public Artifact getErrorPropagatingMiddlemanArtifact(String middlemanName, String purpose,
-      Root middlemanDir) {
+  public Artifact getErrorPropagatingMiddlemanArtifact(
+      String middlemanName, String purpose, ArtifactRoot middlemanDir) {
     return getStampFileArtifact(middlemanName, purpose, middlemanDir);
   }
 
@@ -150,11 +152,15 @@
    * another synchronized method (getArtifact()).
    *
    * @return null iff {@code inputs} is null or empty; the middleman file and the middleman action
-   *         otherwise
+   *     otherwise
    */
   private Pair<Artifact, Action> createMiddleman(
-      ActionOwner owner, String middlemanName, String purpose, Iterable<Artifact> inputs,
-      Root middlemanDir, MiddlemanType middlemanType) {
+      ActionOwner owner,
+      String middlemanName,
+      String purpose,
+      Iterable<Artifact> inputs,
+      ArtifactRoot middlemanDir,
+      MiddlemanType middlemanType) {
     if (inputs == null || CollectionUtils.isEmpty(inputs)) {
       return null;
     }
@@ -175,8 +181,13 @@
    * <p>Note: there's no need to synchronize this method; the only use of a field is via a call to
    * another synchronized method (getArtifact()).
    */
-  public Artifact createMiddlemanAllowMultiple(ActionRegistry registry, ActionOwner owner,
-      PathFragment packageDirectory, String purpose, Iterable<Artifact> inputs, Root middlemanDir) {
+  public Artifact createMiddlemanAllowMultiple(
+      ActionRegistry registry,
+      ActionOwner owner,
+      PathFragment packageDirectory,
+      String purpose,
+      Iterable<Artifact> inputs,
+      ArtifactRoot middlemanDir) {
     String escapedPackageDirectory = Actions.escapedPath(packageDirectory.getPathString());
     PathFragment stampName =
         PathFragment.create("_middlemen/" + (purpose.startsWith(escapedPackageDirectory)
@@ -188,7 +199,8 @@
     return stampFile;
   }
 
-  private Artifact getStampFileArtifact(String middlemanName, String purpose, Root middlemanDir) {
+  private Artifact getStampFileArtifact(
+      String middlemanName, String purpose, ArtifactRoot middlemanDir) {
     String escapedFilename = Actions.escapedPath(middlemanName);
     PathFragment stampName = PathFragment.create("_middlemen/" + escapedFilename + "-" + purpose);
     Artifact stampFile = artifactFactory.getDerivedArtifact(stampName, middlemanDir,
diff --git a/src/main/java/com/google/devtools/build/lib/actions/PackageRootResolver.java b/src/main/java/com/google/devtools/build/lib/actions/PackageRootResolver.java
index 35a795a..e7529bc 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/PackageRootResolver.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/PackageRootResolver.java
@@ -26,13 +26,14 @@
   /**
    * Returns mapping from execPath to Root. Root will be null if the path has no containing package.
    *
-   * @param execPaths the paths to find {@link Root}s for. The search for a containing package will
-   *     start with the path's parent directory, since the path is assumed to be a file.
-   * @return mappings from {@code execPath} to {@link Root}, or null if for some reason we cannot
-   *     determine the result at this time (such as when used within a SkyFunction)
+   * @param execPaths the paths to find {@link ArtifactRoot}s for. The search for a containing
+   *     package will start with the path's parent directory, since the path is assumed to be a
+   *     file.
+   * @return mappings from {@code execPath} to {@link ArtifactRoot}, or null if for some reason we
+   *     cannot determine the result at this time (such as when used within a SkyFunction)
    */
   @Nullable
-  Map<PathFragment, Root> findPackageRootsForFiles(Iterable<PathFragment> execPaths)
+  Map<PathFragment, ArtifactRoot> findPackageRootsForFiles(Iterable<PathFragment> execPaths)
       throws InterruptedException;
 
   /**
@@ -40,13 +41,14 @@
    * Unlike {@link #findPackageRootsForFiles(Iterable)}, this function allows directories in the
    * list of exec paths.
    *
-   * @param execPaths the paths to find {@link Root}s for. The search for a containing package will
-   *     start with the path's parent directory, since the path is assumed to be a file.
-   * @return mappings from {@code execPath} to {@link Root}, or null if for some reason we cannot
-   *     determine the result at this time (such as when used within a SkyFunction)
+   * @param execPaths the paths to find {@link ArtifactRoot}s for. The search for a containing
+   *     package will start with the path's parent directory, since the path is assumed to be a
+   *     file.
+   * @return mappings from {@code execPath} to {@link ArtifactRoot}, or null if for some reason we
+   *     cannot determine the result at this time (such as when used within a SkyFunction)
    */
   // TODO(bazel-team): Remove this once we don't need to find package roots for directories.
   @Nullable
-  Map<PathFragment, Root> findPackageRoots(Iterable<PathFragment> execPaths)
+  Map<PathFragment, ArtifactRoot> findPackageRoots(Iterable<PathFragment> execPaths)
       throws InterruptedException;
 }
diff --git a/src/main/java/com/google/devtools/build/lib/actions/PackageRoots.java b/src/main/java/com/google/devtools/build/lib/actions/PackageRoots.java
index 35f7f3f..9275e3f 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/PackageRoots.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/PackageRoots.java
@@ -39,12 +39,12 @@
   /** Interface for getting the source root of a package, given its {@link PackageIdentifier}. */
   interface PackageRootLookup {
     /**
-     * Returns the {@link Root} of a package, given its {@link PackageIdentifier}. May be null if
-     * the given {@code packageIdentifier} does not correspond to a package in this build. However,
-     * if there is a unique source root for all packages, this may return that root even if the
-     * {@code packageIdentifier} given does not correspond to any packages.
+     * Returns the {@link ArtifactRoot} of a package, given its {@link PackageIdentifier}. May be
+     * null if the given {@code packageIdentifier} does not correspond to a package in this build.
+     * However, if there is a unique source root for all packages, this may return that root even if
+     * the {@code packageIdentifier} given does not correspond to any packages.
      */
     @Nullable
-    Root getRootForPackage(PackageIdentifier packageIdentifier);
+    ArtifactRoot getRootForPackage(PackageIdentifier packageIdentifier);
   }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/AnalysisEnvironment.java b/src/main/java/com/google/devtools/build/lib/analysis/AnalysisEnvironment.java
index 2d7466d..098a04e 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/AnalysisEnvironment.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/AnalysisEnvironment.java
@@ -21,8 +21,8 @@
 import com.google.devtools.build.lib.actions.ActionKeyContext;
 import com.google.devtools.build.lib.actions.ActionRegistry;
 import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.ArtifactRoot;
 import com.google.devtools.build.lib.actions.MiddlemanFactory;
-import com.google.devtools.build.lib.actions.Root;
 import com.google.devtools.build.lib.analysis.buildinfo.BuildInfoFactory.BuildInfoKey;
 import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
 import com.google.devtools.build.lib.events.ExtendedEventHandler;
@@ -52,10 +52,11 @@
   /**
    * Returns the artifact for the derived file {@code rootRelativePath}.
    *
-   * <p><b>DO NOT USE</b> in rule implementations. Use
-   * {@link RuleContext#getPackageRelativeArtifact(PathFragment, Root)} or
-   * {@link RuleContext#getUniqueDirectoryArtifact(String, PathFragment, Root)}, or, if there is
-   * really no other way, {@link RuleContext#getShareableArtifact(PathFragment, Root)} instead.
+   * <p><b>DO NOT USE</b> in rule implementations. Use {@link
+   * RuleContext#getPackageRelativeArtifact(PathFragment, ArtifactRoot)} or {@link
+   * RuleContext#getUniqueDirectoryArtifact(String, PathFragment, ArtifactRoot)}, or, if there is
+   * really no other way, {@link RuleContext#getShareableArtifact(PathFragment, ArtifactRoot)}
+   * instead.
    *
    * <p>Creates the artifact if necessary and sets the root of that artifact to {@code root}.
    *
@@ -63,33 +64,32 @@
    * artifacts generated by two different rules to clash. To avoid this, use the artifact creation
    * method on {@link RuleContext} mentioned above.
    */
-  Artifact getDerivedArtifact(PathFragment rootRelativePath, Root root);
+  Artifact getDerivedArtifact(PathFragment rootRelativePath, ArtifactRoot root);
 
   /**
-   * Returns an artifact for the derived file {@code rootRelativePath} whose changes do not cause
-   * a rebuild.
+   * Returns an artifact for the derived file {@code rootRelativePath} whose changes do not cause a
+   * rebuild.
    *
    * <p>Creates the artifact if necessary and sets the root of that artifact to {@code root}.
    *
    * <p>This is useful for files that store data that changes very frequently (e.g. current time)
    * but does not substantially affect the result of the build.
    */
-  Artifact getConstantMetadataArtifact(PathFragment rootRelativePath,
-      Root root);
+  Artifact getConstantMetadataArtifact(PathFragment rootRelativePath, ArtifactRoot root);
 
   /**
    * Returns the artifact for the derived TreeArtifact with directory {@code rootRelativePath},
-   * creating it if necessary, and setting the root of that artifact to
-   * {@code root}. The artifact will be a TreeArtifact.
+   * creating it if necessary, and setting the root of that artifact to {@code root}. The artifact
+   * will be a TreeArtifact.
    */
-  Artifact getTreeArtifact(PathFragment rootRelativePath, Root root);
+  Artifact getTreeArtifact(PathFragment rootRelativePath, ArtifactRoot root);
 
   /**
-   * Returns the artifact for the derived file {@code rootRelativePath},
-   * creating it if necessary, and setting the root of that artifact to
-   * {@code root}. The artifact will represent the output directory of a {@code Fileset}.
+   * Returns the artifact for the derived file {@code rootRelativePath}, creating it if necessary,
+   * and setting the root of that artifact to {@code root}. The artifact will represent the output
+   * directory of a {@code Fileset}.
    */
-  Artifact getFilesetArtifact(PathFragment rootRelativePath, Root root);
+  Artifact getFilesetArtifact(PathFragment rootRelativePath, ArtifactRoot root);
 
   /**
    * Returns the middleman factory associated with the build.
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/BlazeDirectories.java b/src/main/java/com/google/devtools/build/lib/analysis/BlazeDirectories.java
index 3e7df15..bbae6b4 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/BlazeDirectories.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/BlazeDirectories.java
@@ -16,7 +16,7 @@
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.hash.HashCode;
-import com.google.devtools.build.lib.actions.Root;
+import com.google.devtools.build.lib.actions.ArtifactRoot;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
 import com.google.devtools.build.lib.skyframe.serialization.InjectingObjectCodec;
 import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
@@ -171,8 +171,8 @@
    * Returns the configuration-independent root where the build-data should be placed, given the
    * {@link BlazeDirectories} of this server instance. Nothing else should be placed here.
    */
-  public Root getBuildDataDirectory(String workspaceName) {
-    return Root.asDerivedRoot(getExecRoot(workspaceName), getOutputPath(workspaceName));
+  public ArtifactRoot getBuildDataDirectory(String workspaceName) {
+    return ArtifactRoot.asDerivedRoot(getExecRoot(workspaceName), getOutputPath(workspaceName));
   }
 
   /**
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/CachingAnalysisEnvironment.java b/src/main/java/com/google/devtools/build/lib/analysis/CachingAnalysisEnvironment.java
index 81d5d2e..94cc572 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/CachingAnalysisEnvironment.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/CachingAnalysisEnvironment.java
@@ -23,8 +23,8 @@
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.actions.ArtifactFactory;
 import com.google.devtools.build.lib.actions.ArtifactOwner;
+import com.google.devtools.build.lib.actions.ArtifactRoot;
 import com.google.devtools.build.lib.actions.MiddlemanFactory;
-import com.google.devtools.build.lib.actions.Root;
 import com.google.devtools.build.lib.analysis.buildinfo.BuildInfoCollection;
 import com.google.devtools.build.lib.analysis.buildinfo.BuildInfoFactory;
 import com.google.devtools.build.lib.analysis.buildinfo.BuildInfoFactory.BuildInfoKey;
@@ -233,7 +233,7 @@
   }
 
   @Override
-  public Artifact getDerivedArtifact(PathFragment rootRelativePath, Root root) {
+  public Artifact getDerivedArtifact(PathFragment rootRelativePath, ArtifactRoot root) {
     Preconditions.checkState(enabled);
     return trackArtifactAndOrigin(
         artifactFactory.getDerivedArtifact(rootRelativePath, root, getOwner()),
@@ -241,7 +241,7 @@
   }
 
   @Override
-  public Artifact getTreeArtifact(PathFragment rootRelativePath, Root root) {
+  public Artifact getTreeArtifact(PathFragment rootRelativePath, ArtifactRoot root) {
     Preconditions.checkState(enabled);
     return trackArtifactAndOrigin(
         artifactFactory.getTreeArtifact(rootRelativePath, root, getOwner()),
@@ -249,7 +249,7 @@
   }
 
   @Override
-  public Artifact getFilesetArtifact(PathFragment rootRelativePath, Root root) {
+  public Artifact getFilesetArtifact(PathFragment rootRelativePath, ArtifactRoot root) {
     Preconditions.checkState(enabled);
     return trackArtifactAndOrigin(
         artifactFactory.getFilesetArtifact(rootRelativePath, root, getOwner()),
@@ -257,7 +257,7 @@
   }
 
   @Override
-  public Artifact getConstantMetadataArtifact(PathFragment rootRelativePath, Root root) {
+  public Artifact getConstantMetadataArtifact(PathFragment rootRelativePath, ArtifactRoot root) {
     return artifactFactory.getConstantMetadataArtifact(rootRelativePath, root, getOwner());
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTargetFactory.java b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTargetFactory.java
index 3ad0240..af99802 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTargetFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTargetFactory.java
@@ -22,8 +22,8 @@
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.actions.ArtifactFactory;
 import com.google.devtools.build.lib.actions.ArtifactOwner;
+import com.google.devtools.build.lib.actions.ArtifactRoot;
 import com.google.devtools.build.lib.actions.FailAction;
-import com.google.devtools.build.lib.actions.Root;
 import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
 import com.google.devtools.build.lib.analysis.config.BuildConfiguration.Fragment;
 import com.google.devtools.build.lib.analysis.config.ConfigMatchingProvider;
@@ -163,9 +163,10 @@
       BuildConfiguration configuration, boolean isFileset, ArtifactFactory artifactFactory)
       throws InterruptedException {
     Rule rule = outputFile.getAssociatedRule();
-    Root root = rule.hasBinaryOutput()
-        ? configuration.getBinDirectory(rule.getRepository())
-        : configuration.getGenfilesDirectory(rule.getRepository());
+    ArtifactRoot root =
+        rule.hasBinaryOutput()
+            ? configuration.getBinDirectory(rule.getRepository())
+            : configuration.getGenfilesDirectory(rule.getRepository());
     ArtifactOwner owner =
         ConfiguredTargetKey.of(
             rule.getLabel(),
@@ -276,7 +277,7 @@
       Artifact artifact =
           artifactFactory.getSourceArtifact(
               inputFile.getExecPath(),
-              Root.asSourceRoot(inputFile.getPackage().getSourceRoot()),
+              ArtifactRoot.asSourceRoot(inputFile.getPackage().getSourceRoot()),
               ConfiguredTargetKey.of(target.getLabel(), config));
 
       return new InputFileConfiguredTarget(targetContext, inputFile, artifact);
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
index 2e366d9..674fd55 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
@@ -37,7 +37,7 @@
 import com.google.devtools.build.lib.actions.ActionRegistry;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.actions.ArtifactOwner;
-import com.google.devtools.build.lib.actions.Root;
+import com.google.devtools.build.lib.actions.ArtifactRoot;
 import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider.PrerequisiteValidator;
 import com.google.devtools.build.lib.analysis.actions.ActionConstructionContext;
 import com.google.devtools.build.lib.analysis.buildinfo.BuildInfoFactory.BuildInfoKey;
@@ -269,12 +269,12 @@
   }
 
   @Override
-  public Root getBinDirectory() {
+  public ArtifactRoot getBinDirectory() {
     return getConfiguration().getBinDirectory(rule.getRepository());
   }
 
   @Override
-  public Root getMiddlemanDirectory() {
+  public ArtifactRoot getMiddlemanDirectory() {
     return getConfiguration().getMiddlemanDirectory(rule.getRepository());
   }
 
@@ -565,27 +565,26 @@
         target.getLabel().getPackageIdentifier().equals(getLabel().getPackageIdentifier()),
         "Creating output artifact for target '%s' in different package than the rule '%s' "
             + "being analyzed", target.getLabel(), getLabel());
-    Root root = getBinOrGenfilesDirectory();
+    ArtifactRoot root = getBinOrGenfilesDirectory();
     return getPackageRelativeArtifact(target.getName(), root);
   }
 
   /**
-   * Returns the root of either the "bin" or "genfiles"
-   * tree, based on this target and the current configuration.
-   * The choice of which tree to use is based on the rule with
-   * which this target (which must be an OutputFile or a Rule) is associated.
+   * Returns the root of either the "bin" or "genfiles" tree, based on this target and the current
+   * configuration. The choice of which tree to use is based on the rule with which this target
+   * (which must be an OutputFile or a Rule) is associated.
    */
-  public Root getBinOrGenfilesDirectory() {
+  public ArtifactRoot getBinOrGenfilesDirectory() {
     return rule.hasBinaryOutput()
         ? getConfiguration().getBinDirectory(rule.getRepository())
         : getConfiguration().getGenfilesDirectory(rule.getRepository());
   }
 
   /**
-   * Creates an artifact in a directory that is unique to the package that contains the rule,
-   * thus guaranteeing that it never clashes with artifacts created by rules in other packages.
+   * Creates an artifact in a directory that is unique to the package that contains the rule, thus
+   * guaranteeing that it never clashes with artifacts created by rules in other packages.
    */
-  public Artifact getPackageRelativeArtifact(String relative, Root root) {
+  public Artifact getPackageRelativeArtifact(String relative, ArtifactRoot root) {
     return getPackageRelativeArtifact(PathFragment.create(relative), root);
   }
 
@@ -620,18 +619,18 @@
    * option.
    *
    * <p>This artifact can be created anywhere in the output tree, which, in addition to making
-   * sharing possible, opens up the possibility of action conflicts and makes it impossible to
-   * infer the label of the rule creating the artifact from the path of the artifact.
+   * sharing possible, opens up the possibility of action conflicts and makes it impossible to infer
+   * the label of the rule creating the artifact from the path of the artifact.
    */
-  public Artifact getShareableArtifact(PathFragment rootRelativePath, Root root) {
+  public Artifact getShareableArtifact(PathFragment rootRelativePath, ArtifactRoot root) {
     return getAnalysisEnvironment().getDerivedArtifact(rootRelativePath, root);
   }
 
   /**
-   * Creates an artifact in a directory that is unique to the package that contains the rule,
-   * thus guaranteeing that it never clashes with artifacts created by rules in other packages.
+   * Creates an artifact in a directory that is unique to the package that contains the rule, thus
+   * guaranteeing that it never clashes with artifacts created by rules in other packages.
    */
-  public Artifact getPackageRelativeArtifact(PathFragment relative, Root root) {
+  public Artifact getPackageRelativeArtifact(PathFragment relative, ArtifactRoot root) {
     return getDerivedArtifact(getPackageDirectory().getRelative(relative), root);
   }
 
@@ -639,15 +638,16 @@
    * Returns the root-relative path fragment under which output artifacts of this rule should go.
    *
    * <p>Note that:
+   *
    * <ul>
    *   <li>This doesn't guarantee that there are no clashes with rules in the same package.
-   *   <li>If possible, {@link #getPackageRelativeArtifact(PathFragment, Root)} should be used
-   *   instead of this method.
+   *   <li>If possible, {@link #getPackageRelativeArtifact(PathFragment, ArtifactRoot)} should be
+   *       used instead of this method.
    * </ul>
    *
    * Ideally, user-visible artifacts should all have corresponding output file targets, all others
-   * should go into a rule-specific directory.
-   * {@link #getUniqueDirectoryArtifact(String, PathFragment, Root)}) ensures that this is the case.
+   * should go into a rule-specific directory. {@link #getUniqueDirectoryArtifact(String,
+   * PathFragment, ArtifactRoot)}) ensures that this is the case.
    */
   public PathFragment getPackageDirectory() {
     return getLabel().getPackageIdentifier().getSourceRoot();
@@ -661,7 +661,7 @@
    * method.
    */
   @Override
-  public Artifact getDerivedArtifact(PathFragment rootRelativePath, Root root) {
+  public Artifact getDerivedArtifact(PathFragment rootRelativePath, ArtifactRoot root) {
     Preconditions.checkState(rootRelativePath.startsWith(getPackageDirectory()),
         "Output artifact '%s' not under package directory '%s' for target '%s'",
         rootRelativePath, getPackageDirectory(), getLabel());
@@ -675,7 +675,7 @@
    * thus ensuring that it doesn't clash with other artifacts generated by other rules using this
    * method.
    */
-  public Artifact getTreeArtifact(PathFragment rootRelativePath, Root root) {
+  public Artifact getTreeArtifact(PathFragment rootRelativePath, ArtifactRoot root) {
     Preconditions.checkState(rootRelativePath.startsWith(getPackageDirectory()),
         "Output artifact '%s' not under package directory '%s' for target '%s'",
         rootRelativePath, getPackageDirectory(), getLabel());
@@ -686,7 +686,7 @@
    * Creates a tree artifact in a directory that is unique to the package that contains the rule,
    * thus guaranteeing that it never clashes with artifacts created by rules in other packages.
    */
-  public Artifact getPackageRelativeTreeArtifact(PathFragment relative, Root root) {
+  public Artifact getPackageRelativeTreeArtifact(PathFragment relative, ArtifactRoot root) {
     return getTreeArtifact(getPackageDirectory().getRelative(relative), root);
   }
 
@@ -695,7 +695,7 @@
    * clashes with artifacts created by other rules.
    */
   public Artifact getUniqueDirectoryArtifact(
-      String uniqueDirectory, String relative, Root root) {
+      String uniqueDirectory, String relative, ArtifactRoot root) {
     return getUniqueDirectoryArtifact(uniqueDirectory, PathFragment.create(relative), root);
   }
 
@@ -704,7 +704,7 @@
    * clashes with artifacts created by other rules.
    */
   public Artifact getUniqueDirectoryArtifact(
-      String uniqueDirectory, PathFragment relative, Root root) {
+      String uniqueDirectory, PathFragment relative, ArtifactRoot root) {
     return getDerivedArtifact(getUniqueDirectory(uniqueDirectory).getRelative(relative), root);
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/SkyframePackageRootResolver.java b/src/main/java/com/google/devtools/build/lib/analysis/SkyframePackageRootResolver.java
index 9a9eee3..082c122 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/SkyframePackageRootResolver.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/SkyframePackageRootResolver.java
@@ -14,8 +14,8 @@
 
 package com.google.devtools.build.lib.analysis;
 
+import com.google.devtools.build.lib.actions.ArtifactRoot;
 import com.google.devtools.build.lib.actions.PackageRootResolver;
-import com.google.devtools.build.lib.actions.Root;
 import com.google.devtools.build.lib.events.ExtendedEventHandler;
 import com.google.devtools.build.lib.skyframe.SkyframeExecutor;
 import com.google.devtools.build.lib.vfs.PathFragment;
@@ -37,14 +37,14 @@
   }
 
   @Override
-  public Map<PathFragment, Root> findPackageRootsForFiles(Iterable<PathFragment> execPaths)
+  public Map<PathFragment, ArtifactRoot> findPackageRootsForFiles(Iterable<PathFragment> execPaths)
       throws InterruptedException {
     return executor.getArtifactRootsForFiles(eventHandler, execPaths);
   }
-  
+
   @Override
   @Nullable
-  public Map<PathFragment, Root> findPackageRoots(Iterable<PathFragment> execPaths)
+  public Map<PathFragment, ArtifactRoot> findPackageRoots(Iterable<PathFragment> execPaths)
       throws InterruptedException {
     return executor.getArtifactRoots(eventHandler, execPaths);
   }
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/actions/ActionConstructionContext.java b/src/main/java/com/google/devtools/build/lib/analysis/actions/ActionConstructionContext.java
index 3b10c5a..1eefb53 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/actions/ActionConstructionContext.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/actions/ActionConstructionContext.java
@@ -15,7 +15,7 @@
 
 import com.google.devtools.build.lib.actions.ActionOwner;
 import com.google.devtools.build.lib.actions.Artifact;
-import com.google.devtools.build.lib.actions.Root;
+import com.google.devtools.build.lib.actions.ArtifactRoot;
 import com.google.devtools.build.lib.analysis.AnalysisEnvironment;
 import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
 import com.google.devtools.build.lib.analysis.platform.PlatformInfo;
@@ -28,15 +28,11 @@
  */
 public interface ActionConstructionContext {
 
-  /**
-   * Returns the bin directory for constructed actions.
-   */
-  Root getBinDirectory();
+  /** Returns the bin directory for constructed actions. */
+  ArtifactRoot getBinDirectory();
 
-  /**
-   * Returns the internal directory (used for middlemen) for constructed actions.
-   */
-  Root getMiddlemanDirectory();
+  /** Returns the internal directory (used for middlemen) for constructed actions. */
+  ArtifactRoot getMiddlemanDirectory();
 
   /** Returns the action owner that should be used for actions. */
   ActionOwner getActionOwner();
@@ -54,7 +50,7 @@
    * thus ensuring that it doesn't clash with other artifacts generated by other rules using this
    * method.
    */
-  Artifact getDerivedArtifact(PathFragment rootRelativePath, Root root);
+  Artifact getDerivedArtifact(PathFragment rootRelativePath, ArtifactRoot root);
 
   /** Returns the {@link PlatformInfo} describing the execution platform this action should use. */
   @Nullable
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/buildinfo/BuildInfoFactory.java b/src/main/java/com/google/devtools/build/lib/analysis/buildinfo/BuildInfoFactory.java
index 07e9918..468fb27 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/buildinfo/BuildInfoFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/buildinfo/BuildInfoFactory.java
@@ -14,11 +14,10 @@
 package com.google.devtools.build.lib.analysis.buildinfo;
 
 import com.google.devtools.build.lib.actions.Artifact;
-import com.google.devtools.build.lib.actions.Root;
+import com.google.devtools.build.lib.actions.ArtifactRoot;
 import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
 import com.google.devtools.build.lib.cmdline.RepositoryName;
 import com.google.devtools.build.lib.vfs.PathFragment;
-
 import java.io.Serializable;
 
 /**
@@ -47,7 +46,8 @@
    * Context for the creation of build-info artifacts.
    */
   interface BuildInfoContext {
-    Artifact getBuildInfoArtifact(PathFragment rootRelativePath, Root root, BuildInfoType type);
+    Artifact getBuildInfoArtifact(
+        PathFragment rootRelativePath, ArtifactRoot root, BuildInfoType type);
   }
 
   /**
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java
index 9b6f5d1..10daadd 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java
@@ -34,7 +34,7 @@
 import com.google.common.collect.Multimap;
 import com.google.common.collect.MutableClassToInstanceMap;
 import com.google.devtools.build.lib.actions.ActionEnvironment;
-import com.google.devtools.build.lib.actions.Root;
+import com.google.devtools.build.lib.actions.ArtifactRoot;
 import com.google.devtools.build.lib.analysis.BlazeDirectories;
 import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
 import com.google.devtools.build.lib.analysis.RuleContext;
@@ -1185,8 +1185,10 @@
       this.middleman = false;
     }
 
-    Root getRoot(
-        RepositoryName repositoryName, String outputDirName, BlazeDirectories directories,
+    ArtifactRoot getRoot(
+        RepositoryName repositoryName,
+        String outputDirName,
+        BlazeDirectories directories,
         RepositoryName mainRepositoryName) {
       // e.g., execroot/repo1
       Path execRoot = directories.getExecRoot(mainRepositoryName.strippedName());
@@ -1194,10 +1196,11 @@
       Path outputDir = execRoot.getRelative(directories.getRelativeOutputPath())
           .getRelative(outputDirName);
       if (middleman) {
-        return INTERNER.intern(Root.middlemanRoot(execRoot, outputDir));
+        return INTERNER.intern(ArtifactRoot.middlemanRoot(execRoot, outputDir));
       }
       // e.g., [[execroot/repo1]/bazel-out/config/bin]
-      return INTERNER.intern(Root.asDerivedRoot(execRoot, outputDir.getRelative(nameFragment)));
+      return INTERNER.intern(
+          ArtifactRoot.asDerivedRoot(execRoot, outputDir.getRelative(nameFragment)));
     }
   }
 
@@ -1206,16 +1209,16 @@
 
   // We intern the roots for non-main repositories, so we don't keep around thousands of copies of
   // the same root.
-  private static Interner<Root> INTERNER = Interners.newWeakInterner();
+  private static Interner<ArtifactRoot> INTERNER = Interners.newWeakInterner();
 
   // We precompute the roots for the main repository, since that's the common case.
-  private final Root outputDirectoryForMainRepository;
-  private final Root binDirectoryForMainRepository;
-  private final Root includeDirectoryForMainRepository;
-  private final Root genfilesDirectoryForMainRepository;
-  private final Root coverageDirectoryForMainRepository;
-  private final Root testlogsDirectoryForMainRepository;
-  private final Root middlemanDirectoryForMainRepository;
+  private final ArtifactRoot outputDirectoryForMainRepository;
+  private final ArtifactRoot binDirectoryForMainRepository;
+  private final ArtifactRoot includeDirectoryForMainRepository;
+  private final ArtifactRoot genfilesDirectoryForMainRepository;
+  private final ArtifactRoot coverageDirectoryForMainRepository;
+  private final ArtifactRoot testlogsDirectoryForMainRepository;
+  private final ArtifactRoot middlemanDirectoryForMainRepository;
 
   private final boolean separateGenfilesDirectory;
 
@@ -1575,22 +1578,18 @@
     return platformName;
   }
 
-  /**
-   * Returns the output directory for this build configuration.
-   */
-  public Root getOutputDirectory(RepositoryName repositoryName) {
+  /** Returns the output directory for this build configuration. */
+  public ArtifactRoot getOutputDirectory(RepositoryName repositoryName) {
     return repositoryName.isMain() || repositoryName.equals(mainRepositoryName)
         ? outputDirectoryForMainRepository
         : OutputDirectory.OUTPUT.getRoot(
             repositoryName, outputDirName, directories, mainRepositoryName);
   }
 
-  /**
-   * Returns the bin directory for this build configuration.
-   */
+  /** Returns the bin directory for this build configuration. */
   @SkylarkCallable(name = "bin_dir", structField = true, documented = false)
   @Deprecated
-  public Root getBinDirectory() {
+  public ArtifactRoot getBinDirectory() {
     return getBinDirectory(RepositoryName.MAIN);
   }
 
@@ -1600,7 +1599,7 @@
    * issue right now because it only effects Blaze's include scanning (internal) and Bazel's
    * repositories (external) but will need to be fixed.
    */
-  public Root getBinDirectory(RepositoryName repositoryName) {
+  public ArtifactRoot getBinDirectory(RepositoryName repositoryName) {
     return repositoryName.isMain() || repositoryName.equals(mainRepositoryName)
         ? binDirectoryForMainRepository
         : OutputDirectory.BIN.getRoot(
@@ -1614,26 +1613,22 @@
     return getBinDirectory().getExecPath();
   }
 
-  /**
-   * Returns the include directory for this build configuration.
-   */
-  public Root getIncludeDirectory(RepositoryName repositoryName) {
+  /** Returns the include directory for this build configuration. */
+  public ArtifactRoot getIncludeDirectory(RepositoryName repositoryName) {
     return repositoryName.isMain() || repositoryName.equals(mainRepositoryName)
         ? includeDirectoryForMainRepository
         : OutputDirectory.INCLUDE.getRoot(
             repositoryName, outputDirName, directories, mainRepositoryName);
   }
 
-  /**
-   * Returns the genfiles directory for this build configuration.
-   */
+  /** Returns the genfiles directory for this build configuration. */
   @SkylarkCallable(name = "genfiles_dir", structField = true, documented = false)
   @Deprecated
-  public Root getGenfilesDirectory() {
+  public ArtifactRoot getGenfilesDirectory() {
     return getGenfilesDirectory(RepositoryName.MAIN);
   }
 
-  public Root getGenfilesDirectory(RepositoryName repositoryName) {
+  public ArtifactRoot getGenfilesDirectory(RepositoryName repositoryName) {
     if (!separateGenfilesDirectory) {
       return getBinDirectory(repositoryName);
     }
@@ -1645,21 +1640,19 @@
   }
 
   /**
-   * Returns the directory where coverage-related artifacts and metadata files
-   * should be stored. This includes for example uninstrumented class files
-   * needed for Jacoco's coverage reporting tools.
+   * Returns the directory where coverage-related artifacts and metadata files should be stored.
+   * This includes for example uninstrumented class files needed for Jacoco's coverage reporting
+   * tools.
    */
-  public Root getCoverageMetadataDirectory(RepositoryName repositoryName) {
+  public ArtifactRoot getCoverageMetadataDirectory(RepositoryName repositoryName) {
     return repositoryName.isMain() || repositoryName.equals(mainRepositoryName)
         ? coverageDirectoryForMainRepository
         : OutputDirectory.COVERAGE.getRoot(
             repositoryName, outputDirName, directories, mainRepositoryName);
   }
 
-  /**
-   * Returns the testlogs directory for this build configuration.
-   */
-  public Root getTestLogsDirectory(RepositoryName repositoryName) {
+  /** Returns the testlogs directory for this build configuration. */
+  public ArtifactRoot getTestLogsDirectory(RepositoryName repositoryName) {
     return repositoryName.isMain() || repositoryName.equals(mainRepositoryName)
         ? testlogsDirectoryForMainRepository
         : OutputDirectory.TESTLOGS.getRoot(
@@ -1686,10 +1679,8 @@
     return OS.getCurrent() == OS.WINDOWS ? ";" : ":";
   }
 
-  /**
-   * Returns the internal directory (used for middlemen) for this build configuration.
-   */
-  public Root getMiddlemanDirectory(RepositoryName repositoryName) {
+  /** Returns the internal directory (used for middlemen) for this build configuration. */
+  public ArtifactRoot getMiddlemanDirectory(RepositoryName repositoryName) {
     return repositoryName.isMain() || repositoryName.equals(mainRepositoryName)
         ? middlemanDirectoryForMainRepository
         : OutputDirectory.MIDDLEMAN.getRoot(
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkActionFactory.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkActionFactory.java
index e77b159..4bf9999 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkActionFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkActionFactory.java
@@ -18,8 +18,8 @@
 import com.google.devtools.build.lib.actions.Action;
 import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
 import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.ArtifactRoot;
 import com.google.devtools.build.lib.actions.ParameterFile.ParameterFileType;
-import com.google.devtools.build.lib.actions.Root;
 import com.google.devtools.build.lib.actions.RunfilesSupplier;
 import com.google.devtools.build.lib.actions.extra.SpawnInfo;
 import com.google.devtools.build.lib.analysis.CommandHelper;
@@ -94,7 +94,7 @@
     this.ruleContext = ruleContext;
   }
 
-  Root newFileRoot() throws EvalException {
+  ArtifactRoot newFileRoot() throws EvalException {
     return context.isForAspect()
         ? ruleContext.getConfiguration().getBinDirectory(ruleContext.getRule().getRepository())
         : ruleContext.getBinOrGenfilesDirectory();
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleContext.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleContext.java
index 3dbb8d9..de2bd46 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleContext.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleContext.java
@@ -25,7 +25,7 @@
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Ordering;
 import com.google.devtools.build.lib.actions.Artifact;
-import com.google.devtools.build.lib.actions.Root;
+import com.google.devtools.build.lib.actions.ArtifactRoot;
 import com.google.devtools.build.lib.analysis.ActionsProvider;
 import com.google.devtools.build.lib.analysis.ConfigurationMakeVariableContext;
 import com.google.devtools.build.lib.analysis.DefaultInfo;
@@ -708,16 +708,22 @@
     return ImmutableList.copyOf(ruleContext.getFeatures());
   }
 
-  @SkylarkCallable(name = "bin_dir", structField = true,
-      doc = "The root corresponding to bin directory.")
-  public Root getBinDirectory() throws EvalException {
+  @SkylarkCallable(
+    name = "bin_dir",
+    structField = true,
+    doc = "The root corresponding to bin directory."
+  )
+  public ArtifactRoot getBinDirectory() throws EvalException {
     checkMutable("bin_dir");
     return getConfiguration().getBinDirectory(ruleContext.getRule().getRepository());
   }
 
-  @SkylarkCallable(name = "genfiles_dir", structField = true,
-      doc = "The root corresponding to genfiles directory.")
-  public Root getGenfilesDirectory() throws EvalException {
+  @SkylarkCallable(
+    name = "genfiles_dir",
+    structField = true,
+    doc = "The root corresponding to genfiles directory."
+  )
+  public ArtifactRoot getGenfilesDirectory() throws EvalException {
     checkMutable("genfiles_dir");
     return getConfiguration().getGenfilesDirectory(ruleContext.getRule().getRepository());
   }
@@ -845,7 +851,7 @@
 
   // Kept for compatibility with old code.
   @SkylarkCallable(documented = false)
-  public Artifact newFile(Root root, String filename) throws EvalException {
+  public Artifact newFile(ArtifactRoot root, String filename) throws EvalException {
     checkMutable("new_file");
     return ruleContext.getPackageRelativeArtifact(filename, root);
   }
@@ -877,7 +883,8 @@
 
   // Kept for compatibility with old code.
   @SkylarkCallable(documented = false)
-  public Artifact newFile(Root root, Artifact baseArtifact, String suffix) throws EvalException {
+  public Artifact newFile(ArtifactRoot root, Artifact baseArtifact, String suffix)
+      throws EvalException {
     checkMutable("new_file");
     PathFragment original = baseArtifact.getRootRelativePath();
     PathFragment fragment = original.replaceName(original.getBaseName() + suffix);
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/test/TestActionBuilder.java b/src/main/java/com/google/devtools/build/lib/analysis/test/TestActionBuilder.java
index 81d6993..37cfbbe 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/test/TestActionBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/test/TestActionBuilder.java
@@ -21,7 +21,7 @@
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import com.google.devtools.build.lib.actions.Artifact;
-import com.google.devtools.build.lib.actions.Root;
+import com.google.devtools.build.lib.actions.ArtifactRoot;
 import com.google.devtools.build.lib.analysis.AnalysisEnvironment;
 import com.google.devtools.build.lib.analysis.FileProvider;
 import com.google.devtools.build.lib.analysis.FilesToRunProvider;
@@ -187,7 +187,7 @@
     PathFragment targetName = PathFragment.create(ruleContext.getLabel().getName());
     BuildConfiguration config = ruleContext.getConfiguration();
     AnalysisEnvironment env = ruleContext.getAnalysisEnvironment();
-    Root root = config.getTestLogsDirectory(ruleContext.getRule().getRepository());
+    ArtifactRoot root = config.getTestLogsDirectory(ruleContext.getRule().getRepository());
 
     NestedSetBuilder<Artifact> inputsBuilder = NestedSetBuilder.stableOrder();
     inputsBuilder.addTransitive(
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/BazelWorkspaceStatusModule.java b/src/main/java/com/google/devtools/build/lib/bazel/BazelWorkspaceStatusModule.java
index e3e405b..1fd392d 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/BazelWorkspaceStatusModule.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/BazelWorkspaceStatusModule.java
@@ -30,8 +30,8 @@
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.actions.ArtifactFactory;
 import com.google.devtools.build.lib.actions.ArtifactOwner;
+import com.google.devtools.build.lib.actions.ArtifactRoot;
 import com.google.devtools.build.lib.actions.ExecutionStrategy;
-import com.google.devtools.build.lib.actions.Root;
 import com.google.devtools.build.lib.analysis.BlazeDirectories;
 import com.google.devtools.build.lib.analysis.BuildInfo;
 import com.google.devtools.build.lib.analysis.BuildInfoEvent;
@@ -304,7 +304,7 @@
     public WorkspaceStatusAction createWorkspaceStatusAction(
         ArtifactFactory factory, ArtifactOwner artifactOwner, Supplier<UUID> buildId,
         String workspaceName) {
-      Root root = env.getDirectories().getBuildDataDirectory(workspaceName);
+      ArtifactRoot root = env.getDirectories().getBuildDataDirectory(workspaceName);
 
       Artifact stableArtifact = factory.getDerivedArtifact(
           PathFragment.create("stable-status.txt"), root, artifactOwner);
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcIncLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcIncLibrary.java
index c1a40fc..a459e42 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcIncLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcIncLibrary.java
@@ -17,7 +17,7 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSortedMap;
 import com.google.devtools.build.lib.actions.Artifact;
-import com.google.devtools.build.lib.actions.Root;
+import com.google.devtools.build.lib.actions.ArtifactRoot;
 import com.google.devtools.build.lib.analysis.ConfiguredTarget;
 import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder;
 import com.google.devtools.build.lib.analysis.RuleConfiguredTargetFactory;
@@ -85,7 +85,7 @@
     // is actually a symlink into the source tree.
     PathFragment includeDirectory = PathFragment.create("_")
         .getRelative(ruleContext.getTarget().getName());
-    Root configIncludeDirectory =
+    ArtifactRoot configIncludeDirectory =
         ruleContext.getConfiguration().getIncludeDirectory(ruleContext.getRule().getRepository());
     PathFragment includePath =
         configIncludeDirectory
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppBuildInfo.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppBuildInfo.java
index 8e49f99..1c68580 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppBuildInfo.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppBuildInfo.java
@@ -16,13 +16,12 @@
 import com.google.common.collect.ImmutableList;
 import com.google.devtools.build.lib.actions.Action;
 import com.google.devtools.build.lib.actions.Artifact;
-import com.google.devtools.build.lib.actions.Root;
+import com.google.devtools.build.lib.actions.ArtifactRoot;
 import com.google.devtools.build.lib.analysis.buildinfo.BuildInfoCollection;
 import com.google.devtools.build.lib.analysis.buildinfo.BuildInfoFactory;
 import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
 import com.google.devtools.build.lib.cmdline.RepositoryName;
 import com.google.devtools.build.lib.vfs.PathFragment;
-
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
@@ -69,7 +68,7 @@
       BuildConfiguration config, PathFragment headerName,
       Collection<Artifact> inputs,
       boolean writeVolatileInfo, boolean writeNonVolatileInfo, RepositoryName repositoryName) {
-    Root outputPath = config.getIncludeDirectory(repositoryName);
+    ArtifactRoot outputPath = config.getIncludeDirectory(repositoryName);
     final Artifact header =
         buildInfoContext.getBuildInfoArtifact(headerName, outputPath,
             writeVolatileInfo && !inputs.isEmpty()
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoSupport.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoSupport.java
index 738cc98..8edc2d9 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoSupport.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoSupport.java
@@ -26,7 +26,7 @@
 import com.google.common.collect.Iterables;
 import com.google.common.io.ByteSource;
 import com.google.devtools.build.lib.actions.Artifact;
-import com.google.devtools.build.lib.actions.Root;
+import com.google.devtools.build.lib.actions.ArtifactRoot;
 import com.google.devtools.build.lib.analysis.AnalysisEnvironment;
 import com.google.devtools.build.lib.analysis.RuleContext;
 import com.google.devtools.build.lib.cmdline.Label;
@@ -172,14 +172,13 @@
   private final Path fdoProfile;
 
   /**
-   * Temporary directory to which the coverage ZIP file is extracted to
-   * (relative to the exec root), or {@code null} if FDO optimization is
-   * disabled. This is used to create artifacts for the extracted files.
+   * Temporary directory to which the coverage ZIP file is extracted to (relative to the exec root),
+   * or {@code null} if FDO optimization is disabled. This is used to create artifacts for the
+   * extracted files.
    *
-   * <p>Note that this root is intentionally not registered with the artifact
-   * factory.
+   * <p>Note that this root is intentionally not registered with the artifact factory.
    */
-  private final Root fdoRoot;
+  private final ArtifactRoot fdoRoot;
 
   /**
    * The relative path of the FDO root to the exec root.
@@ -227,8 +226,14 @@
    * @param fdoProfile path to the profile file passed to --fdo_optimize option
    * @param lipoMode value of the --lipo_mode option
    */
-  private FdoSupport(FdoMode fdoMode, LipoMode lipoMode, Root fdoRoot, PathFragment fdoRootExecPath,
-      PathFragment fdoInstrument, Path fdoProfile, FdoZipContents fdoZipContents) {
+  private FdoSupport(
+      FdoMode fdoMode,
+      LipoMode lipoMode,
+      ArtifactRoot fdoRoot,
+      PathFragment fdoRootExecPath,
+      PathFragment fdoInstrument,
+      Path fdoProfile,
+      FdoZipContents fdoZipContents) {
     this.fdoInstrument = fdoInstrument;
     this.fdoProfile = fdoProfile;
     this.fdoRoot = fdoRoot;
@@ -248,7 +253,7 @@
     }
   }
 
-  public Root getFdoRoot() {
+  public ArtifactRoot getFdoRoot() {
     return fdoRoot;
   }
 
@@ -281,10 +286,10 @@
       lipoMode = LipoMode.OFF;
     }
 
-    Root fdoRoot =
+    ArtifactRoot fdoRoot =
         (fdoProfile == null)
             ? null
-            : Root.asDerivedRoot(execRoot, execRoot.getRelative(productName + "-fdo"));
+            : ArtifactRoot.asDerivedRoot(execRoot, execRoot.getRelative(productName + "-fdo"));
 
     PathFragment fdoRootExecPath = fdoProfile == null
         ? null
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/SolibSymlinkAction.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/SolibSymlinkAction.java
index 7f14ee2..7d60680 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/SolibSymlinkAction.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/SolibSymlinkAction.java
@@ -25,7 +25,7 @@
 import com.google.devtools.build.lib.actions.ActionResult;
 import com.google.devtools.build.lib.actions.Actions;
 import com.google.devtools.build.lib.actions.Artifact;
-import com.google.devtools.build.lib.actions.Root;
+import com.google.devtools.build.lib.actions.ArtifactRoot;
 import com.google.devtools.build.lib.analysis.RuleContext;
 import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
@@ -149,7 +149,7 @@
     Preconditions.checkArgument(!library.getRootRelativePath().getSegment(0).startsWith("_solib_"));
 
     // Ignore libraries that are already represented by the symlinks.
-    Root root = configuration.getBinDirectory(ruleContext.getRule().getRepository());
+    ArtifactRoot root = configuration.getBinDirectory(ruleContext.getRule().getRepository());
     Artifact symlink = ruleContext.getShareableArtifact(symlinkName, root);
     ruleContext.registerAction(
         new SolibSymlinkAction(ruleContext.getActionOwner(), library, symlink));
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaBuildInfoFactory.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaBuildInfoFactory.java
index be7abfb..c372146 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaBuildInfoFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaBuildInfoFactory.java
@@ -17,7 +17,7 @@
 import com.google.common.collect.ImmutableList;
 import com.google.devtools.build.lib.actions.Action;
 import com.google.devtools.build.lib.actions.Artifact;
-import com.google.devtools.build.lib.actions.Root;
+import com.google.devtools.build.lib.actions.ArtifactRoot;
 import com.google.devtools.build.lib.analysis.buildinfo.BuildInfoCollection;
 import com.google.devtools.build.lib.analysis.buildinfo.BuildInfoFactory;
 import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
@@ -126,7 +126,7 @@
       boolean includeVolatile,
       boolean includeNonVolatile,
       RepositoryName repositoryName) {
-    Root outputPath = config.getIncludeDirectory(repositoryName);
+    ArtifactRoot outputPath = config.getIncludeDirectory(repositoryName);
     final Artifact output = context.getBuildInfoArtifact(propertyFileName, outputPath,
         includeVolatile && !inputs.isEmpty() ? BuildInfoType.NO_REBUILD
             : BuildInfoType.FORCE_REBUILD_IF_CHANGED);
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 62bce38..7bc087b 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
@@ -32,10 +32,10 @@
 import com.google.devtools.build.lib.actions.ActionOwner;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.actions.ArtifactOwner;
+import com.google.devtools.build.lib.actions.ArtifactRoot;
 import com.google.devtools.build.lib.actions.CommandLineExpansionException;
 import com.google.devtools.build.lib.actions.ParameterFile;
 import com.google.devtools.build.lib.actions.ResourceSet;
-import com.google.devtools.build.lib.actions.Root;
 import com.google.devtools.build.lib.actions.RunfilesSupplier;
 import com.google.devtools.build.lib.actions.extra.ExtraActionInfo;
 import com.google.devtools.build.lib.actions.extra.JavaCompileInfo;
@@ -474,17 +474,15 @@
    */
   public interface ArtifactFactory {
 
-    /**
-     * Create an artifact with the specified root-relative path under the specified root.
-     */
-    Artifact create(PathFragment rootRelativePath, Root root);
+    /** Create an artifact with the specified root-relative path under the specified root. */
+    Artifact create(PathFragment rootRelativePath, ArtifactRoot root);
   }
 
   @VisibleForTesting
   static ArtifactFactory createArtifactFactory(final AnalysisEnvironment env) {
     return new ArtifactFactory() {
       @Override
-      public Artifact create(PathFragment rootRelativePath, Root root) {
+      public Artifact create(PathFragment rootRelativePath, ArtifactRoot root) {
         return env.getDerivedArtifact(rootRelativePath, root);
       }
     };
@@ -557,15 +555,17 @@
      * Creates a Builder from an owner and a build configuration.
      */
     public Builder(final RuleContext ruleContext, JavaSemantics semantics) {
-      this(ruleContext.getActionOwner(),
+      this(
+          ruleContext.getActionOwner(),
           ruleContext.getAnalysisEnvironment(),
           new ArtifactFactory() {
             @Override
-            public Artifact create(PathFragment rootRelativePath, Root root) {
+            public Artifact create(PathFragment rootRelativePath, ArtifactRoot root) {
               return ruleContext.getDerivedArtifact(rootRelativePath, root);
             }
           },
-          ruleContext.getConfiguration(), semantics);
+          ruleContext.getConfiguration(),
+          semantics);
     }
 
     public JavaCompileAction build() {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/nativedeps/NativeDepsHelper.java b/src/main/java/com/google/devtools/build/lib/rules/nativedeps/NativeDepsHelper.java
index 55a8efe..7f6437e 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/nativedeps/NativeDepsHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/nativedeps/NativeDepsHelper.java
@@ -19,7 +19,7 @@
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.devtools.build.lib.actions.Artifact;
-import com.google.devtools.build.lib.actions.Root;
+import com.google.devtools.build.lib.actions.ArtifactRoot;
 import com.google.devtools.build.lib.analysis.RuleContext;
 import com.google.devtools.build.lib.analysis.actions.SymlinkAction;
 import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
@@ -175,7 +175,7 @@
       CcToolchainProvider toolchain,
       Artifact nativeDeps,
       String libraryIdentifier,
-      Root bindirIfShared,
+      ArtifactRoot bindirIfShared,
       boolean useDynamicRuntime,
       CppSemantics cppSemantics)
       throws InterruptedException {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/IntermediateArtifacts.java b/src/main/java/com/google/devtools/build/lib/rules/objc/IntermediateArtifacts.java
index 459de19..4619758 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/IntermediateArtifacts.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/IntermediateArtifacts.java
@@ -17,7 +17,7 @@
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.devtools.build.lib.actions.Artifact;
-import com.google.devtools.build.lib.actions.Root;
+import com.google.devtools.build.lib.actions.ArtifactRoot;
 import com.google.devtools.build.lib.analysis.RuleContext;
 import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
 import com.google.devtools.build.lib.cmdline.Label;
@@ -244,7 +244,7 @@
   }
 
   private Artifact scopedArtifact(PathFragment scopeRelative, boolean inGenfiles) {
-    Root root =
+    ArtifactRoot root =
         inGenfiles
             ? buildConfiguration.getGenfilesDirectory(ruleContext.getRule().getRepository())
             : buildConfiguration.getBinDirectory(ruleContext.getRule().getRepository());
diff --git a/src/main/java/com/google/devtools/build/lib/rules/proto/ProtoCommon.java b/src/main/java/com/google/devtools/build/lib/rules/proto/ProtoCommon.java
index 3d2d555..a09a9af 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/proto/ProtoCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/proto/ProtoCommon.java
@@ -20,7 +20,7 @@
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableList;
 import com.google.devtools.build.lib.actions.Artifact;
-import com.google.devtools.build.lib.actions.Root;
+import com.google.devtools.build.lib.actions.ArtifactRoot;
 import com.google.devtools.build.lib.analysis.RuleContext;
 import com.google.devtools.build.lib.analysis.Runfiles;
 import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
@@ -142,8 +142,8 @@
   public static ImmutableList<Artifact> getGeneratedOutputs(RuleContext ruleContext,
       ImmutableList<Artifact> protoSources, String extension, boolean pythonNames) {
     ImmutableList.Builder<Artifact> outputsBuilder = new ImmutableList.Builder<>();
-    Root genfiles = ruleContext.getConfiguration().getGenfilesDirectory(
-        ruleContext.getRule().getRepository());
+    ArtifactRoot genfiles =
+        ruleContext.getConfiguration().getGenfilesDirectory(ruleContext.getRule().getRepository());
     for (Artifact src : protoSources) {
       PathFragment srcPath = src.getRootRelativePath();
       if (pythonNames) {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/python/PythonUtils.java b/src/main/java/com/google/devtools/build/lib/rules/python/PythonUtils.java
index c44e46e..d76b55b 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/python/PythonUtils.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/python/PythonUtils.java
@@ -15,7 +15,7 @@
 
 import com.google.common.collect.ImmutableSet;
 import com.google.devtools.build.lib.actions.Artifact;
-import com.google.devtools.build.lib.actions.Root;
+import com.google.devtools.build.lib.actions.ArtifactRoot;
 import com.google.devtools.build.lib.analysis.FilesToRunProvider;
 import com.google.devtools.build.lib.analysis.RuleContext;
 import com.google.devtools.build.lib.analysis.Runfiles;
@@ -82,8 +82,8 @@
    * subdirectory to avoid conflicts (eg. when the input file is generated).
    */
   private static Artifact get2to3OutputArtifact(RuleContext ruleContext, Artifact input) {
-    Root root = ruleContext.getConfiguration().getGenfilesDirectory(
-        ruleContext.getRule().getRepository());
+    ArtifactRoot root =
+        ruleContext.getConfiguration().getGenfilesDirectory(ruleContext.getRule().getRepository());
     PathFragment path = PathFragment.create("python3").getRelative(input.getRootRelativePath());
     return ruleContext.getShareableArtifact(path, root);
   }
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java
index 4643235..52b9b26 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java
@@ -29,10 +29,10 @@
 import com.google.devtools.build.lib.actions.ActionLookupValue;
 import com.google.devtools.build.lib.actions.AlreadyReportedActionExecutionException;
 import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.ArtifactRoot;
 import com.google.devtools.build.lib.actions.MissingInputFileException;
 import com.google.devtools.build.lib.actions.NotifyOnActionCacheHit;
 import com.google.devtools.build.lib.actions.PackageRootResolver;
-import com.google.devtools.build.lib.actions.Root;
 import com.google.devtools.build.lib.causes.Cause;
 import com.google.devtools.build.lib.causes.LabelCause;
 import com.google.devtools.build.lib.clock.BlazeClock;
@@ -288,8 +288,8 @@
     }
 
     @Override
-    public Map<PathFragment, Root> findPackageRootsForFiles(Iterable<PathFragment> execPaths)
-        throws InterruptedException {
+    public Map<PathFragment, ArtifactRoot> findPackageRootsForFiles(
+        Iterable<PathFragment> execPaths) throws InterruptedException {
       Preconditions.checkState(keysRequested.isEmpty(),
           "resolver should only be called once: %s %s", keysRequested, execPaths);
       // Create SkyKeys list based on execPaths.
@@ -318,7 +318,7 @@
         return null;
       }
 
-      Map<PathFragment, Root> result = new HashMap<>();
+      Map<PathFragment, ArtifactRoot> result = new HashMap<>();
       for (PathFragment path : execPaths) {
         if (!depKeys.containsKey(path)) {
           continue;
@@ -327,8 +327,9 @@
             (ContainingPackageLookupValue) values.get(depKeys.get(path));
         if (value.hasContainingPackage()) {
           // We have found corresponding root for current execPath.
-          result.put(path,
-              Root.computeSourceRoot(
+          result.put(
+              path,
+              ArtifactRoot.computeSourceRoot(
                   value.getContainingPackageRoot(),
                   value.getContainingPackageName().getRepository()));
         } else {
@@ -341,7 +342,7 @@
 
     @Override
     @Nullable
-    public Map<PathFragment, Root> findPackageRoots(Iterable<PathFragment> execPaths)
+    public Map<PathFragment, ArtifactRoot> findPackageRoots(Iterable<PathFragment> execPaths)
         throws InterruptedException {
       // call sites for this implementation of PackageRootResolver shouldn't be passing in
       // directories.
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/BuildInfoCollectionFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/BuildInfoCollectionFunction.java
index c80875d..b8cbd4a 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/BuildInfoCollectionFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/BuildInfoCollectionFunction.java
@@ -19,7 +19,7 @@
 import com.google.devtools.build.lib.actions.ActionKeyContext;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.actions.ArtifactFactory;
-import com.google.devtools.build.lib.actions.Root;
+import com.google.devtools.build.lib.actions.ArtifactRoot;
 import com.google.devtools.build.lib.analysis.buildinfo.BuildInfoFactory;
 import com.google.devtools.build.lib.analysis.buildinfo.BuildInfoFactory.BuildInfoContext;
 import com.google.devtools.build.lib.analysis.buildinfo.BuildInfoFactory.BuildInfoKey;
@@ -70,15 +70,16 @@
         nameValue.getName());
 
     final ArtifactFactory factory = artifactFactory.get();
-    BuildInfoContext context = new BuildInfoContext() {
-      @Override
-      public Artifact getBuildInfoArtifact(PathFragment rootRelativePath, Root root,
-          BuildInfoType type) {
-        return type == BuildInfoType.NO_REBUILD
-            ? factory.getConstantMetadataArtifact(rootRelativePath, root, keyAndConfig)
-            : factory.getDerivedArtifact(rootRelativePath, root, keyAndConfig);
-      }
-    };
+    BuildInfoContext context =
+        new BuildInfoContext() {
+          @Override
+          public Artifact getBuildInfoArtifact(
+              PathFragment rootRelativePath, ArtifactRoot root, BuildInfoType type) {
+            return type == BuildInfoType.NO_REBUILD
+                ? factory.getConstantMetadataArtifact(rootRelativePath, root, keyAndConfig)
+                : factory.getDerivedArtifact(rootRelativePath, root, keyAndConfig);
+          }
+        };
 
     return new BuildInfoCollectionValue(
         actionKeyContext,
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/MapAsPackageRoots.java b/src/main/java/com/google/devtools/build/lib/skyframe/MapAsPackageRoots.java
index f969c02..f4ac69f 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/MapAsPackageRoots.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/MapAsPackageRoots.java
@@ -15,8 +15,8 @@
 package com.google.devtools.build.lib.skyframe;
 
 import com.google.common.collect.ImmutableMap;
+import com.google.devtools.build.lib.actions.ArtifactRoot;
 import com.google.devtools.build.lib.actions.PackageRoots;
-import com.google.devtools.build.lib.actions.Root;
 import com.google.devtools.build.lib.cmdline.PackageIdentifier;
 import com.google.devtools.build.lib.vfs.Path;
 import java.util.HashMap;
@@ -41,12 +41,12 @@
 
   @Override
   public PackageRootLookup getPackageRootLookup() {
-    Map<Path, Root> rootMap = new HashMap<>();
-    Map<PackageIdentifier, Root> realPackageRoots = new HashMap<>();
+    Map<Path, ArtifactRoot> rootMap = new HashMap<>();
+    Map<PackageIdentifier, ArtifactRoot> realPackageRoots = new HashMap<>();
     for (Map.Entry<PackageIdentifier, Path> entry : packageRootsMap.entrySet()) {
-      Root root = rootMap.get(entry.getValue());
+      ArtifactRoot root = rootMap.get(entry.getValue());
       if (root == null) {
-        root = Root.asSourceRoot(entry.getValue());
+        root = ArtifactRoot.asSourceRoot(entry.getValue());
         rootMap.put(entry.getValue(), root);
       }
       realPackageRoots.put(entry.getKey(), root);
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PackageRootsNoSymlinkCreation.java b/src/main/java/com/google/devtools/build/lib/skyframe/PackageRootsNoSymlinkCreation.java
index d1ee84f..16f03e7 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/PackageRootsNoSymlinkCreation.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/PackageRootsNoSymlinkCreation.java
@@ -16,8 +16,8 @@
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableMap;
+import com.google.devtools.build.lib.actions.ArtifactRoot;
 import com.google.devtools.build.lib.actions.PackageRoots;
-import com.google.devtools.build.lib.actions.Root;
 import com.google.devtools.build.lib.cmdline.PackageIdentifier;
 import com.google.devtools.build.lib.vfs.Path;
 import java.util.Optional;
@@ -27,11 +27,11 @@
  * whose {@link PackageRootLookup} returns the unique source root for any given package identifier.
  */
 public class PackageRootsNoSymlinkCreation implements PackageRoots {
-  private final Root sourceRoot;
+  private final ArtifactRoot sourceRoot;
 
   @VisibleForTesting
   public PackageRootsNoSymlinkCreation(Path sourcePath) {
-    this.sourceRoot = Root.asSourceRoot(sourcePath);
+    this.sourceRoot = ArtifactRoot.asSourceRoot(sourcePath);
   }
 
   @Override
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 429caf8..2038e11 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
@@ -48,11 +48,11 @@
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.actions.ArtifactFactory;
 import com.google.devtools.build.lib.actions.ArtifactOwner;
+import com.google.devtools.build.lib.actions.ArtifactRoot;
 import com.google.devtools.build.lib.actions.EnvironmentalExecException;
 import com.google.devtools.build.lib.actions.Executor;
 import com.google.devtools.build.lib.actions.FileStateType;
 import com.google.devtools.build.lib.actions.ResourceManager;
-import com.google.devtools.build.lib.actions.Root;
 import com.google.devtools.build.lib.analysis.AspectCollection;
 import com.google.devtools.build.lib.analysis.BlazeDirectories;
 import com.google.devtools.build.lib.analysis.ConfiguredAspect;
@@ -830,19 +830,19 @@
     return ImmutableList.of(value.getStableArtifact(), value.getVolatileArtifact());
   }
 
-  public Map<PathFragment, Root> getArtifactRootsForFiles(
+  public Map<PathFragment, ArtifactRoot> getArtifactRootsForFiles(
       final ExtendedEventHandler eventHandler, Iterable<PathFragment> execPaths)
       throws InterruptedException {
     return getArtifactRoots(eventHandler, execPaths, true);
   }
 
-  public Map<PathFragment, Root> getArtifactRoots(
+  public Map<PathFragment, ArtifactRoot> getArtifactRoots(
       final ExtendedEventHandler eventHandler, Iterable<PathFragment> execPaths)
       throws InterruptedException {
     return getArtifactRoots(eventHandler, execPaths, false);
   }
 
-  private Map<PathFragment, Root> getArtifactRoots(
+  private Map<PathFragment, ArtifactRoot> getArtifactRoots(
       final ExtendedEventHandler eventHandler, Iterable<PathFragment> execPaths, boolean forFiles)
       throws InterruptedException {
     final Map<PathFragment, SkyKey> packageKeys = new HashMap<>();
@@ -867,12 +867,13 @@
       return new HashMap<>();
     }
 
-    Map<PathFragment, Root> roots = new HashMap<>();
+    Map<PathFragment, ArtifactRoot> roots = new HashMap<>();
     for (PathFragment execPath : execPaths) {
       ContainingPackageLookupValue value = result.get(packageKeys.get(execPath));
       if (value.hasContainingPackage()) {
-        roots.put(execPath,
-            Root.computeSourceRoot(
+        roots.put(
+            execPath,
+            ArtifactRoot.computeSourceRoot(
                 value.getContainingPackageRoot(),
                 value.getContainingPackageName().getRepository()));
       } else {