Crash on missing children for rewinding.

It should never be tolerated because the graph should just create an absent node if a child is expectedly missing. Still not using `createIfAbsentBatch` because it's not always expected.

PiperOrigin-RevId: 458001143
Change-Id: Ibd8708ab202f87bb3a110502bb5ead8c1973dedc
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/rewinding/RewindableGraphInconsistencyReceiver.java b/src/main/java/com/google/devtools/build/lib/skyframe/rewinding/RewindableGraphInconsistencyReceiver.java
index 1e4e24e..bd2167c 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/rewinding/RewindableGraphInconsistencyReceiver.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/rewinding/RewindableGraphInconsistencyReceiver.java
@@ -95,18 +95,11 @@
             key, childrenAsString);
         return;
 
-      case PARENT_FORCE_REBUILD_OF_MISSING_CHILD:
-      case DIRTY_PARENT_HAD_MISSING_CHILD:
-      case ALREADY_DECLARED_CHILD_MISSING:
+      default:
         throw new IllegalStateException(
             String.format(
                 "Unexpected inconsistency %s, key = %s, otherKeys = %s ",
                 inconsistency, key, childrenAsString));
-      default: // Needed because protobuf creates additional enum values.
-        throw new IllegalStateException(
-            String.format(
-                "Unknown inconsistency %s, key = %s, otherKeys = %s ",
-                inconsistency, key, childrenAsString));
     }
   }
 
diff --git a/src/main/java/com/google/devtools/build/skyframe/AbstractParallelEvaluator.java b/src/main/java/com/google/devtools/build/skyframe/AbstractParallelEvaluator.java
index 01e1f6b..b49c2cf 100644
--- a/src/main/java/com/google/devtools/build/skyframe/AbstractParallelEvaluator.java
+++ b/src/main/java/com/google/devtools/build/skyframe/AbstractParallelEvaluator.java
@@ -13,9 +13,12 @@
 // limitations under the License.
 package com.google.devtools.build.skyframe;
 
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
 import com.github.benmanes.caffeine.cache.Cache;
 import com.github.benmanes.caffeine.cache.Caffeine;
-import com.google.common.base.Preconditions;
 import com.google.common.base.Throwables;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
