Restructure Path#getCachedChildPath to make direct method calls without allocating a garbage TranslatedPath object.

RELNOTES: None

PiperOrigin-RevId: 152130170
diff --git a/src/main/java/com/google/devtools/build/lib/vfs/FileSystem.java b/src/main/java/com/google/devtools/build/lib/vfs/FileSystem.java
index 8048ddf..bce290e 100644
--- a/src/main/java/com/google/devtools/build/lib/vfs/FileSystem.java
+++ b/src/main/java/com/google/devtools/build/lib/vfs/FileSystem.java
@@ -97,8 +97,8 @@
       }
 
       @Override
-      public TranslatedPath translatePath(Path parent, String child) {
-        return new TranslatedPath(parent, child);
+      public Path getCachedChildPathInternal(Path path, String childName) {
+        return Path.getCachedChildPathInternal(path, childName, /*cacheable=*/ true);
       }
     };
   }
diff --git a/src/main/java/com/google/devtools/build/lib/vfs/Path.java b/src/main/java/com/google/devtools/build/lib/vfs/Path.java
index cfa3520..e408841 100644
--- a/src/main/java/com/google/devtools/build/lib/vfs/Path.java
+++ b/src/main/java/com/google/devtools/build/lib/vfs/Path.java
@@ -54,28 +54,6 @@
 
   /** Filesystem-specific factory for {@link Path} objects. */
   public static interface PathFactory {
-
-    /**
-     * A translated path, i.e. where the parent and name are potentially different from the input.
-     *
-     * <p>See {@link PathFactory#translatePath} for details.
-     */
-    public static final class TranslatedPath {
-      public final Path parent;
-      public final String child;
-      public final boolean cacheable;
-
-      public TranslatedPath(Path parent, String child, boolean cacheable) {
-        this.parent = parent;
-        this.child = child;
-        this.cacheable = cacheable;
-      }
-
-      public TranslatedPath(Path parent, String child) {
-        this(parent, child, true);
-      }
-    }
-
     /**
      * Creates the root of all paths used by a filesystem.
      *
@@ -96,13 +74,15 @@
     Path createChildPath(Path parent, String childName);
 
     /**
-     * Translate the input path in a filesystem-specific way if necessary.
+     * Makes the proper invocation of {@link FileSystem#getCachedChildPathInternal}, doing
+     * filesystem-specific logic if necessary.
      *
-     * <p>On Unix filesystems this operation is typically idempotent, but on Windows this can be
-     * used to translate absolute Unix paths to absolute Windows paths, e.g. "/c" to "C:/" or "/usr"
-     * to "C:/tools/msys64/usr".
+     * <p>On Unix filesystems this method merely calls through to {@code
+     * FileSystem.getCachedChildPathInternal(parent, child)}, but on Windows this can be used to
+     * handle the translatation of absolute Unix paths to absolute Windows paths, e.g. "/c" to "C:/"
+     * or "/usr" to "C:/tools/msys64/usr".
      */
-    TranslatedPath translatePath(Path parent, String child);
+    Path getCachedChildPathInternal(Path path, String childName);
   }
 
   private static FileSystem fileSystemForSerialization;
@@ -316,14 +296,16 @@
    * if it doesn't already exist.
    */
   private Path getCachedChildPath(String childName) {
-    return getCachedChildPath(fileSystem.getPathFactory().translatePath(this, childName));
+    return fileSystem.getPathFactory().getCachedChildPathInternal(this, childName);
   }
 
-  private static Path getCachedChildPath(PathFactory.TranslatedPath translated) {
-    Path parent = translated.parent;
+  /**
+   * Internal method only intended to be called by {@link PathFactory#getCachedChildPathInternal}.
+   */
+  public static Path getCachedChildPathInternal(Path parent, String childName, boolean cacheable) {
     // We get a canonical instance since 'children' is an IdentityHashMap.
-    String childName = StringCanonicalizer.intern(translated.child);
-    if (!translated.cacheable) {
+    childName = StringCanonicalizer.intern(childName);
+    if (!cacheable) {
       // Non-cacheable children won't show up in `children` so applyToChildren won't run for these.
       return parent.createChildPath(childName);
     }
diff --git a/src/main/java/com/google/devtools/build/lib/vfs/ZipFileSystem.java b/src/main/java/com/google/devtools/build/lib/vfs/ZipFileSystem.java
index 1eedcd5..d7ad308 100644
--- a/src/main/java/com/google/devtools/build/lib/vfs/ZipFileSystem.java
+++ b/src/main/java/com/google/devtools/build/lib/vfs/ZipFileSystem.java
@@ -17,7 +17,6 @@
 import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
 import com.google.devtools.build.lib.util.Preconditions;
 import com.google.devtools.build.lib.vfs.Path.PathFactory;
-import com.google.devtools.build.lib.vfs.Path.PathFactory.TranslatedPath;
 import java.io.Closeable;
 import java.io.File;
 import java.io.FileNotFoundException;
@@ -113,8 +112,8 @@
         }
 
         @Override
-        public TranslatedPath translatePath(Path parent, String child) {
-          return new TranslatedPath(parent, child);
+        public Path getCachedChildPathInternal(Path path, String childName) {
+          return Path.getCachedChildPathInternal(path, childName, /*cacheable=*/ true);
         }
       };
     }
diff --git a/src/main/java/com/google/devtools/build/lib/windows/WindowsFileSystem.java b/src/main/java/com/google/devtools/build/lib/windows/WindowsFileSystem.java
index ab1ee20..710319f 100644
--- a/src/main/java/com/google/devtools/build/lib/windows/WindowsFileSystem.java
+++ b/src/main/java/com/google/devtools/build/lib/windows/WindowsFileSystem.java
@@ -102,12 +102,13 @@
       }
 
       @Override
-      public TranslatedPath translatePath(Path parent, String child) {
-        return WindowsPathFactory.translatePath(parent, child, WINDOWS_SHORT_PATH_RESOLVER);
+      public Path getCachedChildPathInternal(Path path, String childName) {
+        return WindowsPathFactory.getCachedChildPathInternalImpl(
+            path, childName, WINDOWS_SHORT_PATH_RESOLVER);
       }
     };
 
-    private static TranslatedPath translatePath(
+    private static Path getCachedChildPathInternalImpl(
         Path parent, String child, Function<String, String> resolver) {
       if (parent != null && parent.isRootDirectory()) {
         // This is a top-level directory. It's either a drive name ("C:" or "c") or some other
@@ -165,7 +166,7 @@
         pathString += child;
         resolvedChild = resolver.apply(pathString);
       }
-      return new TranslatedPath(
+      return Path.getCachedChildPathInternal(
           parent,
           // If resolution succeeded, or we didn't attempt to resolve, then `resolvedChild` has the
           // child name. If it's null, then resolution failed; use the unresolved child name in that
@@ -196,8 +197,8 @@
         }
 
         @Override
-        public TranslatedPath translatePath(Path parent, String child) {
-          return WindowsPathFactory.translatePath(parent, child, mockResolver);
+        public Path getCachedChildPathInternal(Path path, String childName) {
+          return WindowsPathFactory.getCachedChildPathInternalImpl(path, childName, mockResolver);
         }
       };
     }