@@ -51,7 +54,6 @@
 import com.google.devtools.build.skyframe.proto.GraphInconsistency.Inconsistency;
 import java.io.IOException;
 import java.time.Duration;
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
@@ -293,7 +295,7 @@
         int childEvaluationPriority,
         boolean enqueueParentIfReady)
         throws InterruptedException {
-      Preconditions.checkState(!entry.isDone(), "%s %s", skyKey, entry);
+      checkState(!entry.isDone(), "%s %s", skyKey, entry);
       DependencyState dependencyState;
       try {
         dependencyState =
@@ -423,7 +425,7 @@
               nodeEntry.signalDep(MinimalVersion.INSTANCE, /*childForDebugging=*/ null);
         }
         if (needsScheduling) {
-          Preconditions.checkState(
+          checkState(
               unknownStatusDeps.isEmpty(),
               "Ready without all deps checked? %s %s %s",
               skyKey,
@@ -543,9 +545,8 @@
     public void run() {
       SkyFunctionEnvironment env = null;
       try {
-        NodeEntry nodeEntry =
-            Preconditions.checkNotNull(graph.get(null, Reason.EVALUATION, skyKey), skyKey);
-        Preconditions.checkState(nodeEntry.isReady(), "%s %s", skyKey, nodeEntry);
+        NodeEntry nodeEntry = checkNotNull(graph.get(null, Reason.EVALUATION, skyKey), skyKey);
+        checkState(nodeEntry.isReady(), "%s %s", skyKey, nodeEntry);
         try {
           evaluatorContext.getProgressReceiver().stateStarting(skyKey, NodeState.CHECK_DIRTY);
           if (maybeHandleDirtyNode(nodeEntry) == DirtyOutcome.ALREADY_PROCESSED) {
@@ -576,7 +577,7 @@
         }
         SkyFunctionName functionName = skyKey.functionName();
         SkyFunction skyFunction =
-            Preconditions.checkNotNull(
+            checkNotNull(
                 evaluatorContext.getSkyFunctions().get(functionName),
                 "Unable to find SkyFunction '%s' for node with key %s, %s",
                 functionName,
@@ -683,7 +684,7 @@
         if (value != null) {
           stateCache.invalidate(skyKey);
 
-          Preconditions.checkState(
+          checkState(
               !env.valuesMissing(),
               "Evaluation of %s returned non-null value but requested dependencies that weren't "
                   + "computed yet (one of %s), NodeEntry: %s",
@@ -711,14 +712,13 @@
 
         SkyKey childErrorKey = env.getDepErrorKey();
         if (childErrorKey != null) {
-          Preconditions.checkState(
-              !evaluatorContext.keepGoing(), "%s %s %s", skyKey, nodeEntry, childErrorKey);
+          checkState(!evaluatorContext.keepGoing(), "%s %s %s", skyKey, nodeEntry, childErrorKey);
           // We encountered a child error in noKeepGoing mode, so we want to fail fast. But we first
           // need to add the edge between the current node and the child error it requested so that
           // error bubbling can occur. Note that this edge will subsequently be removed during graph
           // cleaning (since the current node will never be committed to the graph).
           NodeEntry childErrorEntry =
-              Preconditions.checkNotNull(
+              checkNotNull(
                   graph.get(skyKey, Reason.OTHER, childErrorKey),
                   "skyKey: %s, nodeEntry: %s childErrorKey: %s",
                   skyKey,
@@ -750,13 +750,13 @@
             }
           }
           SkyValue childErrorInfoMaybe =
-              Preconditions.checkNotNull(
+              checkNotNull(
                   env.maybeGetValueFromErrorOrDeps(childErrorKey),
                   "dep error found but then lost while building: %s %s",
                   skyKey,
                   childErrorKey);
           ErrorInfo childErrorInfo =
-              Preconditions.checkNotNull(
+              checkNotNull(
                   ValueWithMetadata.getMaybeErrorInfo(childErrorInfoMaybe),
                   "dep error found but then wasn't an error while building: %s %s %s",
                   skyKey,
@@ -788,12 +788,12 @@
         // we just order it to be built.
         if (uniqueNewDeps.isEmpty() && externalDeps == null) {
           // TODO(bazel-team): This means a bug in the SkyFunction. What to do?
-          Preconditions.checkState(
+          checkState(
               !env.getChildErrorInfos().isEmpty(),
               "Evaluation of SkyKey failed and no dependencies were requested: %s %s",
               skyKey,
               nodeEntry);
-          Preconditions.checkState(
+          checkState(
               evaluatorContext.keepGoing(),
               "nokeep_going evaluation should have failed on first child error: %s %s %s",
               skyKey,
@@ -967,7 +967,7 @@
       restart(key, entry);
       return true;
     }
-    Preconditions.checkArgument(
+    checkArgument(
         rewindGraph.nodes().contains(key),
         "rewindGraph must contain the key for the failed evaluation if it's not empty. key: %s, "
             + "rewindGraph: %s",
@@ -980,43 +980,32 @@
         builder.add(k);
       }
     }
-    ImmutableList<SkyKey> additionalKeysToRestart = builder.build();
-    if (!additionalKeysToRestart.isEmpty()) {
+    ImmutableList<SkyKey> childrenToRestart = builder.build();
+    if (!childrenToRestart.isEmpty()) {
       evaluatorContext
           .getGraphInconsistencyReceiver()
           .noteInconsistencyAndMaybeThrow(
-              key, additionalKeysToRestart, Inconsistency.PARENT_FORCE_REBUILD_OF_CHILD);
-    }
+              key, childrenToRestart, Inconsistency.PARENT_FORCE_REBUILD_OF_CHILD);
 
-    Map<SkyKey, ? extends NodeEntry> additionalNodesToRestart =
-        evaluatorContext.getBatchValues(key, Reason.REWINDING, additionalKeysToRestart);
+      Map<SkyKey, ? extends NodeEntry> children =
+          evaluatorContext.getBatchValues(key, Reason.REWINDING, childrenToRestart);
 
-    ArrayList<SkyKey> missingNodes = null;
-    for (SkyKey keyToRestart : additionalKeysToRestart) {
-      NodeEntry restartEntry = additionalNodesToRestart.get(keyToRestart);
+      for (SkyKey childToRestart : childrenToRestart) {
+        NodeEntry childEntry =
+            checkNotNull(
+                children.get(childToRestart),
+                "Missing child for rewinding: %s (parent=%s)",
+                childToRestart,
+                key);
 
-      if (restartEntry == null) {
-        if (missingNodes == null) {
-          missingNodes = new ArrayList<>();
+        // Nodes are marked "force-rebuild" to ensure that they run, and to allow them to evaluate
+        // to a different value than before, even if their versions remain the same.
+        if (childEntry.markDirty(DirtyType.FORCE_REBUILD) != null) {
+          evaluatorContext
+              .getProgressReceiver()
+              .invalidated(childToRestart, EvaluationProgressReceiver.InvalidationState.DIRTY);
         }
-        missingNodes.add(keyToRestart);
-        continue;
       }
-
-      // Nodes are marked "force-rebuild" to ensure that they run, and to allow them to evaluate to
-      // a different value than before, even if their versions remain the same.
-      if (restartEntry.markDirty(DirtyType.FORCE_REBUILD) != null) {
-        evaluatorContext
-            .getProgressReceiver()
-            .invalidated(keyToRestart, EvaluationProgressReceiver.InvalidationState.DIRTY);
-      }
-    }
-
-    if (missingNodes != null) {
-      evaluatorContext
-          .getGraphInconsistencyReceiver()
-          .noteInconsistencyAndMaybeThrow(
-              key, missingNodes, Inconsistency.PARENT_FORCE_REBUILD_OF_MISSING_CHILD);
     }
 
     // TODO(b/19539699): rdeps of children have to be handled here. If the graph does not keep
@@ -1042,8 +1031,7 @@
       evaluatorContext
           .getReporter()
           .handle(Event.error("Crashes detected: " + evaluatorContext.getVisitor().getCrashes()));
-      throw Preconditions.checkNotNull(
-          Iterables.getFirst(evaluatorContext.getVisitor().getCrashes(), null));
+      throw checkNotNull(Iterables.getFirst(evaluatorContext.getVisitor().getCrashes(), null));
     }
   }
 
@@ -1146,7 +1134,7 @@
       }
     }
 
-    Preconditions.checkState(
+    checkState(
         selfSignalled || dirtyDepFound || uniqueNewDeps.isEmpty(),
         "%s %s %s %s",
         skyKey,
@@ -1175,8 +1163,7 @@
           .noteInconsistencyAndMaybeThrow(
               depKey, missing, Inconsistency.ALREADY_DECLARED_CHILD_MISSING);
       depEntry =
-          Preconditions.checkNotNull(
-              graph.createIfAbsentBatch(requestor, reason, missing).get(depKey), depKey);
+          checkNotNull(graph.createIfAbsentBatch(requestor, reason, missing).get(depKey), depKey);
     }
     return depEntry;
   }
diff --git a/src/main/java/com/google/devtools/build/skyframe/graph_inconsistency.proto b/src/main/java/com/google/devtools/build/skyframe/graph_inconsistency.proto
index f391bdd..6724022 100644
--- a/src/main/java/com/google/devtools/build/skyframe/graph_inconsistency.proto
+++ b/src/main/java/com/google/devtools/build/skyframe/graph_inconsistency.proto
@@ -26,7 +26,10 @@
   RESET_REQUESTED = 1;
   DIRTY_PARENT_HAD_MISSING_CHILD = 2;
   PARENT_FORCE_REBUILD_OF_CHILD = 3;
-  PARENT_FORCE_REBUILD_OF_MISSING_CHILD = 4;
+  // Deprecated: children requested for rewinding should be created if absent.
+  // A missing child is not tolerated and results in a crash, so this
+  // inconsistency will not appear in InconsistencyStats.
+  PARENT_FORCE_REBUILD_OF_MISSING_CHILD = 4 [deprecated = true];
   BUILDING_PARENT_FOUND_UNDONE_CHILD = 5;
   ALREADY_DECLARED_CHILD_MISSING = 6;
 }